From 5efb94ee144c1c7290652495a0f4f29cae845a62 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Sun, 23 Jan 2011 18:58:29 +1100 Subject: hwrng: pixocell - add support for picoxcell TRNG This driver adds support for the True Random Number Generator in the Picochip PC3X3 and later devices. Signed-off-by: Jamie Iles Acked-by: Matt Mackall Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 12 ++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/picoxcell-rng.c | 208 +++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 drivers/char/hw_random/picoxcell-rng.c (limited to 'drivers/char') diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index d31483c54883..beecd1cf9b99 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -198,3 +198,15 @@ config HW_RANDOM_NOMADIK module will be called nomadik-rng. If unsure, say Y. + +config HW_RANDOM_PICOXCELL + tristate "Picochip picoXcell true random number generator support" + depends on HW_RANDOM && ARCH_PICOXCELL && PICOXCELL_PC3X3 + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Picochip PC3x3 and later devices. + + To compile this driver as a module, choose M here: the + module will be called picoxcell-rng. + + If unsure, say Y. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 4273308aa1e3..3db4eb8b19c0 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o +obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c new file mode 100644 index 000000000000..990d55a5e3e8 --- /dev/null +++ b/drivers/char/hw_random/picoxcell-rng.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * All enquiries to support@picochip.com + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define DATA_REG_OFFSET 0x0200 +#define CSR_REG_OFFSET 0x0278 +#define CSR_OUT_EMPTY_MASK (1 << 24) +#define CSR_FAULT_MASK (1 << 1) +#define TRNG_BLOCK_RESET_MASK (1 << 0) +#define TAI_REG_OFFSET 0x0380 + +/* + * The maximum amount of time in microseconds to spend waiting for data if the + * core wants us to wait. The TRNG should generate 32 bits every 320ns so a + * timeout of 20us seems reasonable. The TRNG does builtin tests of the data + * for randomness so we can't always assume there is data present. + */ +#define PICO_TRNG_TIMEOUT 20 + +static void __iomem *rng_base; +static struct clk *rng_clk; +struct device *rng_dev; + +static inline u32 picoxcell_trng_read_csr(void) +{ + return __raw_readl(rng_base + CSR_REG_OFFSET); +} + +static inline bool picoxcell_trng_is_empty(void) +{ + return picoxcell_trng_read_csr() & CSR_OUT_EMPTY_MASK; +} + +/* + * Take the random number generator out of reset and make sure the interrupts + * are masked. We shouldn't need to get large amounts of random bytes so just + * poll the status register. The hardware generates 32 bits every 320ns so we + * shouldn't have to wait long enough to warrant waiting for an IRQ. + */ +static void picoxcell_trng_start(void) +{ + __raw_writel(0, rng_base + TAI_REG_OFFSET); + __raw_writel(0, rng_base + CSR_REG_OFFSET); +} + +static void picoxcell_trng_reset(void) +{ + __raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + CSR_REG_OFFSET); + __raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + TAI_REG_OFFSET); + picoxcell_trng_start(); +} + +/* + * Get some random data from the random number generator. The hw_random core + * layer provides us with locking. + */ +static int picoxcell_trng_read(struct hwrng *rng, void *buf, size_t max, + bool wait) +{ + int i; + + /* Wait for some data to become available. */ + for (i = 0; i < PICO_TRNG_TIMEOUT && picoxcell_trng_is_empty(); ++i) { + if (!wait) + return 0; + + udelay(1); + } + + if (picoxcell_trng_read_csr() & CSR_FAULT_MASK) { + dev_err(rng_dev, "fault detected, resetting TRNG\n"); + picoxcell_trng_reset(); + return -EIO; + } + + if (i == PICO_TRNG_TIMEOUT) + return 0; + + *(u32 *)buf = __raw_readl(rng_base + DATA_REG_OFFSET); + return sizeof(u32); +} + +static struct hwrng picoxcell_trng = { + .name = "picoxcell", + .read = picoxcell_trng_read, +}; + +static int picoxcell_trng_probe(struct platform_device *pdev) +{ + int ret; + struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!mem) { + dev_warn(&pdev->dev, "no memory resource\n"); + return -ENOMEM; + } + + if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), + "picoxcell_trng")) { + dev_warn(&pdev->dev, "unable to request io mem\n"); + return -EBUSY; + } + + rng_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); + if (!rng_base) { + dev_warn(&pdev->dev, "unable to remap io mem\n"); + return -ENOMEM; + } + + rng_clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(rng_clk)) { + dev_warn(&pdev->dev, "no clk\n"); + return PTR_ERR(rng_clk); + } + + ret = clk_enable(rng_clk); + if (ret) { + dev_warn(&pdev->dev, "unable to enable clk\n"); + goto err_enable; + } + + picoxcell_trng_start(); + ret = hwrng_register(&picoxcell_trng); + if (ret) + goto err_register; + + rng_dev = &pdev->dev; + dev_info(&pdev->dev, "pixoxcell random number generator active\n"); + + return 0; + +err_register: + clk_disable(rng_clk); +err_enable: + clk_put(rng_clk); + + return ret; +} + +static int __devexit picoxcell_trng_remove(struct platform_device *pdev) +{ + hwrng_unregister(&picoxcell_trng); + clk_disable(rng_clk); + clk_put(rng_clk); + + return 0; +} + +#ifdef CONFIG_PM +static int picoxcell_trng_suspend(struct device *dev) +{ + clk_disable(rng_clk); + + return 0; +} + +static int picoxcell_trng_resume(struct device *dev) +{ + return clk_enable(rng_clk); +} + +static const struct dev_pm_ops picoxcell_trng_pm_ops = { + .suspend = picoxcell_trng_suspend, + .resume = picoxcell_trng_resume, +}; +#endif /* CONFIG_PM */ + +static struct platform_driver picoxcell_trng_driver = { + .probe = picoxcell_trng_probe, + .remove = __devexit_p(picoxcell_trng_remove), + .driver = { + .name = "picoxcell-trng", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &picoxcell_trng_pm_ops, +#endif /* CONFIG_PM */ + }, +}; + +static int __init picoxcell_trng_init(void) +{ + return platform_driver_register(&picoxcell_trng_driver); +} +module_init(picoxcell_trng_init); + +static void __exit picoxcell_trng_exit(void) +{ + platform_driver_unregister(&picoxcell_trng_driver); +} +module_exit(picoxcell_trng_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jamie Iles"); +MODULE_DESCRIPTION("Picochip picoXcell TRNG driver"); -- cgit v1.2.3 From 1e6d767924c74929c0cfe839ae8f37bcee9e544e Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Tue, 1 Feb 2011 13:50:58 +0000 Subject: time: Correct the *settime* parameters Both settimeofday() and clock_settime() promise with a 'const' attribute not to alter the arguments passed in. This patch adds the missing 'const' attribute into the various kernel functions implementing these calls. Signed-off-by: Richard Cochran Acked-by: John Stultz LKML-Reference: <20110201134417.545698637@linutronix.de> Signed-off-by: Thomas Gleixner --- drivers/char/mmtimer.c | 2 +- include/linux/posix-timers.h | 5 +++-- include/linux/security.h | 9 +++++---- include/linux/time.h | 5 +++-- kernel/posix-timers.c | 4 ++-- kernel/time.c | 2 +- kernel/time/timekeeping.c | 2 +- security/commoncap.c | 2 +- security/security.c | 2 +- 9 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index e6d75627c6c8..ecd0082502ef 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -487,7 +487,7 @@ static int sgi_clock_get(clockid_t clockid, struct timespec *tp) return 0; }; -static int sgi_clock_set(clockid_t clockid, struct timespec *tp) +static int sgi_clock_set(const clockid_t clockid, const struct timespec *tp) { u64 nsec; diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 3e23844a6990..b2c14cbd47a6 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -69,7 +69,8 @@ struct k_itimer { struct k_clock { int res; /* in nanoseconds */ int (*clock_getres) (const clockid_t which_clock, struct timespec *tp); - int (*clock_set) (const clockid_t which_clock, struct timespec * tp); + int (*clock_set) (const clockid_t which_clock, + const struct timespec *tp); int (*clock_get) (const clockid_t which_clock, struct timespec * tp); int (*timer_create) (struct k_itimer *timer); int (*nsleep) (const clockid_t which_clock, int flags, @@ -89,7 +90,7 @@ void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock); /* error handlers for timer_create, nanosleep and settime */ int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *, struct timespec __user *); -int do_posix_clock_nosettime(const clockid_t, struct timespec *tp); +int do_posix_clock_nosettime(const clockid_t, const struct timespec *tp); /* function to call to trigger timer event */ int posix_timer_event(struct k_itimer *timr, int si_private); diff --git a/include/linux/security.h b/include/linux/security.h index c642bb8b8f5a..c096aa6fca60 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -53,7 +53,7 @@ struct audit_krule; */ extern int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap, int audit); -extern int cap_settime(struct timespec *ts, struct timezone *tz); +extern int cap_settime(const struct timespec *ts, const struct timezone *tz); extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); extern int cap_ptrace_traceme(struct task_struct *parent); extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); @@ -1387,7 +1387,7 @@ struct security_operations { int (*quotactl) (int cmds, int type, int id, struct super_block *sb); int (*quota_on) (struct dentry *dentry); int (*syslog) (int type); - int (*settime) (struct timespec *ts, struct timezone *tz); + int (*settime) (const struct timespec *ts, const struct timezone *tz); int (*vm_enough_memory) (struct mm_struct *mm, long pages); int (*bprm_set_creds) (struct linux_binprm *bprm); @@ -1669,7 +1669,7 @@ int security_sysctl(struct ctl_table *table, int op); int security_quotactl(int cmds, int type, int id, struct super_block *sb); int security_quota_on(struct dentry *dentry); int security_syslog(int type); -int security_settime(struct timespec *ts, struct timezone *tz); +int security_settime(const struct timespec *ts, const struct timezone *tz); int security_vm_enough_memory(long pages); int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); int security_vm_enough_memory_kern(long pages); @@ -1904,7 +1904,8 @@ static inline int security_syslog(int type) return 0; } -static inline int security_settime(struct timespec *ts, struct timezone *tz) +static inline int security_settime(const struct timespec *ts, + const struct timezone *tz) { return cap_settime(ts, tz); } diff --git a/include/linux/time.h b/include/linux/time.h index 38c5206c2673..7c44e7778033 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -145,8 +145,9 @@ static inline u32 arch_gettimeoffset(void) { return 0; } #endif extern void do_gettimeofday(struct timeval *tv); -extern int do_settimeofday(struct timespec *tv); -extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz); +extern int do_settimeofday(const struct timespec *tv); +extern int do_sys_settimeofday(const struct timespec *tv, + const struct timezone *tz); #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags); struct itimerval; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 93bd2eb2bc53..21b7ca205f38 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -192,7 +192,7 @@ static int common_clock_get(clockid_t which_clock, struct timespec *tp) } static inline int common_clock_set(const clockid_t which_clock, - struct timespec *tp) + const struct timespec *tp) { return do_sys_settimeofday(tp, NULL); } @@ -928,7 +928,7 @@ void exit_itimers(struct signal_struct *sig) } /* Not available / possible... functions */ -int do_posix_clock_nosettime(const clockid_t clockid, struct timespec *tp) +int do_posix_clock_nosettime(const clockid_t clockid, const struct timespec *tp) { return -EINVAL; } diff --git a/kernel/time.c b/kernel/time.c index a31b51220ac6..5cb80533d8b5 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -150,7 +150,7 @@ static inline void warp_clock(void) * various programs will get confused when the clock gets warped. */ -int do_sys_settimeofday(struct timespec *tv, struct timezone *tz) +int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz) { static int firsttime = 1; int error = 0; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 02c13a313d15..4f9f65b91323 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -353,7 +353,7 @@ EXPORT_SYMBOL(do_gettimeofday); * * Sets the time of day to the new time and update NTP and notify hrtimers */ -int do_settimeofday(struct timespec *tv) +int do_settimeofday(const struct timespec *tv) { struct timespec ts_delta; unsigned long flags; diff --git a/security/commoncap.c b/security/commoncap.c index 64c2ed9c9015..dbfdaed4cc66 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -93,7 +93,7 @@ int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap, * Determine whether the current process may set the system clock and timezone * information, returning 0 if permission granted, -ve if denied. */ -int cap_settime(struct timespec *ts, struct timezone *tz) +int cap_settime(const struct timespec *ts, const struct timezone *tz) { if (!capable(CAP_SYS_TIME)) return -EPERM; diff --git a/security/security.c b/security/security.c index 739e40362f44..b995428f1c96 100644 --- a/security/security.c +++ b/security/security.c @@ -202,7 +202,7 @@ int security_syslog(int type) return security_ops->syslog(type); } -int security_settime(struct timespec *ts, struct timezone *tz) +int security_settime(const struct timespec *ts, const struct timezone *tz) { return security_ops->settime(ts, tz); } -- cgit v1.2.3 From 2fd1f04089cb657c5d6c484b280ec4d3398aa157 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 1 Feb 2011 13:51:03 +0000 Subject: posix-timers: Cleanup struct initializers Cosmetic. No functional change Signed-off-by: Thomas Gleixner Acked-by: John Stultz Tested-by: Richard Cochran LKML-Reference: <20110201134417.745627057@linutronix.de> --- drivers/char/mmtimer.c | 14 +++++++------- kernel/posix-cpu-timers.c | 24 ++++++++++++------------ kernel/posix-timers.c | 38 +++++++++++++++++++------------------- 3 files changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index ecd0082502ef..fd51cd8ee063 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -765,13 +765,13 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, static struct k_clock sgi_clock = { .res = 0, - .clock_set = sgi_clock_set, - .clock_get = sgi_clock_get, - .timer_create = sgi_timer_create, - .nsleep = do_posix_clock_nonanosleep, - .timer_set = sgi_timer_set, - .timer_del = sgi_timer_del, - .timer_get = sgi_timer_get + .clock_set = sgi_clock_set, + .clock_get = sgi_clock_get, + .timer_create = sgi_timer_create, + .nsleep = do_posix_clock_nonanosleep, + .timer_set = sgi_timer_set, + .timer_del = sgi_timer_del, + .timer_get = sgi_timer_get }; /** diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 05bb7173850e..11b91dc0992b 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1607,20 +1607,20 @@ static long thread_cpu_nsleep_restart(struct restart_block *restart_block) static __init int init_posix_cpu_timers(void) { struct k_clock process = { - .clock_getres = process_cpu_clock_getres, - .clock_get = process_cpu_clock_get, - .clock_set = do_posix_clock_nosettime, - .timer_create = process_cpu_timer_create, - .nsleep = process_cpu_nsleep, - .nsleep_restart = process_cpu_nsleep_restart, + .clock_getres = process_cpu_clock_getres, + .clock_get = process_cpu_clock_get, + .clock_set = do_posix_clock_nosettime, + .timer_create = process_cpu_timer_create, + .nsleep = process_cpu_nsleep, + .nsleep_restart = process_cpu_nsleep_restart, }; struct k_clock thread = { - .clock_getres = thread_cpu_clock_getres, - .clock_get = thread_cpu_clock_get, - .clock_set = do_posix_clock_nosettime, - .timer_create = thread_cpu_timer_create, - .nsleep = thread_cpu_nsleep, - .nsleep_restart = thread_cpu_nsleep_restart, + .clock_getres = thread_cpu_clock_getres, + .clock_get = thread_cpu_clock_get, + .clock_set = do_posix_clock_nosettime, + .timer_create = thread_cpu_timer_create, + .nsleep = thread_cpu_nsleep, + .nsleep_restart = thread_cpu_nsleep_restart, }; struct timespec ts; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 89bff3766d7d..e7d26afd8ee5 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -281,33 +281,33 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec *tp static __init int init_posix_timers(void) { struct k_clock clock_realtime = { - .clock_getres = hrtimer_get_res, + .clock_getres = hrtimer_get_res, }; struct k_clock clock_monotonic = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_ktime_get_ts, - .clock_set = do_posix_clock_nosettime, + .clock_getres = hrtimer_get_res, + .clock_get = posix_ktime_get_ts, + .clock_set = do_posix_clock_nosettime, }; struct k_clock clock_monotonic_raw = { - .clock_getres = hrtimer_get_res, - .clock_get = posix_get_monotonic_raw, - .clock_set = do_posix_clock_nosettime, - .timer_create = no_timer_create, - .nsleep = no_nsleep, + .clock_getres = hrtimer_get_res, + .clock_get = posix_get_monotonic_raw, + .clock_set = do_posix_clock_nosettime, + .timer_create = no_timer_create, + .nsleep = no_nsleep, }; struct k_clock clock_realtime_coarse = { - .clock_getres = posix_get_coarse_res, - .clock_get = posix_get_realtime_coarse, - .clock_set = do_posix_clock_nosettime, - .timer_create = no_timer_create, - .nsleep = no_nsleep, + .clock_getres = posix_get_coarse_res, + .clock_get = posix_get_realtime_coarse, + .clock_set = do_posix_clock_nosettime, + .timer_create = no_timer_create, + .nsleep = no_nsleep, }; struct k_clock clock_monotonic_coarse = { - .clock_getres = posix_get_coarse_res, - .clock_get = posix_get_monotonic_coarse, - .clock_set = do_posix_clock_nosettime, - .timer_create = no_timer_create, - .nsleep = no_nsleep, + .clock_getres = posix_get_coarse_res, + .clock_get = posix_get_monotonic_coarse, + .clock_set = do_posix_clock_nosettime, + .timer_create = no_timer_create, + .nsleep = no_nsleep, }; register_posix_clock(CLOCK_REALTIME, &clock_realtime); -- cgit v1.2.3 From a5cd2880106cb2c79b3fe24f1c53dadba6a542a0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 1 Feb 2011 13:51:11 +0000 Subject: posix-timers: Convert clock_nanosleep to clockid_to_kclock() Use the new kclock decoding function in clock_nanosleep and cleanup all kclocks which use the default functions. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Tested-by: Richard Cochran LKML-Reference: <20110201134418.034175556@linutronix.de> --- drivers/char/mmtimer.c | 1 - include/linux/posix-timers.h | 2 -- kernel/posix-timers.c | 26 +++++++------------------- 3 files changed, 7 insertions(+), 22 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index fd51cd8ee063..262d10453cb8 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -768,7 +768,6 @@ static struct k_clock sgi_clock = { .clock_set = sgi_clock_set, .clock_get = sgi_clock_get, .timer_create = sgi_timer_create, - .nsleep = do_posix_clock_nonanosleep, .timer_set = sgi_timer_set, .timer_del = sgi_timer_del, .timer_get = sgi_timer_get diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 1330ff331526..cd6da067bce1 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -90,8 +90,6 @@ extern struct k_clock clock_posix_cpu; void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock); /* error handlers for timer_create, nanosleep and settime */ -int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *, - struct timespec __user *); int do_posix_clock_nosettime(const clockid_t, const struct timespec *tp); /* function to call to trigger timer event */ diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 14b0a70ffb1e..ee69b216d5c3 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -216,12 +216,6 @@ static int no_timer_create(struct k_itimer *new_timer) return -EOPNOTSUPP; } -static int no_nsleep(const clockid_t which_clock, int flags, - struct timespec *tsave, struct timespec __user *rmtp) -{ - return -EOPNOTSUPP; -} - /* * Return nonzero if we know a priori this clockid_t value is bogus. */ @@ -282,32 +276,31 @@ static __init int init_posix_timers(void) { struct k_clock clock_realtime = { .clock_getres = hrtimer_get_res, + .nsleep = common_nsleep, }; struct k_clock clock_monotonic = { .clock_getres = hrtimer_get_res, .clock_get = posix_ktime_get_ts, .clock_set = do_posix_clock_nosettime, + .nsleep = common_nsleep, }; struct k_clock clock_monotonic_raw = { .clock_getres = hrtimer_get_res, .clock_get = posix_get_monotonic_raw, .clock_set = do_posix_clock_nosettime, .timer_create = no_timer_create, - .nsleep = no_nsleep, }; struct k_clock clock_realtime_coarse = { .clock_getres = posix_get_coarse_res, .clock_get = posix_get_realtime_coarse, .clock_set = do_posix_clock_nosettime, .timer_create = no_timer_create, - .nsleep = no_nsleep, }; struct k_clock clock_monotonic_coarse = { .clock_getres = posix_get_coarse_res, .clock_get = posix_get_monotonic_coarse, .clock_set = do_posix_clock_nosettime, .timer_create = no_timer_create, - .nsleep = no_nsleep, }; register_posix_clock(CLOCK_REALTIME, &clock_realtime); @@ -952,13 +945,6 @@ int do_posix_clock_nosettime(const clockid_t clockid, const struct timespec *tp) } EXPORT_SYMBOL_GPL(do_posix_clock_nosettime); -int do_posix_clock_nonanosleep(const clockid_t clock, int flags, - struct timespec *t, struct timespec __user *r) -{ - return -ENANOSLEEP_NOTSUP; -} -EXPORT_SYMBOL_GPL(do_posix_clock_nonanosleep); - SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, const struct timespec __user *, tp) { @@ -1023,10 +1009,13 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, const struct timespec __user *, rqtp, struct timespec __user *, rmtp) { + struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec t; - if (invalid_clockid(which_clock)) + if (!kc) return -EINVAL; + if (!kc->nsleep) + return -ENANOSLEEP_NOTSUP; if (copy_from_user(&t, rqtp, sizeof (struct timespec))) return -EFAULT; @@ -1034,8 +1023,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, if (!timespec_valid(&t)) return -EINVAL; - return CLOCK_DISPATCH(which_clock, nsleep, - (which_clock, flags, &t, rmtp)); + return kc->nsleep(which_clock, flags, &t, rmtp); } /* -- cgit v1.2.3 From e5e542eea9075dd008993c2ee80b2cc9f31fc494 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 1 Feb 2011 13:51:53 +0000 Subject: posix-timers: Convert clock_getres() to clockid_to_kclock() Use the new kclock decoding. Fixup the fallout in mmtimer.c Signed-off-by: Thomas Gleixner Acked-by: John Stultz Tested-by: Richard Cochran LKML-Reference: <20110201134418.709802797@linutronix.de> --- drivers/char/mmtimer.c | 10 ++++++++++ kernel/posix-timers.c | 17 ++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 262d10453cb8..141ffaeb976c 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -53,6 +53,8 @@ MODULE_LICENSE("GPL"); #define RTC_BITS 55 /* 55 bits for this implementation */ +static struct k_clock sgi_clock; + extern unsigned long sn_rtc_cycles_per_second; #define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC)) @@ -763,10 +765,18 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, return err; } +static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp) +{ + tp->tv_sec = 0; + tp->tv_nsec = sgi_clock.res; + return 0; +} + static struct k_clock sgi_clock = { .res = 0, .clock_set = sgi_clock_set, .clock_get = sgi_clock_get, + .clock_getres = sgi_clock_getres, .timer_create = sgi_timer_create, .timer_set = sgi_timer_set, .timer_del = sgi_timer_del, diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 7f66143d1ce5..748497fffd0f 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -182,14 +182,6 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags) * the function pointer CALL in struct k_clock. */ -static inline int common_clock_getres(const clockid_t which_clock, - struct timespec *tp) -{ - tp->tv_sec = 0; - tp->tv_nsec = posix_clocks[which_clock].res; - return 0; -} - static int common_timer_create(struct k_itimer *new_timer) { hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0); @@ -984,18 +976,17 @@ SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) { + struct k_clock *kc = clockid_to_kclock(which_clock); struct timespec rtn_tp; int error; - if (invalid_clockid(which_clock)) + if (!kc) return -EINVAL; - error = CLOCK_DISPATCH(which_clock, clock_getres, - (which_clock, &rtn_tp)); + error = kc->clock_getres(which_clock, &rtn_tp); - if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) { + if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) error = -EFAULT; - } return error; } -- cgit v1.2.3 From ebaac757acae0431e2c79c00e09f1debdabbddd7 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 1 Feb 2011 13:51:56 +0000 Subject: posix-timers: Remove useless res field from k_clock The res member of kclock is only used by mmtimer.c, but even there it contains redundant information. Remove the field and fixup mmtimer. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Tested-by: Richard Cochran LKML-Reference: <20110201134418.808714587@linutronix.de> --- drivers/char/mmtimer.c | 5 ++--- include/linux/posix-timers.h | 1 - kernel/posix-timers.c | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 141ffaeb976c..ff41eb3eec92 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -768,12 +768,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp) { tp->tv_sec = 0; - tp->tv_nsec = sgi_clock.res; + tp->tv_nsec = sgi_clock_period; return 0; } static struct k_clock sgi_clock = { - .res = 0, .clock_set = sgi_clock_set, .clock_get = sgi_clock_get, .clock_getres = sgi_clock_getres, @@ -840,7 +839,7 @@ static int __init mmtimer_init(void) (unsigned long) node); } - sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second; + sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second; register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 4aaf0c5c7cea..ef574d177fb6 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -67,7 +67,6 @@ struct k_itimer { }; struct k_clock { - int res; /* in nanoseconds */ int (*clock_getres) (const clockid_t which_clock, struct timespec *tp); int (*clock_set) (const clockid_t which_clock, const struct timespec *tp); diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 748497fffd0f..f9142a99b5cb 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -204,8 +204,6 @@ static inline int invalid_clockid(const clockid_t which_clock) return 1; if (posix_clocks[which_clock].clock_getres != NULL) return 0; - if (posix_clocks[which_clock].res != 0) - return 0; return 1; } -- cgit v1.2.3 From 527087374faa488776a789375a7d6ea74fda6f71 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 2 Feb 2011 12:10:09 +0100 Subject: posix-timers: Cleanup namespace Rename register_posix_clock() to posix_timers_register_clock(). That's what the function really does. As a side effect this cleans up the posix_clock namespace for the upcoming dynamic posix_clock infrastructure. Signed-off-by: Thomas Gleixner Tested-by: Richard Cochran Cc: John Stultz LKML-Reference: --- drivers/char/mmtimer.c | 2 +- include/linux/posix-timers.h | 2 +- kernel/posix-cpu-timers.c | 4 ++-- kernel/posix-timers.c | 15 ++++++++------- 4 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index ff41eb3eec92..33dc2298af73 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -840,7 +840,7 @@ static int __init mmtimer_init(void) } sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second; - register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); + posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock); printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, sn_rtc_cycles_per_second/(unsigned long)1E6); diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 88b9256169f8..9d6ffe2c92e5 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -101,7 +101,7 @@ struct k_clock { extern struct k_clock clock_posix_cpu; -void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock); +void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock); /* function to call to trigger timer event */ int posix_timer_event(struct k_itimer *timr, int si_private); diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 609e187f43e7..67fea9d25d55 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1618,8 +1618,8 @@ static __init int init_posix_cpu_timers(void) }; struct timespec ts; - register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process); - register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread); + posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process); + posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread); cputime_to_timespec(cputime_one_jiffy, &ts); onecputick = ts.tv_nsec; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index df629d853a81..af936fd37140 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -253,11 +253,11 @@ static __init int init_posix_timers(void) .clock_get = posix_get_monotonic_coarse, }; - register_posix_clock(CLOCK_REALTIME, &clock_realtime); - register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic); - register_posix_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw); - register_posix_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse); - register_posix_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse); + posix_timers_register_clock(CLOCK_REALTIME, &clock_realtime); + posix_timers_register_clock(CLOCK_MONOTONIC, &clock_monotonic); + posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw); + posix_timers_register_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse); + posix_timers_register_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse); posix_timers_cache = kmem_cache_create("posix_timers_cache", sizeof (struct k_itimer), 0, SLAB_PANIC, @@ -433,7 +433,8 @@ static struct pid *good_sigevent(sigevent_t * event) return task_pid(rtn); } -void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock) +void posix_timers_register_clock(const clockid_t clock_id, + struct k_clock *new_clock) { if ((unsigned) clock_id >= MAX_CLOCKS) { printk(KERN_WARNING "POSIX clock register failed for clock_id %d\n", @@ -454,7 +455,7 @@ void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock) posix_clocks[clock_id] = *new_clock; } -EXPORT_SYMBOL_GPL(register_posix_clock); +EXPORT_SYMBOL_GPL(posix_timers_register_clock); static struct k_itimer * alloc_posix_timer(void) { -- cgit v1.2.3 From c652759b6a27be04ef5d747d81e8c36cde7f55d1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 16 Feb 2011 13:05:54 +1100 Subject: hwrng: omap - Convert release_resource to release_region/release_mem_region Request_region should be used with release_region, not release_resource. The local variable mem, storing the result of request_mem_region, is dropped and instead the pointer res is stored in the drvdata field of the platform device. This information is retrieved in omap_rng_remove to release the region. The drvdata field is not used elsewhere. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,E; @@ ( *x = request_region(...) | *x = request_mem_region(...) ) ... when != release_region(x) when != x = E * release_resource(x); // Signed-off-by: Julia Lawall Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 06aad0831c73..2cc755a64302 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -91,7 +91,7 @@ static struct hwrng omap_rng_ops = { static int __devinit omap_rng_probe(struct platform_device *pdev) { - struct resource *res, *mem; + struct resource *res; int ret; /* @@ -116,14 +116,12 @@ static int __devinit omap_rng_probe(struct platform_device *pdev) if (!res) return -ENOENT; - mem = request_mem_region(res->start, resource_size(res), - pdev->name); - if (mem == NULL) { + if (!request_mem_region(res->start, resource_size(res), pdev->name)) { ret = -EBUSY; goto err_region; } - dev_set_drvdata(&pdev->dev, mem); + dev_set_drvdata(&pdev->dev, res); rng_base = ioremap(res->start, resource_size(res)); if (!rng_base) { ret = -ENOMEM; @@ -146,7 +144,7 @@ err_register: iounmap(rng_base); rng_base = NULL; err_ioremap: - release_resource(mem); + release_mem_region(res->start, resource_size(res)); err_region: if (cpu_is_omap24xx()) { clk_disable(rng_ick); @@ -157,7 +155,7 @@ err_region: static int __exit omap_rng_remove(struct platform_device *pdev) { - struct resource *mem = dev_get_drvdata(&pdev->dev); + struct resource *res = dev_get_drvdata(&pdev->dev); hwrng_unregister(&omap_rng_ops); @@ -170,7 +168,7 @@ static int __exit omap_rng_remove(struct platform_device *pdev) clk_put(rng_ick); } - release_resource(mem); + release_mem_region(res->start, resource_size(res)); rng_base = NULL; return 0; -- cgit v1.2.3 From 5427bcf5e95245d3e220742ac703182bdb973769 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 4 Feb 2011 20:45:49 -0500 Subject: hvc: add Blackfin JTAG console support This converts the existing bfin_jtag_comm TTY driver to the HVC layer so that the common HVC code can worry about all of the TTY/polling crap and leave the Blackfin code to worry about the Blackfin bits. Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 9 ++++ drivers/tty/hvc/Makefile | 1 + drivers/tty/hvc/hvc_bfin_jtag.c | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 drivers/tty/hvc/hvc_bfin_jtag.c (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index b7980a83ce2d..17f9b968b988 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -691,6 +691,15 @@ config HVC_DCC driver. This console is used through a JTAG only on ARM. If you don't have a JTAG then you probably don't want this option. +config HVC_BFIN_JTAG + bool "Blackfin JTAG console" + depends on BLACKFIN + select HVC_DRIVER + help + This console uses the Blackfin JTAG to create a console under the + the HVC driver. If you don't have JTAG, then you probably don't + want this option. + config VIRTIO_CONSOLE tristate "Virtio console" depends on VIRTIO diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile index e6bed5f177ff..7b0edbce9009 100644 --- a/drivers/tty/hvc/Makefile +++ b/drivers/tty/hvc/Makefile @@ -9,5 +9,6 @@ obj-$(CONFIG_HVC_IRQ) += hvc_irq.o obj-$(CONFIG_HVC_XEN) += hvc_xen.o obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o +obj-$(CONFIG_HVC_BFIN_JTAG) += hvc_bfin_jtag.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o diff --git a/drivers/tty/hvc/hvc_bfin_jtag.c b/drivers/tty/hvc/hvc_bfin_jtag.c new file mode 100644 index 000000000000..31d6cc6a77af --- /dev/null +++ b/drivers/tty/hvc/hvc_bfin_jtag.c @@ -0,0 +1,105 @@ +/* + * Console via Blackfin JTAG Communication + * + * Copyright 2008-2011 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include + +#include "hvc_console.h" + +/* See the Debug/Emulation chapter in the HRM */ +#define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ +#define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ +#define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ +#define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ + +/* Helper functions to glue the register API to simple C operations */ +static inline uint32_t bfin_write_emudat(uint32_t emudat) +{ + __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); + return emudat; +} + +static inline uint32_t bfin_read_emudat(void) +{ + uint32_t emudat; + __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); + return emudat; +} + +/* Send data to the host */ +static int hvc_bfin_put_chars(uint32_t vt, const char *buf, int count) +{ + static uint32_t outbound_len; + uint32_t emudat; + int ret; + + if (bfin_read_DBGSTAT() & EMUDOF) + return 0; + + if (!outbound_len) { + outbound_len = count; + bfin_write_emudat(outbound_len); + return 0; + } + + ret = min(outbound_len, (uint32_t)4); + memcpy(&emudat, buf, ret); + bfin_write_emudat(emudat); + outbound_len -= ret; + + return ret; +} + +/* Receive data from the host */ +static int hvc_bfin_get_chars(uint32_t vt, char *buf, int count) +{ + static uint32_t inbound_len; + uint32_t emudat; + int ret; + + if (!(bfin_read_DBGSTAT() & EMUDIF)) + return 0; + emudat = bfin_read_emudat(); + + if (!inbound_len) { + inbound_len = emudat; + return 0; + } + + ret = min(inbound_len, (uint32_t)4); + memcpy(buf, &emudat, ret); + inbound_len -= ret; + + return ret; +} + +/* Glue the HVC layers to the Blackfin layers */ +static const struct hv_ops hvc_bfin_get_put_ops = { + .get_chars = hvc_bfin_get_chars, + .put_chars = hvc_bfin_put_chars, +}; + +static int __init hvc_bfin_console_init(void) +{ + hvc_instantiate(0, 0, &hvc_bfin_get_put_ops); + return 0; +} +console_initcall(hvc_bfin_console_init); + +static int __init hvc_bfin_init(void) +{ + hvc_alloc(0, 0, &hvc_bfin_get_put_ops, 128); + return 0; +} +device_initcall(hvc_bfin_init); -- cgit v1.2.3 From 60b33c133ca0b7c0b6072c87234b63fee6e80558 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 14 Feb 2011 16:26:14 +0000 Subject: tiocmget: kill off the passing of the struct file We don't actually need this and it causes problems for internal use of this functionality. Currently there is a single use of the FILE * pointer. That is the serial core which uses it to check tty_hung_up_p. However if that is true then IO_ERROR is also already set so the check may be removed. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 2 +- drivers/char/cyclades.c | 2 +- drivers/char/epca.c | 4 ++-- drivers/char/ip2/ip2main.c | 4 ++-- drivers/char/isicom.c | 2 +- drivers/char/istallion.c | 2 +- drivers/char/moxa.c | 4 ++-- drivers/char/mxser.c | 2 +- drivers/char/nozomi.c | 2 +- drivers/char/pcmcia/ipwireless/tty.c | 2 +- drivers/char/pcmcia/synclink_cs.c | 4 ++-- drivers/char/riscom8.c | 2 +- drivers/char/rocket.c | 2 +- drivers/char/serial167.c | 2 +- drivers/char/specialix.c | 2 +- drivers/char/stallion.c | 2 +- drivers/char/sx.c | 2 +- drivers/char/synclink.c | 4 ++-- drivers/char/synclink_gt.c | 4 ++-- drivers/char/synclinkmp.c | 4 ++-- drivers/isdn/gigaset/interface.c | 4 ++-- drivers/isdn/i4l/isdn_tty.c | 2 +- drivers/mmc/card/sdio_uart.c | 2 +- drivers/net/usb/hso.c | 2 +- drivers/net/wan/pc300_tty.c | 4 ++-- drivers/staging/quatech_usb2/quatech_usb2.c | 2 +- drivers/staging/serqt_usb2/serqt_usb2.c | 6 +++--- drivers/tty/hvc/hvsi.c | 2 +- drivers/tty/n_gsm.c | 2 +- drivers/tty/serial/68360serial.c | 2 +- drivers/tty/serial/crisv10.c | 2 +- drivers/tty/serial/ifx6x60.c | 2 +- drivers/tty/serial/serial_core.c | 6 ++---- drivers/tty/tty_io.c | 6 +++--- drivers/usb/class/cdc-acm.c | 2 +- drivers/usb/serial/ark3116.c | 2 +- drivers/usb/serial/belkin_sa.c | 4 ++-- drivers/usb/serial/ch341.c | 2 +- drivers/usb/serial/cp210x.c | 4 ++-- drivers/usb/serial/cypress_m8.c | 4 ++-- drivers/usb/serial/digi_acceleport.c | 4 ++-- drivers/usb/serial/ftdi_sio.c | 4 ++-- drivers/usb/serial/io_edgeport.c | 4 ++-- drivers/usb/serial/io_ti.c | 2 +- drivers/usb/serial/iuu_phoenix.c | 2 +- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/serial/keyspan.h | 3 +-- drivers/usb/serial/keyspan_pda.c | 2 +- drivers/usb/serial/kl5kusb105.c | 4 ++-- drivers/usb/serial/kobil_sct.c | 4 ++-- drivers/usb/serial/mct_u232.c | 4 ++-- drivers/usb/serial/mos7720.c | 4 ++-- drivers/usb/serial/mos7840.c | 2 +- drivers/usb/serial/opticon.c | 2 +- drivers/usb/serial/oti6858.c | 4 ++-- drivers/usb/serial/pl2303.c | 2 +- drivers/usb/serial/sierra.c | 2 +- drivers/usb/serial/spcp8x5.c | 2 +- drivers/usb/serial/ssu100.c | 2 +- drivers/usb/serial/ti_usb_3410_5052.c | 4 ++-- drivers/usb/serial/usb-serial.c | 4 ++-- drivers/usb/serial/usb-wwan.h | 2 +- drivers/usb/serial/usb_wwan.c | 2 +- drivers/usb/serial/whiteheat.c | 4 ++-- include/linux/tty_driver.h | 2 +- include/linux/usb/serial.h | 2 +- include/net/irda/ircomm_tty.h | 2 +- net/bluetooth/rfcomm/tty.c | 2 +- net/irda/ircomm/ircomm_tty_ioctl.c | 4 ++-- 69 files changed, 98 insertions(+), 101 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 6ee3348bc3e4..bc67e6839059 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1194,7 +1194,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int __user *value) } -static int rs_tiocmget(struct tty_struct *tty, struct file *file) +static int rs_tiocmget(struct tty_struct *tty) { struct async_struct * info = tty->driver_data; unsigned char control, status; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 4f152c28f40e..e7945ddacd18 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -2429,7 +2429,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) return put_user(result, (unsigned long __user *)value); } -static int cy_tiocmget(struct tty_struct *tty, struct file *file) +static int cy_tiocmget(struct tty_struct *tty) { struct cyclades_port *info = tty->driver_data; struct cyclades_card *card; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index d9df46aa0fba..ecf6f0a889fc 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -1982,7 +1982,7 @@ static int info_ioctl(struct tty_struct *tty, struct file *file, return 0; } -static int pc_tiocmget(struct tty_struct *tty, struct file *file) +static int pc_tiocmget(struct tty_struct *tty) { struct channel *ch = tty->driver_data; struct board_chan __iomem *bc; @@ -2074,7 +2074,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, return -EINVAL; switch (cmd) { case TIOCMODG: - mflag = pc_tiocmget(tty, file); + mflag = pc_tiocmget(tty); if (put_user(mflag, (unsigned long __user *)argp)) return -EFAULT; break; diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index c3a025356b8b..476cd087118e 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -181,7 +181,7 @@ static void ip2_unthrottle(PTTY); static void ip2_stop(PTTY); static void ip2_start(PTTY); static void ip2_hangup(PTTY); -static int ip2_tiocmget(struct tty_struct *tty, struct file *file); +static int ip2_tiocmget(struct tty_struct *tty); static int ip2_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int ip2_get_icount(struct tty_struct *tty, @@ -2038,7 +2038,7 @@ ip2_stop ( PTTY tty ) /* Device Ioctl Section */ /******************************************************************************/ -static int ip2_tiocmget(struct tty_struct *tty, struct file *file) +static int ip2_tiocmget(struct tty_struct *tty) { i2ChanStrPtr pCh = DevTable[tty->index]; #ifdef ENABLE_DSSNOW diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index c27e9d21fea9..836370bc04c2 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1065,7 +1065,7 @@ static int isicom_send_break(struct tty_struct *tty, int length) return 0; } -static int isicom_tiocmget(struct tty_struct *tty, struct file *file) +static int isicom_tiocmget(struct tty_struct *tty) { struct isi_port *port = tty->driver_data; /* just send the port status */ diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 7c6de4c92458..7843a847b76a 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -1501,7 +1501,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s /*****************************************************************************/ -static int stli_tiocmget(struct tty_struct *tty, struct file *file) +static int stli_tiocmget(struct tty_struct *tty) { struct stliport *portp = tty->driver_data; struct stlibrd *brdp; diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 107b0bd58d19..fdf069bb702f 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -199,7 +199,7 @@ static void moxa_set_termios(struct tty_struct *, struct ktermios *); static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); static void moxa_hangup(struct tty_struct *); -static int moxa_tiocmget(struct tty_struct *tty, struct file *file); +static int moxa_tiocmget(struct tty_struct *tty); static int moxa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void moxa_poll(unsigned long); @@ -1257,7 +1257,7 @@ static int moxa_chars_in_buffer(struct tty_struct *tty) return chars; } -static int moxa_tiocmget(struct tty_struct *tty, struct file *file) +static int moxa_tiocmget(struct tty_struct *tty) { struct moxa_port *ch = tty->driver_data; int flag = 0, dtr, rts; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index dd9d75351cd6..4d2f03ec06cd 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1320,7 +1320,7 @@ static int mxser_get_lsr_info(struct mxser_port *info, return put_user(result, value); } -static int mxser_tiocmget(struct tty_struct *tty, struct file *file) +static int mxser_tiocmget(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; unsigned char control, status; diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 294d03e8c61a..0e1dff2ffb1e 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1750,7 +1750,7 @@ static int ntty_write_room(struct tty_struct *tty) } /* Gets io control parameters */ -static int ntty_tiocmget(struct tty_struct *tty, struct file *file) +static int ntty_tiocmget(struct tty_struct *tty) { const struct port *port = tty->driver_data; const struct ctrl_dl *ctrl_dl = &port->ctrl_dl; diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index f5eb28b6cb0f..7d2ef4909a73 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -395,7 +395,7 @@ static int set_control_lines(struct ipw_tty *tty, unsigned int set, return 0; } -static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file) +static int ipw_tiocmget(struct tty_struct *linux_tty) { struct ipw_tty *tty = linux_tty->driver_data; /* FIXME: Exactly how is the tty object locked here .. */ diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index eaa41992fbe2..7b68ba6609fe 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -418,7 +418,7 @@ static void bh_status(MGSLPC_INFO *info); /* * ioctl handlers */ -static int tiocmget(struct tty_struct *tty, struct file *file); +static int tiocmget(struct tty_struct *tty); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount); @@ -2114,7 +2114,7 @@ static int modem_input_wait(MGSLPC_INFO *info,int arg) /* return the state of the serial control and status signals */ -static int tiocmget(struct tty_struct *tty, struct file *file) +static int tiocmget(struct tty_struct *tty) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned int result; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index af4de1fe8445..5d0c98456c93 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1086,7 +1086,7 @@ static int rc_chars_in_buffer(struct tty_struct *tty) return port->xmit_cnt; } -static int rc_tiocmget(struct tty_struct *tty, struct file *file) +static int rc_tiocmget(struct tty_struct *tty) { struct riscom_port *port = tty->driver_data; struct riscom_board *bp; diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 3e4e73a0d7c1..75e98efbc8e9 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1169,7 +1169,7 @@ static int sGetChanRI(CHANNEL_T * ChP) * Returns the state of the serial modem control lines. These next 2 functions * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs. */ -static int rp_tiocmget(struct tty_struct *tty, struct file *file) +static int rp_tiocmget(struct tty_struct *tty) { struct r_port *info = tty->driver_data; unsigned int control, result, ChanStatus; diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 748c3b0ecd89..fda90643ead7 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1308,7 +1308,7 @@ check_and_exit: return startup(info); } /* set_serial_info */ -static int cy_tiocmget(struct tty_struct *tty, struct file *file) +static int cy_tiocmget(struct tty_struct *tty) { struct cyclades_port *info = tty->driver_data; int channel; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index c2bca3f25ef3..bfecfbef0895 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1737,7 +1737,7 @@ static int sx_chars_in_buffer(struct tty_struct *tty) return port->xmit_cnt; } -static int sx_tiocmget(struct tty_struct *tty, struct file *file) +static int sx_tiocmget(struct tty_struct *tty) { struct specialix_port *port = tty->driver_data; struct specialix_board *bp; diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 461a5a045517..8c2bf3fb5b89 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1094,7 +1094,7 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp /*****************************************************************************/ -static int stl_tiocmget(struct tty_struct *tty, struct file *file) +static int stl_tiocmget(struct tty_struct *tty) { struct stlport *portp; diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a786326cea2f..f46214e60d0c 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1873,7 +1873,7 @@ static int sx_break(struct tty_struct *tty, int flag) return 0; } -static int sx_tiocmget(struct tty_struct *tty, struct file *file) +static int sx_tiocmget(struct tty_struct *tty) { struct sx_port *port = tty->driver_data; return sx_getsignals(port); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 3a6824f12be2..d359e092904a 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -823,7 +823,7 @@ static isr_dispatch_func UscIsrTable[7] = /* * ioctl call handlers */ -static int tiocmget(struct tty_struct *tty, struct file *file); +static int tiocmget(struct tty_struct *tty); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount @@ -2846,7 +2846,7 @@ static int modem_input_wait(struct mgsl_struct *info,int arg) /* return the state of the serial control and status signals */ -static int tiocmget(struct tty_struct *tty, struct file *file) +static int tiocmget(struct tty_struct *tty) { struct mgsl_struct *info = tty->driver_data; unsigned int result; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index d01fffeac951..f18ab8af0e1c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -512,7 +512,7 @@ static int tx_abort(struct slgt_info *info); static int rx_enable(struct slgt_info *info, int enable); static int modem_input_wait(struct slgt_info *info,int arg); static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); -static int tiocmget(struct tty_struct *tty, struct file *file); +static int tiocmget(struct tty_struct *tty); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int set_break(struct tty_struct *tty, int break_state); @@ -3195,7 +3195,7 @@ static int modem_input_wait(struct slgt_info *info,int arg) /* * return state of serial control and status signals */ -static int tiocmget(struct tty_struct *tty, struct file *file) +static int tiocmget(struct tty_struct *tty) { struct slgt_info *info = tty->driver_data; unsigned int result; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 2f9eb4b0dec1..5900213ae75b 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -546,7 +546,7 @@ static int tx_abort(SLMP_INFO *info); static int rx_enable(SLMP_INFO *info, int enable); static int modem_input_wait(SLMP_INFO *info,int arg); static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); -static int tiocmget(struct tty_struct *tty, struct file *file); +static int tiocmget(struct tty_struct *tty); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int set_break(struct tty_struct *tty, int break_state); @@ -3207,7 +3207,7 @@ static int modem_input_wait(SLMP_INFO *info,int arg) /* return the state of the serial control and status signals */ -static int tiocmget(struct tty_struct *tty, struct file *file) +static int tiocmget(struct tty_struct *tty) { SLMP_INFO *info = tty->driver_data; unsigned int result; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index bb710d16a526..e1a7c14f5f1d 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -122,7 +122,7 @@ static int if_chars_in_buffer(struct tty_struct *tty); static void if_throttle(struct tty_struct *tty); static void if_unthrottle(struct tty_struct *tty); static void if_set_termios(struct tty_struct *tty, struct ktermios *old); -static int if_tiocmget(struct tty_struct *tty, struct file *file); +static int if_tiocmget(struct tty_struct *tty); static int if_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int if_write(struct tty_struct *tty, @@ -280,7 +280,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, return retval; } -static int if_tiocmget(struct tty_struct *tty, struct file *file) +static int if_tiocmget(struct tty_struct *tty) { struct cardstate *cs; int retval; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index c463162843ba..ba6c2f124b58 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1345,7 +1345,7 @@ isdn_tty_get_lsr_info(modem_info * info, uint __user * value) static int -isdn_tty_tiocmget(struct tty_struct *tty, struct file *file) +isdn_tty_tiocmget(struct tty_struct *tty) { modem_info *info = (modem_info *) tty->driver_data; u_char control, status; diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index a0716967b7c8..86bb04d821b1 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -956,7 +956,7 @@ static int sdio_uart_break_ctl(struct tty_struct *tty, int break_state) return 0; } -static int sdio_uart_tiocmget(struct tty_struct *tty, struct file *file) +static int sdio_uart_tiocmget(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; int result; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index bed8fcedff49..7c68c456c035 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1656,7 +1656,7 @@ static int hso_get_count(struct tty_struct *tty, } -static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file) +static int hso_serial_tiocmget(struct tty_struct *tty) { int retval; struct hso_serial *serial = get_serial_by_tty(tty); diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 515d9b8af01e..d999e54a7730 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -133,7 +133,7 @@ static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char); static int pc300_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); -static int pc300_tiocmget(struct tty_struct *, struct file *); +static int pc300_tiocmget(struct tty_struct *); /* functions called by PC300 driver */ void cpc_tty_init(pc300dev_t *dev); @@ -570,7 +570,7 @@ static int pc300_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int pc300_tiocmget(struct tty_struct *tty, struct file *file) +static int pc300_tiocmget(struct tty_struct *tty) { unsigned int result; unsigned char status; diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c index ed58f482c963..1e50292aef74 100644 --- a/drivers/staging/quatech_usb2/quatech_usb2.c +++ b/drivers/staging/quatech_usb2/quatech_usb2.c @@ -1078,7 +1078,7 @@ static void qt2_set_termios(struct tty_struct *tty, } } -static int qt2_tiocmget(struct tty_struct *tty, struct file *file) +static int qt2_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 27841ef6a568..56ded56db7b4 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -1383,7 +1383,7 @@ static void qt_break(struct tty_struct *tty, int break_state) static inline int qt_real_tiocmget(struct tty_struct *tty, struct usb_serial_port *port, - struct file *file, struct usb_serial *serial) + struct usb_serial *serial) { u8 mcr; @@ -1462,7 +1462,7 @@ static inline int qt_real_tiocmset(struct tty_struct *tty, return 0; } -static int qt_tiocmget(struct tty_struct *tty, struct file *file) +static int qt_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = get_usb_serial(port, __func__); @@ -1480,7 +1480,7 @@ static int qt_tiocmget(struct tty_struct *tty, struct file *file) dbg("%s - port %d\n", __func__, port->number); dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); - retval = qt_real_tiocmget(tty, port, file, serial); + retval = qt_real_tiocmget(tty, port, serial); spin_unlock_irqrestore(&qt_port->lock, flags); return retval; diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 67a75a502c01..55293105a56c 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -1095,7 +1095,7 @@ static void hvsi_unthrottle(struct tty_struct *tty) h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE); } -static int hvsi_tiocmget(struct tty_struct *tty, struct file *file) +static int hvsi_tiocmget(struct tty_struct *tty) { struct hvsi_struct *hp = tty->driver_data; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 44b8412a04e8..97e3d509ff82 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2648,7 +2648,7 @@ static void gsmtty_wait_until_sent(struct tty_struct *tty, int timeout) to do here */ } -static int gsmtty_tiocmget(struct tty_struct *tty, struct file *filp) +static int gsmtty_tiocmget(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; return dlci->modem_rx; diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c index 88b13356ec10..2a52cf14ce50 100644 --- a/drivers/tty/serial/68360serial.c +++ b/drivers/tty/serial/68360serial.c @@ -1240,7 +1240,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value) } #endif -static int rs_360_tiocmget(struct tty_struct *tty, struct file *file) +static int rs_360_tiocmget(struct tty_struct *tty) { ser_info_t *info = (ser_info_t *)tty->driver_data; unsigned int result = 0; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index bcc31f2140ac..8cc5c0224b25 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3614,7 +3614,7 @@ rs_tiocmset(struct tty_struct *tty, struct file *file, } static int -rs_tiocmget(struct tty_struct *tty, struct file *file) +rs_tiocmget(struct tty_struct *tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned int result; diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index b68b96f53e6c..4d26d39ec344 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -245,7 +245,7 @@ static void ifx_spi_timeout(unsigned long arg) * Map the signal state into Linux modem flags and report the value * in Linux terms */ -static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp) +static int ifx_spi_tiocmget(struct tty_struct *tty) { unsigned int value; struct ifx_spi_device *ifx_dev = tty->driver_data; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 20563c509b21..53e490e47560 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -905,7 +905,7 @@ static int uart_get_lsr_info(struct tty_struct *tty, return put_user(result, value); } -static int uart_tiocmget(struct tty_struct *tty, struct file *file) +static int uart_tiocmget(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct tty_port *port = &state->port; @@ -913,10 +913,8 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) int result = -EIO; mutex_lock(&port->mutex); - if ((!file || !tty_hung_up_p(file)) && - !(tty->flags & (1 << TTY_IO_ERROR))) { + if (!(tty->flags & (1 << TTY_IO_ERROR))) { result = uport->mctrl; - spin_lock_irq(&uport->lock); result |= uport->ops->get_mctrl(uport); spin_unlock_irq(&uport->lock); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 0065da4b11c1..fde5a4dae3dd 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2465,12 +2465,12 @@ out: * Locking: none (up to the driver) */ -static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p) +static int tty_tiocmget(struct tty_struct *tty, int __user *p) { int retval = -EINVAL; if (tty->ops->tiocmget) { - retval = tty->ops->tiocmget(tty, file); + retval = tty->ops->tiocmget(tty); if (retval >= 0) retval = put_user(retval, p); @@ -2655,7 +2655,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return send_break(tty, arg ? arg*100 : 250); case TIOCMGET: - return tty_tiocmget(tty, file, p); + return tty_tiocmget(tty, p); case TIOCMSET: case TIOCMBIC: case TIOCMBIS: diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d6ede989ff22..2ae996b7ce7b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -776,7 +776,7 @@ static int acm_tty_break_ctl(struct tty_struct *tty, int state) return retval; } -static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file) +static int acm_tty_tiocmget(struct tty_struct *tty) { struct acm *acm = tty->driver_data; diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 8f1d4fb19d24..35b610aa3f92 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -485,7 +485,7 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, return -ENOIOCTLCMD; } -static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) +static int ark3116_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct ark3116_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 36df35295db2..48fb3bad3cd6 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -100,7 +100,7 @@ static void belkin_sa_process_read_urb(struct urb *urb); static void belkin_sa_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios * old); static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state); -static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file); +static int belkin_sa_tiocmget(struct tty_struct *tty); static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); @@ -497,7 +497,7 @@ static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "Set break_ctl %d\n", break_state); } -static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file) +static int belkin_sa_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct belkin_sa_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 7b8815ddf368..aa0962b72f4c 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -572,7 +572,7 @@ static int ch341_ioctl(struct tty_struct *tty, struct file *file, return -ENOIOCTLCMD; } -static int ch341_tiocmget(struct tty_struct *tty, struct file *file) +static int ch341_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct ch341_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 735ea03157ab..b3873815035c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -41,7 +41,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int *cflagp, unsigned int *baudp); static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); -static int cp210x_tiocmget(struct tty_struct *, struct file *); +static int cp210x_tiocmget(struct tty_struct *); static int cp210x_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, @@ -742,7 +742,7 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on) cp210x_tiocmset_port(p, NULL, 0, TIOCM_DTR|TIOCM_RTS); } -static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) +static int cp210x_tiocmget (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned int control; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 2edf238b00b9..9c96cff691fd 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -173,7 +173,7 @@ static int cypress_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void cypress_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); -static int cypress_tiocmget(struct tty_struct *tty, struct file *file); +static int cypress_tiocmget(struct tty_struct *tty); static int cypress_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int cypress_chars_in_buffer(struct tty_struct *tty); @@ -864,7 +864,7 @@ static int cypress_write_room(struct tty_struct *tty) } -static int cypress_tiocmget(struct tty_struct *tty, struct file *file) +static int cypress_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 666e5a6edd82..08da46cb5825 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -445,7 +445,7 @@ static void digi_rx_unthrottle(struct tty_struct *tty); static void digi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); static void digi_break_ctl(struct tty_struct *tty, int break_state); -static int digi_tiocmget(struct tty_struct *tty, struct file *file); +static int digi_tiocmget(struct tty_struct *tty); static int digi_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -1118,7 +1118,7 @@ static void digi_break_ctl(struct tty_struct *tty, int break_state) } -static int digi_tiocmget(struct tty_struct *tty, struct file *file) +static int digi_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 4787c0cd063f..281d18141051 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -856,7 +856,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, void *dest, size_t size); static void ftdi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); -static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); +static int ftdi_tiocmget(struct tty_struct *tty); static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int ftdi_ioctl(struct tty_struct *tty, struct file *file, @@ -2149,7 +2149,7 @@ static void ftdi_set_termios(struct tty_struct *tty, } } -static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) +static int ftdi_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index cd769ef24f8a..e8fe4dcf72f0 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -219,7 +219,7 @@ static void edge_set_termios(struct tty_struct *tty, static int edge_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void edge_break(struct tty_struct *tty, int break_state); -static int edge_tiocmget(struct tty_struct *tty, struct file *file); +static int edge_tiocmget(struct tty_struct *tty); static int edge_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int edge_get_icount(struct tty_struct *tty, @@ -1599,7 +1599,7 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int edge_tiocmget(struct tty_struct *tty, struct file *file) +static int edge_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 22506b095c4f..7cb9f5cb91f3 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2477,7 +2477,7 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int edge_tiocmget(struct tty_struct *tty, struct file *file) +static int edge_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 99b97c04896f..1d96142f135a 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -179,7 +179,7 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file, * When no card , the reader respond with TIOCM_CD * This is known as CD autodetect mechanism */ -static int iuu_tiocmget(struct tty_struct *tty, struct file *file) +static int iuu_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct iuu_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 0791778a66f3..1beebbb7a20a 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -301,7 +301,7 @@ static void keyspan_set_termios(struct tty_struct *tty, keyspan_send_setup(port, 0); } -static int keyspan_tiocmget(struct tty_struct *tty, struct file *file) +static int keyspan_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct keyspan_port_private *p_priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index ce134dc28ddf..5e5fc71e68df 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -58,8 +58,7 @@ static void keyspan_set_termios (struct tty_struct *tty, struct ktermios *old); static void keyspan_break_ctl (struct tty_struct *tty, int break_state); -static int keyspan_tiocmget (struct tty_struct *tty, - struct file *file); +static int keyspan_tiocmget (struct tty_struct *tty); static int keyspan_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 554a8693a463..49ad2baf77cd 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -457,7 +457,7 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial, return rc; } -static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file) +static int keyspan_pda_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index e8a65ce45a2f..a570f5201c73 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -68,7 +68,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); -static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file); +static int klsi_105_tiocmget(struct tty_struct *tty); static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void klsi_105_process_read_urb(struct urb *urb); @@ -637,7 +637,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) } #endif -static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) +static int klsi_105_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct klsi_105_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index bd5bd8589e04..81d07fb299b8 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -77,7 +77,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, static int kobil_write_room(struct tty_struct *tty); static int kobil_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static int kobil_tiocmget(struct tty_struct *tty, struct file *file); +static int kobil_tiocmget(struct tty_struct *tty); static int kobil_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void kobil_read_int_callback(struct urb *urb); @@ -504,7 +504,7 @@ static int kobil_write_room(struct tty_struct *tty) } -static int kobil_tiocmget(struct tty_struct *tty, struct file *file) +static int kobil_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct kobil_private *priv; diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 2849f8c32015..27447095feae 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -101,7 +101,7 @@ static void mct_u232_read_int_callback(struct urb *urb); static void mct_u232_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); -static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); +static int mct_u232_tiocmget(struct tty_struct *tty); static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void mct_u232_throttle(struct tty_struct *tty); @@ -762,7 +762,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) } /* mct_u232_break_ctl */ -static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file) +static int mct_u232_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct mct_u232_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 7d3bc9a3e2b6..5d40d4151b5a 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1833,7 +1833,7 @@ static int get_lsr_info(struct tty_struct *tty, return 0; } -static int mos7720_tiocmget(struct tty_struct *tty, struct file *file) +static int mos7720_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port = usb_get_serial_port_data(port); @@ -1865,7 +1865,7 @@ static int mos7720_tiocmset(struct tty_struct *tty, struct file *file, struct moschip_port *mos7720_port = usb_get_serial_port_data(port); unsigned int mcr ; dbg("%s - port %d", __func__, port->number); - dbg("he was at tiocmget"); + dbg("he was at tiocmset"); mcr = mos7720_port->shadowMCR; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 5627993f9e41..ee0dc9a0890c 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1644,7 +1644,7 @@ static void mos7840_unthrottle(struct tty_struct *tty) } } -static int mos7840_tiocmget(struct tty_struct *tty, struct file *file) +static int mos7840_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port; diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index eda1f9266c4e..e305df807396 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -352,7 +352,7 @@ static void opticon_unthrottle(struct tty_struct *tty) } } -static int opticon_tiocmget(struct tty_struct *tty, struct file *file) +static int opticon_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct opticon_private *priv = usb_get_serial_data(port->serial); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 73613205be7a..4cd3b0ef4e61 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -144,7 +144,7 @@ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int oti6858_write_room(struct tty_struct *tty); static int oti6858_chars_in_buffer(struct tty_struct *tty); -static int oti6858_tiocmget(struct tty_struct *tty, struct file *file); +static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int oti6858_startup(struct usb_serial *serial); @@ -657,7 +657,7 @@ static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int oti6858_tiocmget(struct tty_struct *tty, struct file *file) +static int oti6858_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct oti6858_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 08c9181b8e48..6cb4f503a3f1 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -531,7 +531,7 @@ static int pl2303_tiocmset(struct tty_struct *tty, struct file *file, return set_control_lines(port->serial->dev, control); } -static int pl2303_tiocmget(struct tty_struct *tty, struct file *file) +static int pl2303_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct pl2303_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 7481ff8a49e4..66437f1e9e5b 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -389,7 +389,7 @@ static void sierra_set_termios(struct tty_struct *tty, sierra_send_setup(port); } -static int sierra_tiocmget(struct tty_struct *tty, struct file *file) +static int sierra_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned int value; diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index cbfb70bffdd0..cac13009fc5c 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -618,7 +618,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file, return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); } -static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file) +static int spcp8x5_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct spcp8x5_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 8359ec798959..b21583fa825c 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -484,7 +484,7 @@ static int ssu100_attach(struct usb_serial *serial) return ssu100_initdevice(serial->dev); } -static int ssu100_tiocmget(struct tty_struct *tty, struct file *file) +static int ssu100_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_device *dev = port->serial->dev; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index b2902f307b47..223e60e31735 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -112,7 +112,7 @@ static int ti_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount); static void ti_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); -static int ti_tiocmget(struct tty_struct *tty, struct file *file); +static int ti_tiocmget(struct tty_struct *tty); static int ti_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void ti_break(struct tty_struct *tty, int break_state); @@ -1000,7 +1000,7 @@ static void ti_set_termios(struct tty_struct *tty, } -static int ti_tiocmget(struct tty_struct *tty, struct file *file) +static int ti_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 546a52179bec..df105c6531a1 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -496,14 +496,14 @@ static const struct file_operations serial_proc_fops = { .release = single_release, }; -static int serial_tiocmget(struct tty_struct *tty, struct file *file) +static int serial_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); if (port->serial->type->tiocmget) - return port->serial->type->tiocmget(tty, file); + return port->serial->type->tiocmget(tty); return -EINVAL; } diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 3ab77c5d9819..8b68fc783d5f 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -15,7 +15,7 @@ extern int usb_wwan_write_room(struct tty_struct *tty); extern void usb_wwan_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); -extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file); +extern int usb_wwan_tiocmget(struct tty_struct *tty); extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index b004b2a485c3..60f942632cb4 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -79,7 +79,7 @@ void usb_wwan_set_termios(struct tty_struct *tty, } EXPORT_SYMBOL(usb_wwan_set_termios); -int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file) +int usb_wwan_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned int value; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 3f9ac88d588c..bf850139e0b8 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -156,7 +156,7 @@ static int whiteheat_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void whiteheat_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); -static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file); +static int whiteheat_tiocmget(struct tty_struct *tty); static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); @@ -833,7 +833,7 @@ static int whiteheat_write_room(struct tty_struct *tty) return (room); } -static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file) +static int whiteheat_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct whiteheat_private *info = usb_get_serial_port_data(port); diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index c3d43eb4150c..9539d74171db 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -271,7 +271,7 @@ struct tty_operations { void (*set_ldisc)(struct tty_struct *tty); void (*wait_until_sent)(struct tty_struct *tty, int timeout); void (*send_xchar)(struct tty_struct *tty, char ch); - int (*tiocmget)(struct tty_struct *tty, struct file *file); + int (*tiocmget)(struct tty_struct *tty); int (*tiocmset)(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); int (*resize)(struct tty_struct *tty, struct winsize *ws); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index c9049139a7a5..30b945397d19 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -268,7 +268,7 @@ struct usb_serial_driver { int (*chars_in_buffer)(struct tty_struct *tty); void (*throttle)(struct tty_struct *tty); void (*unthrottle)(struct tty_struct *tty); - int (*tiocmget)(struct tty_struct *tty, struct file *file); + int (*tiocmget)(struct tty_struct *tty); int (*tiocmset)(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); int (*get_icount)(struct tty_struct *tty, diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index eea2e6152389..fa3793b5392d 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -120,7 +120,7 @@ struct ircomm_tty_cb { void ircomm_tty_start(struct tty_struct *tty); void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self); -extern int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file); +extern int ircomm_tty_tiocmget(struct tty_struct *tty); extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 2575c2db6404..7f67fa4f2f5e 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -1089,7 +1089,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty) } } -static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp) +static int rfcomm_tty_tiocmget(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index 24cb3aa2bbfb..bb47caeba7e6 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -189,12 +189,12 @@ void ircomm_tty_set_termios(struct tty_struct *tty, } /* - * Function ircomm_tty_tiocmget (tty, file) + * Function ircomm_tty_tiocmget (tty) * * * */ -int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file) +int ircomm_tty_tiocmget(struct tty_struct *tty) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; unsigned int result; -- cgit v1.2.3 From 20b9d17715017ae4dd4ec87fabc36d33b9de708e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 14 Feb 2011 16:26:50 +0000 Subject: tiocmset: kill the file pointer argument Doing tiocmget was such fun we should do tiocmset as well for the same reasons Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 4 ++-- drivers/char/cyclades.c | 2 +- drivers/char/epca.c | 4 ++-- drivers/char/ip2/ip2main.c | 4 ++-- drivers/char/isicom.c | 4 ++-- drivers/char/istallion.c | 2 +- drivers/char/moxa.c | 4 ++-- drivers/char/mxser.c | 2 +- drivers/char/nozomi.c | 4 ++-- drivers/char/pcmcia/ipwireless/tty.c | 2 +- drivers/char/pcmcia/synclink_cs.c | 6 +++--- drivers/char/riscom8.c | 4 ++-- drivers/char/rocket.c | 4 ++-- drivers/char/serial167.c | 3 +-- drivers/char/specialix.c | 2 +- drivers/char/stallion.c | 2 +- drivers/char/sx.c | 4 ++-- drivers/char/synclink.c | 6 +++--- drivers/char/synclink_gt.c | 6 +++--- drivers/char/synclinkmp.c | 8 ++++---- drivers/isdn/gigaset/interface.c | 4 ++-- drivers/isdn/gigaset/ser-gigaset.c | 2 +- drivers/isdn/i4l/isdn_tty.c | 2 +- drivers/mmc/card/sdio_uart.c | 2 +- drivers/net/irda/irtty-sir.c | 2 +- drivers/net/usb/hso.c | 6 +++--- drivers/net/wan/pc300_tty.c | 5 ++--- drivers/staging/quatech_usb2/quatech_usb2.c | 2 +- drivers/staging/serqt_usb2/serqt_usb2.c | 5 ++--- drivers/tty/hvc/hvsi.c | 4 ++-- drivers/tty/n_gsm.c | 2 +- drivers/tty/serial/68360serial.c | 2 +- drivers/tty/serial/crisv10.c | 3 +-- drivers/tty/serial/ifx6x60.c | 3 +-- drivers/tty/serial/serial_core.c | 6 ++---- drivers/tty/tty_io.c | 7 +++---- drivers/usb/class/cdc-acm.c | 2 +- drivers/usb/serial/ark3116.c | 2 +- drivers/usb/serial/belkin_sa.c | 4 ++-- drivers/usb/serial/ch341.c | 2 +- drivers/usb/serial/cp210x.c | 15 +++++++-------- drivers/usb/serial/cypress_m8.c | 4 ++-- drivers/usb/serial/digi_acceleport.c | 10 +++++----- drivers/usb/serial/ftdi_sio.c | 4 ++-- drivers/usb/serial/io_edgeport.c | 4 ++-- drivers/usb/serial/io_ti.c | 2 +- drivers/usb/serial/iuu_phoenix.c | 2 +- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/serial/keyspan.h | 2 +- drivers/usb/serial/keyspan_pda.c | 2 +- drivers/usb/serial/kl5kusb105.c | 4 ++-- drivers/usb/serial/kobil_sct.c | 4 ++-- drivers/usb/serial/mct_u232.c | 4 ++-- drivers/usb/serial/mos7720.c | 2 +- drivers/usb/serial/mos7840.c | 2 +- drivers/usb/serial/oti6858.c | 4 ++-- drivers/usb/serial/pl2303.c | 2 +- drivers/usb/serial/sierra.c | 2 +- drivers/usb/serial/spcp8x5.c | 2 +- drivers/usb/serial/ssu100.c | 2 +- drivers/usb/serial/ti_usb_3410_5052.c | 6 +++--- drivers/usb/serial/usb-serial.c | 4 ++-- drivers/usb/serial/usb-wwan.h | 2 +- drivers/usb/serial/usb_wwan.c | 2 +- drivers/usb/serial/whiteheat.c | 4 ++-- include/linux/tty_driver.h | 2 +- include/linux/usb/serial.h | 2 +- include/net/irda/ircomm_tty.h | 2 +- net/bluetooth/rfcomm/tty.c | 2 +- net/irda/ircomm/ircomm_tty_ioctl.c | 4 ++-- 70 files changed, 120 insertions(+), 129 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index bc67e6839059..5c15fad71ad2 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1216,8 +1216,8 @@ static int rs_tiocmget(struct tty_struct *tty) | (!(status & SER_CTS) ? TIOCM_CTS : 0); } -static int rs_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int rs_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear) { struct async_struct * info = tty->driver_data; unsigned long flags; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e7945ddacd18..942b6f2b70a4 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -2483,7 +2483,7 @@ end: } /* cy_tiomget */ static int -cy_tiocmset(struct tty_struct *tty, struct file *file, +cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct cyclades_port *info = tty->driver_data; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index ecf6f0a889fc..e5872b59f9cd 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -2015,7 +2015,7 @@ static int pc_tiocmget(struct tty_struct *tty) return mflag; } -static int pc_tiocmset(struct tty_struct *tty, struct file *file, +static int pc_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct channel *ch = tty->driver_data; @@ -2081,7 +2081,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, case TIOCMODS: if (get_user(mstat, (unsigned __user *)argp)) return -EFAULT; - return pc_tiocmset(tty, file, mstat, ~mstat); + return pc_tiocmset(tty, mstat, ~mstat); case TIOCSDTR: spin_lock_irqsave(&epca_lock, flags); ch->omodem |= ch->m_dtr; diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 476cd087118e..d5f866c7c672 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -182,7 +182,7 @@ static void ip2_stop(PTTY); static void ip2_start(PTTY); static void ip2_hangup(PTTY); static int ip2_tiocmget(struct tty_struct *tty); -static int ip2_tiocmset(struct tty_struct *tty, struct file *file, +static int ip2_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int ip2_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount); @@ -2085,7 +2085,7 @@ static int ip2_tiocmget(struct tty_struct *tty) | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); } -static int ip2_tiocmset(struct tty_struct *tty, struct file *file, +static int ip2_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { i2ChanStrPtr pCh = DevTable[tty->index]; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 836370bc04c2..60f4d8ae7a49 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1082,8 +1082,8 @@ static int isicom_tiocmget(struct tty_struct *tty) ((status & ISI_RI ) ? TIOCM_RI : 0); } -static int isicom_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int isicom_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct isi_port *port = tty->driver_data; unsigned long flags; diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 7843a847b76a..763b58d58255 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -1524,7 +1524,7 @@ static int stli_tiocmget(struct tty_struct *tty) return stli_mktiocm(portp->asig.sigvalue); } -static int stli_tiocmset(struct tty_struct *tty, struct file *file, +static int stli_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct stliport *portp = tty->driver_data; diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index fdf069bb702f..9f4cd8968a5a 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -200,7 +200,7 @@ static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); static void moxa_hangup(struct tty_struct *); static int moxa_tiocmget(struct tty_struct *tty); -static int moxa_tiocmset(struct tty_struct *tty, struct file *file, +static int moxa_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void moxa_poll(unsigned long); static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); @@ -1277,7 +1277,7 @@ static int moxa_tiocmget(struct tty_struct *tty) return flag; } -static int moxa_tiocmset(struct tty_struct *tty, struct file *file, +static int moxa_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct moxa_port *ch; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 4d2f03ec06cd..150a862c4989 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1347,7 +1347,7 @@ static int mxser_tiocmget(struct tty_struct *tty) ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); } -static int mxser_tiocmset(struct tty_struct *tty, struct file *file, +static int mxser_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct mxser_port *info = tty->driver_data; diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 0e1dff2ffb1e..1b74c48c4016 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1767,8 +1767,8 @@ static int ntty_tiocmget(struct tty_struct *tty) } /* Sets io controls parameters */ -static int ntty_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int ntty_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct nozomi *dc = get_dc_by_tty(tty); unsigned long flags; diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 7d2ef4909a73..748190dfbab0 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -410,7 +410,7 @@ static int ipw_tiocmget(struct tty_struct *linux_tty) } static int -ipw_tiocmset(struct tty_struct *linux_tty, struct file *file, +ipw_tiocmset(struct tty_struct *linux_tty, unsigned int set, unsigned int clear) { struct ipw_tty *tty = linux_tty->driver_data; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 7b68ba6609fe..02127cad0980 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -419,8 +419,8 @@ static void bh_status(MGSLPC_INFO *info); * ioctl handlers */ static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount); static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params); static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty); @@ -2139,7 +2139,7 @@ static int tiocmget(struct tty_struct *tty) /* set modem control signals (DTR/RTS) */ -static int tiocmset(struct tty_struct *tty, struct file *file, +static int tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 5d0c98456c93..3666decc6438 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1115,8 +1115,8 @@ static int rc_tiocmget(struct tty_struct *tty) return result; } -static int rc_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int rc_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct riscom_port *port = tty->driver_data; unsigned long flags; diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 75e98efbc8e9..36c108811a81 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1189,8 +1189,8 @@ static int rp_tiocmget(struct tty_struct *tty) /* * Sets the modem control lines */ -static int rp_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int rp_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct r_port *info = tty->driver_data; diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index fda90643ead7..89ac542ffff2 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1331,8 +1331,7 @@ static int cy_tiocmget(struct tty_struct *tty) } /* cy_tiocmget */ static int -cy_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct cyclades_port *info = tty->driver_data; int channel; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index bfecfbef0895..a6b23847e4a7 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1778,7 +1778,7 @@ static int sx_tiocmget(struct tty_struct *tty) } -static int sx_tiocmset(struct tty_struct *tty, struct file *file, +static int sx_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct specialix_port *port = tty->driver_data; diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 8c2bf3fb5b89..c42dbffbed16 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1107,7 +1107,7 @@ static int stl_tiocmget(struct tty_struct *tty) return stl_getsignals(portp); } -static int stl_tiocmset(struct tty_struct *tty, struct file *file, +static int stl_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct stlport *portp; diff --git a/drivers/char/sx.c b/drivers/char/sx.c index f46214e60d0c..342c6ae67da5 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1879,8 +1879,8 @@ static int sx_tiocmget(struct tty_struct *tty) return sx_getsignals(port); } -static int sx_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int sx_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct sx_port *port = tty->driver_data; int rts = -1, dtr = -1; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index d359e092904a..691e1094c20b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -824,7 +824,7 @@ static isr_dispatch_func UscIsrTable[7] = * ioctl call handlers */ static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, struct file *file, +static int tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount); @@ -2871,8 +2871,8 @@ static int tiocmget(struct tty_struct *tty) /* set modem control signals (DTR/RTS) */ -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct mgsl_struct *info = tty->driver_data; unsigned long flags; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index f18ab8af0e1c..04da6d61dc4f 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -513,8 +513,8 @@ static int rx_enable(struct slgt_info *info, int enable); static int modem_input_wait(struct slgt_info *info,int arg); static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); static int set_break(struct tty_struct *tty, int break_state); static int get_interface(struct slgt_info *info, int __user *if_mode); static int set_interface(struct slgt_info *info, int if_mode); @@ -3223,7 +3223,7 @@ static int tiocmget(struct tty_struct *tty) * TIOCMSET = set/clear signal values * value bit mask for command */ -static int tiocmset(struct tty_struct *tty, struct file *file, +static int tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct slgt_info *info = tty->driver_data; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 5900213ae75b..1f9de97e8cfc 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -547,8 +547,8 @@ static int rx_enable(SLMP_INFO *info, int enable); static int modem_input_wait(SLMP_INFO *info,int arg); static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); static int set_break(struct tty_struct *tty, int break_state); static void add_device(SLMP_INFO *info); @@ -3232,8 +3232,8 @@ static int tiocmget(struct tty_struct *tty) /* set modem control signals (DTR/RTS) */ -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { SLMP_INFO *info = tty->driver_data; unsigned long flags; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index e1a7c14f5f1d..9b2bb491c614 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -123,7 +123,7 @@ static void if_throttle(struct tty_struct *tty); static void if_unthrottle(struct tty_struct *tty); static void if_set_termios(struct tty_struct *tty, struct ktermios *old); static int if_tiocmget(struct tty_struct *tty); -static int if_tiocmset(struct tty_struct *tty, struct file *file, +static int if_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int if_write(struct tty_struct *tty, const unsigned char *buf, int count); @@ -303,7 +303,7 @@ static int if_tiocmget(struct tty_struct *tty) return retval; } -static int if_tiocmset(struct tty_struct *tty, struct file *file, +static int if_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct cardstate *cs; diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 0ef09d0eb96b..86a5c4f7775e 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -440,7 +440,7 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, if (!set && !clear) return 0; gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear); - return tty->ops->tiocmset(tty, NULL, set, clear); + return tty->ops->tiocmset(tty, set, clear); } static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index ba6c2f124b58..0341c69eb152 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1372,7 +1372,7 @@ isdn_tty_tiocmget(struct tty_struct *tty) } static int -isdn_tty_tiocmset(struct tty_struct *tty, struct file *file, +isdn_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { modem_info *info = (modem_info *) tty->driver_data; diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 86bb04d821b1..c8c9edb3d7cb 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -970,7 +970,7 @@ static int sdio_uart_tiocmget(struct tty_struct *tty) return result; } -static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, +static int sdio_uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct sdio_uart_port *port = tty->driver_data; diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index ee1dde52e8fc..3352b2443e58 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -167,7 +167,7 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts) * let's be careful... Jean II */ IRDA_ASSERT(priv->tty->ops->tiocmset != NULL, return -1;); - priv->tty->ops->tiocmset(priv->tty, NULL, set, clear); + priv->tty->ops->tiocmset(priv->tty, set, clear); return 0; } diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 7c68c456c035..956e1d6e72a5 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -324,7 +324,7 @@ struct hso_device { /* Prototypes */ /*****************************************************************************/ /* Serial driver functions */ -static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, +static int hso_serial_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void ctrl_callback(struct urb *urb); static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial); @@ -1335,7 +1335,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) /* done */ if (result) - hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0); + hso_serial_tiocmset(tty, TIOCM_RTS | TIOCM_DTR, 0); err_out: mutex_unlock(&serial->parent->mutex); return result; @@ -1687,7 +1687,7 @@ static int hso_serial_tiocmget(struct tty_struct *tty) return retval; } -static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, +static int hso_serial_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { int val = 0; diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index d999e54a7730..1c65d1c33873 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -131,8 +131,7 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx); static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char); static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char); -static int pc300_tiocmset(struct tty_struct *, struct file *, - unsigned int, unsigned int); +static int pc300_tiocmset(struct tty_struct *, unsigned int, unsigned int); static int pc300_tiocmget(struct tty_struct *); /* functions called by PC300 driver */ @@ -543,7 +542,7 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty) return 0; } -static int pc300_tiocmset(struct tty_struct *tty, struct file *file, +static int pc300_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { st_cpc_tty_area *cpc_tty; diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c index 1e50292aef74..3734448d1b82 100644 --- a/drivers/staging/quatech_usb2/quatech_usb2.c +++ b/drivers/staging/quatech_usb2/quatech_usb2.c @@ -1121,7 +1121,7 @@ static int qt2_tiocmget(struct tty_struct *tty) } } -static int qt2_tiocmset(struct tty_struct *tty, struct file *file, +static int qt2_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 56ded56db7b4..39776c1cf10f 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -1425,7 +1425,6 @@ static inline int qt_real_tiocmget(struct tty_struct *tty, static inline int qt_real_tiocmset(struct tty_struct *tty, struct usb_serial_port *port, - struct file *file, struct usb_serial *serial, unsigned int value) { @@ -1486,7 +1485,7 @@ static int qt_tiocmget(struct tty_struct *tty) return retval; } -static int qt_tiocmset(struct tty_struct *tty, struct file *file, +static int qt_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { @@ -1506,7 +1505,7 @@ static int qt_tiocmset(struct tty_struct *tty, struct file *file, dbg("%s - port %d\n", __func__, port->number); dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding); - retval = qt_real_tiocmset(tty, port, file, serial, set); + retval = qt_real_tiocmset(tty, port, serial, set); spin_unlock_irqrestore(&qt_port->lock, flags); return retval; diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 55293105a56c..8a8d6373f164 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -1103,8 +1103,8 @@ static int hvsi_tiocmget(struct tty_struct *tty) return hp->mctrl; } -static int hvsi_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int hvsi_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct hvsi_struct *hp = tty->driver_data; unsigned long flags; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 97e3d509ff82..88477d16b8b7 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2654,7 +2654,7 @@ static int gsmtty_tiocmget(struct tty_struct *tty) return dlci->modem_rx; } -static int gsmtty_tiocmset(struct tty_struct *tty, struct file *filp, +static int gsmtty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct gsm_dlci *dlci = tty->driver_data; diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c index 2a52cf14ce50..217fe1c299e0 100644 --- a/drivers/tty/serial/68360serial.c +++ b/drivers/tty/serial/68360serial.c @@ -1271,7 +1271,7 @@ static int rs_360_tiocmget(struct tty_struct *tty) return result; } -static int rs_360_tiocmset(struct tty_struct *tty, struct file *file, +static int rs_360_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { #ifdef modem_control diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 8cc5c0224b25..b9fcd0bda60c 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3581,8 +3581,7 @@ rs_break(struct tty_struct *tty, int break_state) } static int -rs_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +rs_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned long flags; diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 4d26d39ec344..8ee5a41d340d 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -263,7 +263,6 @@ static int ifx_spi_tiocmget(struct tty_struct *tty) /** * ifx_spi_tiocmset - set modem bits * @tty: the tty structure - * @filp: file handle issuing the request * @set: bits to set * @clear: bits to clear * @@ -272,7 +271,7 @@ static int ifx_spi_tiocmget(struct tty_struct *tty) * * FIXME: do we need to kick the tranfers when we do this ? */ -static int ifx_spi_tiocmset(struct tty_struct *tty, struct file *filp, +static int ifx_spi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct ifx_spi_device *ifx_dev = tty->driver_data; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 53e490e47560..623d6bd911d7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -925,8 +925,7 @@ static int uart_tiocmget(struct tty_struct *tty) } static int -uart_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct uart_state *state = tty->driver_data; struct uart_port *uport = state->uart_port; @@ -934,8 +933,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file, int ret = -EIO; mutex_lock(&port->mutex); - if ((!file || !tty_hung_up_p(file)) && - !(tty->flags & (1 << TTY_IO_ERROR))) { + if (!(tty->flags & (1 << TTY_IO_ERROR))) { uart_update_mctrl(uport, set, clear); ret = 0; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index fde5a4dae3dd..83af24ca1e5e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2481,7 +2481,6 @@ static int tty_tiocmget(struct tty_struct *tty, int __user *p) /** * tty_tiocmset - set modem status * @tty: tty device - * @file: user file pointer * @cmd: command - clear bits, set bits or set all * @p: pointer to desired bits * @@ -2491,7 +2490,7 @@ static int tty_tiocmget(struct tty_struct *tty, int __user *p) * Locking: none (up to the driver) */ -static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd, +static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd, unsigned __user *p) { int retval; @@ -2518,7 +2517,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int } set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; - return tty->ops->tiocmset(tty, file, set, clear); + return tty->ops->tiocmset(tty, set, clear); } static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) @@ -2659,7 +2658,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case TIOCMSET: case TIOCMBIC: case TIOCMBIS: - return tty_tiocmset(tty, file, cmd, p); + return tty_tiocmset(tty, cmd, p); case TIOCGICOUNT: retval = tty_tiocgicount(tty, p); /* For the moment allow fall through to the old method */ diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 2ae996b7ce7b..e9a26fbd079c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -791,7 +791,7 @@ static int acm_tty_tiocmget(struct tty_struct *tty) TIOCM_CTS; } -static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file, +static int acm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct acm *acm = tty->driver_data; diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 35b610aa3f92..2f837e983339 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -511,7 +511,7 @@ static int ark3116_tiocmget(struct tty_struct *tty) (ctrl & UART_MCR_OUT2 ? TIOCM_OUT2 : 0); } -static int ark3116_tiocmset(struct tty_struct *tty, struct file *file, +static int ark3116_tiocmset(struct tty_struct *tty, unsigned set, unsigned clr) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 48fb3bad3cd6..d6921fa1403c 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -101,7 +101,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios * old); static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state); static int belkin_sa_tiocmget(struct tty_struct *tty); -static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, +static int belkin_sa_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -513,7 +513,7 @@ static int belkin_sa_tiocmget(struct tty_struct *tty) return control_state; } -static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, +static int belkin_sa_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index aa0962b72f4c..5cbef313281e 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -431,7 +431,7 @@ out: kfree(break_reg); } -static int ch341_tiocmset(struct tty_struct *tty, struct file *file, +static int ch341_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index b3873815035c..4df3e0cecbae 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -42,9 +42,8 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp210x_tiocmget(struct tty_struct *); -static int cp210x_tiocmset(struct tty_struct *, struct file *, - unsigned int, unsigned int); -static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, +static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int); +static int cp210x_tiocmset_port(struct usb_serial_port *port, unsigned int, unsigned int); static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); @@ -698,14 +697,14 @@ static void cp210x_set_termios(struct tty_struct *tty, } -static int cp210x_tiocmset (struct tty_struct *tty, struct file *file, +static int cp210x_tiocmset (struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; - return cp210x_tiocmset_port(port, file, set, clear); + return cp210x_tiocmset_port(port, set, clear); } -static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file, +static int cp210x_tiocmset_port(struct usb_serial_port *port, unsigned int set, unsigned int clear) { unsigned int control = 0; @@ -737,9 +736,9 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file, static void cp210x_dtr_rts(struct usb_serial_port *p, int on) { if (on) - cp210x_tiocmset_port(p, NULL, TIOCM_DTR|TIOCM_RTS, 0); + cp210x_tiocmset_port(p, TIOCM_DTR|TIOCM_RTS, 0); else - cp210x_tiocmset_port(p, NULL, 0, TIOCM_DTR|TIOCM_RTS); + cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS); } static int cp210x_tiocmget (struct tty_struct *tty) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 9c96cff691fd..2beb5a66180d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -174,7 +174,7 @@ static int cypress_ioctl(struct tty_struct *tty, struct file *file, static void cypress_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static int cypress_tiocmget(struct tty_struct *tty); -static int cypress_tiocmset(struct tty_struct *tty, struct file *file, +static int cypress_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int cypress_chars_in_buffer(struct tty_struct *tty); static void cypress_throttle(struct tty_struct *tty); @@ -892,7 +892,7 @@ static int cypress_tiocmget(struct tty_struct *tty) } -static int cypress_tiocmset(struct tty_struct *tty, struct file *file, +static int cypress_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 08da46cb5825..86fbba6336c9 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -446,10 +446,10 @@ static void digi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); static void digi_break_ctl(struct tty_struct *tty, int break_state); static int digi_tiocmget(struct tty_struct *tty); -static int digi_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); +static int digi_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear); static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *buf, int count); + const unsigned char *buf, int count); static void digi_write_bulk_callback(struct urb *urb); static int digi_write_room(struct tty_struct *tty); static int digi_chars_in_buffer(struct tty_struct *tty); @@ -1134,8 +1134,8 @@ static int digi_tiocmget(struct tty_struct *tty) } -static int digi_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int digi_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 281d18141051..f521ab1eb60f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -857,7 +857,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, static void ftdi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static int ftdi_tiocmget(struct tty_struct *tty); -static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, +static int ftdi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int ftdi_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); @@ -2202,7 +2202,7 @@ out: return ret; } -static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, +static int ftdi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index e8fe4dcf72f0..0b8846e27a79 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -220,7 +220,7 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void edge_break(struct tty_struct *tty, int break_state); static int edge_tiocmget(struct tty_struct *tty); -static int edge_tiocmset(struct tty_struct *tty, struct file *file, +static int edge_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int edge_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount); @@ -1568,7 +1568,7 @@ static int get_lsr_info(struct edgeport_port *edge_port, return 0; } -static int edge_tiocmset(struct tty_struct *tty, struct file *file, +static int edge_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 7cb9f5cb91f3..88120523710b 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2444,7 +2444,7 @@ static void edge_set_termios(struct tty_struct *tty, change_port_settings(tty, edge_port, old_termios); } -static int edge_tiocmset(struct tty_struct *tty, struct file *file, +static int edge_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 1d96142f135a..6aca631a407a 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -150,7 +150,7 @@ static void iuu_release(struct usb_serial *serial) } } -static int iuu_tiocmset(struct tty_struct *tty, struct file *file, +static int iuu_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 1beebbb7a20a..c6e968f24e04 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -317,7 +317,7 @@ static int keyspan_tiocmget(struct tty_struct *tty) return value; } -static int keyspan_tiocmset(struct tty_struct *tty, struct file *file, +static int keyspan_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 5e5fc71e68df..13fa1d1cc900 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -60,7 +60,7 @@ static void keyspan_break_ctl (struct tty_struct *tty, int break_state); static int keyspan_tiocmget (struct tty_struct *tty); static int keyspan_tiocmset (struct tty_struct *tty, - struct file *file, unsigned int set, + unsigned int set, unsigned int clear); static int keyspan_fake_startup (struct usb_serial *serial); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 49ad2baf77cd..207caabdc4ff 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -478,7 +478,7 @@ static int keyspan_pda_tiocmget(struct tty_struct *tty) return value; } -static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file, +static int keyspan_pda_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index a570f5201c73..19373cb7c5bf 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -69,7 +69,7 @@ static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static int klsi_105_tiocmget(struct tty_struct *tty); -static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, +static int klsi_105_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void klsi_105_process_read_urb(struct urb *urb); static int klsi_105_prepare_write_buffer(struct usb_serial_port *port, @@ -661,7 +661,7 @@ static int klsi_105_tiocmget(struct tty_struct *tty) return (int)line_state; } -static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, +static int klsi_105_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { int retval = -EINVAL; diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 81d07fb299b8..22cd0c08f46f 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -78,7 +78,7 @@ static int kobil_write_room(struct tty_struct *tty); static int kobil_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static int kobil_tiocmget(struct tty_struct *tty); -static int kobil_tiocmset(struct tty_struct *tty, struct file *file, +static int kobil_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void kobil_read_int_callback(struct urb *urb); static void kobil_write_callback(struct urb *purb); @@ -544,7 +544,7 @@ static int kobil_tiocmget(struct tty_struct *tty) return result; } -static int kobil_tiocmset(struct tty_struct *tty, struct file *file, +static int kobil_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 27447095feae..ef49902c5a51 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -102,7 +102,7 @@ static void mct_u232_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); static int mct_u232_tiocmget(struct tty_struct *tty); -static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, +static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void mct_u232_throttle(struct tty_struct *tty); static void mct_u232_unthrottle(struct tty_struct *tty); @@ -778,7 +778,7 @@ static int mct_u232_tiocmget(struct tty_struct *tty) return control_state; } -static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, +static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 5d40d4151b5a..95b1c64cac03 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1858,7 +1858,7 @@ static int mos7720_tiocmget(struct tty_struct *tty) return result; } -static int mos7720_tiocmset(struct tty_struct *tty, struct file *file, +static int mos7720_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index ee0dc9a0890c..9424178c6689 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1674,7 +1674,7 @@ static int mos7840_tiocmget(struct tty_struct *tty) return result; } -static int mos7840_tiocmset(struct tty_struct *tty, struct file *file, +static int mos7840_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 4cd3b0ef4e61..63734cb0fb0f 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -145,7 +145,7 @@ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, static int oti6858_write_room(struct tty_struct *tty); static int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); -static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, +static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int oti6858_startup(struct usb_serial *serial); static void oti6858_release(struct usb_serial *serial); @@ -624,7 +624,7 @@ static void oti6858_close(struct usb_serial_port *port) usb_kill_urb(port->interrupt_in_urb); } -static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, +static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 6cb4f503a3f1..b797992fa54b 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -505,7 +505,7 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) return 0; } -static int pl2303_tiocmset(struct tty_struct *tty, struct file *file, +static int pl2303_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 66437f1e9e5b..79ee6c79ad54 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -408,7 +408,7 @@ static int sierra_tiocmget(struct tty_struct *tty) return value; } -static int sierra_tiocmset(struct tty_struct *tty, struct file *file, +static int sierra_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index cac13009fc5c..dfbc543e0db8 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -595,7 +595,7 @@ static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file, return -ENOIOCTLCMD; } -static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file, +static int spcp8x5_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index b21583fa825c..abceee9d3af9 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -517,7 +517,7 @@ mget_out: return r; } -static int ssu100_tiocmset(struct tty_struct *tty, struct file *file, +static int ssu100_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 223e60e31735..c7fea4a2a1be 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -113,7 +113,7 @@ static int ti_get_icount(struct tty_struct *tty, static void ti_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); static int ti_tiocmget(struct tty_struct *tty); -static int ti_tiocmset(struct tty_struct *tty, struct file *file, +static int ti_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void ti_break(struct tty_struct *tty, int break_state); static void ti_interrupt_callback(struct urb *urb); @@ -1033,8 +1033,8 @@ static int ti_tiocmget(struct tty_struct *tty) } -static int ti_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int ti_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index df105c6531a1..dab679e5b7ea 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -507,7 +507,7 @@ static int serial_tiocmget(struct tty_struct *tty) return -EINVAL; } -static int serial_tiocmset(struct tty_struct *tty, struct file *file, +static int serial_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; @@ -515,7 +515,7 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file, dbg("%s - port %d", __func__, port->number); if (port->serial->type->tiocmset) - return port->serial->type->tiocmset(tty, file, set, clear); + return port->serial->type->tiocmset(tty, set, clear); return -EINVAL; } diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 8b68fc783d5f..4d65f1c8dd93 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -16,7 +16,7 @@ extern void usb_wwan_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); extern int usb_wwan_tiocmget(struct tty_struct *tty); -extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file, +extern int usb_wwan_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 60f942632cb4..b72912027ae8 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -98,7 +98,7 @@ int usb_wwan_tiocmget(struct tty_struct *tty) } EXPORT_SYMBOL(usb_wwan_tiocmget); -int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file, +int usb_wwan_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index bf850139e0b8..6e0c397e869f 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -157,7 +157,7 @@ static int whiteheat_ioctl(struct tty_struct *tty, struct file *file, static void whiteheat_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static int whiteheat_tiocmget(struct tty_struct *tty); -static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file, +static int whiteheat_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); static int whiteheat_chars_in_buffer(struct tty_struct *tty); @@ -850,7 +850,7 @@ static int whiteheat_tiocmget(struct tty_struct *tty) return modem_signals; } -static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file, +static int whiteheat_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 9539d74171db..5dabaa2e6da3 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -272,7 +272,7 @@ struct tty_operations { void (*wait_until_sent)(struct tty_struct *tty, int timeout); void (*send_xchar)(struct tty_struct *tty, char ch); int (*tiocmget)(struct tty_struct *tty); - int (*tiocmset)(struct tty_struct *tty, struct file *file, + int (*tiocmset)(struct tty_struct *tty, unsigned int set, unsigned int clear); int (*resize)(struct tty_struct *tty, struct winsize *ws); int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 30b945397d19..c1aa1b243ba3 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -269,7 +269,7 @@ struct usb_serial_driver { void (*throttle)(struct tty_struct *tty); void (*unthrottle)(struct tty_struct *tty); int (*tiocmget)(struct tty_struct *tty); - int (*tiocmset)(struct tty_struct *tty, struct file *file, + int (*tiocmset)(struct tty_struct *tty, unsigned int set, unsigned int clear); int (*get_icount)(struct tty_struct *tty, struct serial_icounter_struct *icount); diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index fa3793b5392d..980ccb66e1b4 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -121,7 +121,7 @@ void ircomm_tty_start(struct tty_struct *tty); void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self); extern int ircomm_tty_tiocmget(struct tty_struct *tty); -extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file, +extern int ircomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 7f67fa4f2f5e..8e78e7447726 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -1098,7 +1098,7 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty) return dev->modem_status; } -static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear) +static int rfcomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; struct rfcomm_dlc *dlc = dev->dlc; diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index bb47caeba7e6..5e0e718c930a 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -214,12 +214,12 @@ int ircomm_tty_tiocmget(struct tty_struct *tty) } /* - * Function ircomm_tty_tiocmset (tty, file, set, clear) + * Function ircomm_tty_tiocmset (tty, set, clear) * * * */ -int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file, +int ircomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; -- cgit v1.2.3 From 6caa76b7786891b42b66a0e61e2c2fff2c884620 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 14 Feb 2011 16:27:22 +0000 Subject: tty: now phase out the ioctl file pointer for good Only oddities here are a couple of drivers that bogusly called the ldisc helpers instead of returning -ENOIOCTLCMD. Fix the bug and the rest goes away. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 2 +- drivers/char/cyclades.c | 2 +- drivers/char/epca.c | 8 ++++---- drivers/char/ip2/ip2main.c | 4 ++-- drivers/char/isicom.c | 2 +- drivers/char/istallion.c | 4 ++-- drivers/char/moxa.c | 2 +- drivers/char/mxser.c | 2 +- drivers/char/nozomi.c | 2 +- drivers/char/pcmcia/ipwireless/tty.c | 4 ++-- drivers/char/riscom8.c | 2 +- drivers/char/rocket.c | 2 +- drivers/char/ser_a2232.c | 6 +++--- drivers/char/serial167.c | 2 +- drivers/char/specialix.c | 2 +- drivers/char/stallion.c | 5 ++--- drivers/char/sx.c | 2 +- drivers/char/synclink.c | 3 +-- drivers/char/synclink_gt.c | 9 ++++----- drivers/char/synclinkmp.c | 5 ++--- drivers/char/ttyprintk.c | 2 +- drivers/char/vme_scc.c | 4 ++-- drivers/isdn/capi/capi.c | 10 ++-------- drivers/isdn/gigaset/interface.c | 4 ++-- drivers/isdn/i4l/isdn_tty.c | 3 +-- drivers/net/usb/hso.c | 2 +- drivers/tty/n_gsm.c | 2 +- drivers/tty/pty.c | 4 ++-- drivers/tty/serial/68328serial.c | 2 +- drivers/tty/serial/68360serial.c | 2 +- drivers/tty/serial/crisv10.c | 2 +- drivers/tty/serial/serial_core.c | 4 ++-- drivers/tty/tty_io.c | 4 ++-- drivers/tty/vt/vt_ioctl.c | 6 +++--- drivers/usb/class/cdc-acm.c | 2 +- drivers/usb/serial/usb-serial.c | 2 +- include/linux/tty.h | 2 +- include/linux/tty_driver.h | 9 ++++----- include/net/irda/ircomm_tty.h | 2 +- net/bluetooth/rfcomm/tty.c | 2 +- net/irda/ircomm/ircomm_tty_ioctl.c | 4 ++-- 41 files changed, 66 insertions(+), 78 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 5c15fad71ad2..f214e5022472 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1293,7 +1293,7 @@ static int rs_get_icount(struct tty_struct *tty, return 0; } -static int rs_ioctl(struct tty_struct *tty, struct file * file, +static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct async_struct * info = tty->driver_data; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 942b6f2b70a4..c99728f0cd9f 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -2680,7 +2680,7 @@ static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg, * not recognized by the driver, it should return ENOIOCTLCMD. */ static int -cy_ioctl(struct tty_struct *tty, struct file *file, +cy_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct cyclades_port *info = tty->driver_data; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index e5872b59f9cd..7ad3638967ae 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -175,9 +175,9 @@ static unsigned termios2digi_i(struct channel *ch, unsigned); static unsigned termios2digi_c(struct channel *ch, unsigned); static void epcaparam(struct tty_struct *, struct channel *); static void receive_data(struct channel *, struct tty_struct *tty); -static int pc_ioctl(struct tty_struct *, struct file *, +static int pc_ioctl(struct tty_struct *, unsigned int, unsigned long); -static int info_ioctl(struct tty_struct *, struct file *, +static int info_ioctl(struct tty_struct *, unsigned int, unsigned long); static void pc_set_termios(struct tty_struct *, struct ktermios *); static void do_softint(struct work_struct *work); @@ -1919,7 +1919,7 @@ static void receive_data(struct channel *ch, struct tty_struct *tty) tty_schedule_flip(tty); } -static int info_ioctl(struct tty_struct *tty, struct file *file, +static int info_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { switch (cmd) { @@ -2057,7 +2057,7 @@ static int pc_tiocmset(struct tty_struct *tty, return 0; } -static int pc_ioctl(struct tty_struct *tty, struct file *file, +static int pc_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { digiflow_t dflow; diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index d5f866c7c672..ea7a8fb08283 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -173,7 +173,7 @@ static void ip2_flush_chars(PTTY); static int ip2_write_room(PTTY); static int ip2_chars_in_buf(PTTY); static void ip2_flush_buffer(PTTY); -static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); +static int ip2_ioctl(PTTY, UINT, ULONG); static void ip2_set_termios(PTTY, struct ktermios *); static void ip2_set_line_discipline(PTTY); static void ip2_throttle(PTTY); @@ -2127,7 +2127,7 @@ static int ip2_tiocmset(struct tty_struct *tty, /* */ /******************************************************************************/ static int -ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) +ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg ) { wait_queue_t wait; i2ChanStrPtr pCh = DevTable[tty->index]; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 60f4d8ae7a49..db1cf9c328d8 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1167,7 +1167,7 @@ static int isicom_get_serial_info(struct isi_port *port, return 0; } -static int isicom_ioctl(struct tty_struct *tty, struct file *filp, +static int isicom_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct isi_port *port = tty->driver_data; diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 763b58d58255..0b266272cccd 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -603,7 +603,7 @@ static int stli_putchar(struct tty_struct *tty, unsigned char ch); static void stli_flushchars(struct tty_struct *tty); static int stli_writeroom(struct tty_struct *tty); static int stli_charsinbuffer(struct tty_struct *tty); -static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); +static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static void stli_settermios(struct tty_struct *tty, struct ktermios *old); static void stli_throttle(struct tty_struct *tty); static void stli_unthrottle(struct tty_struct *tty); @@ -1556,7 +1556,7 @@ static int stli_tiocmset(struct tty_struct *tty, sizeof(asysigs_t), 0); } -static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) +static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct stliport *portp; struct stlibrd *brdp; diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 9f4cd8968a5a..35b0c38590e6 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -287,7 +287,7 @@ static void moxa_low_water_check(void __iomem *ofsAddr) * TTY operations */ -static int moxa_ioctl(struct tty_struct *tty, struct file *file, +static int moxa_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct moxa_port *ch = tty->driver_data; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 150a862c4989..d188f378684d 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1655,7 +1655,7 @@ static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg, return ret; } -static int mxser_ioctl(struct tty_struct *tty, struct file *file, +static int mxser_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct mxser_port *info = tty->driver_data; diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 1b74c48c4016..513ba12064ea 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1824,7 +1824,7 @@ static int ntty_tiocgicount(struct tty_struct *tty, return 0; } -static int ntty_ioctl(struct tty_struct *tty, struct file *file, +static int ntty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct port *port = tty->driver_data; diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 748190dfbab0..ef92869502a7 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -425,7 +425,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, return set_control_lines(tty, set, clear); } -static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, +static int ipw_ioctl(struct tty_struct *linux_tty, unsigned int cmd, unsigned long arg) { struct ipw_tty *tty = linux_tty->driver_data; @@ -484,7 +484,7 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, return tty_perform_flush(linux_tty, arg); } } - return tty_mode_ioctl(linux_tty, file, cmd , arg); + return -ENOIOCTLCMD; } static int add_tty(int j, diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 3666decc6438..602643a40b4b 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1236,7 +1236,7 @@ static int rc_get_serial_info(struct riscom_port *port, return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; } -static int rc_ioctl(struct tty_struct *tty, struct file *filp, +static int rc_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct riscom_port *port = tty->driver_data; diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 36c108811a81..3780da8ad12d 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1326,7 +1326,7 @@ static int get_version(struct r_port *info, struct rocket_version __user *retver } /* IOCTL call handler into the driver */ -static int rp_ioctl(struct tty_struct *tty, struct file *file, +static int rp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct r_port *info = tty->driver_data; diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 9610861d1f5f..3f47c2ead8e5 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -133,8 +133,8 @@ static void a2232_hungup(void *ptr); /* END GENERIC_SERIAL PROTOTYPES */ /* Functions that the TTY driver struct expects */ -static int a2232_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); +static int a2232_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg); static void a2232_throttle(struct tty_struct *tty); static void a2232_unthrottle(struct tty_struct *tty); static int a2232_open(struct tty_struct * tty, struct file * filp); @@ -447,7 +447,7 @@ static void a2232_hungup(void *ptr) /*** END OF REAL_DRIVER FUNCTIONS ***/ /*** BEGIN FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/ -static int a2232_ioctl( struct tty_struct *tty, struct file *file, +static int a2232_ioctl( struct tty_struct *tty, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 89ac542ffff2..674af6933978 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1492,7 +1492,7 @@ get_default_timeout(struct cyclades_port *info, unsigned long __user * value) } static int -cy_ioctl(struct tty_struct *tty, struct file *file, +cy_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct cyclades_port *info = tty->driver_data; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index a6b23847e4a7..47e5753f732a 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1928,7 +1928,7 @@ static int sx_get_serial_info(struct specialix_port *port, } -static int sx_ioctl(struct tty_struct *tty, struct file *filp, +static int sx_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct specialix_port *port = tty->driver_data; diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index c42dbffbed16..4fff5cd3b163 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1132,14 +1132,13 @@ static int stl_tiocmset(struct tty_struct *tty, return 0; } -static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) +static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct stlport *portp; int rc; void __user *argp = (void __user *)arg; - pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd, - arg); + pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg); portp = tty->driver_data; if (portp == NULL) diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 342c6ae67da5..1291462bcddb 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1899,7 +1899,7 @@ static int sx_tiocmset(struct tty_struct *tty, return 0; } -static int sx_ioctl(struct tty_struct *tty, struct file *filp, +static int sx_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { int rc; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 691e1094c20b..18888d005a0a 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -2962,13 +2962,12 @@ static int msgl_get_icount(struct tty_struct *tty, * Arguments: * * tty pointer to tty instance data - * file pointer to associated file object for device * cmd IOCTL command code * arg command argument/context * * Return Value: 0 if success, otherwise error code */ -static int mgsl_ioctl(struct tty_struct *tty, struct file * file, +static int mgsl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct mgsl_struct * info = tty->driver_data; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 04da6d61dc4f..a35dd549a008 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -154,7 +154,7 @@ static void flush_buffer(struct tty_struct *tty); static void tx_hold(struct tty_struct *tty); static void tx_release(struct tty_struct *tty); -static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); +static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static int chars_in_buffer(struct tty_struct *tty); static void throttle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty); @@ -1030,13 +1030,12 @@ static void tx_release(struct tty_struct *tty) * Arguments * * tty pointer to tty instance data - * file pointer to associated file object for device * cmd IOCTL command code * arg command argument/context * * Return 0 if success, otherwise error code */ -static int ioctl(struct tty_struct *tty, struct file *file, +static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct slgt_info *info = tty->driver_data; @@ -1200,7 +1199,7 @@ static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *ne return 0; } -static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, +static long slgt_compat_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct slgt_info *info = tty->driver_data; @@ -1239,7 +1238,7 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, case MGSL_IOCSIF: case MGSL_IOCSXSYNC: case MGSL_IOCSXCTRL: - rc = ioctl(tty, file, cmd, arg); + rc = ioctl(tty, cmd, arg); break; } diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 1f9de97e8cfc..327343694473 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -520,7 +520,7 @@ static void flush_buffer(struct tty_struct *tty); static void tx_hold(struct tty_struct *tty); static void tx_release(struct tty_struct *tty); -static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); +static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static int chars_in_buffer(struct tty_struct *tty); static void throttle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty); @@ -1248,13 +1248,12 @@ static void tx_release(struct tty_struct *tty) * Arguments: * * tty pointer to tty instance data - * file pointer to associated file object for device * cmd IOCTL command code * arg command argument/context * * Return Value: 0 if success, otherwise error code */ -static int ioctl(struct tty_struct *tty, struct file *file, +static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { SLMP_INFO *info = tty->driver_data; diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index c40c1612c8a7..a1f68af4ccf4 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -144,7 +144,7 @@ static int tpk_write_room(struct tty_struct *tty) /* * TTY operations ioctl function. */ -static int tpk_ioctl(struct tty_struct *tty, struct file *file, +static int tpk_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct ttyprintk_port *tpkp = tty->driver_data; diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index 12de1202d22c..96838640f575 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -75,7 +75,7 @@ static void scc_hungup(void *ptr); static void scc_close(void *ptr); static int scc_chars_in_buffer(void * ptr); static int scc_open(struct tty_struct * tty, struct file * filp); -static int scc_ioctl(struct tty_struct * tty, struct file * filp, +static int scc_ioctl(struct tty_struct * tty, unsigned int cmd, unsigned long arg); static void scc_throttle(struct tty_struct *tty); static void scc_unthrottle(struct tty_struct *tty); @@ -1046,7 +1046,7 @@ static void scc_unthrottle (struct tty_struct * tty) } -static int scc_ioctl(struct tty_struct *tty, struct file *file, +static int scc_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index f80a7c48a35f..0d7088367038 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1219,16 +1219,10 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty) return mp->outbytes; } -static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, +static int capinc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - int error = 0; - switch (cmd) { - default: - error = n_tty_ioctl_helper(tty, file, cmd, arg); - break; - } - return error; + return -ENOIOCTLCMD; } static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old) diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 9b2bb491c614..59de638225fe 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -115,7 +115,7 @@ static int if_config(struct cardstate *cs, int *arg) static int if_open(struct tty_struct *tty, struct file *filp); static void if_close(struct tty_struct *tty, struct file *filp); -static int if_ioctl(struct tty_struct *tty, struct file *file, +static int if_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static int if_write_room(struct tty_struct *tty); static int if_chars_in_buffer(struct tty_struct *tty); @@ -205,7 +205,7 @@ static void if_close(struct tty_struct *tty, struct file *filp) module_put(cs->driver->owner); } -static int if_ioctl(struct tty_struct *tty, struct file *file, +static int if_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct cardstate *cs; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 0341c69eb152..3d88f15aa218 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1413,8 +1413,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, } static int -isdn_tty_ioctl(struct tty_struct *tty, struct file *file, - uint cmd, ulong arg) +isdn_tty_ioctl(struct tty_struct *tty, uint cmd, ulong arg) { modem_info *info = (modem_info *) tty->driver_data; int retval; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 956e1d6e72a5..2ad58a0377b7 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1730,7 +1730,7 @@ static int hso_serial_tiocmset(struct tty_struct *tty, USB_CTRL_SET_TIMEOUT); } -static int hso_serial_ioctl(struct tty_struct *tty, struct file *file, +static int hso_serial_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct hso_serial *serial = get_serial_by_tty(tty); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 88477d16b8b7..50f3ffd610b7 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2671,7 +2671,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty, } -static int gsmtty_ioctl(struct tty_struct *tty, struct file *filp, +static int gsmtty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 923a48585501..c88029af84dd 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -334,7 +334,7 @@ free_mem_out: return -ENOMEM; } -static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, +static int pty_bsd_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { switch (cmd) { @@ -489,7 +489,7 @@ static struct ctl_table pty_root_table[] = { }; -static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, +static int pty_unix98_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { switch (cmd) { diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index a9d99856c892..1de0e8d4bde1 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -945,7 +945,7 @@ static void send_break(struct m68k_serial * info, unsigned int duration) local_irq_restore(flags); } -static int rs_ioctl(struct tty_struct *tty, struct file * file, +static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { int error; diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c index 217fe1c299e0..514a356d8d64 100644 --- a/drivers/tty/serial/68360serial.c +++ b/drivers/tty/serial/68360serial.c @@ -1405,7 +1405,7 @@ static int rs_360_get_icount(struct tty_struct *tty, return 0; } -static int rs_360_ioctl(struct tty_struct *tty, struct file * file, +static int rs_360_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { int error; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index b9fcd0bda60c..225123b37f19 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3647,7 +3647,7 @@ rs_tiocmget(struct tty_struct *tty) static int -rs_ioctl(struct tty_struct *tty, struct file * file, +rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct e100_serial * info = (struct e100_serial *)tty->driver_data; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 623d6bd911d7..733fe8e73f0f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1099,7 +1099,7 @@ static int uart_get_icount(struct tty_struct *tty, * Called via sys_ioctl. We can use spin_lock_irq() here. */ static int -uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, +uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct uart_state *state = tty->driver_data; @@ -1152,7 +1152,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, mutex_lock(&port->mutex); - if (tty_hung_up_p(filp)) { + if (tty->flags & (1 << TTY_IO_ERROR)) { ret = -EIO; goto out_up; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 83af24ca1e5e..20a862a2a0c2 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2676,7 +2676,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } if (tty->ops->ioctl) { - retval = (tty->ops->ioctl)(tty, file, cmd, arg); + retval = (tty->ops->ioctl)(tty, cmd, arg); if (retval != -ENOIOCTLCMD) return retval; } @@ -2704,7 +2704,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, return -EINVAL; if (tty->ops->compat_ioctl) { - retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg); + retval = (tty->ops->compat_ioctl)(tty, cmd, arg); if (retval != -ENOIOCTLCMD) return retval; } diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 9e9a901442a3..b64804965316 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -495,7 +495,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_ * We handle the console-specific ioctl's here. We allow the * capability to modify any console, not just the fg_console. */ -int vt_ioctl(struct tty_struct *tty, struct file * file, +int vt_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct vc_data *vc = tty->driver_data; @@ -1495,7 +1495,7 @@ compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud, return 0; } -long vt_compat_ioctl(struct tty_struct *tty, struct file * file, +long vt_compat_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct vc_data *vc = tty->driver_data; @@ -1581,7 +1581,7 @@ out: fallback: tty_unlock(); - return vt_ioctl(tty, file, cmd, arg); + return vt_ioctl(tty, cmd, arg); } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e9a26fbd079c..8d994a8bdc90 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -813,7 +813,7 @@ static int acm_tty_tiocmset(struct tty_struct *tty, return acm_set_control(acm, acm->ctrlout = newctrl); } -static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, +static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct acm *acm = tty->driver_data; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index b1110e136c33..a72575349744 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -406,7 +406,7 @@ static void serial_unthrottle(struct tty_struct *tty) port->serial->type->unthrottle(tty); } -static int serial_ioctl(struct tty_struct *tty, struct file *file, +static int serial_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; diff --git a/include/linux/tty.h b/include/linux/tty.h index 54e4eaaa0561..483df15146d2 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -584,7 +584,7 @@ extern int pcxe_open(struct tty_struct *tty, struct file *filp); /* vt.c */ -extern int vt_ioctl(struct tty_struct *tty, struct file *file, +extern int vt_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 5dabaa2e6da3..9deeac855240 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -98,8 +98,7 @@ * * Note: Do not call this function directly, call tty_write_room * - * int (*ioctl)(struct tty_struct *tty, struct file * file, - * unsigned int cmd, unsigned long arg); + * int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); * * This routine allows the tty driver to implement * device-specific ioctls. If the ioctl number passed in cmd @@ -107,7 +106,7 @@ * * Optional * - * long (*compat_ioctl)(struct tty_struct *tty, struct file * file, + * long (*compat_ioctl)(struct tty_struct *tty,, * unsigned int cmd, unsigned long arg); * * implement ioctl processing for 32 bit process on 64 bit system @@ -256,9 +255,9 @@ struct tty_operations { void (*flush_chars)(struct tty_struct *tty); int (*write_room)(struct tty_struct *tty); int (*chars_in_buffer)(struct tty_struct *tty); - int (*ioctl)(struct tty_struct *tty, struct file * file, + int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); - long (*compat_ioctl)(struct tty_struct *tty, struct file * file, + long (*compat_ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index 980ccb66e1b4..59ba38bc400f 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -123,7 +123,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self); extern int ircomm_tty_tiocmget(struct tty_struct *tty); extern int ircomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, +extern int ircomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); extern void ircomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 8e78e7447726..b1805ff95415 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -830,7 +830,7 @@ static int rfcomm_tty_write_room(struct tty_struct *tty) return room; } -static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg) +static int rfcomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { BT_DBG("tty %p cmd 0x%02x", tty, cmd); diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index 5e0e718c930a..77c5e6499f8f 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -365,12 +365,12 @@ static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self, } /* - * Function ircomm_tty_ioctl (tty, file, cmd, arg) + * Function ircomm_tty_ioctl (tty, cmd, arg) * * * */ -int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, +int ircomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; -- cgit v1.2.3 From d5bb2923cfa0a29c5854f9618703ff60849b949e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 13 Feb 2011 13:12:10 +0100 Subject: drivers/char/pcmcia/ipwireless/main.c: Convert release_resource to release_region/release_mem_region Request_region should be used with release_region, not release_resource. This patch contains a number of changes, related to calls to request_region, request_mem_region, and the associated error handling code. 1. For the call to request_region, the variable io_resource storing the result is dropped. The call to release_resource at the end of the function is changed to a call to release_region with the first two arguments of request_region as its arguments. The same call to release_region is also added to release_ipwireless. 2. The first call to request_mem_region is now tested and ret is set to -EBUSY if the the call has failed. This call was associated with the initialization of ipw->attr_memory. But the error handling code was testing ipw->common_memory. The definition of release_ipwireless also suggests that this call should be associated with ipw->common_memory, not ipw->attr_memory. 3. The second call to request_mem_region is now tested and ret is set to -EBUSY if the the call has failed. 4. The various gotos to the error handling code is adjusted so that there is no need for ifs. 5. Return the value stored in the ret variable rather than -1. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,E; @@ ( *x = request_region(...) | *x = request_mem_region(...) ) ... when != release_region(x) when != x = E * release_resource(x); // Signed-off-by: Julia Lawall Signed-off-by: Jiri Kosina Signed-off-by: Dominik Brodowski --- drivers/char/pcmcia/ipwireless/main.c | 52 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 94b8eb4d691d..444155a305ae 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -78,7 +78,6 @@ static void signalled_reboot_callback(void *callback_data) static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) { struct ipw_dev *ipw = priv_data; - struct resource *io_resource; int ret; p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; @@ -92,9 +91,12 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) if (ret) return ret; - io_resource = request_region(p_dev->resource[0]->start, - resource_size(p_dev->resource[0]), - IPWIRELESS_PCCARD_NAME); + if (!request_region(p_dev->resource[0]->start, + resource_size(p_dev->resource[0]), + IPWIRELESS_PCCARD_NAME)) { + ret = -EBUSY; + goto exit; + } p_dev->resource[2]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; @@ -105,22 +107,25 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr); if (ret != 0) - goto exit2; + goto exit1; ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100; - ipw->attr_memory = ioremap(p_dev->resource[2]->start, + ipw->common_memory = ioremap(p_dev->resource[2]->start, resource_size(p_dev->resource[2])); - request_mem_region(p_dev->resource[2]->start, - resource_size(p_dev->resource[2]), - IPWIRELESS_PCCARD_NAME); + if (!request_mem_region(p_dev->resource[2]->start, + resource_size(p_dev->resource[2]), + IPWIRELESS_PCCARD_NAME)) { + ret = -EBUSY; + goto exit2; + } p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; p_dev->resource[3]->end = 0; /* this used to be 0x1000 */ ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0); if (ret != 0) - goto exit2; + goto exit3; ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0); if (ret != 0) @@ -128,23 +133,28 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) ipw->attr_memory = ioremap(p_dev->resource[3]->start, resource_size(p_dev->resource[3])); - request_mem_region(p_dev->resource[3]->start, - resource_size(p_dev->resource[3]), - IPWIRELESS_PCCARD_NAME); + if (!request_mem_region(p_dev->resource[3]->start, + resource_size(p_dev->resource[3]), + IPWIRELESS_PCCARD_NAME)) { + ret = -EBUSY; + goto exit4; + } return 0; +exit4: + iounmap(ipw->attr_memory); exit3: + release_mem_region(p_dev->resource[2]->start, + resource_size(p_dev->resource[2])); exit2: - if (ipw->common_memory) { - release_mem_region(p_dev->resource[2]->start, - resource_size(p_dev->resource[2])); - iounmap(ipw->common_memory); - } + iounmap(ipw->common_memory); exit1: - release_resource(io_resource); + release_region(p_dev->resource[0]->start, + resource_size(p_dev->resource[0])); +exit: pcmcia_disable_device(p_dev); - return -1; + return ret; } static int config_ipwireless(struct ipw_dev *ipw) @@ -219,6 +229,8 @@ exit: static void release_ipwireless(struct ipw_dev *ipw) { + release_region(ipw->link->resource[0]->start, + resource_size(ipw->link->resource[0])); if (ipw->common_memory) { release_mem_region(ipw->link->resource[2]->start, resource_size(ipw->link->resource[2])); -- cgit v1.2.3 From 644e6e4a7fa6b11d59f24032997d90ea0d858d03 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Feb 2011 15:46:05 +0000 Subject: cm4000_cs: Fix undefined ops warning Signed-off-by: Alan Cox Signed-off-by: Dominik Brodowski --- drivers/char/pcmcia/cm4000_cs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 777181a2e603..bcbbc71febb7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -830,8 +830,7 @@ static void monitor_card(unsigned long p) test_bit(IS_ANY_T1, &dev->flags))) { DEBUGP(4, dev, "Perform AUTOPPS\n"); set_bit(IS_AUTOPPS_ACT, &dev->flags); - ptsreq.protocol = ptsreq.protocol = - (0x01 << dev->proto); + ptsreq.protocol = (0x01 << dev->proto); ptsreq.flags = 0x01; ptsreq.pts1 = 0x00; ptsreq.pts2 = 0x00; -- cgit v1.2.3 From 442a4fffffa26fc3080350b4d50172f7589c3ac2 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 21 Feb 2011 21:43:10 +1100 Subject: random: update interface comments to reflect reality At present, the comment header in random.c makes no mention of add_disk_randomness, and instead, suggests that disk activity adds to the random pool by way of add_interrupt_randomness, which appears to not have been the case since sometime prior to the existence of git, and even prior to bitkeeper. Didn't look any further back. At least, as far as I can tell, there are no storage drivers setting IRQF_SAMPLE_RANDOM, which is a requirement for add_interrupt_randomness to trigger, so the only way for a disk to contribute entropy is by way of add_disk_randomness. Update comments accordingly, complete with special mention about solid state drives being a crappy source of entropy (see e2e1a148bc for reference). Signed-off-by: Jarod Wilson Acked-by: Matt Mackall Signed-off-by: Herbert Xu --- drivers/char/random.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/random.c b/drivers/char/random.c index 72a4fcb17745..5e29e8031bbc 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -128,6 +128,7 @@ * void add_input_randomness(unsigned int type, unsigned int code, * unsigned int value); * void add_interrupt_randomness(int irq); + * void add_disk_randomness(struct gendisk *disk); * * add_input_randomness() uses the input layer interrupt timing, as well as * the event type information from the hardware. @@ -136,9 +137,15 @@ * inputs to the entropy pool. Note that not all interrupts are good * sources of randomness! For example, the timer interrupts is not a * good choice, because the periodicity of the interrupts is too - * regular, and hence predictable to an attacker. Disk interrupts are - * a better measure, since the timing of the disk interrupts are more - * unpredictable. + * regular, and hence predictable to an attacker. Network Interface + * Controller interrupts are a better measure, since the timing of the + * NIC interrupts are more unpredictable. + * + * add_disk_randomness() uses what amounts to the seek time of block + * layer request events, on a per-disk_devt basis, as input to the + * entropy pool. Note that high-speed solid state drives with very low + * seek times do not make for good sources of entropy, as their seek + * times are usually fairly consistent. * * All of these routines try to estimate how many bits of randomness a * particular randomness source. They do this by keeping track of the -- cgit v1.2.3 From bdb8b975fc66e081c3f39be6267701f8226d11aa Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 22 Dec 2010 11:37:09 +0000 Subject: agp/intel: Experiment with a 855GM GWB bit Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=27187 Tested-by: Thorsten Vollmer (DFI-ACP G5M150-N w/852GME) Tested-by: Moritz Brunner <2points@gmx.org> (Asus M2400N/i855GM) Tested-by: Indan Zupancic (Thinkpad X40/855GM rev 02) Tested-by: Eric Anholt (865G) Signed-off-by: Chris Wilson --- drivers/char/agp/intel-agp.h | 1 + drivers/char/agp/intel-gtt.c | 56 +++++++++++++++++--------------------------- 2 files changed, 22 insertions(+), 35 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index c195bfeade11..5feebe2800e9 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -130,6 +130,7 @@ #define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) #define I915_IFPADDR 0x60 +#define I830_HIC 0x70 /* Intel 965G registers */ #define I965_MSAC 0x62 diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index fab3d3265adb..0d09b537bb9a 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "agp.h" #include "intel-agp.h" @@ -70,12 +71,8 @@ static struct _intel_private { u32 __iomem *gtt; /* I915G */ bool clear_fake_agp; /* on first access via agp, fill with scratch */ int num_dcache_entries; - union { - void __iomem *i9xx_flush_page; - void *i8xx_flush_page; - }; + void __iomem *i9xx_flush_page; char *i81x_gtt_table; - struct page *i8xx_page; struct resource ifp_resource; int resource_valid; struct page *scratch_page; @@ -722,28 +719,6 @@ static int intel_fake_agp_fetch_size(void) static void i830_cleanup(void) { - if (intel_private.i8xx_flush_page) { - kunmap(intel_private.i8xx_flush_page); - intel_private.i8xx_flush_page = NULL; - } - - __free_page(intel_private.i8xx_page); - intel_private.i8xx_page = NULL; -} - -static void intel_i830_setup_flush(void) -{ - /* return if we've already set the flush mechanism up */ - if (intel_private.i8xx_page) - return; - - intel_private.i8xx_page = alloc_page(GFP_KERNEL); - if (!intel_private.i8xx_page) - return; - - intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); - if (!intel_private.i8xx_flush_page) - i830_cleanup(); } /* The chipset_flush interface needs to get data that has already been @@ -758,14 +733,27 @@ static void intel_i830_setup_flush(void) */ static void i830_chipset_flush(void) { - unsigned int *pg = intel_private.i8xx_flush_page; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + /* Forcibly evict everything from the CPU write buffers. + * clflush appears to be insufficient. + */ + wbinvd_on_all_cpus(); + + /* Now we've only seen documents for this magic bit on 855GM, + * we hope it exists for the other gen2 chipsets... + * + * Also works as advertised on my 845G. + */ + writel(readl(intel_private.registers+I830_HIC) | (1<<31), + intel_private.registers+I830_HIC); - memset(pg, 0, 1024); + while (readl(intel_private.registers+I830_HIC) & (1<<31)) { + if (time_after(jiffies, timeout)) + break; - if (cpu_has_clflush) - clflush_cache_range(pg, 1024); - else if (wbinvd_on_all_cpus() != 0) - printk(KERN_ERR "Timed out waiting for cache flush.\n"); + udelay(50); + } } static void i830_write_entry(dma_addr_t addr, unsigned int entry, @@ -849,8 +837,6 @@ static int i830_setup(void) intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; - intel_i830_setup_flush(); - return 0; } -- cgit v1.2.3 From bdcffc5a1a28b566a38a4b0d5bcefc78a97f4ecb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Feb 2011 15:41:47 -0800 Subject: tty: move Kconfig entries into drivers/tty from drivers/char The Kconfig options for the drivers/tty/ files still were hanging around in the "big" drivers/char/Kconfig file, so move them to the proper location under drivers/tty and drivers/tty/hvc/ Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 254 +----------------------------------------------- drivers/tty/Kconfig | 150 ++++++++++++++++++++++++++++ drivers/tty/hvc/Kconfig | 105 ++++++++++++++++++++ 3 files changed, 257 insertions(+), 252 deletions(-) create mode 100644 drivers/tty/Kconfig create mode 100644 drivers/tty/hvc/Kconfig (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 17f9b968b988..9b9ab867f50e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -4,89 +4,7 @@ menu "Character devices" -config VT - bool "Virtual terminal" if EXPERT - depends on !S390 - select INPUT - default y - ---help--- - If you say Y here, you will get support for terminal devices with - display and keyboard devices. These are called "virtual" because you - can run several virtual terminals (also called virtual consoles) on - one physical terminal. This is rather useful, for example one - virtual terminal can collect system messages and warnings, another - one can be used for a text-mode user session, and a third could run - an X session, all in parallel. Switching between virtual terminals - is done with certain key combinations, usually Alt-. - - The setterm command ("man setterm") can be used to change the - properties (such as colors or beeping) of a virtual terminal. The - man page console_codes(4) ("man console_codes") contains the special - character sequences that can be used to change those properties - directly. The fonts used on virtual terminals can be changed with - the setfont ("man setfont") command and the key bindings are defined - with the loadkeys ("man loadkeys") command. - - You need at least one virtual terminal device in order to make use - of your keyboard and monitor. Therefore, only people configuring an - embedded system would want to say N here in order to save some - memory; the only way to log into such a system is then via a serial - or network connection. - - If unsure, say Y, or else you won't be able to do much with your new - shiny Linux system :-) - -config CONSOLE_TRANSLATIONS - depends on VT - default y - bool "Enable character translations in console" if EXPERT - ---help--- - This enables support for font mapping and Unicode translation - on virtual consoles. - -config VT_CONSOLE - bool "Support for console on virtual terminal" if EXPERT - depends on VT - default y - ---help--- - The system console is the device which receives all kernel messages - and warnings and which allows logins in single user mode. If you - answer Y here, a virtual terminal (the device used to interact with - a physical terminal) can be used as system console. This is the most - common mode of operations, so you should say Y here unless you want - the kernel messages be output only to a serial port (in which case - you should say Y to "Console on serial port", below). - - If you do say Y here, by default the currently visible virtual - terminal (/dev/tty0) will be used as system console. You can change - that with a kernel command line option such as "console=tty3" which - would use the third virtual terminal as system console. (Try "man - bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time.) - - If unsure, say Y. - -config HW_CONSOLE - bool - depends on VT && !S390 && !UML - default y - -config VT_HW_CONSOLE_BINDING - bool "Support for binding and unbinding console drivers" - depends on HW_CONSOLE - default n - ---help--- - The virtual terminal is the device that interacts with the physical - terminal through console drivers. On these systems, at least one - console driver is loaded. In other configurations, additional console - drivers may be enabled, such as the framebuffer console. If more than - 1 console driver is enabled, setting this to 'y' will allow you to - select the console driver that will serve as the backend for the - virtual terminals. - - See for more - information. For framebuffer console users, please refer to - . +source "drivers/tty/Kconfig" config DEVKMEM bool "/dev/kmem virtual device support" @@ -428,71 +346,6 @@ config SGI_MBCS source "drivers/tty/serial/Kconfig" -config UNIX98_PTYS - bool "Unix98 PTY support" if EXPERT - default y - ---help--- - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx for - masters and /dev/ttyxx for slaves of pseudo terminals. This scheme - has a number of problems. The GNU C library glibc 2.1 and later, - however, supports the Unix98 naming standard: in order to acquire a - pseudo terminal, a process opens /dev/ptmx; the number of the pseudo - terminal is then made available to the process and the pseudo - terminal slave can be accessed as /dev/pts/. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - All modern Linux systems use the Unix98 ptys. Say Y unless - you're on an embedded system and want to conserve memory. - -config DEVPTS_MULTIPLE_INSTANCES - bool "Support multiple instances of devpts" - depends on UNIX98_PTYS - default n - ---help--- - Enable support for multiple instances of devpts filesystem. - If you want to have isolated PTY namespaces (eg: in containers), - say Y here. Otherwise, say N. If enabled, each mount of devpts - filesystem with the '-o newinstance' option will create an - independent PTY namespace. - -config LEGACY_PTYS - bool "Legacy (BSD) PTY support" - default y - ---help--- - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx - for masters and /dev/ttyxx for slaves of pseudo - terminals. This scheme has a number of problems, including - security. This option enables these legacy devices; on most - systems, it is safe to say N. - - -config LEGACY_PTY_COUNT - int "Maximum number of legacy PTY in use" - depends on LEGACY_PTYS - range 0 256 - default "256" - ---help--- - The maximum number of legacy PTYs that can be used at any one time. - The default is 256, and should be more than enough. Embedded - systems may want to reduce this to save memory. - - When not in use, each legacy PTY occupies 12 bytes on 32-bit - architectures and 24 bytes on 64-bit architectures. - config TTY_PRINTK bool "TTY driver to output user messages via printk" depends on EXPERT @@ -612,93 +465,7 @@ config PPDEV If unsure, say N. -config HVC_DRIVER - bool - help - Generic "hypervisor virtual console" infrastructure for various - hypervisors (pSeries, iSeries, Xen, lguest). - It will automatically be selected if one of the back-end console drivers - is selected. - -config HVC_IRQ - bool - -config HVC_CONSOLE - bool "pSeries Hypervisor Virtual Console support" - depends on PPC_PSERIES - select HVC_DRIVER - select HVC_IRQ - help - pSeries machines when partitioned support a hypervisor virtual - console. This driver allows each pSeries partition to have a console - which is accessed via the HMC. - -config HVC_ISERIES - bool "iSeries Hypervisor Virtual Console support" - depends on PPC_ISERIES - default y - select HVC_DRIVER - select HVC_IRQ - select VIOPATH - help - iSeries machines support a hypervisor virtual console. - -config HVC_RTAS - bool "IBM RTAS Console support" - depends on PPC_RTAS - select HVC_DRIVER - 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 HVC_IUCV - bool "z/VM IUCV Hypervisor console support (VM only)" - depends on S390 - select HVC_DRIVER - select IUCV - default y - help - This driver provides a Hypervisor console (HVC) back-end to access - a Linux (console) terminal via a z/VM IUCV communication path. - -config HVC_XEN - bool "Xen Hypervisor Console support" - depends on XEN - select HVC_DRIVER - select HVC_IRQ - default y - help - Xen virtual console device driver - -config HVC_UDBG - bool "udbg based fake hypervisor console" - depends on PPC && EXPERIMENTAL - select HVC_DRIVER - default n - -config HVC_DCC - bool "ARM JTAG DCC console" - depends on ARM - select HVC_DRIVER - help - This console uses the JTAG DCC on ARM to create a console under the HVC - driver. This console is used through a JTAG only on ARM. If you don't have - a JTAG then you probably don't want this option. - -config HVC_BFIN_JTAG - bool "Blackfin JTAG console" - depends on BLACKFIN - select HVC_DRIVER - help - This console uses the Blackfin JTAG to create a console under the - the HVC driver. If you don't have JTAG, then you probably don't - want this option. +source "drivers/tty/hvc/Kconfig" config VIRTIO_CONSOLE tristate "Virtio console" @@ -716,23 +483,6 @@ config VIRTIO_CONSOLE the port which can be used by udev scripts to create a symlink to the device. -config HVCS - tristate "IBM Hypervisor Virtual Console Server support" - depends on PPC_PSERIES && HVC_CONSOLE - help - Partitionable IBM Power5 ppc64 machines allow hosting of - firmware virtual consoles from one Linux partition by - another Linux partition. This driver allows console data - from Linux partitions to be accessed through TTY device - interfaces in the device tree of a Linux partition running - this driver. - - To compile this driver as a module, choose M here: the - module will be called hvcs. Additionally, this module - will depend on arch specific APIs exported from hvcserver.ko - which will also be compiled when this driver is built as a - module. - config IBM_BSR tristate "IBM POWER Barrier Synchronization Register support" depends on PPC_PSERIES diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig new file mode 100644 index 000000000000..9cfbdb318ed9 --- /dev/null +++ b/drivers/tty/Kconfig @@ -0,0 +1,150 @@ +config VT + bool "Virtual terminal" if EXPERT + depends on !S390 + select INPUT + default y + ---help--- + If you say Y here, you will get support for terminal devices with + display and keyboard devices. These are called "virtual" because you + can run several virtual terminals (also called virtual consoles) on + one physical terminal. This is rather useful, for example one + virtual terminal can collect system messages and warnings, another + one can be used for a text-mode user session, and a third could run + an X session, all in parallel. Switching between virtual terminals + is done with certain key combinations, usually Alt-. + + The setterm command ("man setterm") can be used to change the + properties (such as colors or beeping) of a virtual terminal. The + man page console_codes(4) ("man console_codes") contains the special + character sequences that can be used to change those properties + directly. The fonts used on virtual terminals can be changed with + the setfont ("man setfont") command and the key bindings are defined + with the loadkeys ("man loadkeys") command. + + You need at least one virtual terminal device in order to make use + of your keyboard and monitor. Therefore, only people configuring an + embedded system would want to say N here in order to save some + memory; the only way to log into such a system is then via a serial + or network connection. + + If unsure, say Y, or else you won't be able to do much with your new + shiny Linux system :-) + +config CONSOLE_TRANSLATIONS + depends on VT + default y + bool "Enable character translations in console" if EXPERT + ---help--- + This enables support for font mapping and Unicode translation + on virtual consoles. + +config VT_CONSOLE + bool "Support for console on virtual terminal" if EXPERT + depends on VT + default y + ---help--- + The system console is the device which receives all kernel messages + and warnings and which allows logins in single user mode. If you + answer Y here, a virtual terminal (the device used to interact with + a physical terminal) can be used as system console. This is the most + common mode of operations, so you should say Y here unless you want + the kernel messages be output only to a serial port (in which case + you should say Y to "Console on serial port", below). + + If you do say Y here, by default the currently visible virtual + terminal (/dev/tty0) will be used as system console. You can change + that with a kernel command line option such as "console=tty3" which + would use the third virtual terminal as system console. (Try "man + bootparam" or see the documentation of your boot loader (lilo or + loadlin) about how to pass options to the kernel at boot time.) + + If unsure, say Y. + +config HW_CONSOLE + bool + depends on VT && !S390 && !UML + default y + +config VT_HW_CONSOLE_BINDING + bool "Support for binding and unbinding console drivers" + depends on HW_CONSOLE + default n + ---help--- + The virtual terminal is the device that interacts with the physical + terminal through console drivers. On these systems, at least one + console driver is loaded. In other configurations, additional console + drivers may be enabled, such as the framebuffer console. If more than + 1 console driver is enabled, setting this to 'y' will allow you to + select the console driver that will serve as the backend for the + virtual terminals. + + See for more + information. For framebuffer console users, please refer to + . + +config UNIX98_PTYS + bool "Unix98 PTY support" if EXPERT + default y + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx for + masters and /dev/ttyxx for slaves of pseudo terminals. This scheme + has a number of problems. The GNU C library glibc 2.1 and later, + however, supports the Unix98 naming standard: in order to acquire a + pseudo terminal, a process opens /dev/ptmx; the number of the pseudo + terminal is then made available to the process and the pseudo + terminal slave can be accessed as /dev/pts/. What was + traditionally /dev/ttyp2 will then be /dev/pts/2, for example. + + All modern Linux systems use the Unix98 ptys. Say Y unless + you're on an embedded system and want to conserve memory. + +config DEVPTS_MULTIPLE_INSTANCES + bool "Support multiple instances of devpts" + depends on UNIX98_PTYS + default n + ---help--- + Enable support for multiple instances of devpts filesystem. + If you want to have isolated PTY namespaces (eg: in containers), + say Y here. Otherwise, say N. If enabled, each mount of devpts + filesystem with the '-o newinstance' option will create an + independent PTY namespace. + +config LEGACY_PTYS + bool "Legacy (BSD) PTY support" + default y + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx + for masters and /dev/ttyxx for slaves of pseudo + terminals. This scheme has a number of problems, including + security. This option enables these legacy devices; on most + systems, it is safe to say N. + + +config LEGACY_PTY_COUNT + int "Maximum number of legacy PTY in use" + depends on LEGACY_PTYS + range 0 256 + default "256" + ---help--- + The maximum number of legacy PTYs that can be used at any one time. + The default is 256, and should be more than enough. Embedded + systems may want to reduce this to save memory. + + When not in use, each legacy PTY occupies 12 bytes on 32-bit + architectures and 24 bytes on 64-bit architectures. + + diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig new file mode 100644 index 000000000000..6f2c9809f1fb --- /dev/null +++ b/drivers/tty/hvc/Kconfig @@ -0,0 +1,105 @@ +config HVC_DRIVER + bool + help + Generic "hypervisor virtual console" infrastructure for various + hypervisors (pSeries, iSeries, Xen, lguest). + It will automatically be selected if one of the back-end console drivers + is selected. + +config HVC_IRQ + bool + +config HVC_CONSOLE + bool "pSeries Hypervisor Virtual Console support" + depends on PPC_PSERIES + select HVC_DRIVER + select HVC_IRQ + help + pSeries machines when partitioned support a hypervisor virtual + console. This driver allows each pSeries partition to have a console + which is accessed via the HMC. + +config HVC_ISERIES + bool "iSeries Hypervisor Virtual Console support" + depends on PPC_ISERIES + default y + select HVC_DRIVER + select HVC_IRQ + select VIOPATH + help + iSeries machines support a hypervisor virtual console. + +config HVC_RTAS + bool "IBM RTAS Console support" + depends on PPC_RTAS + select HVC_DRIVER + 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 HVC_IUCV + bool "z/VM IUCV Hypervisor console support (VM only)" + depends on S390 + select HVC_DRIVER + select IUCV + default y + help + This driver provides a Hypervisor console (HVC) back-end to access + a Linux (console) terminal via a z/VM IUCV communication path. + +config HVC_XEN + bool "Xen Hypervisor Console support" + depends on XEN + select HVC_DRIVER + select HVC_IRQ + default y + help + Xen virtual console device driver + +config HVC_UDBG + bool "udbg based fake hypervisor console" + depends on PPC && EXPERIMENTAL + select HVC_DRIVER + default n + +config HVC_DCC + bool "ARM JTAG DCC console" + depends on ARM + select HVC_DRIVER + help + This console uses the JTAG DCC on ARM to create a console under the HVC + driver. This console is used through a JTAG only on ARM. If you don't have + a JTAG then you probably don't want this option. + +config HVC_BFIN_JTAG + bool "Blackfin JTAG console" + depends on BLACKFIN + select HVC_DRIVER + help + This console uses the Blackfin JTAG to create a console under the + the HVC driver. If you don't have JTAG, then you probably don't + want this option. + +config HVCS + tristate "IBM Hypervisor Virtual Console Server support" + depends on PPC_PSERIES && HVC_CONSOLE + help + Partitionable IBM Power5 ppc64 machines allow hosting of + firmware virtual consoles from one Linux partition by + another Linux partition. This driver allows console data + from Linux partitions to be accessed through TTY device + interfaces in the device tree of a Linux partition running + this driver. + + To compile this driver as a module, choose M here: the + module will be called hvcs. Additionally, this module + will depend on arch specific APIs exported from hvcserver.ko + which will also be compiled when this driver is built as a + module. + -- cgit v1.2.3 From a6afd9f3e819de4795fcd356e5bfad446e4323f2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Feb 2011 16:14:56 -0800 Subject: tty: move a number of tty drivers from drivers/char/ to drivers/tty/ As planned by Arnd Bergmann, this moves the following drivers from drivers/char/ to drivers/tty/ as that's where they really belong: amiserial nozomi synclink rocket cyclades moxa mxser isicom bfin_jtag_comm Cc: Arnd Bergmann Cc: Alan Cox Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 172 - drivers/char/Makefile | 11 - drivers/char/amiserial.c | 2178 ----------- drivers/char/bfin_jtag_comm.c | 366 -- drivers/char/cyclades.c | 4200 --------------------- drivers/char/isicom.c | 1736 --------- drivers/char/moxa.c | 2092 ----------- drivers/char/moxa.h | 304 -- drivers/char/mxser.c | 2757 -------------- drivers/char/mxser.h | 150 - drivers/char/nozomi.c | 1993 ---------- drivers/char/rocket.c | 3199 ---------------- drivers/char/rocket.h | 111 - drivers/char/rocket_int.h | 1214 ------ drivers/char/synclink.c | 8119 ----------------------------------------- drivers/char/synclink_gt.c | 5161 -------------------------- drivers/char/synclinkmp.c | 5600 ---------------------------- drivers/tty/Kconfig | 171 + drivers/tty/Makefile | 13 + drivers/tty/amiserial.c | 2178 +++++++++++ drivers/tty/bfin_jtag_comm.c | 366 ++ drivers/tty/cyclades.c | 4200 +++++++++++++++++++++ drivers/tty/isicom.c | 1736 +++++++++ drivers/tty/moxa.c | 2092 +++++++++++ drivers/tty/moxa.h | 304 ++ drivers/tty/mxser.c | 2757 ++++++++++++++ drivers/tty/mxser.h | 150 + drivers/tty/nozomi.c | 1993 ++++++++++ drivers/tty/rocket.c | 3199 ++++++++++++++++ drivers/tty/rocket.h | 111 + drivers/tty/rocket_int.h | 1214 ++++++ drivers/tty/synclink.c | 8119 +++++++++++++++++++++++++++++++++++++++++ drivers/tty/synclink_gt.c | 5161 ++++++++++++++++++++++++++ drivers/tty/synclinkmp.c | 5600 ++++++++++++++++++++++++++++ 34 files changed, 39364 insertions(+), 39363 deletions(-) delete mode 100644 drivers/char/amiserial.c delete mode 100644 drivers/char/bfin_jtag_comm.c delete mode 100644 drivers/char/cyclades.c delete mode 100644 drivers/char/isicom.c delete mode 100644 drivers/char/moxa.c delete mode 100644 drivers/char/moxa.h delete mode 100644 drivers/char/mxser.c delete mode 100644 drivers/char/mxser.h delete mode 100644 drivers/char/nozomi.c delete mode 100644 drivers/char/rocket.c delete mode 100644 drivers/char/rocket.h delete mode 100644 drivers/char/rocket_int.h delete mode 100644 drivers/char/synclink.c delete mode 100644 drivers/char/synclink_gt.c delete mode 100644 drivers/char/synclinkmp.c create mode 100644 drivers/tty/amiserial.c create mode 100644 drivers/tty/bfin_jtag_comm.c create mode 100644 drivers/tty/cyclades.c create mode 100644 drivers/tty/isicom.c create mode 100644 drivers/tty/moxa.c create mode 100644 drivers/tty/moxa.h create mode 100644 drivers/tty/mxser.c create mode 100644 drivers/tty/mxser.h create mode 100644 drivers/tty/nozomi.c create mode 100644 drivers/tty/rocket.c create mode 100644 drivers/tty/rocket.h create mode 100644 drivers/tty/rocket_int.h create mode 100644 drivers/tty/synclink.c create mode 100644 drivers/tty/synclink_gt.c create mode 100644 drivers/tty/synclinkmp.c (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9b9ab867f50e..1adfac6a7b0b 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -15,36 +15,6 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". -config BFIN_JTAG_COMM - tristate "Blackfin JTAG Communication" - depends on BLACKFIN - help - Add support for emulating a TTY device over the Blackfin JTAG. - - To compile this driver as a module, choose M here: the - module will be called bfin_jtag_comm. - -config BFIN_JTAG_COMM_CONSOLE - bool "Console on Blackfin JTAG" - depends on BFIN_JTAG_COMM=y - -config SERIAL_NONSTANDARD - bool "Non-standard serial port support" - depends on HAS_IOMEM - ---help--- - Say Y here if you have any non-standard serial boards -- boards - which aren't supported using the standard "dumb" serial driver. - This includes intelligent serial boards such as Cyclades, - Digiboards, etc. These are usually used for systems that need many - serial ports because they serve many terminals or dial-in - connections. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about non-standard serial boards. - - Most people can say N here. - config COMPUTONE tristate "Computone IntelliPort Plus serial support" depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) @@ -60,50 +30,6 @@ config COMPUTONE To compile this driver as module, choose M here: the module will be called ip2. -config ROCKETPORT - tristate "Comtrol RocketPort support" - depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) - help - This driver supports Comtrol RocketPort and RocketModem PCI boards. - These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or - modems. For information about the RocketPort/RocketModem boards - and this driver read . - - To compile this driver as a module, choose M here: the - module will be called rocket. - - If you want to compile this driver into the kernel, say Y here. If - you don't have a Comtrol RocketPort/RocketModem card installed, say N. - -config CYCLADES - tristate "Cyclades async mux support" - depends on SERIAL_NONSTANDARD && (PCI || ISA) - select FW_LOADER - ---help--- - This driver supports Cyclades Z and Y multiserial boards. - You would need something like this to connect more than two modems to - your Linux box, for instance in order to become a dial-in server. - - For information about the Cyclades-Z card, read - . - - To compile this driver as a module, choose M here: the - module will be called cyclades. - - If you haven't heard about it, it's safe to say N. - -config CYZ_INTR - bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)" - depends on EXPERIMENTAL && CYCLADES - help - The Cyclades-Z family of multiport cards allows 2 (two) driver op - modes: polling and interrupt. In polling mode, the driver will check - the status of the Cyclades-Z ports every certain amount of time - (which is called polling cycle and is configurable). In interrupt - mode, it will use an interrupt line (IRQ) in order to check the - status of the Cyclades-Z ports. The default op mode is polling. If - unsure, say N. - config DIGIEPCA tristate "Digiboard Intelligent Async Support" depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) @@ -119,94 +45,6 @@ config DIGIEPCA To compile this driver as a module, choose M here: the module will be called epca. -config MOXA_INTELLIO - tristate "Moxa Intellio support" - depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) - select FW_LOADER - help - Say Y here if you have a Moxa Intellio multiport serial card. - - To compile this driver as a module, choose M here: the - module will be called moxa. - -config MOXA_SMARTIO - 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 - want to help develop a new version of this driver. - - This is upgraded (1.9.1) driver from original Moxa drivers with - changes finally resulting in PCI probing. - - This driver can also be built as a module. The module will be called - mxser. If you want to do that, say M here. - -config ISI - tristate "Multi-Tech multiport card support (EXPERIMENTAL)" - depends on SERIAL_NONSTANDARD && PCI - select FW_LOADER - help - This is a driver for the Multi-Tech cards which provide several - serial ports. The driver is experimental and can currently only be - built as a module. The module will be called isicom. - If you want to do that, choose M here. - -config SYNCLINK - tristate "Microgate SyncLink card support" - depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API - help - Provides support for the SyncLink ISA and PCI multiprotocol serial - adapters. These adapters support asynchronous and HDLC bit - synchronous communication up to 10Mbps (PCI adapter). - - This driver can only be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called synclink. If you want to do that, say M - here. - -config SYNCLINKMP - tristate "SyncLink Multiport support" - depends on SERIAL_NONSTANDARD && PCI - help - Enable support for the SyncLink Multiport (2 or 4 ports) - serial adapter, running asynchronous and HDLC communications up - to 2.048Mbps. Each ports is independently selectable for - RS-232, V.35, RS-449, RS-530, and X.21 - - This driver may be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called synclinkmp. If you want to do that, say M - here. - -config SYNCLINK_GT - tristate "SyncLink GT/AC support" - depends on SERIAL_NONSTANDARD && PCI - help - Support for SyncLink GT and SyncLink AC families of - synchronous and asynchronous serial adapters - manufactured by Microgate Systems, Ltd. (www.microgate.com) - -config N_HDLC - tristate "HDLC line discipline support" - depends on SERIAL_NONSTANDARD - help - Allows synchronous HDLC communications with tty device drivers that - support synchronous HDLC such as the Microgate SyncLink adapter. - - This driver can be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called n_hdlc. If you want to do that, say M - here. - -config N_GSM - tristate "GSM MUX line discipline support (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on NET - help - This line discipline provides support for the GSM MUX protocol and - presents the mux as a set of 61 individual tty devices. - config RISCOM8 tristate "SDL RISCom/8 card support" depends on SERIAL_NONSTANDARD @@ -296,16 +134,6 @@ config ISTALLION To compile this driver as a module, choose M here: the module will be called istallion. -config NOZOMI - tristate "HSDPA Broadband Wireless Data Card - Globe Trotter" - depends on PCI && EXPERIMENTAL - help - If you have a HSDPA driver Broadband Wireless Data Card - - Globe Trotter PCMCIA card, say Y here. - - To compile this driver as a module, choose M here, the module - will be called nozomi. - config A2232 tristate "Commodore A2232 serial support (EXPERIMENTAL)" depends on EXPERIMENTAL && ZORRO && BROKEN diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 5bc765d4c3ca..f5dc7c9bce6b 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -5,29 +5,18 @@ obj-y += mem.o random.o obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o -obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o -obj-$(CONFIG_ROCKETPORT) += rocket.o obj-$(CONFIG_SERIAL167) += serial167.o -obj-$(CONFIG_CYCLADES) += cyclades.o obj-$(CONFIG_STALLION) += stallion.o obj-$(CONFIG_ISTALLION) += istallion.o -obj-$(CONFIG_NOZOMI) += nozomi.o obj-$(CONFIG_DIGIEPCA) += epca.o obj-$(CONFIG_SPECIALIX) += specialix.o -obj-$(CONFIG_MOXA_INTELLIO) += moxa.o obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o -obj-$(CONFIG_MOXA_SMARTIO) += mxser.o obj-$(CONFIG_COMPUTONE) += ip2/ obj-$(CONFIG_RISCOM8) += riscom8.o -obj-$(CONFIG_ISI) += isicom.o -obj-$(CONFIG_SYNCLINK) += synclink.o -obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o -obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o -obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_RAW_DRIVER) += raw.o diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c deleted file mode 100644 index f214e5022472..000000000000 --- a/drivers/char/amiserial.c +++ /dev/null @@ -1,2178 +0,0 @@ -/* - * linux/drivers/char/amiserial.c - * - * Serial driver for the amiga builtin port. - * - * This code was created by taking serial.c version 4.30 from kernel - * release 2.3.22, replacing all hardware related stuff with the - * corresponding amiga hardware actions, and removing all irrelevant - * code. As a consequence, it uses many of the constants and names - * associated with the registers and bits of 16550 compatible UARTS - - * but only to keep track of status, etc in the state variables. It - * was done this was to make it easier to keep the code in line with - * (non hardware specific) changes to serial.c. - * - * The port is registered with the tty driver as minor device 64, and - * therefore other ports should should only use 65 upwards. - * - * Richard Lucock 28/12/99 - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, - * 1998, 1999 Theodore Ts'o - * - */ - -/* - * Serial driver configuration section. Here are the various options: - * - * SERIAL_PARANOIA_CHECK - * Check the magic number for the async_structure where - * ever possible. - */ - -#include - -#undef SERIAL_PARANOIA_CHECK -#define SERIAL_DO_RESTART - -/* Set of debugging defines */ - -#undef SERIAL_DEBUG_INTR -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW -#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - -/* Sanity checks */ - -#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) -#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ - tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s) -#else -#define DBG_CNT(s) -#endif - -/* - * End of serial driver configuration section. - */ - -#include - -#include -#include -#include -#include -static char *serial_version = "4.30"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include - -#define custom amiga_custom -static char *serial_name = "Amiga-builtin serial driver"; - -static struct tty_driver *serial_driver; - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -static struct async_struct *IRQ_ports; - -static unsigned char current_ctl_bits; - -static void change_speed(struct async_struct *info, struct ktermios *old); -static void rs_wait_until_sent(struct tty_struct *tty, int timeout); - - -static struct serial_state rs_table[1]; - -#define NR_PORTS ARRAY_SIZE(rs_table) - -#include - -#define serial_isroot() (capable(CAP_SYS_ADMIN)) - - -static inline int serial_paranoia_check(struct async_struct *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 async_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* some serial hardware definitions */ -#define SDR_OVRUN (1<<15) -#define SDR_RBF (1<<14) -#define SDR_TBE (1<<13) -#define SDR_TSRE (1<<12) - -#define SERPER_PARENB (1<<15) - -#define AC_SETCLR (1<<15) -#define AC_UARTBRK (1<<11) - -#define SER_DTR (1<<7) -#define SER_RTS (1<<6) -#define SER_DCD (1<<5) -#define SER_CTS (1<<4) -#define SER_DSR (1<<3) - -static __inline__ void rtsdtr_ctrl(int bits) -{ - ciab.pra = ((bits & (SER_RTS | SER_DTR)) ^ (SER_RTS | SER_DTR)) | (ciab.pra & ~(SER_RTS | SER_DTR)); -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - - local_irq_save(flags); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; - /* disable Tx interrupt and remove any pending interrupts */ - custom.intena = IF_TBE; - mb(); - custom.intreq = IF_TBE; - mb(); - } - local_irq_restore(flags); -} - -static void rs_start(struct tty_struct *tty) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - - local_irq_save(flags); - if (info->xmit.head != info->xmit.tail - && info->xmit.buf - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - custom.intena = IF_SETCLR | IF_TBE; - mb(); - /* set a pending Tx Interrupt, transmitter should restart now */ - custom.intreq = IF_SETCLR | IF_TBE; - mb(); - } - local_irq_restore(flags); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_interrupt(). They were separated out for readability's sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static void rs_sched_event(struct async_struct *info, - int event) -{ - info->event |= 1 << event; - tasklet_schedule(&info->tlet); -} - -static void receive_chars(struct async_struct *info) -{ - int status; - int serdatr; - struct tty_struct *tty = info->tty; - unsigned char ch, flag; - struct async_icount *icount; - int oe = 0; - - icount = &info->state->icount; - - status = UART_LSR_DR; /* We obviously have a character! */ - serdatr = custom.serdatr; - mb(); - custom.intreq = IF_RBF; - mb(); - - if((serdatr & 0x1ff) == 0) - status |= UART_LSR_BI; - if(serdatr & SDR_OVRUN) - status |= UART_LSR_OE; - - ch = serdatr & 0xff; - icount->rx++; - -#ifdef SERIAL_DEBUG_INTR - printk("DR%02x:%02x...", ch, status); -#endif - flag = TTY_NORMAL; - - /* - * We don't handle parity or frame errors - but I have left - * the code in, since I'm not sure that the errors can't be - * detected. - */ - - if (status & (UART_LSR_BI | UART_LSR_PE | - UART_LSR_FE | UART_LSR_OE)) { - /* - * For statistics only - */ - if (status & UART_LSR_BI) { - status &= ~(UART_LSR_FE | UART_LSR_PE); - icount->brk++; - } else if (status & UART_LSR_PE) - icount->parity++; - else if (status & UART_LSR_FE) - icount->frame++; - if (status & UART_LSR_OE) - icount->overrun++; - - /* - * Now check to see if character should be - * ignored, and mask off conditions which - * should be ignored. - */ - if (status & info->ignore_status_mask) - goto out; - - status &= info->read_status_mask; - - if (status & (UART_LSR_BI)) { -#ifdef SERIAL_DEBUG_INTR - printk("handling break...."); -#endif - flag = TTY_BREAK; - if (info->flags & ASYNC_SAK) - do_SAK(tty); - } else if (status & UART_LSR_PE) - flag = TTY_PARITY; - else if (status & UART_LSR_FE) - flag = TTY_FRAME; - if (status & UART_LSR_OE) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - oe = 1; - } - } - tty_insert_flip_char(tty, ch, flag); - if (oe == 1) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - tty_flip_buffer_push(tty); -out: - return; -} - -static void transmit_chars(struct async_struct *info) -{ - custom.intreq = IF_TBE; - mb(); - if (info->x_char) { - custom.serdat = info->x_char | 0x100; - mb(); - info->state->icount.tx++; - info->x_char = 0; - return; - } - if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { - info->IER &= ~UART_IER_THRI; - custom.intena = IF_TBE; - mb(); - return; - } - - custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100; - mb(); - info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1); - info->state->icount.tx++; - - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - -#ifdef SERIAL_DEBUG_INTR - printk("THRE..."); -#endif - if (info->xmit.head == info->xmit.tail) { - custom.intena = IF_TBE; - mb(); - info->IER &= ~UART_IER_THRI; - } -} - -static void check_modem_status(struct async_struct *info) -{ - unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); - unsigned char dstatus; - struct async_icount *icount; - - /* Determine bits that have changed */ - dstatus = status ^ current_ctl_bits; - current_ctl_bits = status; - - if (dstatus) { - icount = &info->state->icount; - /* update input line counters */ - if (dstatus & SER_DSR) - icount->dsr++; - if (dstatus & SER_DCD) { - icount->dcd++; -#ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && - !(status & SER_DCD)) - hardpps(); -#endif - } - if (dstatus & SER_CTS) - icount->cts++; - wake_up_interruptible(&info->delta_msr_wait); - } - - if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { -#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttyS%d CD now %s...", info->line, - (!(status & SER_DCD)) ? "on" : "off"); -#endif - if (!(status & SER_DCD)) - wake_up_interruptible(&info->open_wait); - else { -#ifdef SERIAL_DEBUG_OPEN - printk("doing serial hangup..."); -#endif - if (info->tty) - tty_hangup(info->tty); - } - } - if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { - if (!(status & SER_CTS)) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx start..."); -#endif - info->tty->hw_stopped = 0; - info->IER |= UART_IER_THRI; - custom.intena = IF_SETCLR | IF_TBE; - mb(); - /* set a pending Tx Interrupt, transmitter should restart now */ - custom.intreq = IF_SETCLR | IF_TBE; - mb(); - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - return; - } - } else { - if ((status & SER_CTS)) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx stop..."); -#endif - info->tty->hw_stopped = 1; - info->IER &= ~UART_IER_THRI; - /* disable Tx interrupt and remove any pending interrupts */ - custom.intena = IF_TBE; - mb(); - custom.intreq = IF_TBE; - mb(); - } - } - } -} - -static irqreturn_t ser_vbl_int( int irq, void *data) -{ - /* vbl is just a periodic interrupt we tie into to update modem status */ - struct async_struct * info = IRQ_ports; - /* - * TBD - is it better to unregister from this interrupt or to - * ignore it if MSI is clear ? - */ - if(info->IER & UART_IER_MSI) - check_modem_status(info); - return IRQ_HANDLED; -} - -static irqreturn_t ser_rx_int(int irq, void *dev_id) -{ - struct async_struct * info; - -#ifdef SERIAL_DEBUG_INTR - printk("ser_rx_int..."); -#endif - - info = IRQ_ports; - if (!info || !info->tty) - return IRQ_NONE; - - receive_chars(info); - info->last_active = jiffies; -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif - return IRQ_HANDLED; -} - -static irqreturn_t ser_tx_int(int irq, void *dev_id) -{ - struct async_struct * info; - - if (custom.serdatr & SDR_TBE) { -#ifdef SERIAL_DEBUG_INTR - printk("ser_tx_int..."); -#endif - - info = IRQ_ports; - if (!info || !info->tty) - return IRQ_NONE; - - transmit_chars(info); - info->last_active = jiffies; -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif - } - return IRQ_HANDLED; -} - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ - -static void do_softint(unsigned long private_) -{ - struct async_struct *info = (struct async_struct *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) - tty_wakeup(tty); -} - -/* - * --------------------------------------------------------------- - * Low level utility subroutines for the serial driver: routines to - * figure out the appropriate timeout for an interrupt chain, routines - * to initialize and startup a serial port, and routines to shutdown a - * serial port. Useful stuff like that. - * --------------------------------------------------------------- - */ - -static int startup(struct async_struct * info) -{ - unsigned long flags; - int retval=0; - unsigned long page; - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - local_irq_save(flags); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - - if (info->xmit.buf) - free_page(page); - else - info->xmit.buf = (unsigned char *) page; - -#ifdef SERIAL_DEBUG_OPEN - printk("starting up ttys%d ...", info->line); -#endif - - /* Clear anything in the input buffer */ - - custom.intreq = IF_RBF; - mb(); - - retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info); - if (retval) { - if (serial_isroot()) { - if (info->tty) - set_bit(TTY_IO_ERROR, - &info->tty->flags); - retval = 0; - } - goto errout; - } - - /* enable both Rx and Tx interrupts */ - custom.intena = IF_SETCLR | IF_RBF | IF_TBE; - mb(); - info->IER = UART_IER_MSI; - - /* remember current state of the DCD and CTS bits */ - current_ctl_bits = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); - - IRQ_ports = info; - - info->MCR = 0; - if (info->tty->termios->c_cflag & CBAUD) - info->MCR = SER_DTR | SER_RTS; - rtsdtr_ctrl(info->MCR); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit.head = info->xmit.tail = 0; - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - /* - * and set the speed of the serial port - */ - change_speed(info, NULL); - - info->flags |= ASYNC_INITIALIZED; - local_irq_restore(flags); - return 0; - -errout: - local_irq_restore(flags); - return retval; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct async_struct * info) -{ - unsigned long flags; - struct serial_state *state; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - state = info->state; - -#ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial port %d ....\n", info->line); -#endif - - local_irq_save(flags); /* Disable interrupts */ - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be waken up - */ - wake_up_interruptible(&info->delta_msr_wait); - - IRQ_ports = NULL; - - /* - * Free the IRQ, if necessary - */ - free_irq(IRQ_AMIGA_VERTB, info); - - if (info->xmit.buf) { - free_page((unsigned long) info->xmit.buf); - info->xmit.buf = NULL; - } - - info->IER = 0; - custom.intena = IF_RBF | IF_TBE; - mb(); - - /* disable break condition */ - custom.adkcon = AC_UARTBRK; - mb(); - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->MCR &= ~(SER_DTR|SER_RTS); - rtsdtr_ctrl(info->MCR); - - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - local_irq_restore(flags); -} - - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void change_speed(struct async_struct *info, - struct ktermios *old_termios) -{ - int quot = 0, baud_base, baud; - unsigned cflag, cval = 0; - int bits; - unsigned long flags; - - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - - /* Byte size is always 8 bits plus parity bit if requested */ - - cval = 3; bits = 10; - if (cflag & CSTOPB) { - cval |= 0x04; - bits++; - } - if (cflag & PARENB) { - cval |= UART_LCR_PARITY; - bits++; - } - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; -#ifdef CMSPAR - if (cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; /* B0 transition handled in rs_set_termios */ - baud_base = info->state->baud_base; - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - /* If the quotient is zero refuse the change */ - if (!quot && old_termios) { - /* FIXME: Will need updating for new tty in the end */ - info->tty->termios->c_cflag &= ~CBAUD; - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - } - /* As a last resort, if the quotient is zero, default to 9600 bps */ - if (!quot) - quot = baud_base / 9600; - info->quot = quot; - info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - /* CTS flow control flag and modem status interrupts */ - info->IER &= ~UART_IER_MSI; - if (info->flags & ASYNC_HARDPPS_CD) - info->IER |= UART_IER_MSI; - if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; - info->IER |= UART_IER_MSI; - } else - info->flags &= ~ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else { - info->flags |= ASYNC_CHECK_CD; - info->IER |= UART_IER_MSI; - } - /* TBD: - * Does clearing IER_MSI imply that we should disable the VBL interrupt ? - */ - - /* - * Set up parity check flag - */ - - info->read_status_mask = UART_LSR_OE | UART_LSR_DR; - if (I_INPCK(info->tty)) - info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= UART_LSR_BI; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= UART_LSR_BI; - /* - * If we're ignore parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= UART_LSR_OE; - } - /* - * !!! ignore all characters if CREAD is not set - */ - if ((cflag & CREAD) == 0) - info->ignore_status_mask |= UART_LSR_DR; - local_irq_save(flags); - - { - short serper; - - /* Set up the baud rate */ - serper = quot - 1; - - /* Enable or disable parity bit */ - - if(cval & UART_LCR_PARITY) - serper |= (SERPER_PARENB); - - custom.serper = serper; - mb(); - } - - info->LCR = cval; /* Save LCR */ - local_irq_restore(flags); -} - -static int rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct async_struct *info; - unsigned long flags; - - info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_put_char")) - return 0; - - if (!info->xmit.buf) - return 0; - - local_irq_save(flags); - if (CIRC_SPACE(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) == 0) { - local_irq_restore(flags); - return 0; - } - - info->xmit.buf[info->xmit.head++] = ch; - info->xmit.head &= SERIAL_XMIT_SIZE-1; - local_irq_restore(flags); - return 1; -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; - - if (info->xmit.head == info->xmit.tail - || tty->stopped - || tty->hw_stopped - || !info->xmit.buf) - return; - - local_irq_save(flags); - info->IER |= UART_IER_THRI; - custom.intena = IF_SETCLR | IF_TBE; - mb(); - /* set a pending Tx Interrupt, transmitter should restart now */ - custom.intreq = IF_SETCLR | IF_TBE; - mb(); - local_irq_restore(flags); -} - -static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) -{ - int c, ret = 0; - struct async_struct *info; - unsigned long flags; - - info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - - if (!info->xmit.buf) - return 0; - - local_irq_save(flags); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; - } - local_irq_restore(flags); - - if (info->xmit.head != info->xmit.tail - && !tty->stopped - && !tty->hw_stopped - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - local_irq_disable(); - custom.intena = IF_SETCLR | IF_TBE; - mb(); - /* set a pending Tx Interrupt, transmitter should restart now */ - custom.intreq = IF_SETCLR | IF_TBE; - mb(); - local_irq_restore(flags); - } - return ret; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct async_struct *info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct async_struct *info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; - local_irq_save(flags); - info->xmit.head = info->xmit.tail = 0; - local_irq_restore(flags); - tty_wakeup(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void rs_send_xchar(struct tty_struct *tty, char ch) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_send_char")) - return; - - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - - /* Check this ! */ - local_irq_save(flags); - if(!(custom.intenar & IF_TBE)) { - custom.intena = IF_SETCLR | IF_TBE; - mb(); - /* set a pending Tx Interrupt, transmitter should restart now */ - custom.intreq = IF_SETCLR | IF_TBE; - mb(); - } - local_irq_restore(flags); - - info->IER |= UART_IER_THRI; - } -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct * tty) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) - info->MCR &= ~SER_RTS; - - local_irq_save(flags); - rtsdtr_ctrl(info->MCR); - local_irq_restore(flags); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("unthrottle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - if (tty->termios->c_cflag & CRTSCTS) - info->MCR |= SER_RTS; - local_irq_save(flags); - rtsdtr_ctrl(info->MCR); - local_irq_restore(flags); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct async_struct * info, - struct serial_struct __user * retinfo) -{ - struct serial_struct tmp; - struct serial_state *state = info->state; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tty_lock(); - tmp.type = state->type; - tmp.line = state->line; - tmp.port = state->port; - tmp.irq = state->irq; - tmp.flags = state->flags; - tmp.xmit_fifo_size = state->xmit_fifo_size; - tmp.baud_base = state->baud_base; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; - tty_unlock(); - if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct async_struct * info, - struct serial_struct __user * new_info) -{ - struct serial_struct new_serial; - struct serial_state old_state, *state; - unsigned int change_irq,change_port; - int retval = 0; - - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - - tty_lock(); - state = info->state; - old_state = *state; - - change_irq = new_serial.irq != state->irq; - change_port = (new_serial.port != state->port); - if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { - tty_unlock(); - return -EINVAL; - } - - if (!serial_isroot()) { - if ((new_serial.baud_base != state->baud_base) || - (new_serial.close_delay != state->close_delay) || - (new_serial.xmit_fifo_size != state->xmit_fifo_size) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) - return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - if (new_serial.baud_base < 9600) { - tty_unlock(); - return -EINVAL; - } - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - state->baud_base = new_serial.baud_base; - state->flags = ((state->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | - (info->flags & ASYNC_INTERNAL_FLAGS)); - state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ/100; - state->closing_wait = new_serial.closing_wait * HZ/100; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - -check_and_exit: - if (info->flags & ASYNC_INITIALIZED) { - if (((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK)) || - (old_state.custom_divisor != state->custom_divisor)) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - change_speed(info, NULL); - } - } else - retval = startup(info); - tty_unlock(); - return retval; -} - - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct async_struct * info, unsigned int __user *value) -{ - unsigned char status; - unsigned int result; - unsigned long flags; - - local_irq_save(flags); - status = custom.serdatr; - mb(); - local_irq_restore(flags); - result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0); - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - - -static int rs_tiocmget(struct tty_struct *tty) -{ - struct async_struct * info = tty->driver_data; - unsigned char control, status; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - control = info->MCR; - local_irq_save(flags); - status = ciab.pra; - local_irq_restore(flags); - return ((control & SER_RTS) ? TIOCM_RTS : 0) - | ((control & SER_DTR) ? TIOCM_DTR : 0) - | (!(status & SER_DCD) ? TIOCM_CAR : 0) - | (!(status & SER_DSR) ? TIOCM_DSR : 0) - | (!(status & SER_CTS) ? TIOCM_CTS : 0); -} - -static int rs_tiocmset(struct tty_struct *tty, unsigned int set, - unsigned int clear) -{ - struct async_struct * info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - local_irq_save(flags); - if (set & TIOCM_RTS) - info->MCR |= SER_RTS; - if (set & TIOCM_DTR) - info->MCR |= SER_DTR; - if (clear & TIOCM_RTS) - info->MCR &= ~SER_RTS; - if (clear & TIOCM_DTR) - info->MCR &= ~SER_DTR; - rtsdtr_ctrl(info->MCR); - local_irq_restore(flags); - return 0; -} - -/* - * rs_break() --- routine which turns the break handling on or off - */ -static int rs_break(struct tty_struct *tty, int break_state) -{ - struct async_struct * info = tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_break")) - return -EINVAL; - - local_irq_save(flags); - if (break_state == -1) - custom.adkcon = AC_SETCLR | AC_UARTBRK; - else - custom.adkcon = AC_UARTBRK; - mb(); - local_irq_restore(flags); - return 0; -} - -/* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ -static int rs_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct async_struct *info = tty->driver_data; - struct async_icount cnow; - unsigned long flags; - - local_irq_save(flags); - cnow = info->state->icount; - local_irq_restore(flags); - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - -static int rs_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct async_struct * info = tty->driver_data; - struct async_icount cprev, cnow; /* kernel counter temps */ - void __user *argp = (void __user *)arg; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCGSERIAL: - return get_serial_info(info, argp); - case TIOCSSERIAL: - return set_serial_info(info, argp); - case TIOCSERCONFIG: - return 0; - - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, argp); - - case TIOCSERGSTRUCT: - if (copy_to_user(argp, - info, sizeof(struct async_struct))) - return -EFAULT; - return 0; - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - local_irq_save(flags); - /* note the counters on entry */ - cprev = info->state->icount; - local_irq_restore(flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - local_irq_save(flags); - cnow = info->state->icount; /* atomic copy */ - local_irq_restore(flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct async_struct *info = tty->driver_data; - unsigned long flags; - unsigned int cflag = tty->termios->c_cflag; - - change_speed(info, old_termios); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { - info->MCR &= ~(SER_DTR|SER_RTS); - local_irq_save(flags); - rtsdtr_ctrl(info->MCR); - local_irq_restore(flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { - info->MCR |= SER_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->MCR |= SER_RTS; - } - local_irq_save(flags); - rtsdtr_ctrl(info->MCR); - local_irq_restore(flags); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rs_start(tty); - } - -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); -#endif -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file * filp) -{ - struct async_struct * info = tty->driver_data; - struct serial_state *state; - unsigned long flags; - - if (!info || serial_paranoia_check(info, tty->name, "rs_close")) - return; - - state = info->state; - - local_irq_save(flags); - - if (tty_hung_up_p(filp)) { - DBG_CNT("before DEC-hung"); - local_irq_restore(flags); - return; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", info->line, state->count); -#endif - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->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("rs_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", - info->line, state->count); - state->count = 0; - } - if (state->count) { - DBG_CNT("before DEC-2"); - local_irq_restore(flags); - return; - } - info->flags |= ASYNC_CLOSING; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - info->read_status_mask &= ~UART_LSR_DR; - if (info->flags & ASYNC_INITIALIZED) { - /* disable receive interrupts */ - custom.intena = IF_RBF; - mb(); - /* clear any pending receive interrupt */ - custom.intreq = IF_RBF; - mb(); - - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - rs_wait_until_sent(tty, info->timeout); - } - shutdown(info); - rs_flush_buffer(tty); - - tty_ldisc_flush(tty); - tty->closing = 0; - 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); - local_irq_restore(flags); -} - -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct async_struct * info = tty->driver_data; - unsigned long orig_jiffies, char_time; - int tty_was_locked = tty_locked(); - int lsr; - - if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - orig_jiffies = jiffies; - - /* - * tty_wait_until_sent is called from lots of places, - * with or without the BTM. - */ - if (!tty_was_locked) - tty_lock(); - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout) - char_time = min_t(unsigned long, char_time, timeout); - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2*info->timeout) - timeout = 2*info->timeout; -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); -#endif - while(!((lsr = custom.serdatr) & SDR_TSRE)) { -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("serdatr = %d (jiff=%lu)...", lsr, jiffies); -#endif - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - __set_current_state(TASK_RUNNING); - if (!tty_was_locked) - tty_unlock(); -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); -#endif -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void rs_hangup(struct tty_struct *tty) -{ - struct async_struct * info = tty->driver_data; - struct serial_state *state = info->state; - - if (serial_paranoia_check(info, tty->name, "rs_hangup")) - return; - - state = info->state; - - rs_flush_buffer(tty); - shutdown(info); - info->event = 0; - state->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = NULL; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct async_struct *info) -{ -#ifdef DECLARE_WAITQUEUE - DECLARE_WAITQUEUE(wait, current); -#else - struct wait_queue wait = { current, NULL }; -#endif - struct serial_state *state = info->state; - int retval; - int do_clocal = 0, extra_count = 0; - unsigned long flags; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - - /* - * 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, state->count is dropped by one, so that - * rs_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: ttys%d, count = %d\n", - state->line, state->count); -#endif - local_irq_save(flags); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - state->count--; - } - local_irq_restore(flags); - info->blocked_open++; - while (1) { - local_irq_save(flags); - if (tty->termios->c_cflag & CBAUD) - rtsdtr_ctrl(SER_DTR|SER_RTS); - local_irq_restore(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ASYNC_CLOSING) && - (do_clocal || (!(ciab.pra & SER_DCD)) )) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - tty_unlock(); - schedule(); - tty_lock(); - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - if (extra_count) - state->count++; - info->blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - if (sstate->info) { - *ret_info = sstate->info; - return 0; - } - info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } -#ifdef DECLARE_WAITQUEUE - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); -#endif - info->magic = SERIAL_MAGIC; - info->port = sstate->port; - info->flags = sstate->flags; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->line = line; - tasklet_init(&info->tlet, do_softint, (unsigned long)info); - info->state = sstate; - if (sstate->info) { - kfree(info); - *ret_info = sstate->info; - return 0; - } - *ret_info = sstate->info = info; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int rs_open(struct tty_struct *tty, struct file * filp) -{ - struct async_struct *info; - int retval, line; - - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) { - return -ENODEV; - } - retval = get_async_struct(line, &info); - if (retval) { - return retval; - } - tty->driver_data = info; - info->tty = tty; - if (serial_paranoia_check(info, tty->name, "rs_open")) - return -ENODEV; - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s, count = %d\n", tty->name, info->state->count); -#endif - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) { - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open returning after block_til_ready with %d\n", - retval); -#endif - return retval; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s successful...", tty->name); -#endif - return 0; -} - -/* - * /proc fs routines.... - */ - -static inline void line_info(struct seq_file *m, struct serial_state *state) -{ - struct async_struct *info = state->info, scr_info; - char stat_buf[30], control, status; - unsigned long flags; - - seq_printf(m, "%d: uart:amiga_builtin",state->line); - - /* - * Figure out the current RS-232 lines - */ - if (!info) { - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->flags = state->flags; - info->quot = 0; - info->tty = NULL; - } - local_irq_save(flags); - status = ciab.pra; - control = info ? info->MCR : status; - local_irq_restore(flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if(!(control & SER_RTS)) - strcat(stat_buf, "|RTS"); - if(!(status & SER_CTS)) - strcat(stat_buf, "|CTS"); - if(!(control & SER_DTR)) - strcat(stat_buf, "|DTR"); - if(!(status & SER_DSR)) - strcat(stat_buf, "|DSR"); - if(!(status & SER_DCD)) - strcat(stat_buf, "|CD"); - - if (info->quot) { - seq_printf(m, " baud:%d", state->baud_base / info->quot); - } - - seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx); - - if (state->icount.frame) - seq_printf(m, " fe:%d", state->icount.frame); - - if (state->icount.parity) - seq_printf(m, " pe:%d", state->icount.parity); - - if (state->icount.brk) - seq_printf(m, " brk:%d", state->icount.brk); - - if (state->icount.overrun) - seq_printf(m, " oe:%d", state->icount.overrun); - - /* - * Last thing is the RS-232 status lines - */ - seq_printf(m, " %s\n", stat_buf+1); -} - -static int rs_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); - line_info(m, &rs_table[0]); - return 0; -} - -static int rs_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, rs_proc_show, NULL); -} - -static const struct file_operations rs_proc_fops = { - .owner = THIS_MODULE, - .open = rs_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * --------------------------------------------------------------------- - * rs_init() and friends - * - * rs_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static void show_serial_version(void) -{ - printk(KERN_INFO "%s version %s\n", serial_name, serial_version); -} - - -static const struct tty_operations serial_ops = { - .open = rs_open, - .close = rs_close, - .write = rs_write, - .put_char = rs_put_char, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = rs_hangup, - .break_ctl = rs_break, - .send_xchar = rs_send_xchar, - .wait_until_sent = rs_wait_until_sent, - .tiocmget = rs_tiocmget, - .tiocmset = rs_tiocmset, - .get_icount = rs_get_icount, - .proc_fops = &rs_proc_fops, -}; - -/* - * The serial driver boot-time initialization code! - */ -static int __init amiga_serial_probe(struct platform_device *pdev) -{ - unsigned long flags; - struct serial_state * state; - int error; - - serial_driver = alloc_tty_driver(1); - if (!serial_driver) - return -ENOMEM; - - IRQ_ports = NULL; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - - serial_driver->owner = THIS_MODULE; - serial_driver->driver_name = "amiserial"; - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &serial_ops); - - error = tty_register_driver(serial_driver); - if (error) - goto fail_put_tty_driver; - - state = rs_table; - state->magic = SSTATE_MAGIC; - state->port = (int)&custom.serdatr; /* Just to give it a value */ - state->line = 0; - state->custom_divisor = 0; - state->close_delay = 5*HZ/10; - state->closing_wait = 30*HZ; - state->icount.cts = state->icount.dsr = - state->icount.rng = state->icount.dcd = 0; - state->icount.rx = state->icount.tx = 0; - state->icount.frame = state->icount.parity = 0; - state->icount.overrun = state->icount.brk = 0; - - printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", - state->line); - - /* Hardware set up */ - - state->baud_base = amiga_colorclock; - state->xmit_fifo_size = 1; - - /* set ISRs, and then disable the rx interrupts */ - error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state); - if (error) - goto fail_unregister; - - error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, - "serial RX", state); - if (error) - goto fail_free_irq; - - local_irq_save(flags); - - /* turn off Rx and Tx interrupts */ - custom.intena = IF_RBF | IF_TBE; - mb(); - - /* clear any pending interrupt */ - custom.intreq = IF_RBF | IF_TBE; - mb(); - - local_irq_restore(flags); - - /* - * set the appropriate directions for the modem control flags, - * and clear RTS and DTR - */ - ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ - ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ - - platform_set_drvdata(pdev, state); - - return 0; - -fail_free_irq: - free_irq(IRQ_AMIGA_TBE, state); -fail_unregister: - tty_unregister_driver(serial_driver); -fail_put_tty_driver: - put_tty_driver(serial_driver); - return error; -} - -static int __exit amiga_serial_remove(struct platform_device *pdev) -{ - int error; - struct serial_state *state = platform_get_drvdata(pdev); - struct async_struct *info = state->info; - - /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - tasklet_kill(&info->tlet); - if ((error = tty_unregister_driver(serial_driver))) - printk("SERIAL: failed to unregister serial driver (%d)\n", - error); - put_tty_driver(serial_driver); - - rs_table[0].info = NULL; - kfree(info); - - free_irq(IRQ_AMIGA_TBE, rs_table); - free_irq(IRQ_AMIGA_RBF, rs_table); - - platform_set_drvdata(pdev, NULL); - - return error; -} - -static struct platform_driver amiga_serial_driver = { - .remove = __exit_p(amiga_serial_remove), - .driver = { - .name = "amiga-serial", - .owner = THIS_MODULE, - }, -}; - -static int __init amiga_serial_init(void) -{ - return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe); -} - -module_init(amiga_serial_init); - -static void __exit amiga_serial_exit(void) -{ - platform_driver_unregister(&amiga_serial_driver); -} - -module_exit(amiga_serial_exit); - - -#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) - -/* - * ------------------------------------------------------------ - * Serial console driver - * ------------------------------------------------------------ - */ - -static void amiga_serial_putc(char c) -{ - custom.serdat = (unsigned char)c | 0x100; - while (!(custom.serdatr & 0x2000)) - barrier(); -} - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console must be locked when we get here. - */ -static void serial_console_write(struct console *co, const char *s, - unsigned count) -{ - unsigned short intena = custom.intenar; - - custom.intena = IF_TBE; - - while (count--) { - if (*s == '\n') - amiga_serial_putc('\r'); - amiga_serial_putc(*s++); - } - - custom.intena = IF_SETCLR | (intena & IF_TBE); -} - -static struct tty_driver *serial_console_device(struct console *c, int *index) -{ - *index = 0; - return serial_driver; -} - -static struct console sercons = { - .name = "ttyS", - .write = serial_console_write, - .device = serial_console_device, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * Register console. - */ -static int __init amiserial_console_init(void) -{ - register_console(&sercons); - return 0; -} -console_initcall(amiserial_console_init); - -#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:amiga-serial"); diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c deleted file mode 100644 index 16402445f2b2..000000000000 --- a/drivers/char/bfin_jtag_comm.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * TTY over Blackfin JTAG Communication - * - * Copyright 2008-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#define DRV_NAME "bfin-jtag-comm" -#define DEV_NAME "ttyBFJC" -#define pr_fmt(fmt) DRV_NAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) - -/* See the Debug/Emulation chapter in the HRM */ -#define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ -#define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ -#define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ -#define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ - -static inline uint32_t bfin_write_emudat(uint32_t emudat) -{ - __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); - return emudat; -} - -static inline uint32_t bfin_read_emudat(void) -{ - uint32_t emudat; - __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); - return emudat; -} - -static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d) -{ - return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24)); -} - -#define CIRC_SIZE 2048 /* see comment in tty_io.c:do_tty_write() */ -#define CIRC_MASK (CIRC_SIZE - 1) -#define circ_empty(circ) ((circ)->head == (circ)->tail) -#define circ_free(circ) CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE) -#define circ_cnt(circ) CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE) -#define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK]) - -static struct tty_driver *bfin_jc_driver; -static struct task_struct *bfin_jc_kthread; -static struct tty_struct * volatile bfin_jc_tty; -static unsigned long bfin_jc_count; -static DEFINE_MUTEX(bfin_jc_tty_mutex); -static volatile struct circ_buf bfin_jc_write_buf; - -static int -bfin_jc_emudat_manager(void *arg) -{ - uint32_t inbound_len = 0, outbound_len = 0; - - while (!kthread_should_stop()) { - /* no one left to give data to, so sleep */ - if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) { - pr_debug("waiting for readers\n"); - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule(); - __set_current_state(TASK_RUNNING); - } - - /* no data available, so just chill */ - if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) { - pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n", - inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head); - if (inbound_len) - schedule(); - else - schedule_timeout_interruptible(HZ); - continue; - } - - /* if incoming data is ready, eat it */ - if (bfin_read_DBGSTAT() & EMUDIF) { - struct tty_struct *tty; - mutex_lock(&bfin_jc_tty_mutex); - tty = (struct tty_struct *)bfin_jc_tty; - if (tty != NULL) { - uint32_t emudat = bfin_read_emudat(); - if (inbound_len == 0) { - pr_debug("incoming length: 0x%08x\n", emudat); - inbound_len = emudat; - } else { - size_t num_chars = (4 <= inbound_len ? 4 : inbound_len); - pr_debug(" incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars); - inbound_len -= num_chars; - tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars); - tty_flip_buffer_push(tty); - } - } - mutex_unlock(&bfin_jc_tty_mutex); - } - - /* if outgoing data is ready, post it */ - if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) { - if (outbound_len == 0) { - outbound_len = circ_cnt(&bfin_jc_write_buf); - bfin_write_emudat(outbound_len); - pr_debug("outgoing length: 0x%08x\n", outbound_len); - } else { - struct tty_struct *tty; - int tail = bfin_jc_write_buf.tail; - size_t ate = (4 <= outbound_len ? 4 : outbound_len); - uint32_t emudat = - bfin_write_emudat_chars( - circ_byte(&bfin_jc_write_buf, tail + 0), - circ_byte(&bfin_jc_write_buf, tail + 1), - circ_byte(&bfin_jc_write_buf, tail + 2), - circ_byte(&bfin_jc_write_buf, tail + 3) - ); - bfin_jc_write_buf.tail += ate; - outbound_len -= ate; - mutex_lock(&bfin_jc_tty_mutex); - tty = (struct tty_struct *)bfin_jc_tty; - if (tty) - tty_wakeup(tty); - mutex_unlock(&bfin_jc_tty_mutex); - pr_debug(" outgoing data: 0x%08x (pushing %zu)\n", emudat, ate); - } - } - } - - __set_current_state(TASK_RUNNING); - return 0; -} - -static int -bfin_jc_open(struct tty_struct *tty, struct file *filp) -{ - mutex_lock(&bfin_jc_tty_mutex); - pr_debug("open %lu\n", bfin_jc_count); - ++bfin_jc_count; - bfin_jc_tty = tty; - wake_up_process(bfin_jc_kthread); - mutex_unlock(&bfin_jc_tty_mutex); - return 0; -} - -static void -bfin_jc_close(struct tty_struct *tty, struct file *filp) -{ - mutex_lock(&bfin_jc_tty_mutex); - pr_debug("close %lu\n", bfin_jc_count); - if (--bfin_jc_count == 0) - bfin_jc_tty = NULL; - wake_up_process(bfin_jc_kthread); - mutex_unlock(&bfin_jc_tty_mutex); -} - -/* XXX: we dont handle the put_char() case where we must handle count = 1 */ -static int -bfin_jc_circ_write(const unsigned char *buf, int count) -{ - int i; - count = min(count, circ_free(&bfin_jc_write_buf)); - pr_debug("going to write chunk of %i bytes\n", count); - for (i = 0; i < count; ++i) - circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i]; - bfin_jc_write_buf.head += i; - return i; -} - -#ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE -# define console_lock() -# define console_unlock() -#endif -static int -bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - int i; - console_lock(); - i = bfin_jc_circ_write(buf, count); - console_unlock(); - wake_up_process(bfin_jc_kthread); - return i; -} - -static void -bfin_jc_flush_chars(struct tty_struct *tty) -{ - wake_up_process(bfin_jc_kthread); -} - -static int -bfin_jc_write_room(struct tty_struct *tty) -{ - return circ_free(&bfin_jc_write_buf); -} - -static int -bfin_jc_chars_in_buffer(struct tty_struct *tty) -{ - return circ_cnt(&bfin_jc_write_buf); -} - -static void -bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) -{ - unsigned long expire = jiffies + timeout; - while (!circ_empty(&bfin_jc_write_buf)) { - if (signal_pending(current)) - break; - if (time_after(jiffies, expire)) - break; - } -} - -static const struct tty_operations bfin_jc_ops = { - .open = bfin_jc_open, - .close = bfin_jc_close, - .write = bfin_jc_write, - /*.put_char = bfin_jc_put_char,*/ - .flush_chars = bfin_jc_flush_chars, - .write_room = bfin_jc_write_room, - .chars_in_buffer = bfin_jc_chars_in_buffer, - .wait_until_sent = bfin_jc_wait_until_sent, -}; - -static int __init bfin_jc_init(void) -{ - int ret; - - bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME); - if (IS_ERR(bfin_jc_kthread)) - return PTR_ERR(bfin_jc_kthread); - - ret = -ENOMEM; - - bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0; - bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL); - if (!bfin_jc_write_buf.buf) - goto err; - - bfin_jc_driver = alloc_tty_driver(1); - if (!bfin_jc_driver) - goto err; - - bfin_jc_driver->owner = THIS_MODULE; - bfin_jc_driver->driver_name = DRV_NAME; - bfin_jc_driver->name = DEV_NAME; - bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; - bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL; - bfin_jc_driver->init_termios = tty_std_termios; - tty_set_operations(bfin_jc_driver, &bfin_jc_ops); - - ret = tty_register_driver(bfin_jc_driver); - if (ret) - goto err; - - pr_init(KERN_INFO DRV_NAME ": initialized\n"); - - return 0; - - err: - put_tty_driver(bfin_jc_driver); - kfree(bfin_jc_write_buf.buf); - kthread_stop(bfin_jc_kthread); - return ret; -} -module_init(bfin_jc_init); - -static void __exit bfin_jc_exit(void) -{ - kthread_stop(bfin_jc_kthread); - kfree(bfin_jc_write_buf.buf); - tty_unregister_driver(bfin_jc_driver); - put_tty_driver(bfin_jc_driver); -} -module_exit(bfin_jc_exit); - -#if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK) -static void -bfin_jc_straight_buffer_write(const char *buf, unsigned count) -{ - unsigned ate = 0; - while (bfin_read_DBGSTAT() & EMUDOF) - continue; - bfin_write_emudat(count); - while (ate < count) { - while (bfin_read_DBGSTAT() & EMUDOF) - continue; - bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]); - ate += 4; - } -} -#endif - -#ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE -static void -bfin_jc_console_write(struct console *co, const char *buf, unsigned count) -{ - if (bfin_jc_kthread == NULL) - bfin_jc_straight_buffer_write(buf, count); - else - bfin_jc_circ_write(buf, count); -} - -static struct tty_driver * -bfin_jc_console_device(struct console *co, int *index) -{ - *index = co->index; - return bfin_jc_driver; -} - -static struct console bfin_jc_console = { - .name = DEV_NAME, - .write = bfin_jc_console_write, - .device = bfin_jc_console_device, - .flags = CON_ANYTIME | CON_PRINTBUFFER, - .index = -1, -}; - -static int __init bfin_jc_console_init(void) -{ - register_console(&bfin_jc_console); - return 0; -} -console_initcall(bfin_jc_console_init); -#endif - -#ifdef CONFIG_EARLY_PRINTK -static void __init -bfin_jc_early_write(struct console *co, const char *buf, unsigned int count) -{ - bfin_jc_straight_buffer_write(buf, count); -} - -static struct __initdata console bfin_jc_early_console = { - .name = "early_BFJC", - .write = bfin_jc_early_write, - .flags = CON_ANYTIME | CON_PRINTBUFFER, - .index = -1, -}; - -struct console * __init -bfin_jc_early_init(unsigned int port, unsigned int cflag) -{ - return &bfin_jc_early_console; -} -#endif - -MODULE_AUTHOR("Mike Frysinger "); -MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication"); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c deleted file mode 100644 index c99728f0cd9f..000000000000 --- a/drivers/char/cyclades.c +++ /dev/null @@ -1,4200 +0,0 @@ -#undef BLOCKMOVE -#define Z_WAKE -#undef Z_EXT_CHARS_IN_BUFFER - -/* - * linux/drivers/char/cyclades.c - * - * This file contains the driver for the Cyclades async multiport - * serial boards. - * - * Initially written by Randolph Bentson . - * Modified and maintained by Marcio Saito . - * - * Copyright (C) 2007-2009 Jiri Slaby - * - * Much of the design and some of the code came from serial.c - * which was copyright (C) 1991, 1992 Linus Torvalds. It was - * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, - * and then fixed as suggested by Michael K. Johnson 12/12/92. - * Converted to pci probing and cleaned up by Jiri Slaby. - * - */ - -#define CY_VERSION "2.6" - -/* If you need to install more boards than NR_CARDS, change the constant - in the definition below. No other change is necessary to support up to - eight boards. Beyond that you'll have to extend cy_isa_addresses. */ - -#define NR_CARDS 4 - -/* - If the total number of ports is larger than NR_PORTS, change this - constant in the definition below. No other change is necessary to - support more boards/ports. */ - -#define NR_PORTS 256 - -#define ZO_V1 0 -#define ZO_V2 1 -#define ZE_V1 2 - -#define SERIAL_PARANOIA_CHECK -#undef CY_DEBUG_OPEN -#undef CY_DEBUG_THROTTLE -#undef CY_DEBUG_OTHER -#undef CY_DEBUG_IO -#undef CY_DEBUG_COUNT -#undef CY_DEBUG_DTR -#undef CY_DEBUG_WAIT_UNTIL_SENT -#undef CY_DEBUG_INTERRUPTS -#undef CY_16Y_HACK -#undef CY_ENABLE_MONITORING -#undef CY_PCI_DEBUG - -/* - * Include section - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -static void cy_send_xchar(struct tty_struct *tty, char ch); - -#ifndef SERIAL_XMIT_SIZE -#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) -#endif - -#define STD_COM_FLAGS (0) - -/* firmware stuff */ -#define ZL_MAX_BLOCKS 16 -#define DRIVER_VERSION 0x02010203 -#define RAM_SIZE 0x80000 - -enum zblock_type { - ZBLOCK_PRG = 0, - ZBLOCK_FPGA = 1 -}; - -struct zfile_header { - char name[64]; - char date[32]; - char aux[32]; - u32 n_config; - u32 config_offset; - u32 n_blocks; - u32 block_offset; - u32 reserved[9]; -} __attribute__ ((packed)); - -struct zfile_config { - char name[64]; - u32 mailbox; - u32 function; - u32 n_blocks; - u32 block_list[ZL_MAX_BLOCKS]; -} __attribute__ ((packed)); - -struct zfile_block { - u32 type; - u32 file_offset; - u32 ram_offset; - u32 size; -} __attribute__ ((packed)); - -static struct tty_driver *cy_serial_driver; - -#ifdef CONFIG_ISA -/* This is the address lookup table. The driver will probe for - Cyclom-Y/ISA boards at all addresses in here. If you want the - driver to probe addresses at a different address, add it to - this table. If the driver is probing some other board and - causing problems, remove the offending address from this table. -*/ - -static unsigned int cy_isa_addresses[] = { - 0xD0000, - 0xD2000, - 0xD4000, - 0xD6000, - 0xD8000, - 0xDA000, - 0xDC000, - 0xDE000, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) - -static long maddr[NR_CARDS]; -static int irq[NR_CARDS]; - -module_param_array(maddr, long, NULL, 0); -module_param_array(irq, int, NULL, 0); - -#endif /* CONFIG_ISA */ - -/* This is the per-card data structure containing address, irq, number of - channels, etc. This driver supports a maximum of NR_CARDS cards. -*/ -static struct cyclades_card cy_card[NR_CARDS]; - -static int cy_next_channel; /* next minor available */ - -/* - * This is used to look up the divisor speeds and the timeouts - * We're normally limited to 15 distinct baud rates. The extra - * are accessed via settings in info->port.flags. - * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - * HI VHI - * 20 - */ -static const int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, - 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, - 230400, 0 -}; - -static const char baud_co_25[] = { /* 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 const char baud_bpr_25[] = { /* 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 const char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 -}; - -static const char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ - 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, - 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, - 0x21 -}; - -static const char baud_cor3[] = { /* receive threshold */ - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, - 0x07 -}; - -/* - * The Cyclades driver implements HW flow control as any serial driver. - * The cyclades_port structure member rflow and the vector rflow_thr - * allows us to take advantage of a special feature in the CD1400 to avoid - * data loss even when the system interrupt latency is too high. These flags - * are to be used only with very special applications. Setting these flags - * requires the use of a special cable (DTR and RTS reversed). In the new - * CD1400-based boards (rev. 6.00 or later), there is no need for special - * cables. - */ - -static const char rflow_thr[] = { /* rflow threshold */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a -}; - -/* The Cyclom-Ye has placed the sequential chips in non-sequential - * address order. This look-up table overcomes that problem. - */ -static const unsigned int cy_chip_offset[] = { 0x0000, - 0x0400, - 0x0800, - 0x0C00, - 0x0200, - 0x0600, - 0x0A00, - 0x0E00 -}; - -/* PCI related definitions */ - -#ifdef CONFIG_PCI -static const struct pci_device_id cy_pci_dev_id[] = { - /* PCI < 1Mb */ - { 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) }, - /* 4Y 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) }, - /* 8Y 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) }, - /* Z 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) }, - { } /* end of table */ -}; -MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); -#endif - -static void cy_start(struct tty_struct *); -static void cy_set_line_char(struct cyclades_port *, struct tty_struct *); -static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); -#ifdef CONFIG_ISA -static unsigned detect_isa_irq(void __iomem *); -#endif /* CONFIG_ISA */ - -#ifndef CONFIG_CYZ_INTR -static void cyz_poll(unsigned long); - -/* The Cyclades-Z polling cycle is defined by this variable */ -static long cyz_polling_cycle = CZ_DEF_POLL; - -static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); - -#else /* CONFIG_CYZ_INTR */ -static void cyz_rx_restart(unsigned long); -static struct timer_list cyz_rx_full_timer[NR_PORTS]; -#endif /* CONFIG_CYZ_INTR */ - -static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val) -{ - struct cyclades_card *card = port->card; - - cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val); -} - -static inline u8 cyy_readb(struct cyclades_port *port, u32 reg) -{ - struct cyclades_card *card = port->card; - - return readb(port->u.cyy.base_addr + (reg << card->bus_index)); -} - -static inline bool cy_is_Z(struct cyclades_card *card) -{ - return card->num_chips == (unsigned int)-1; -} - -static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr) -{ - return readl(&ctl_addr->init_ctrl) & (1 << 17); -} - -static inline bool cyz_fpga_loaded(struct cyclades_card *card) -{ - return __cyz_fpga_loaded(card->ctl_addr.p9060); -} - -static inline bool cyz_is_loaded(struct cyclades_card *card) -{ - struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS; - - return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) && - readl(&fw_id->signature) == ZFIRM_ID; -} - -static inline int serial_paranoia_check(struct cyclades_port *info, - const char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - if (!info) { - printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) " - "in %s\n", name, routine); - return 1; - } - - if (info->magic != CYCLADES_MAGIC) { - printk(KERN_WARNING "cyc Warning: bad magic number for serial " - "struct (%s) in %s\n", name, routine); - return 1; - } -#endif - return 0; -} - -/***********************************************************/ -/********* Start of block of Cyclom-Y specific code ********/ - -/* This routine waits up to 1000 micro-seconds for the previous - command to the Cirrus chip to complete and then issues the - new command. An error is returned if the previous command - didn't finish within the time limit. - - This function is only called from inside spinlock-protected code. - */ -static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index) -{ - void __iomem *ccr = base_addr + (CyCCR << index); - unsigned int i; - - /* Check to see that the previous command has completed */ - for (i = 0; i < 100; i++) { - if (readb(ccr) == 0) - break; - udelay(10L); - } - /* if the CCR never cleared, the previous command - didn't finish within the "reasonable time" */ - if (i == 100) - return -1; - - /* Issue the new command */ - cy_writeb(ccr, cmd); - - return 0; -} - -static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd) -{ - return __cyy_issue_cmd(port->u.cyy.base_addr, cmd, - port->card->bus_index); -} - -#ifdef CONFIG_ISA -/* ISA interrupt detection code */ -static unsigned detect_isa_irq(void __iomem *address) -{ - int irq; - unsigned long irqs, flags; - int save_xir, save_car; - int index = 0; /* IRQ probing is only for ISA */ - - /* forget possible initially masked and pending IRQ */ - irq = probe_irq_off(probe_irq_on()); - - /* Clear interrupts on the board first */ - cy_writeb(address + (Cy_ClrIntr << index), 0); - /* Cy_ClrIntr is 0x1800 */ - - irqs = probe_irq_on(); - /* Wait ... */ - msleep(5); - - /* Enable the Tx interrupts on the CD1400 */ - local_irq_save(flags); - cy_writeb(address + (CyCAR << index), 0); - __cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index); - - cy_writeb(address + (CyCAR << index), 0); - cy_writeb(address + (CySRER << index), - readb(address + (CySRER << index)) | CyTxRdy); - local_irq_restore(flags); - - /* Wait ... */ - msleep(5); - - /* Check which interrupt is in use */ - irq = probe_irq_off(irqs); - - /* Clean up */ - save_xir = (u_char) readb(address + (CyTIR << index)); - save_car = readb(address + (CyCAR << index)); - cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); - cy_writeb(address + (CySRER << index), - readb(address + (CySRER << index)) & ~CyTxRdy); - cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); - cy_writeb(address + (CyCAR << index), (save_car)); - cy_writeb(address + (Cy_ClrIntr << index), 0); - /* Cy_ClrIntr is 0x1800 */ - - return (irq > 0) ? irq : 0; -} -#endif /* CONFIG_ISA */ - -static void cyy_chip_rx(struct cyclades_card *cinfo, int chip, - void __iomem *base_addr) -{ - struct cyclades_port *info; - struct tty_struct *tty; - int len, index = cinfo->bus_index; - u8 ivr, save_xir, channel, save_car, data, char_count; - -#ifdef CY_DEBUG_INTERRUPTS - printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip); -#endif - /* determine the channel & change to that context */ - save_xir = readb(base_addr + (CyRIR << index)); - channel = save_xir & CyIRChannel; - info = &cinfo->ports[channel + chip * 4]; - save_car = cyy_readb(info, CyCAR); - cyy_writeb(info, CyCAR, save_xir); - ivr = cyy_readb(info, CyRIVR) & CyIVRMask; - - tty = tty_port_tty_get(&info->port); - /* if there is nowhere to put the data, discard it */ - if (tty == NULL) { - if (ivr == CyIVRRxEx) { /* exception */ - data = cyy_readb(info, CyRDSR); - } else { /* normal character reception */ - char_count = cyy_readb(info, CyRDCR); - while (char_count--) - data = cyy_readb(info, CyRDSR); - } - goto end; - } - /* there is an open port for this data */ - if (ivr == CyIVRRxEx) { /* exception */ - data = cyy_readb(info, CyRDSR); - - /* For statistics only */ - if (data & CyBREAK) - info->icount.brk++; - else if (data & CyFRAME) - info->icount.frame++; - else if (data & CyPARITY) - info->icount.parity++; - else if (data & CyOVERRUN) - info->icount.overrun++; - - if (data & info->ignore_status_mask) { - info->icount.rx++; - tty_kref_put(tty); - return; - } - if (tty_buffer_request_room(tty, 1)) { - if (data & info->read_status_mask) { - if (data & CyBREAK) { - tty_insert_flip_char(tty, - cyy_readb(info, CyRDSR), - TTY_BREAK); - info->icount.rx++; - if (info->port.flags & ASYNC_SAK) - do_SAK(tty); - } else if (data & CyFRAME) { - tty_insert_flip_char(tty, - cyy_readb(info, CyRDSR), - TTY_FRAME); - info->icount.rx++; - info->idle_stats.frame_errs++; - } else if (data & CyPARITY) { - /* Pieces of seven... */ - tty_insert_flip_char(tty, - cyy_readb(info, CyRDSR), - TTY_PARITY); - info->icount.rx++; - info->idle_stats.parity_errs++; - } else if (data & CyOVERRUN) { - tty_insert_flip_char(tty, 0, - TTY_OVERRUN); - info->icount.rx++; - /* If the flip buffer itself is - overflowing, we still lose - the next incoming character. - */ - tty_insert_flip_char(tty, - cyy_readb(info, CyRDSR), - TTY_FRAME); - info->icount.rx++; - info->idle_stats.overruns++; - /* 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); - info->icount.rx++; - } - } else { - tty_insert_flip_char(tty, 0, TTY_NORMAL); - info->icount.rx++; - } - } else { - /* there was a software buffer overrun and nothing - * could be done about it!!! */ - info->icount.buf_overrun++; - info->idle_stats.overruns++; - } - } else { /* normal character reception */ - /* load # chars available from the chip */ - char_count = cyy_readb(info, CyRDCR); - -#ifdef CY_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 = cyy_readb(info, CyRDSR); - tty_insert_flip_char(tty, data, TTY_NORMAL); - info->idle_stats.recv_bytes++; - info->icount.rx++; -#ifdef CY_16Y_HACK - udelay(10L); -#endif - } - info->idle_stats.recv_idle = jiffies; - } - tty_schedule_flip(tty); - tty_kref_put(tty); -end: - /* end of service */ - cyy_writeb(info, CyRIR, save_xir & 0x3f); - cyy_writeb(info, CyCAR, save_car); -} - -static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, - void __iomem *base_addr) -{ - struct cyclades_port *info; - struct tty_struct *tty; - int char_count, index = cinfo->bus_index; - u8 save_xir, channel, save_car, outch; - - /* Since we only get here when the transmit buffer - is empty, we know we can always stuff a dozen - characters. */ -#ifdef CY_DEBUG_INTERRUPTS - printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip); -#endif - - /* determine the channel & change to that context */ - save_xir = readb(base_addr + (CyTIR << index)); - channel = save_xir & CyIRChannel; - save_car = readb(base_addr + (CyCAR << index)); - cy_writeb(base_addr + (CyCAR << index), save_xir); - - info = &cinfo->ports[channel + chip * 4]; - tty = tty_port_tty_get(&info->port); - if (tty == NULL) { - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); - goto end; - } - - /* load the on-chip space for outbound data */ - char_count = info->xmit_fifo_size; - - if (info->x_char) { /* send special char */ - outch = info->x_char; - cyy_writeb(info, CyTDR, outch); - char_count--; - info->icount.tx++; - info->x_char = 0; - } - - if (info->breakon || info->breakoff) { - if (info->breakon) { - cyy_writeb(info, CyTDR, 0); - cyy_writeb(info, CyTDR, 0x81); - info->breakon = 0; - char_count -= 2; - } - if (info->breakoff) { - cyy_writeb(info, CyTDR, 0); - cyy_writeb(info, CyTDR, 0x83); - info->breakoff = 0; - char_count -= 2; - } - } - - while (char_count-- > 0) { - if (!info->xmit_cnt) { - if (cyy_readb(info, CySRER) & CyTxMpty) { - cyy_writeb(info, CySRER, - cyy_readb(info, CySRER) & ~CyTxMpty); - } else { - cyy_writeb(info, CySRER, CyTxMpty | - (cyy_readb(info, CySRER) & ~CyTxRdy)); - } - goto done; - } - if (info->port.xmit_buf == NULL) { - cyy_writeb(info, CySRER, - cyy_readb(info, CySRER) & ~CyTxRdy); - goto done; - } - if (tty->stopped || tty->hw_stopped) { - cyy_writeb(info, CySRER, - cyy_readb(info, CySRER) & ~CyTxRdy); - goto done; - } - /* 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->port.xmit_buf[info->xmit_tail]; - if (outch) { - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) & - (SERIAL_XMIT_SIZE - 1); - cyy_writeb(info, CyTDR, outch); - info->icount.tx++; - } else { - if (char_count > 1) { - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) & - (SERIAL_XMIT_SIZE - 1); - cyy_writeb(info, CyTDR, outch); - cyy_writeb(info, CyTDR, 0); - info->icount.tx++; - char_count--; - } - } - } - -done: - tty_wakeup(tty); - tty_kref_put(tty); -end: - /* end of service */ - cyy_writeb(info, CyTIR, save_xir & 0x3f); - cyy_writeb(info, CyCAR, save_car); -} - -static void cyy_chip_modem(struct cyclades_card *cinfo, int chip, - void __iomem *base_addr) -{ - struct cyclades_port *info; - struct tty_struct *tty; - int index = cinfo->bus_index; - u8 save_xir, channel, save_car, mdm_change, mdm_status; - - /* determine the channel & change to that context */ - save_xir = readb(base_addr + (CyMIR << index)); - channel = save_xir & CyIRChannel; - info = &cinfo->ports[channel + chip * 4]; - save_car = cyy_readb(info, CyCAR); - cyy_writeb(info, CyCAR, save_xir); - - mdm_change = cyy_readb(info, CyMISR); - mdm_status = cyy_readb(info, CyMSVR1); - - tty = tty_port_tty_get(&info->port); - if (!tty) - goto end; - - if (mdm_change & CyANY_DELTA) { - /* For statistics only */ - if (mdm_change & CyDCD) - info->icount.dcd++; - if (mdm_change & CyCTS) - info->icount.cts++; - if (mdm_change & CyDSR) - info->icount.dsr++; - if (mdm_change & CyRI) - info->icount.rng++; - - wake_up_interruptible(&info->port.delta_msr_wait); - } - - if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) { - if (mdm_status & CyDCD) - wake_up_interruptible(&info->port.open_wait); - else - tty_hangup(tty); - } - if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) { - if (tty->hw_stopped) { - if (mdm_status & CyCTS) { - /* cy_start isn't used - because... !!! */ - tty->hw_stopped = 0; - cyy_writeb(info, CySRER, - cyy_readb(info, CySRER) | CyTxRdy); - tty_wakeup(tty); - } - } else { - if (!(mdm_status & CyCTS)) { - /* cy_stop isn't used - because ... !!! */ - tty->hw_stopped = 1; - cyy_writeb(info, CySRER, - cyy_readb(info, CySRER) & ~CyTxRdy); - } - } - } -/* if (mdm_change & CyDSR) { - } - if (mdm_change & CyRI) { - }*/ - tty_kref_put(tty); -end: - /* end of service */ - cyy_writeb(info, CyMIR, save_xir & 0x3f); - cyy_writeb(info, CyCAR, save_car); -} - -/* The real interrupt service routine is called - whenever the card wants its hand held--chars - received, out buffer empty, modem change, etc. - */ -static irqreturn_t cyy_interrupt(int irq, void *dev_id) -{ - int status; - struct cyclades_card *cinfo = dev_id; - void __iomem *base_addr, *card_base_addr; - unsigned int chip, too_many, had_work; - int index; - - if (unlikely(cinfo == NULL)) { -#ifdef CY_DEBUG_INTERRUPTS - printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n", - irq); -#endif - return IRQ_NONE; /* spurious interrupt */ - } - - card_base_addr = cinfo->base_addr; - index = cinfo->bus_index; - - /* card was not initialized yet (e.g. DEBUG_SHIRQ) */ - if (unlikely(card_base_addr == NULL)) - return IRQ_HANDLED; - - /* This loop checks all chips in the card. Make a note whenever - _any_ chip had some work to do, as this is considered an - indication that there will be more to do. Only when no chip - has any work does this outermost loop exit. - */ - do { - had_work = 0; - for (chip = 0; chip < cinfo->num_chips; chip++) { - base_addr = cinfo->base_addr + - (cy_chip_offset[chip] << index); - too_many = 0; - while ((status = readb(base_addr + - (CySVRR << index))) != 0x00) { - had_work++; - /* The purpose of the following test is to ensure that - no chip can monopolize the driver. This forces the - chips to be checked in a round-robin fashion (after - draining each of a bunch (1000) of characters). - */ - if (1000 < too_many++) - break; - spin_lock(&cinfo->card_lock); - if (status & CySRReceive) /* rx intr */ - cyy_chip_rx(cinfo, chip, base_addr); - if (status & CySRTransmit) /* tx intr */ - cyy_chip_tx(cinfo, chip, base_addr); - if (status & CySRModem) /* modem intr */ - cyy_chip_modem(cinfo, chip, base_addr); - spin_unlock(&cinfo->card_lock); - } - } - } while (had_work); - - /* clear interrupts */ - spin_lock(&cinfo->card_lock); - cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0); - /* Cy_ClrIntr is 0x1800 */ - spin_unlock(&cinfo->card_lock); - return IRQ_HANDLED; -} /* cyy_interrupt */ - -static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set, - unsigned int clear) -{ - struct cyclades_card *card = info->card; - int channel = info->line - card->first_line; - u32 rts, dtr, msvrr, msvrd; - - channel &= 0x03; - - if (info->rtsdtr_inv) { - msvrr = CyMSVR2; - msvrd = CyMSVR1; - rts = CyDTR; - dtr = CyRTS; - } else { - msvrr = CyMSVR1; - msvrd = CyMSVR2; - rts = CyRTS; - dtr = CyDTR; - } - if (set & TIOCM_RTS) { - cyy_writeb(info, CyCAR, channel); - cyy_writeb(info, msvrr, rts); - } - if (clear & TIOCM_RTS) { - cyy_writeb(info, CyCAR, channel); - cyy_writeb(info, msvrr, ~rts); - } - if (set & TIOCM_DTR) { - cyy_writeb(info, CyCAR, channel); - cyy_writeb(info, msvrd, dtr); -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); - printk(KERN_DEBUG " status: 0x%x, 0x%x\n", - cyy_readb(info, CyMSVR1), - cyy_readb(info, CyMSVR2)); -#endif - } - if (clear & TIOCM_DTR) { - cyy_writeb(info, CyCAR, channel); - cyy_writeb(info, msvrd, ~dtr); -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); - printk(KERN_DEBUG " status: 0x%x, 0x%x\n", - cyy_readb(info, CyMSVR1), - cyy_readb(info, CyMSVR2)); -#endif - } -} - -/***********************************************************/ -/********* End of block of Cyclom-Y specific code **********/ -/******** Start of block of Cyclades-Z specific code *******/ -/***********************************************************/ - -static int -cyz_fetch_msg(struct cyclades_card *cinfo, - __u32 *channel, __u8 *cmd, __u32 *param) -{ - struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; - unsigned long loc_doorbell; - - loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); - if (loc_doorbell) { - *cmd = (char)(0xff & loc_doorbell); - *channel = readl(&board_ctrl->fwcmd_channel); - *param = (__u32) readl(&board_ctrl->fwcmd_param); - cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff); - return 1; - } - return 0; -} /* cyz_fetch_msg */ - -static int -cyz_issue_cmd(struct cyclades_card *cinfo, - __u32 channel, __u8 cmd, __u32 param) -{ - struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; - __u32 __iomem *pci_doorbell; - unsigned int index; - - if (!cyz_is_loaded(cinfo)) - return -1; - - index = 0; - pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell; - while ((readl(pci_doorbell) & 0xff) != 0) { - if (index++ == 1000) - return (int)(readl(pci_doorbell) & 0xff); - udelay(50L); - } - cy_writel(&board_ctrl->hcmd_channel, channel); - cy_writel(&board_ctrl->hcmd_param, param); - cy_writel(pci_doorbell, (long)cmd); - - return 0; -} /* cyz_issue_cmd */ - -static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty) -{ - struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; - struct cyclades_card *cinfo = info->card; - unsigned int char_count; - int len; -#ifdef BLOCKMOVE - unsigned char *buf; -#else - char data; -#endif - __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; - - rx_get = new_rx_get = readl(&buf_ctrl->rx_get); - rx_put = readl(&buf_ctrl->rx_put); - rx_bufsize = readl(&buf_ctrl->rx_bufsize); - rx_bufaddr = readl(&buf_ctrl->rx_bufaddr); - if (rx_put >= rx_get) - char_count = rx_put - rx_get; - else - char_count = rx_put - rx_get + rx_bufsize; - - if (char_count) { -#ifdef CY_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 - if (tty == NULL) { - /* flush received characters */ - new_rx_get = (new_rx_get + char_count) & - (rx_bufsize - 1); - info->rflush_count++; - } else { -#ifdef BLOCKMOVE - /* we'd like to use memcpy(t, f, n) and memset(s, c, count) - for performance, but because of buffer boundaries, there - may be several steps to the operation */ - while (1) { - len = tty_prepare_flip_string(tty, &buf, - char_count); - if (!len) - break; - - len = min_t(unsigned int, min(len, char_count), - rx_bufsize - new_rx_get); - - memcpy_fromio(buf, cinfo->base_addr + - rx_bufaddr + new_rx_get, len); - - new_rx_get = (new_rx_get + len) & - (rx_bufsize - 1); - char_count -= len; - info->icount.rx += len; - info->idle_stats.recv_bytes += len; - } -#else - len = tty_buffer_request_room(tty, char_count); - while (len--) { - data = readb(cinfo->base_addr + rx_bufaddr + - new_rx_get); - new_rx_get = (new_rx_get + 1) & - (rx_bufsize - 1); - tty_insert_flip_char(tty, data, TTY_NORMAL); - info->idle_stats.recv_bytes++; - info->icount.rx++; - } -#endif -#ifdef CONFIG_CYZ_INTR - /* Recalculate the number of chars in the RX buffer and issue - a cmd in case it's higher than the RX high water mark */ - rx_put = readl(&buf_ctrl->rx_put); - if (rx_put >= rx_get) - char_count = rx_put - rx_get; - else - char_count = rx_put - rx_get + rx_bufsize; - if (char_count >= readl(&buf_ctrl->rx_threshold) && - !timer_pending(&cyz_rx_full_timer[ - info->line])) - mod_timer(&cyz_rx_full_timer[info->line], - jiffies + 1); -#endif - info->idle_stats.recv_idle = jiffies; - tty_schedule_flip(tty); - } - /* Update rx_get */ - cy_writel(&buf_ctrl->rx_get, new_rx_get); - } -} - -static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty) -{ - struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; - struct cyclades_card *cinfo = info->card; - u8 data; - unsigned int char_count; -#ifdef BLOCKMOVE - int small_count; -#endif - __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr; - - if (info->xmit_cnt <= 0) /* Nothing to transmit */ - return; - - tx_get = readl(&buf_ctrl->tx_get); - tx_put = readl(&buf_ctrl->tx_put); - tx_bufsize = readl(&buf_ctrl->tx_bufsize); - tx_bufaddr = readl(&buf_ctrl->tx_bufaddr); - if (tx_put >= tx_get) - char_count = tx_get - tx_put - 1 + tx_bufsize; - else - char_count = tx_get - tx_put - 1; - - if (char_count) { - - if (tty == NULL) - goto ztxdone; - - if (info->x_char) { /* send special char */ - data = info->x_char; - - cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); - tx_put = (tx_put + 1) & (tx_bufsize - 1); - info->x_char = 0; - char_count--; - info->icount.tx++; - } -#ifdef BLOCKMOVE - while (0 < (small_count = min_t(unsigned int, - tx_bufsize - tx_put, min_t(unsigned int, - (SERIAL_XMIT_SIZE - info->xmit_tail), - min_t(unsigned int, info->xmit_cnt, - char_count))))) { - - memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + - tx_put), - &info->port.xmit_buf[info->xmit_tail], - small_count); - - tx_put = (tx_put + small_count) & (tx_bufsize - 1); - char_count -= small_count; - info->icount.tx += small_count; - info->xmit_cnt -= small_count; - info->xmit_tail = (info->xmit_tail + small_count) & - (SERIAL_XMIT_SIZE - 1); - } -#else - while (info->xmit_cnt && char_count) { - data = info->port.xmit_buf[info->xmit_tail]; - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) & - (SERIAL_XMIT_SIZE - 1); - - cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); - tx_put = (tx_put + 1) & (tx_bufsize - 1); - char_count--; - info->icount.tx++; - } -#endif - tty_wakeup(tty); -ztxdone: - /* Update tx_put */ - cy_writel(&buf_ctrl->tx_put, tx_put); - } -} - -static void cyz_handle_cmd(struct cyclades_card *cinfo) -{ - struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; - struct tty_struct *tty; - struct cyclades_port *info; - __u32 channel, param, fw_ver; - __u8 cmd; - int special_count; - int delta_count; - - fw_ver = readl(&board_ctrl->fw_version); - - while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { - special_count = 0; - delta_count = 0; - info = &cinfo->ports[channel]; - tty = tty_port_tty_get(&info->port); - if (tty == NULL) - continue; - - switch (cmd) { - case C_CM_PR_ERROR: - tty_insert_flip_char(tty, 0, TTY_PARITY); - info->icount.rx++; - special_count++; - break; - case C_CM_FR_ERROR: - tty_insert_flip_char(tty, 0, TTY_FRAME); - info->icount.rx++; - special_count++; - break; - case C_CM_RXBRK: - tty_insert_flip_char(tty, 0, TTY_BREAK); - info->icount.rx++; - special_count++; - break; - case C_CM_MDCD: - info->icount.dcd++; - delta_count++; - if (info->port.flags & ASYNC_CHECK_CD) { - u32 dcd = fw_ver > 241 ? param : - readl(&info->u.cyz.ch_ctrl->rs_status); - if (dcd & C_RS_DCD) - wake_up_interruptible(&info->port.open_wait); - else - tty_hangup(tty); - } - break; - case C_CM_MCTS: - info->icount.cts++; - delta_count++; - break; - case C_CM_MRI: - info->icount.rng++; - delta_count++; - break; - case C_CM_MDSR: - info->icount.dsr++; - delta_count++; - break; -#ifdef Z_WAKE - case C_CM_IOCTLW: - complete(&info->shutdown_wait); - break; -#endif -#ifdef CONFIG_CYZ_INTR - case C_CM_RXHIWM: - case C_CM_RXNNDT: - case C_CM_INTBACK2: - /* Reception Interrupt */ -#ifdef CY_DEBUG_INTERRUPTS - printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " - "port %ld\n", info->card, channel); -#endif - cyz_handle_rx(info, tty); - break; - case C_CM_TXBEMPTY: - case C_CM_TXLOWWM: - case C_CM_INTBACK: - /* Transmission Interrupt */ -#ifdef CY_DEBUG_INTERRUPTS - printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " - "port %ld\n", info->card, channel); -#endif - cyz_handle_tx(info, tty); - break; -#endif /* CONFIG_CYZ_INTR */ - case C_CM_FATAL: - /* should do something with this !!! */ - break; - default: - break; - } - if (delta_count) - wake_up_interruptible(&info->port.delta_msr_wait); - if (special_count) - tty_schedule_flip(tty); - tty_kref_put(tty); - } -} - -#ifdef CONFIG_CYZ_INTR -static irqreturn_t cyz_interrupt(int irq, void *dev_id) -{ - struct cyclades_card *cinfo = dev_id; - - if (unlikely(!cyz_is_loaded(cinfo))) { -#ifdef CY_DEBUG_INTERRUPTS - printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " - "(IRQ%d).\n", irq); -#endif - return IRQ_NONE; - } - - /* Handle the interrupts */ - cyz_handle_cmd(cinfo); - - return IRQ_HANDLED; -} /* cyz_interrupt */ - -static void cyz_rx_restart(unsigned long arg) -{ - struct cyclades_port *info = (struct cyclades_port *)arg; - struct cyclades_card *card = info->card; - int retval; - __u32 channel = info->line - card->first_line; - unsigned long flags; - - spin_lock_irqsave(&card->card_lock, flags); - retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n", - info->line, retval); - } - spin_unlock_irqrestore(&card->card_lock, flags); -} - -#else /* CONFIG_CYZ_INTR */ - -static void cyz_poll(unsigned long arg) -{ - struct cyclades_card *cinfo; - struct cyclades_port *info; - unsigned long expires = jiffies + HZ; - unsigned int port, card; - - for (card = 0; card < NR_CARDS; card++) { - cinfo = &cy_card[card]; - - if (!cy_is_Z(cinfo)) - continue; - if (!cyz_is_loaded(cinfo)) - continue; - - /* Skip first polling cycle to avoid racing conditions with the FW */ - if (!cinfo->intr_enabled) { - cinfo->intr_enabled = 1; - continue; - } - - cyz_handle_cmd(cinfo); - - for (port = 0; port < cinfo->nports; port++) { - struct tty_struct *tty; - - info = &cinfo->ports[port]; - tty = tty_port_tty_get(&info->port); - /* OK to pass NULL to the handle functions below. - They need to drop the data in that case. */ - - if (!info->throttle) - cyz_handle_rx(info, tty); - cyz_handle_tx(info, tty); - tty_kref_put(tty); - } - /* poll every 'cyz_polling_cycle' period */ - expires = jiffies + cyz_polling_cycle; - } - mod_timer(&cyz_timerlist, expires); -} /* cyz_poll */ - -#endif /* CONFIG_CYZ_INTR */ - -/********** End of block of Cyclades-Z specific code *********/ -/***********************************************************/ - -/* This is called whenever a port becomes active; - interrupts are enabled and DTR & RTS are turned on. - */ -static int cy_startup(struct cyclades_port *info, struct tty_struct *tty) -{ - struct cyclades_card *card; - unsigned long flags; - int retval = 0; - int channel; - unsigned long page; - - card = info->card; - channel = info->line - card->first_line; - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - spin_lock_irqsave(&card->card_lock, flags); - - if (info->port.flags & ASYNC_INITIALIZED) - goto errout; - - if (!info->type) { - set_bit(TTY_IO_ERROR, &tty->flags); - goto errout; - } - - if (info->port.xmit_buf) - free_page(page); - else - info->port.xmit_buf = (unsigned char *)page; - - spin_unlock_irqrestore(&card->card_lock, flags); - - cy_set_line_char(info, tty); - - if (!cy_is_Z(card)) { - channel &= 0x03; - - spin_lock_irqsave(&card->card_lock, flags); - - cyy_writeb(info, CyCAR, channel); - - cyy_writeb(info, CyRTPR, - (info->default_timeout ? info->default_timeout : 0x02)); - /* 10ms rx timeout */ - - cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR); - - cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0); - - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData); - } else { - struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; - - if (!cyz_is_loaded(card)) - return -ENODEV; - -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " - "base_addr %p\n", card, channel, card->base_addr); -#endif - spin_lock_irqsave(&card->card_lock, flags); - - cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE); -#ifdef Z_WAKE -#ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl->intr_enable, - C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | - C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); -#else - cy_writel(&ch_ctrl->intr_enable, - C_IN_IOCTLW | C_IN_MDCD); -#endif /* CONFIG_CYZ_INTR */ -#else -#ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl->intr_enable, - C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | - C_IN_RXNNDT | C_IN_MDCD); -#else - cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD); -#endif /* CONFIG_CYZ_INTR */ -#endif /* Z_WAKE */ - - retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was " - "%x\n", info->line, retval); - } - - /* Flush RX buffers before raising DTR and RTS */ - retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was " - "%x\n", info->line, retval); - } - - /* set timeout !!! */ - /* set RTS and DTR !!! */ - tty_port_raise_dtr_rts(&info->port); - - /* enable send, recv, modem !!! */ - } - - info->port.flags |= ASYNC_INITIALIZED; - - clear_bit(TTY_IO_ERROR, &tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - info->breakon = info->breakoff = 0; - memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); - info->idle_stats.in_use = - info->idle_stats.recv_idle = - info->idle_stats.xmit_idle = jiffies; - - spin_unlock_irqrestore(&card->card_lock, flags); - -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc startup done\n"); -#endif - return 0; - -errout: - spin_unlock_irqrestore(&card->card_lock, flags); - free_page(page); - return retval; -} /* startup */ - -static void start_xmit(struct cyclades_port *info) -{ - struct cyclades_card *card = info->card; - unsigned long flags; - int channel = info->line - card->first_line; - - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - cyy_writeb(info, CyCAR, channel & 0x03); - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); - spin_unlock_irqrestore(&card->card_lock, flags); - } else { -#ifdef CONFIG_CYZ_INTR - int retval; - - spin_lock_irqsave(&card->card_lock, flags); - retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was " - "%x\n", info->line, retval); - } - spin_unlock_irqrestore(&card->card_lock, flags); -#else /* CONFIG_CYZ_INTR */ - /* Don't have to do anything at this time */ -#endif /* CONFIG_CYZ_INTR */ - } -} /* 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 cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) -{ - struct cyclades_card *card; - unsigned long flags; - int channel; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - - card = info->card; - channel = info->line - card->first_line; - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - - /* Clear delta_msr_wait queue to avoid mem leaks. */ - wake_up_interruptible(&info->port.delta_msr_wait); - - if (info->port.xmit_buf) { - unsigned char *temp; - temp = info->port.xmit_buf; - info->port.xmit_buf = NULL; - free_page((unsigned long)temp); - } - if (tty->termios->c_cflag & HUPCL) - cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); - - cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); - /* it may be appropriate to clear _XMIT at - some later date (after testing)!!! */ - - set_bit(TTY_IO_ERROR, &tty->flags); - info->port.flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&card->card_lock, flags); - } else { -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " - "base_addr %p\n", card, channel, card->base_addr); -#endif - - if (!cyz_is_loaded(card)) - return; - - spin_lock_irqsave(&card->card_lock, flags); - - if (info->port.xmit_buf) { - unsigned char *temp; - temp = info->port.xmit_buf; - info->port.xmit_buf = NULL; - free_page((unsigned long)temp); - } - - if (tty->termios->c_cflag & HUPCL) - tty_port_lower_dtr_rts(&info->port); - - set_bit(TTY_IO_ERROR, &tty->flags); - info->port.flags &= ~ASYNC_INITIALIZED; - - spin_unlock_irqrestore(&card->card_lock, flags); - } - -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc shutdown done\n"); -#endif -} /* shutdown */ - -/* - * ------------------------------------------------------------ - * cy_open() and friends - * ------------------------------------------------------------ - */ - -/* - * This routine is called whenever a serial port is opened. It - * performs the serial-specific initialization for the tty structure. - */ -static int cy_open(struct tty_struct *tty, struct file *filp) -{ - struct cyclades_port *info; - unsigned int i, line; - int retval; - - line = tty->index; - if (tty->index < 0 || NR_PORTS <= line) - return -ENODEV; - - for (i = 0; i < NR_CARDS; i++) - if (line < cy_card[i].first_line + cy_card[i].nports && - line >= cy_card[i].first_line) - break; - if (i >= NR_CARDS) - return -ENODEV; - info = &cy_card[i].ports[line - cy_card[i].first_line]; - if (info->line < 0) - return -ENODEV; - - /* If the card's firmware hasn't been loaded, - treat it as absent from the system. This - will make the user pay attention. - */ - if (cy_is_Z(info->card)) { - struct cyclades_card *cinfo = info->card; - struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; - - if (!cyz_is_loaded(cinfo)) { - if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && - readl(&firm_id->signature) == - ZFIRM_HLT) { - printk(KERN_ERR "cyc:Cyclades-Z Error: you " - "need an external power supply for " - "this number of ports.\nFirmware " - "halted.\n"); - } else { - printk(KERN_ERR "cyc:Cyclades-Z firmware not " - "yet loaded\n"); - } - return -ENODEV; - } -#ifdef CONFIG_CYZ_INTR - else { - /* In case this Z board is operating in interrupt mode, its - interrupts should be enabled as soon as the first open - happens to one of its ports. */ - if (!cinfo->intr_enabled) { - u16 intr; - - /* Enable interrupts on the PLX chip */ - intr = readw(&cinfo->ctl_addr.p9060-> - intr_ctrl_stat) | 0x0900; - cy_writew(&cinfo->ctl_addr.p9060-> - intr_ctrl_stat, intr); - /* Enable interrupts on the FW */ - retval = cyz_issue_cmd(cinfo, 0, - C_CM_IRQ_ENBL, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:IRQ enable retval " - "was %x\n", retval); - } - cinfo->intr_enabled = 1; - } - } -#endif /* CONFIG_CYZ_INTR */ - /* Make sure this Z port really exists in hardware */ - if (info->line > (cinfo->first_line + cinfo->nports - 1)) - return -ENODEV; - } -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); -#endif - tty->driver_data = info; - if (serial_paranoia_check(info, tty->name, "cy_open")) - return -ENODEV; - -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, - info->port.count); -#endif - info->port.count++; -#ifdef CY_DEBUG_COUNT - printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", - current->pid, info->port.count); -#endif - - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->port.close_wait, - !(info->port.flags & ASYNC_CLOSING)); - return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; - } - - /* - * Start up serial port - */ - retval = cy_startup(info, tty); - if (retval) - return retval; - - retval = tty_port_block_til_ready(&info->port, tty, filp); - if (retval) { -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " - "with %d\n", retval); -#endif - return retval; - } - - info->throttle = 0; - tty_port_tty_set(&info->port, tty); - -#ifdef CY_DEBUG_OPEN - printk(KERN_DEBUG "cyc:cy_open done\n"); -#endif - return 0; -} /* cy_open */ - -/* - * cy_wait_until_sent() --- wait until the transmitter is empty - */ -static void cy_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct cyclades_card *card; - struct cyclades_port *info = tty->driver_data; - unsigned long orig_jiffies; - int char_time; - - if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time <= 0) - char_time = 1; - if (timeout < 0) - timeout = 0; - if (timeout) - char_time = min(char_time, timeout); - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2 * info->timeout) - timeout = 2 * info->timeout; -#ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...", - timeout, char_time, jiffies); -#endif - card = info->card; - if (!cy_is_Z(card)) { - while (cyy_readb(info, CySRER) & CyTxRdy) { -#ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies); -#endif - if (msleep_interruptible(jiffies_to_msecs(char_time))) - break; - if (timeout && time_after(jiffies, orig_jiffies + - timeout)) - break; - } - } - /* Run one more char cycle */ - msleep_interruptible(jiffies_to_msecs(char_time * 5)); -#ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); -#endif -} - -static void cy_flush_buffer(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - int channel, retval; - unsigned long flags; - -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) - return; - - card = info->card; - channel = info->line - card->first_line; - - spin_lock_irqsave(&card->card_lock, flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - spin_unlock_irqrestore(&card->card_lock, flags); - - if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board - buffers as well */ - spin_lock_irqsave(&card->card_lock, flags); - retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d " - "was %x\n", info->line, retval); - } - spin_unlock_irqrestore(&card->card_lock, flags); - } - tty_wakeup(tty); -} /* cy_flush_buffer */ - - -static void cy_do_close(struct tty_port *port) -{ - struct cyclades_port *info = container_of(port, struct cyclades_port, - port); - struct cyclades_card *card; - unsigned long flags; - int channel; - - card = info->card; - channel = info->line - card->first_line; - spin_lock_irqsave(&card->card_lock, flags); - - if (!cy_is_Z(card)) { - /* Stop accepting input */ - cyy_writeb(info, CyCAR, channel & 0x03); - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData); - if (info->port.flags & ASYNC_INITIALIZED) { - /* Waiting for on-board buffers to be empty before - closing the port */ - spin_unlock_irqrestore(&card->card_lock, flags); - cy_wait_until_sent(port->tty, info->timeout); - spin_lock_irqsave(&card->card_lock, flags); - } - } else { -#ifdef Z_WAKE - /* Waiting for on-board buffers to be empty before closing - the port */ - struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; - int retval; - - if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) { - retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); - if (retval != 0) { - printk(KERN_DEBUG "cyc:cy_close retval on " - "ttyC%d was %x\n", info->line, retval); - } - spin_unlock_irqrestore(&card->card_lock, flags); - wait_for_completion_interruptible(&info->shutdown_wait); - spin_lock_irqsave(&card->card_lock, flags); - } -#endif - } - spin_unlock_irqrestore(&card->card_lock, flags); - cy_shutdown(info, port->tty); -} - -/* - * This routine is called when a particular tty device is closed. - */ -static void cy_close(struct tty_struct *tty, struct file *filp) -{ - struct cyclades_port *info = tty->driver_data; - if (!info || serial_paranoia_check(info, tty->name, "cy_close")) - return; - tty_port_close(&info->port, tty, filp); -} /* cy_close */ - -/* This routine gets called when tty_write has put something into - * the write_queue. The characters may come from user space or - * kernel space. - * - * This routine will return the number of characters actually - * accepted for writing. - * - * If the port is not already transmitting stuff, start it off by - * enabling interrupts. The interrupt service 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) -{ - struct cyclades_port *info = tty->driver_data; - unsigned long flags; - int c, ret = 0; - -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_write")) - return 0; - - if (!info->port.xmit_buf) - return 0; - - spin_lock_irqsave(&info->card->card_lock, flags); - while (1) { - c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1)); - c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head)); - - if (c <= 0) - break; - - memcpy(info->port.xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & - (SERIAL_XMIT_SIZE - 1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - spin_unlock_irqrestore(&info->card->card_lock, flags); - - info->idle_stats.xmit_bytes += ret; - info->idle_stats.xmit_idle = jiffies; - - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) - start_xmit(info); - - return ret; -} /* cy_write */ - -/* - * This routine is called by the kernel to write a single - * character to the tty device. If the kernel uses this routine, - * it must call the flush_chars() routine (if defined) when it is - * done stuffing characters into the driver. If there is no room - * in the queue, the character is ignored. - */ -static int cy_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct cyclades_port *info = tty->driver_data; - unsigned long flags; - -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_put_char")) - return 0; - - if (!info->port.xmit_buf) - return 0; - - spin_lock_irqsave(&info->card->card_lock, flags); - if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { - spin_unlock_irqrestore(&info->card->card_lock, flags); - return 0; - } - - info->port.xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE - 1; - info->xmit_cnt++; - info->idle_stats.xmit_bytes++; - info->idle_stats.xmit_idle = jiffies; - spin_unlock_irqrestore(&info->card->card_lock, flags); - return 1; -} /* cy_put_char */ - -/* - * This routine is called by the kernel after it has written a - * series of characters to the tty device using put_char(). - */ -static void cy_flush_chars(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->port.xmit_buf) - return; - - start_xmit(info); -} /* cy_flush_chars */ - -/* - * This routine returns the numbers of characters the tty driver - * will accept for queuing to be written. This number is subject - * to change as output buffers get emptied, or if the output flow - * control is activated. - */ -static int cy_write_room(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - int ret; - -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_write_room")) - return 0; - ret = SERIAL_XMIT_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) -{ - struct cyclades_port *info = tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) - return 0; - -#ifdef Z_EXT_CHARS_IN_BUFFER - if (!cy_is_Z(info->card)) { -#endif /* Z_EXT_CHARS_IN_BUFFER */ -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", - info->line, info->xmit_cnt); -#endif - return info->xmit_cnt; -#ifdef Z_EXT_CHARS_IN_BUFFER - } else { - struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; - int char_count; - __u32 tx_put, tx_get, tx_bufsize; - - tx_get = readl(&buf_ctrl->tx_get); - tx_put = readl(&buf_ctrl->tx_put); - tx_bufsize = readl(&buf_ctrl->tx_bufsize); - if (tx_put >= tx_get) - char_count = tx_put - tx_get; - else - char_count = tx_put - tx_get + tx_bufsize; -#ifdef CY_DEBUG_IO - printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", - info->line, info->xmit_cnt + char_count); -#endif - return info->xmit_cnt + char_count; - } -#endif /* Z_EXT_CHARS_IN_BUFFER */ -} /* cy_chars_in_buffer */ - -/* - * ------------------------------------------------------------ - * cy_ioctl() and friends - * ------------------------------------------------------------ - */ - -static void cyy_baud_calc(struct cyclades_port *info, __u32 baud) -{ - int co, co_val, bpr; - __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : - 25000000); - - if (baud == 0) { - info->tbpr = info->tco = info->rbpr = info->rco = 0; - return; - } - - /* determine which prescaler to use */ - for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { - if (cy_clock / co_val / baud > 63) - break; - } - - bpr = (cy_clock / co_val * 2 / baud + 1) / 2; - if (bpr > 255) - bpr = 255; - - info->tbpr = info->rbpr = bpr; - info->tco = info->rco = co; -} - -/* - * This routine finds or computes the various line characteristics. - * It used to be called config_setup - */ -static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) -{ - struct cyclades_card *card; - unsigned long flags; - int channel; - unsigned cflag, iflag; - int baud, baud_rate = 0; - int i; - - if (!tty->termios) /* XXX can this happen at all? */ - return; - - if (info->line == -1) - return; - - cflag = tty->termios->c_cflag; - iflag = tty->termios->c_iflag; - - /* - * Set up the tty->alt_speed kludge - */ - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - tty->alt_speed = 57600; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - tty->alt_speed = 115200; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - tty->alt_speed = 230400; - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - tty->alt_speed = 460800; - - card = info->card; - channel = info->line - card->first_line; - - if (!cy_is_Z(card)) { - u32 cflags; - - /* baud rate */ - baud = tty_get_baud_rate(tty); - if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == - ASYNC_SPD_CUST) { - if (info->custom_divisor) - baud_rate = info->baud / info->custom_divisor; - else - baud_rate = info->baud; - } else if (baud > CD1400_MAX_SPEED) { - baud = CD1400_MAX_SPEED; - } - /* find the baud index */ - for (i = 0; i < 20; i++) { - if (baud == baud_table[i]) - break; - } - if (i == 20) - i = 19; /* CD1400_MAX_SPEED */ - - if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == - ASYNC_SPD_CUST) { - cyy_baud_calc(info, baud_rate); - } else { - if (info->chip_rev >= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[i]; /* Tx BPR */ - info->tco = baud_co_60[i]; /* Tx CO */ - info->rbpr = baud_bpr_60[i]; /* Rx BPR */ - info->rco = baud_co_60[i]; /* Rx CO */ - } else { - info->tbpr = baud_bpr_25[i]; /* Tx BPR */ - info->tco = baud_co_25[i]; /* Tx CO */ - info->rbpr = baud_bpr_25[i]; /* Rx BPR */ - info->rco = baud_co_25[i]; /* Rx CO */ - } - } - if (baud_table[i] == 134) { - /* get it right for 134.5 baud */ - info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + - 2; - } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == - ASYNC_SPD_CUST) { - info->timeout = (info->xmit_fifo_size * HZ * 15 / - baud_rate) + 2; - } 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->cor5 = 0; - info->cor4 = 0; - /* receive threshold */ - info->cor3 = (info->default_threshold ? - info->default_threshold : baud_cor3[i]); - 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 & CSTOPB) - info->cor1 |= Cy_2_STOP; - - 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 (cflag & CRTSCTS) { - info->port.flags |= ASYNC_CTS_FLOW; - info->cor2 |= CyCtsAE; - } else { - info->port.flags &= ~ASYNC_CTS_FLOW; - info->cor2 &= ~CyCtsAE; - } - if (cflag & CLOCAL) - info->port.flags &= ~ASYNC_CHECK_CD; - else - info->port.flags |= ASYNC_CHECK_CD; - - /*********************************************** - The hardware option, CyRtsAO, presents RTS when - the chip has characters to send. Since most modems - use RTS as reverse (inbound) flow control, this - option is not used. If inbound flow control is - necessary, DTR can be programmed to provide the - appropriate signals for use with a non-standard - cable. Contact Marcio Saito for details. - ***********************************************/ - - channel &= 0x03; - - spin_lock_irqsave(&card->card_lock, flags); - cyy_writeb(info, CyCAR, channel); - - /* tx and rx baud rate */ - - cyy_writeb(info, CyTCOR, info->tco); - cyy_writeb(info, CyTBPR, info->tbpr); - cyy_writeb(info, CyRCOR, info->rco); - cyy_writeb(info, CyRBPR, info->rbpr); - - /* set line characteristics according configuration */ - - cyy_writeb(info, CySCHR1, START_CHAR(tty)); - cyy_writeb(info, CySCHR2, STOP_CHAR(tty)); - cyy_writeb(info, CyCOR1, info->cor1); - cyy_writeb(info, CyCOR2, info->cor2); - cyy_writeb(info, CyCOR3, info->cor3); - cyy_writeb(info, CyCOR4, info->cor4); - cyy_writeb(info, CyCOR5, info->cor5); - - cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | - CyCOR3ch); - - /* !!! Is this needed? */ - cyy_writeb(info, CyCAR, channel); - cyy_writeb(info, CyRTPR, - (info->default_timeout ? info->default_timeout : 0x02)); - /* 10ms rx timeout */ - - cflags = CyCTS; - if (!C_CLOCAL(tty)) - cflags |= CyDSR | CyRI | CyDCD; - /* without modem intr */ - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh); - /* act on 1->0 modem transitions */ - if ((cflag & CRTSCTS) && info->rflow) - cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]); - else - cyy_writeb(info, CyMCOR1, cflags); - /* act on 0->1 modem transitions */ - cyy_writeb(info, CyMCOR2, cflags); - - if (i == 0) /* baud rate is zero, turn off line */ - cyy_change_rts_dtr(info, 0, TIOCM_DTR); - else - cyy_change_rts_dtr(info, TIOCM_DTR, 0); - - clear_bit(TTY_IO_ERROR, &tty->flags); - spin_unlock_irqrestore(&card->card_lock, flags); - - } else { - struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; - __u32 sw_flow; - int retval; - - if (!cyz_is_loaded(card)) - return; - - /* baud rate */ - baud = tty_get_baud_rate(tty); - if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == - ASYNC_SPD_CUST) { - if (info->custom_divisor) - baud_rate = info->baud / info->custom_divisor; - else - baud_rate = info->baud; - } else if (baud > CYZ_MAX_SPEED) { - baud = CYZ_MAX_SPEED; - } - cy_writel(&ch_ctrl->comm_baud, baud); - - if (baud == 134) { - /* get it right for 134.5 baud */ - info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + - 2; - } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == - ASYNC_SPD_CUST) { - info->timeout = (info->xmit_fifo_size * HZ * 15 / - baud_rate) + 2; - } else if (baud) { - info->timeout = (info->xmit_fifo_size * HZ * 15 / - baud) + 2; - /* this needs to be propagated into the card info */ - } else { - info->timeout = 0; - } - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: - cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5); - break; - case CS6: - cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6); - break; - case CS7: - cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7); - break; - case CS8: - cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8); - break; - } - if (cflag & CSTOPB) { - cy_writel(&ch_ctrl->comm_data_l, - readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); - } else { - cy_writel(&ch_ctrl->comm_data_l, - readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); - } - if (cflag & PARENB) { - if (cflag & PARODD) - cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); - else - cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); - } else - cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); - - /* CTS flow control flag */ - if (cflag & CRTSCTS) { - cy_writel(&ch_ctrl->hw_flow, - readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); - } else { - cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & - ~(C_RS_CTS | C_RS_RTS)); - } - /* As the HW flow control is done in firmware, the driver - doesn't need to care about it */ - info->port.flags &= ~ASYNC_CTS_FLOW; - - /* XON/XOFF/XANY flow control flags */ - sw_flow = 0; - if (iflag & IXON) { - sw_flow |= C_FL_OXX; - if (iflag & IXANY) - sw_flow |= C_FL_OIXANY; - } - cy_writel(&ch_ctrl->sw_flow, sw_flow); - - retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " - "was %x\n", info->line, retval); - } - - /* CD sensitivity */ - if (cflag & CLOCAL) - info->port.flags &= ~ASYNC_CHECK_CD; - else - info->port.flags |= ASYNC_CHECK_CD; - - if (baud == 0) { /* baud rate is zero, turn off line */ - cy_writel(&ch_ctrl->rs_control, - readl(&ch_ctrl->rs_control) & ~C_RS_DTR); -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n"); -#endif - } else { - cy_writel(&ch_ctrl->rs_control, - readl(&ch_ctrl->rs_control) | C_RS_DTR); -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n"); -#endif - } - - retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " - "was %x\n", info->line, retval); - } - - clear_bit(TTY_IO_ERROR, &tty->flags); - } -} /* set_line_char */ - -static int cy_get_serial_info(struct cyclades_port *info, - struct serial_struct __user *retinfo) -{ - struct cyclades_card *cinfo = info->card; - struct serial_struct tmp = { - .type = info->type, - .line = info->line, - .port = (info->card - cy_card) * 0x100 + info->line - - cinfo->first_line, - .irq = cinfo->irq, - .flags = info->port.flags, - .close_delay = info->port.close_delay, - .closing_wait = info->port.closing_wait, - .baud_base = info->baud, - .custom_divisor = info->custom_divisor, - .hub6 = 0, /*!!! */ - }; - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; -} - -static int -cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, - struct serial_struct __user *new_info) -{ - struct serial_struct new_serial; - int ret; - - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - - mutex_lock(&info->port.mutex); - if (!capable(CAP_SYS_ADMIN)) { - if (new_serial.close_delay != info->port.close_delay || - new_serial.baud_base != info->baud || - (new_serial.flags & ASYNC_FLAGS & - ~ASYNC_USR_MASK) != - (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) - { - mutex_unlock(&info->port.mutex); - return -EPERM; - } - info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK); - info->baud = new_serial.baud_base; - info->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud = new_serial.baud_base; - info->custom_divisor = new_serial.custom_divisor; - info->port.flags = (info->port.flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS); - info->port.close_delay = new_serial.close_delay * HZ / 100; - info->port.closing_wait = new_serial.closing_wait * HZ / 100; - -check_and_exit: - if (info->port.flags & ASYNC_INITIALIZED) { - cy_set_line_char(info, tty); - ret = 0; - } else { - ret = cy_startup(info, tty); - } - mutex_unlock(&info->port.mutex); - return ret; -} /* set_serial_info */ - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) -{ - struct cyclades_card *card = info->card; - unsigned int result; - unsigned long flags; - u8 status; - - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty); - spin_unlock_irqrestore(&card->card_lock, flags); - result = (status ? 0 : TIOCSER_TEMT); - } else { - /* Not supported yet */ - return -EINVAL; - } - return put_user(result, (unsigned long __user *)value); -} - -static int cy_tiocmget(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - int result; - - if (serial_paranoia_check(info, tty->name, __func__)) - return -ENODEV; - - card = info->card; - - if (!cy_is_Z(card)) { - unsigned long flags; - int channel = info->line - card->first_line; - u8 status; - - spin_lock_irqsave(&card->card_lock, flags); - cyy_writeb(info, CyCAR, channel & 0x03); - status = cyy_readb(info, CyMSVR1); - status |= cyy_readb(info, CyMSVR2); - spin_unlock_irqrestore(&card->card_lock, flags); - - if (info->rtsdtr_inv) { - result = ((status & CyRTS) ? TIOCM_DTR : 0) | - ((status & CyDTR) ? TIOCM_RTS : 0); - } else { - result = ((status & CyRTS) ? TIOCM_RTS : 0) | - ((status & CyDTR) ? TIOCM_DTR : 0); - } - result |= ((status & CyDCD) ? TIOCM_CAR : 0) | - ((status & CyRI) ? TIOCM_RNG : 0) | - ((status & CyDSR) ? TIOCM_DSR : 0) | - ((status & CyCTS) ? TIOCM_CTS : 0); - } else { - u32 lstatus; - - if (!cyz_is_loaded(card)) { - result = -ENODEV; - goto end; - } - - lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); - result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | - ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | - ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | - ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | - ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | - ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); - } -end: - return result; -} /* cy_tiomget */ - -static int -cy_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, __func__)) - return -ENODEV; - - card = info->card; - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - cyy_change_rts_dtr(info, set, clear); - spin_unlock_irqrestore(&card->card_lock, flags); - } else { - struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; - int retval, channel = info->line - card->first_line; - u32 rs; - - if (!cyz_is_loaded(card)) - return -ENODEV; - - spin_lock_irqsave(&card->card_lock, flags); - rs = readl(&ch_ctrl->rs_control); - if (set & TIOCM_RTS) - rs |= C_RS_RTS; - if (clear & TIOCM_RTS) - rs &= ~C_RS_RTS; - if (set & TIOCM_DTR) { - rs |= C_RS_DTR; -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n"); -#endif - } - if (clear & TIOCM_DTR) { - rs &= ~C_RS_DTR; -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "cyc:set_modem_info clearing " - "Z DTR\n"); -#endif - } - cy_writel(&ch_ctrl->rs_control, rs); - retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); - spin_unlock_irqrestore(&card->card_lock, flags); - if (retval != 0) { - printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " - "was %x\n", info->line, retval); - } - } - return 0; -} - -/* - * cy_break() --- routine which turns the break handling on or off - */ -static int cy_break(struct tty_struct *tty, int break_state) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - unsigned long flags; - int retval = 0; - - if (serial_paranoia_check(info, tty->name, "cy_break")) - return -EINVAL; - - card = info->card; - - spin_lock_irqsave(&card->card_lock, flags); - if (!cy_is_Z(card)) { - /* Let the transmit ISR take care of this (since it - requires stuffing characters into the output stream). - */ - if (break_state == -1) { - if (!info->breakon) { - info->breakon = 1; - if (!info->xmit_cnt) { - spin_unlock_irqrestore(&card->card_lock, flags); - start_xmit(info); - spin_lock_irqsave(&card->card_lock, flags); - } - } - } else { - if (!info->breakoff) { - info->breakoff = 1; - if (!info->xmit_cnt) { - spin_unlock_irqrestore(&card->card_lock, flags); - start_xmit(info); - spin_lock_irqsave(&card->card_lock, flags); - } - } - } - } else { - if (break_state == -1) { - retval = cyz_issue_cmd(card, - info->line - card->first_line, - C_CM_SET_BREAK, 0L); - if (retval != 0) { - printk(KERN_ERR "cyc:cy_break (set) retval on " - "ttyC%d was %x\n", info->line, retval); - } - } else { - retval = cyz_issue_cmd(card, - info->line - card->first_line, - C_CM_CLR_BREAK, 0L); - if (retval != 0) { - printk(KERN_DEBUG "cyc:cy_break (clr) retval " - "on ttyC%d was %x\n", info->line, - retval); - } - } - } - spin_unlock_irqrestore(&card->card_lock, flags); - return retval; -} /* cy_break */ - -static int set_threshold(struct cyclades_port *info, unsigned long value) -{ - struct cyclades_card *card = info->card; - unsigned long flags; - - if (!cy_is_Z(card)) { - info->cor3 &= ~CyREC_FIFO; - info->cor3 |= value & CyREC_FIFO; - - spin_lock_irqsave(&card->card_lock, flags); - cyy_writeb(info, CyCOR3, info->cor3); - cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch); - spin_unlock_irqrestore(&card->card_lock, flags); - } - return 0; -} /* set_threshold */ - -static int get_threshold(struct cyclades_port *info, - unsigned long __user *value) -{ - struct cyclades_card *card = info->card; - - if (!cy_is_Z(card)) { - u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO; - return put_user(tmp, value); - } - return 0; -} /* get_threshold */ - -static int set_timeout(struct cyclades_port *info, unsigned long value) -{ - struct cyclades_card *card = info->card; - unsigned long flags; - - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - cyy_writeb(info, CyRTPR, value & 0xff); - spin_unlock_irqrestore(&card->card_lock, flags); - } - return 0; -} /* set_timeout */ - -static int get_timeout(struct cyclades_port *info, - unsigned long __user *value) -{ - struct cyclades_card *card = info->card; - - if (!cy_is_Z(card)) { - u8 tmp = cyy_readb(info, CyRTPR); - return put_user(tmp, value); - } - return 0; -} /* get_timeout */ - -static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg, - struct cyclades_icount *cprev) -{ - struct cyclades_icount cnow; - unsigned long flags; - int ret; - - spin_lock_irqsave(&info->card->card_lock, flags); - cnow = info->icount; /* atomic copy */ - spin_unlock_irqrestore(&info->card->card_lock, flags); - - ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); - - *cprev = cnow; - - return ret; -} - -/* - * This routine allows the tty driver to implement device- - * specific ioctl's. If the ioctl number passed in cmd is - * not recognized by the driver, it should return ENOIOCTLCMD. - */ -static int -cy_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_icount cnow; /* kernel counter temps */ - int ret_val = 0; - unsigned long flags; - void __user *argp = (void __user *)arg; - - if (serial_paranoia_check(info, tty->name, "cy_ioctl")) - return -ENODEV; - -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", - info->line, cmd, arg); -#endif - - switch (cmd) { - case CYGETMON: - if (copy_to_user(argp, &info->mon, sizeof(info->mon))) { - ret_val = -EFAULT; - break; - } - memset(&info->mon, 0, sizeof(info->mon)); - break; - case CYGETTHRESH: - ret_val = get_threshold(info, argp); - break; - case CYSETTHRESH: - ret_val = set_threshold(info, arg); - break; - case CYGETDEFTHRESH: - ret_val = put_user(info->default_threshold, - (unsigned long __user *)argp); - break; - case CYSETDEFTHRESH: - info->default_threshold = arg & 0x0f; - break; - case CYGETTIMEOUT: - ret_val = get_timeout(info, argp); - break; - case CYSETTIMEOUT: - ret_val = set_timeout(info, arg); - break; - case CYGETDEFTIMEOUT: - ret_val = put_user(info->default_timeout, - (unsigned long __user *)argp); - break; - case CYSETDEFTIMEOUT: - info->default_timeout = arg & 0xff; - break; - case CYSETRFLOW: - info->rflow = (int)arg; - break; - case CYGETRFLOW: - ret_val = info->rflow; - break; - case CYSETRTSDTR_INV: - info->rtsdtr_inv = (int)arg; - break; - case CYGETRTSDTR_INV: - ret_val = info->rtsdtr_inv; - break; - case CYGETCD1400VER: - ret_val = info->chip_rev; - break; -#ifndef CONFIG_CYZ_INTR - case CYZSETPOLLCYCLE: - cyz_polling_cycle = (arg * HZ) / 1000; - break; - case CYZGETPOLLCYCLE: - ret_val = (cyz_polling_cycle * 1000) / HZ; - break; -#endif /* CONFIG_CYZ_INTR */ - case CYSETWAIT: - info->port.closing_wait = (unsigned short)arg * HZ / 100; - break; - case CYGETWAIT: - ret_val = info->port.closing_wait / (HZ / 100); - break; - case TIOCGSERIAL: - ret_val = cy_get_serial_info(info, argp); - break; - case TIOCSSERIAL: - ret_val = cy_set_serial_info(info, tty, argp); - break; - case TIOCSERGETLSR: /* Get line status register */ - ret_val = get_lsr_info(info, argp); - break; - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - spin_lock_irqsave(&info->card->card_lock, flags); - /* note the counters on entry */ - cnow = info->icount; - spin_unlock_irqrestore(&info->card->card_lock, flags); - ret_val = wait_event_interruptible(info->port.delta_msr_wait, - cy_cflags_changed(info, arg, &cnow)); - break; - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - default: - ret_val = -ENOIOCTLCMD; - } - -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_ioctl done\n"); -#endif - return ret_val; -} /* cy_ioctl */ - -static int cy_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *sic) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_icount cnow; /* Used to snapshot */ - unsigned long flags; - - spin_lock_irqsave(&info->card->card_lock, flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->card->card_lock, flags); - - sic->cts = cnow.cts; - sic->dsr = cnow.dsr; - sic->rng = cnow.rng; - sic->dcd = cnow.dcd; - sic->rx = cnow.rx; - sic->tx = cnow.tx; - sic->frame = cnow.frame; - sic->overrun = cnow.overrun; - sic->parity = cnow.parity; - sic->brk = cnow.brk; - sic->buf_overrun = cnow.buf_overrun; - return 0; -} - -/* - * This routine allows the tty driver to be notified when - * device's termios settings have changed. Note that a - * well-designed tty driver should be prepared to accept the case - * where old == NULL, and try to do something rational. - */ -static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct cyclades_port *info = tty->driver_data; - -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); -#endif - - cy_set_line_char(info, tty); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - cy_start(tty); - } -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->port.open_wait); -#endif -} /* cy_set_termios */ - -/* This function is used to send a high-priority XON/XOFF character to - the device. -*/ -static void cy_send_xchar(struct tty_struct *tty, char ch) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - int channel; - - if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) - return; - - info->x_char = ch; - - if (ch) - cy_start(tty); - - card = info->card; - channel = info->line - card->first_line; - - if (cy_is_Z(card)) { - if (ch == STOP_CHAR(tty)) - cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); - else if (ch == START_CHAR(tty)) - cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); - } -} - -/* This routine is called by the upper-layer tty layer to signal - that incoming characters should be throttled because the input - buffers are close to full. - */ -static void cy_throttle(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - unsigned long flags; - -#ifdef CY_DEBUG_THROTTLE - char buf[64]; - - printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty), info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_throttle")) - return; - - card = info->card; - - if (I_IXOFF(tty)) { - if (!cy_is_Z(card)) - cy_send_xchar(tty, STOP_CHAR(tty)); - else - info->throttle = 1; - } - - if (tty->termios->c_cflag & CRTSCTS) { - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - cyy_change_rts_dtr(info, 0, TIOCM_RTS); - spin_unlock_irqrestore(&card->card_lock, flags); - } else { - info->throttle = 1; - } - } -} /* cy_throttle */ - -/* - * This routine notifies the tty driver that it should signal - * that characters can now be sent to the tty without fear of - * overrunning the input buffers of the line disciplines. - */ -static void cy_unthrottle(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - struct cyclades_card *card; - unsigned long flags; - -#ifdef CY_DEBUG_THROTTLE - char buf[64]; - - printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", - tty_name(tty, buf), tty_chars_in_buffer(tty), info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - cy_send_xchar(tty, START_CHAR(tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - card = info->card; - if (!cy_is_Z(card)) { - spin_lock_irqsave(&card->card_lock, flags); - cyy_change_rts_dtr(info, TIOCM_RTS, 0); - spin_unlock_irqrestore(&card->card_lock, flags); - } else { - info->throttle = 0; - } - } -} /* cy_unthrottle */ - -/* 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) -{ - struct cyclades_card *cinfo; - struct cyclades_port *info = tty->driver_data; - int channel; - unsigned long flags; - -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_stop")) - return; - - cinfo = info->card; - channel = info->line - cinfo->first_line; - if (!cy_is_Z(cinfo)) { - spin_lock_irqsave(&cinfo->card_lock, flags); - cyy_writeb(info, CyCAR, channel & 0x03); - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); - spin_unlock_irqrestore(&cinfo->card_lock, flags); - } -} /* cy_stop */ - -static void cy_start(struct tty_struct *tty) -{ - struct cyclades_card *cinfo; - struct cyclades_port *info = tty->driver_data; - int channel; - unsigned long flags; - -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_start")) - return; - - cinfo = info->card; - channel = info->line - cinfo->first_line; - if (!cy_is_Z(cinfo)) { - spin_lock_irqsave(&cinfo->card_lock, flags); - cyy_writeb(info, CyCAR, channel & 0x03); - cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); - spin_unlock_irqrestore(&cinfo->card_lock, flags); - } -} /* cy_start */ - -/* - * cy_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void cy_hangup(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - -#ifdef CY_DEBUG_OTHER - printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_hangup")) - return; - - cy_flush_buffer(tty); - cy_shutdown(info, tty); - tty_port_hangup(&info->port); -} /* cy_hangup */ - -static int cyy_carrier_raised(struct tty_port *port) -{ - struct cyclades_port *info = container_of(port, struct cyclades_port, - port); - struct cyclades_card *cinfo = info->card; - unsigned long flags; - int channel = info->line - cinfo->first_line; - u32 cd; - - spin_lock_irqsave(&cinfo->card_lock, flags); - cyy_writeb(info, CyCAR, channel & 0x03); - cd = cyy_readb(info, CyMSVR1) & CyDCD; - spin_unlock_irqrestore(&cinfo->card_lock, flags); - - return cd; -} - -static void cyy_dtr_rts(struct tty_port *port, int raise) -{ - struct cyclades_port *info = container_of(port, struct cyclades_port, - port); - struct cyclades_card *cinfo = info->card; - unsigned long flags; - - spin_lock_irqsave(&cinfo->card_lock, flags); - cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0, - raise ? 0 : TIOCM_RTS | TIOCM_DTR); - spin_unlock_irqrestore(&cinfo->card_lock, flags); -} - -static int cyz_carrier_raised(struct tty_port *port) -{ - struct cyclades_port *info = container_of(port, struct cyclades_port, - port); - - return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD; -} - -static void cyz_dtr_rts(struct tty_port *port, int raise) -{ - struct cyclades_port *info = container_of(port, struct cyclades_port, - port); - struct cyclades_card *cinfo = info->card; - struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; - int ret, channel = info->line - cinfo->first_line; - u32 rs; - - rs = readl(&ch_ctrl->rs_control); - if (raise) - rs |= C_RS_RTS | C_RS_DTR; - else - rs &= ~(C_RS_RTS | C_RS_DTR); - cy_writel(&ch_ctrl->rs_control, rs); - ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); - if (ret != 0) - printk(KERN_ERR "%s: retval on ttyC%d was %x\n", - __func__, info->line, ret); -#ifdef CY_DEBUG_DTR - printk(KERN_DEBUG "%s: raising Z DTR\n", __func__); -#endif -} - -static const struct tty_port_operations cyy_port_ops = { - .carrier_raised = cyy_carrier_raised, - .dtr_rts = cyy_dtr_rts, - .shutdown = cy_do_close, -}; - -static const struct tty_port_operations cyz_port_ops = { - .carrier_raised = cyz_carrier_raised, - .dtr_rts = cyz_dtr_rts, - .shutdown = cy_do_close, -}; - -/* - * --------------------------------------------------------------------- - * cy_init() and friends - * - * cy_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -static int __devinit cy_init_card(struct cyclades_card *cinfo) -{ - struct cyclades_port *info; - unsigned int channel, port; - - spin_lock_init(&cinfo->card_lock); - cinfo->intr_enabled = 0; - - cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), - GFP_KERNEL); - if (cinfo->ports == NULL) { - printk(KERN_ERR "Cyclades: cannot allocate ports\n"); - return -ENOMEM; - } - - for (channel = 0, port = cinfo->first_line; channel < cinfo->nports; - channel++, port++) { - info = &cinfo->ports[channel]; - tty_port_init(&info->port); - info->magic = CYCLADES_MAGIC; - info->card = cinfo; - info->line = port; - - info->port.closing_wait = CLOSING_WAIT_DELAY; - info->port.close_delay = 5 * HZ / 10; - info->port.flags = STD_COM_FLAGS; - init_completion(&info->shutdown_wait); - - if (cy_is_Z(cinfo)) { - struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS; - struct ZFW_CTRL *zfw_ctrl; - - info->port.ops = &cyz_port_ops; - info->type = PORT_STARTECH; - - zfw_ctrl = cinfo->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel]; - info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; - - if (cinfo->hw_ver == ZO_V1) - info->xmit_fifo_size = CYZ_FIFO_SIZE; - else - info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; -#ifdef CONFIG_CYZ_INTR - setup_timer(&cyz_rx_full_timer[port], - cyz_rx_restart, (unsigned long)info); -#endif - } else { - unsigned short chip_number; - int index = cinfo->bus_index; - - info->port.ops = &cyy_port_ops; - info->type = PORT_CIRRUS; - info->xmit_fifo_size = CyMAX_CHAR_FIFO; - info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; - info->cor2 = CyETC; - info->cor3 = 0x08; /* _very_ small rcv threshold */ - - chip_number = channel / CyPORTS_PER_CHIP; - info->u.cyy.base_addr = cinfo->base_addr + - (cy_chip_offset[chip_number] << index); - info->chip_rev = cyy_readb(info, CyGFRCR); - - if (info->chip_rev >= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[13]; /* Tx BPR */ - info->tco = baud_co_60[13]; /* Tx CO */ - info->rbpr = baud_bpr_60[13]; /* Rx BPR */ - info->rco = baud_co_60[13]; /* Rx CO */ - info->rtsdtr_inv = 1; - } else { - info->tbpr = baud_bpr_25[13]; /* Tx BPR */ - info->tco = baud_co_25[13]; /* Tx CO */ - info->rbpr = baud_bpr_25[13]; /* Rx BPR */ - info->rco = baud_co_25[13]; /* Rx CO */ - info->rtsdtr_inv = 0; - } - info->read_status_mask = CyTIMEOUT | CySPECHAR | - CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; - } - - } - -#ifndef CONFIG_CYZ_INTR - if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { - mod_timer(&cyz_timerlist, jiffies + 1); -#ifdef CY_PCI_DEBUG - printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); -#endif - } -#endif - return 0; -} - -/* initialize chips on Cyclom-Y card -- return number of valid - chips (which is number of ports/4) */ -static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, - int index) -{ - unsigned int chip_number; - void __iomem *base_addr; - - cy_writeb(true_base_addr + (Cy_HwReset << index), 0); - /* Cy_HwReset is 0x1400 */ - cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0); - /* Cy_ClrIntr is 0x1800 */ - udelay(500L); - - for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; - chip_number++) { - base_addr = - true_base_addr + (cy_chip_offset[chip_number] << index); - mdelay(1); - if (readb(base_addr + (CyCCR << index)) != 0x00) { - /************* - printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", - chip_number, (unsigned long)base_addr); - *************/ - return chip_number; - } - - cy_writeb(base_addr + (CyGFRCR << index), 0); - udelay(10L); - - /* The Cyclom-16Y does not decode address bit 9 and therefore - cannot distinguish between references to chip 0 and a non- - existent chip 4. If the preceding clearing of the supposed - chip 4 GFRCR register appears at chip 0, there is no chip 4 - and this must be a Cyclom-16Y, not a Cyclom-32Ye. - */ - if (chip_number == 4 && readb(true_base_addr + - (cy_chip_offset[0] << index) + - (CyGFRCR << index)) == 0) { - return chip_number; - } - - cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); - mdelay(1); - - if (readb(base_addr + (CyGFRCR << index)) == 0x00) { - /* - printk(" chip #%d at %#6lx is not responding ", - chip_number, (unsigned long)base_addr); - printk("(GFRCR stayed 0)\n", - */ - return chip_number; - } - if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != - 0x40) { - /* - printk(" chip #%d at %#6lx is not valid (GFRCR == " - "%#2x)\n", - chip_number, (unsigned long)base_addr, - base_addr[CyGFRCR<= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - /* Impossible to reach 5ms with this chip. - Changed to 2ms instead (f = 500 Hz). */ - cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS); - } else { - /* f = 200 Hz */ - cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS); - } - - /* - printk(" chip #%d at %#6lx is rev 0x%2x\n", - chip_number, (unsigned long)base_addr, - readb(base_addr+(CyGFRCR< NR_PORTS) { - printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " - "more channels are available. Change NR_PORTS " - "in cyclades.c and recompile kernel.\n", - (unsigned long)cy_isa_address); - iounmap(cy_isa_address); - return nboard; - } - /* fill the next cy_card structure available */ - for (j = 0; j < NR_CARDS; j++) { - if (cy_card[j].base_addr == NULL) - break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " - "more cards can be used. Change NR_CARDS in " - "cyclades.c and recompile kernel.\n", - (unsigned long)cy_isa_address); - iounmap(cy_isa_address); - return nboard; - } - - /* allocate IRQ */ - if (request_irq(cy_isa_irq, cyy_interrupt, - IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { - printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " - "could not allocate IRQ#%d.\n", - (unsigned long)cy_isa_address, cy_isa_irq); - iounmap(cy_isa_address); - return nboard; - } - - /* set cy_card */ - cy_card[j].base_addr = cy_isa_address; - cy_card[j].ctl_addr.p9050 = NULL; - cy_card[j].irq = (int)cy_isa_irq; - cy_card[j].bus_index = 0; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; - cy_card[j].nports = cy_isa_nchan; - if (cy_init_card(&cy_card[j])) { - cy_card[j].base_addr = NULL; - free_irq(cy_isa_irq, &cy_card[j]); - iounmap(cy_isa_address); - continue; - } - nboard++; - - printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: " - "%d channels starting from port %d\n", - j + 1, (unsigned long)cy_isa_address, - (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), - cy_isa_irq, cy_isa_nchan, cy_next_channel); - - for (j = cy_next_channel; - j < cy_next_channel + cy_isa_nchan; j++) - tty_register_device(cy_serial_driver, j, NULL); - cy_next_channel += cy_isa_nchan; - } - return nboard; -#else - return 0; -#endif /* CONFIG_ISA */ -} /* cy_detect_isa */ - -#ifdef CONFIG_PCI -static inline int __devinit cyc_isfwstr(const char *str, unsigned int size) -{ - unsigned int a; - - for (a = 0; a < size && *str; a++, str++) - if (*str & 0x80) - return -EINVAL; - - for (; a < size; a++, str++) - if (*str) - return -EINVAL; - - return 0; -} - -static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data, - unsigned int size) -{ - for (; size > 0; size--) { - cy_writel(fpga, *data++); - udelay(10); - } -} - -static void __devinit plx_init(struct pci_dev *pdev, int irq, - struct RUNTIME_9060 __iomem *addr) -{ - /* Reset PLX */ - cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000); - udelay(100L); - cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000); - - /* Reload Config. Registers from EEPROM */ - cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000); - udelay(100L); - cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000); - - /* For some yet unknown reason, once the PLX9060 reloads the EEPROM, - * the IRQ is lost and, thus, we have to re-write it to the PCI config. - * registers. This will remain here until we find a permanent fix. - */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); -} - -static int __devinit __cyz_load_fw(const struct firmware *fw, - const char *name, const u32 mailbox, void __iomem *base, - void __iomem *fpga) -{ - const void *ptr = fw->data; - const struct zfile_header *h = ptr; - const struct zfile_config *c, *cs; - const struct zfile_block *b, *bs; - unsigned int a, tmp, len = fw->size; -#define BAD_FW KERN_ERR "Bad firmware: " - if (len < sizeof(*h)) { - printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h)); - return -EINVAL; - } - - cs = ptr + h->config_offset; - bs = ptr + h->block_offset; - - if ((void *)(cs + h->n_config) > ptr + len || - (void *)(bs + h->n_blocks) > ptr + len) { - printk(BAD_FW "too short"); - return -EINVAL; - } - - if (cyc_isfwstr(h->name, sizeof(h->name)) || - cyc_isfwstr(h->date, sizeof(h->date))) { - printk(BAD_FW "bad formatted header string\n"); - return -EINVAL; - } - - if (strncmp(name, h->name, sizeof(h->name))) { - printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name); - return -EINVAL; - } - - tmp = 0; - for (c = cs; c < cs + h->n_config; c++) { - for (a = 0; a < c->n_blocks; a++) - if (c->block_list[a] > h->n_blocks) { - printk(BAD_FW "bad block ref number in cfgs\n"); - return -EINVAL; - } - if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */ - tmp++; - } - if (!tmp) { - printk(BAD_FW "nothing appropriate\n"); - return -EINVAL; - } - - for (b = bs; b < bs + h->n_blocks; b++) - if (b->file_offset + b->size > len) { - printk(BAD_FW "bad block data offset\n"); - return -EINVAL; - } - - /* everything is OK, let's seek'n'load it */ - for (c = cs; c < cs + h->n_config; c++) - if (c->mailbox == mailbox && c->function == 0) - break; - - for (a = 0; a < c->n_blocks; a++) { - b = &bs[c->block_list[a]]; - if (b->type == ZBLOCK_FPGA) { - if (fpga != NULL) - cyz_fpga_copy(fpga, ptr + b->file_offset, - b->size); - } else { - if (base != NULL) - memcpy_toio(base + b->ram_offset, - ptr + b->file_offset, b->size); - } - } -#undef BAD_FW - return 0; -} - -static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, - struct RUNTIME_9060 __iomem *ctl_addr, int irq) -{ - const struct firmware *fw; - struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS; - struct CUSTOM_REG __iomem *cust = base_addr; - struct ZFW_CTRL __iomem *pt_zfwctrl; - void __iomem *tmp; - u32 mailbox, status, nchan; - unsigned int i; - int retval; - - retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev); - if (retval) { - dev_err(&pdev->dev, "can't get firmware\n"); - goto err; - } - - /* Check whether the firmware is already loaded and running. If - positive, skip this board */ - if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { - u32 cntval = readl(base_addr + 0x190); - - udelay(100); - if (cntval != readl(base_addr + 0x190)) { - /* FW counter is working, FW is running */ - dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. " - "Skipping board.\n"); - retval = 0; - goto err_rel; - } - } - - /* start boot */ - cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) & - ~0x00030800UL); - - mailbox = readl(&ctl_addr->mail_box_0); - - if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { - /* stops CPU and set window to beginning of RAM */ - cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); - cy_writel(&cust->cpu_stop, 0); - cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); - udelay(100); - } - - plx_init(pdev, irq, ctl_addr); - - if (mailbox != 0) { - /* load FPGA */ - retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL, - base_addr); - if (retval) - goto err_rel; - if (!__cyz_fpga_loaded(ctl_addr)) { - dev_err(&pdev->dev, "fw upload successful, but fw is " - "not loaded\n"); - goto err_rel; - } - } - - /* stops CPU and set window to beginning of RAM */ - cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); - cy_writel(&cust->cpu_stop, 0); - cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); - udelay(100); - - /* clear memory */ - for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) - cy_writeb(tmp, 255); - if (mailbox != 0) { - /* set window to last 512K of RAM */ - cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE); - for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) - cy_writeb(tmp, 255); - /* set window to beginning of RAM */ - cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); - } - - retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL); - release_firmware(fw); - if (retval) - goto err; - - /* finish boot and start boards */ - cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); - cy_writel(&cust->cpu_start, 0); - cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); - i = 0; - while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40) - msleep(100); - if (status != ZFIRM_ID) { - if (status == ZFIRM_HLT) { - dev_err(&pdev->dev, "you need an external power supply " - "for this number of ports. Firmware halted and " - "board reset.\n"); - retval = -EIO; - goto err; - } - dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting " - "some more time\n", status); - while ((status = readl(&fid->signature)) != ZFIRM_ID && - i++ < 200) - msleep(100); - if (status != ZFIRM_ID) { - dev_err(&pdev->dev, "Board not started in 20 seconds! " - "Giving up. (fid->signature = 0x%x)\n", - status); - dev_info(&pdev->dev, "*** Warning ***: if you are " - "upgrading the FW, please power cycle the " - "system before loading the new FW to the " - "Cyclades-Z.\n"); - - if (__cyz_fpga_loaded(ctl_addr)) - plx_init(pdev, irq, ctl_addr); - - retval = -EIO; - goto err; - } - dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n", - i / 10); - } - pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr); - - dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n", - base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), - base_addr + readl(&fid->zfwctrl_addr)); - - nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); - dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", - readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); - - if (nchan == 0) { - dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " - "check the connection between the Z host card and the " - "serial expanders.\n"); - - if (__cyz_fpga_loaded(ctl_addr)) - plx_init(pdev, irq, ctl_addr); - - dev_info(&pdev->dev, "Null number of ports detected. Board " - "reset.\n"); - retval = 0; - goto err; - } - - cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX); - cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION); - - /* - Early firmware failed to start looking for commands. - This enables firmware interrupts for those commands. - */ - cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | - (1 << 17)); - cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | - 0x00030800UL); - - return nchan; -err_rel: - release_firmware(fw); -err: - return retval; -} - -static int __devinit cy_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - void __iomem *addr0 = NULL, *addr2 = NULL; - char *card_name = NULL; - u32 uninitialized_var(mailbox); - unsigned int device_id, nchan = 0, card_no, i; - unsigned char plx_ver; - int retval, irq; - - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "cannot enable device\n"); - goto err; - } - - /* read PCI configuration area */ - irq = pdev->irq; - device_id = pdev->device & ~PCI_DEVICE_ID_MASK; - -#if defined(__alpha__) - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ - dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low " - "addresses on Alpha systems.\n"); - retval = -EIO; - goto err_dis; - } -#endif - if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { - dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low " - "addresses\n"); - retval = -EIO; - goto err_dis; - } - - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring " - "it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } - - retval = pci_request_regions(pdev, "cyclades"); - if (retval) { - dev_err(&pdev->dev, "failed to reserve resources\n"); - goto err_dis; - } - - retval = -EIO; - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || - device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { - card_name = "Cyclom-Y"; - - addr0 = ioremap_nocache(pci_resource_start(pdev, 0), - CyPCI_Yctl); - if (addr0 == NULL) { - dev_err(&pdev->dev, "can't remap ctl region\n"); - goto err_reg; - } - addr2 = ioremap_nocache(pci_resource_start(pdev, 2), - CyPCI_Ywin); - if (addr2 == NULL) { - dev_err(&pdev->dev, "can't remap base region\n"); - goto err_unmap; - } - - nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); - if (nchan == 0) { - dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " - "Serial-Modules\n"); - goto err_unmap; - } - } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { - struct RUNTIME_9060 __iomem *ctl_addr; - - ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), - CyPCI_Zctl); - if (addr0 == NULL) { - dev_err(&pdev->dev, "can't remap ctl region\n"); - goto err_reg; - } - - /* Disable interrupts on the PLX before resetting it */ - cy_writew(&ctl_addr->intr_ctrl_stat, - readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); - - plx_init(pdev, irq, addr0); - - mailbox = readl(&ctl_addr->mail_box_0); - - addr2 = ioremap_nocache(pci_resource_start(pdev, 2), - mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); - if (addr2 == NULL) { - dev_err(&pdev->dev, "can't remap base region\n"); - goto err_unmap; - } - - if (mailbox == ZE_V1) { - card_name = "Cyclades-Ze"; - } else { - card_name = "Cyclades-8Zo"; -#ifdef CY_PCI_DEBUG - if (mailbox == ZO_V1) { - cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); - dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA " - "id %lx, ver %lx\n", (ulong)(0xff & - readl(&((struct CUSTOM_REG *)addr2)-> - fpga_id)), (ulong)(0xff & - readl(&((struct CUSTOM_REG *)addr2)-> - fpga_version))); - cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); - } else { - dev_info(&pdev->dev, "Cyclades-Z/PCI: New " - "Cyclades-Z board. FPGA not loaded\n"); - } -#endif - /* The following clears the firmware id word. This - ensures that the driver will not attempt to talk to - the board until it has been properly initialized. - */ - if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) - cy_writel(addr2 + ID_ADDRESS, 0L); - } - - retval = cyz_load_fw(pdev, addr2, addr0, irq); - if (retval <= 0) - goto err_unmap; - nchan = retval; - } - - if ((cy_next_channel + nchan) > NR_PORTS) { - dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " - "channels are available. Change NR_PORTS in " - "cyclades.c and recompile kernel.\n"); - goto err_unmap; - } - /* fill the next cy_card structure available */ - for (card_no = 0; card_no < NR_CARDS; card_no++) { - if (cy_card[card_no].base_addr == NULL) - break; - } - if (card_no == NR_CARDS) { /* no more cy_cards available */ - dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " - "more cards can be used. Change NR_CARDS in " - "cyclades.c and recompile kernel.\n"); - goto err_unmap; - } - - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || - device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { - /* allocate IRQ */ - retval = request_irq(irq, cyy_interrupt, - IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); - if (retval) { - dev_err(&pdev->dev, "could not allocate IRQ\n"); - goto err_unmap; - } - cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; - } else { - struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS; - struct ZFW_CTRL __iomem *zfw_ctrl; - - zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - - cy_card[card_no].hw_ver = mailbox; - cy_card[card_no].num_chips = (unsigned int)-1; - cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; -#ifdef CONFIG_CYZ_INTR - /* allocate IRQ only if board has an IRQ */ - if (irq != 0 && irq != 255) { - retval = request_irq(irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", - &cy_card[card_no]); - if (retval) { - dev_err(&pdev->dev, "could not allocate IRQ\n"); - goto err_unmap; - } - } -#endif /* CONFIG_CYZ_INTR */ - } - - /* set cy_card */ - cy_card[card_no].base_addr = addr2; - cy_card[card_no].ctl_addr.p9050 = addr0; - cy_card[card_no].irq = irq; - cy_card[card_no].bus_index = 1; - cy_card[card_no].first_line = cy_next_channel; - cy_card[card_no].nports = nchan; - retval = cy_init_card(&cy_card[card_no]); - if (retval) - goto err_null; - - pci_set_drvdata(pdev, &cy_card[card_no]); - - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || - device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { - /* enable interrupts in the PCI interface */ - plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; - switch (plx_ver) { - case PLX_9050: - cy_writeb(addr0 + 0x4c, 0x43); - break; - - case PLX_9060: - case PLX_9080: - default: /* Old boards, use PLX_9060 */ - { - struct RUNTIME_9060 __iomem *ctl_addr = addr0; - plx_init(pdev, irq, ctl_addr); - cy_writew(&ctl_addr->intr_ctrl_stat, - readw(&ctl_addr->intr_ctrl_stat) | 0x0900); - break; - } - } - } - - dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " - "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); - for (i = cy_next_channel; i < cy_next_channel + nchan; i++) - tty_register_device(cy_serial_driver, i, &pdev->dev); - cy_next_channel += nchan; - - return 0; -err_null: - cy_card[card_no].base_addr = NULL; - free_irq(irq, &cy_card[card_no]); -err_unmap: - iounmap(addr0); - if (addr2) - iounmap(addr2); -err_reg: - pci_release_regions(pdev); -err_dis: - pci_disable_device(pdev); -err: - return retval; -} - -static void __devexit cy_pci_remove(struct pci_dev *pdev) -{ - struct cyclades_card *cinfo = pci_get_drvdata(pdev); - unsigned int i; - - /* non-Z with old PLX */ - if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == - PLX_9050) - cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); - else -#ifndef CONFIG_CYZ_INTR - if (!cy_is_Z(cinfo)) -#endif - cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat, - readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) & - ~0x0900); - - iounmap(cinfo->base_addr); - if (cinfo->ctl_addr.p9050) - iounmap(cinfo->ctl_addr.p9050); - if (cinfo->irq -#ifndef CONFIG_CYZ_INTR - && !cy_is_Z(cinfo) -#endif /* CONFIG_CYZ_INTR */ - ) - free_irq(cinfo->irq, cinfo); - pci_release_regions(pdev); - - cinfo->base_addr = NULL; - for (i = cinfo->first_line; i < cinfo->first_line + - cinfo->nports; i++) - tty_unregister_device(cy_serial_driver, i); - cinfo->nports = 0; - kfree(cinfo->ports); -} - -static struct pci_driver cy_pci_driver = { - .name = "cyclades", - .id_table = cy_pci_dev_id, - .probe = cy_pci_probe, - .remove = __devexit_p(cy_pci_remove) -}; -#endif - -static int cyclades_proc_show(struct seq_file *m, void *v) -{ - struct cyclades_port *info; - unsigned int i, j; - __u32 cur_jifs = jiffies; - - seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " - "IdleIn Overruns Ldisc\n"); - - /* Output one line for each known port */ - for (i = 0; i < NR_CARDS; i++) - for (j = 0; j < cy_card[i].nports; j++) { - info = &cy_card[i].ports[j]; - - if (info->port.count) { - /* XXX is the ldisc num worth this? */ - struct tty_struct *tty; - struct tty_ldisc *ld; - int num = 0; - tty = tty_port_tty_get(&info->port); - if (tty) { - ld = tty_ldisc_ref(tty); - if (ld) { - num = ld->ops->num; - tty_ldisc_deref(ld); - } - tty_kref_put(tty); - } - seq_printf(m, "%3d %8lu %10lu %8lu " - "%10lu %8lu %9lu %6d\n", info->line, - (cur_jifs - info->idle_stats.in_use) / - HZ, info->idle_stats.xmit_bytes, - (cur_jifs - info->idle_stats.xmit_idle)/ - HZ, info->idle_stats.recv_bytes, - (cur_jifs - info->idle_stats.recv_idle)/ - HZ, info->idle_stats.overruns, - num); - } else - seq_printf(m, "%3d %8lu %10lu %8lu " - "%10lu %8lu %9lu %6ld\n", - info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); - } - return 0; -} - -static int cyclades_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cyclades_proc_show, NULL); -} - -static const struct file_operations cyclades_proc_fops = { - .owner = THIS_MODULE, - .open = cyclades_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* 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 - for Cyclom cards in the system. As each is found, it is probed - to discover how many chips (and thus how many ports) are present. - These ports are mapped to the tty ports 32 and upward in monotonic - fashion. If an 8-port card is replaced with a 16-port card, the - port mapping on a following card will shift. - - This approach is different from what is used in the other serial - device driver because the Cyclom is more properly a multiplexer, - not just an aggregation of serial ports on one card. - - 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 const struct tty_operations cy_ops = { - .open = cy_open, - .close = cy_close, - .write = cy_write, - .put_char = cy_put_char, - .flush_chars = cy_flush_chars, - .write_room = cy_write_room, - .chars_in_buffer = cy_chars_in_buffer, - .flush_buffer = cy_flush_buffer, - .ioctl = cy_ioctl, - .throttle = cy_throttle, - .unthrottle = cy_unthrottle, - .set_termios = cy_set_termios, - .stop = cy_stop, - .start = cy_start, - .hangup = cy_hangup, - .break_ctl = cy_break, - .wait_until_sent = cy_wait_until_sent, - .tiocmget = cy_tiocmget, - .tiocmset = cy_tiocmset, - .get_icount = cy_get_icount, - .proc_fops = &cyclades_proc_fops, -}; - -static int __init cy_init(void) -{ - unsigned int nboards; - int retval = -ENOMEM; - - cy_serial_driver = alloc_tty_driver(NR_PORTS); - if (!cy_serial_driver) - goto err; - - printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n", - __DATE__, __TIME__); - - /* Initialize the tty_driver structure */ - - cy_serial_driver->owner = THIS_MODULE; - cy_serial_driver->driver_name = "cyclades"; - cy_serial_driver->name = "ttyC"; - cy_serial_driver->major = CYCLADES_MAJOR; - cy_serial_driver->minor_start = 0; - 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_DRIVER_DYNAMIC_DEV; - tty_set_operations(cy_serial_driver, &cy_ops); - - retval = tty_register_driver(cy_serial_driver); - if (retval) { - printk(KERN_ERR "Couldn't register Cyclades serial driver\n"); - goto err_frtty; - } - - /* the code below is responsible to find the boards. Each different - type of board has its own detection routine. If a board is found, - the next cy_card structure available is set by the detection - routine. These functions are responsible for checking the - availability of cy_card and cy_port data structures and updating - the cy_next_channel. */ - - /* look for isa boards */ - nboards = cy_detect_isa(); - -#ifdef CONFIG_PCI - /* look for pci boards */ - retval = pci_register_driver(&cy_pci_driver); - if (retval && !nboards) { - tty_unregister_driver(cy_serial_driver); - goto err_frtty; - } -#endif - - return 0; -err_frtty: - put_tty_driver(cy_serial_driver); -err: - return retval; -} /* cy_init */ - -static void __exit cy_cleanup_module(void) -{ - struct cyclades_card *card; - unsigned int i, e1; - -#ifndef CONFIG_CYZ_INTR - del_timer_sync(&cyz_timerlist); -#endif /* CONFIG_CYZ_INTR */ - - e1 = tty_unregister_driver(cy_serial_driver); - if (e1) - printk(KERN_ERR "failed to unregister Cyclades serial " - "driver(%d)\n", e1); - -#ifdef CONFIG_PCI - pci_unregister_driver(&cy_pci_driver); -#endif - - for (i = 0; i < NR_CARDS; i++) { - card = &cy_card[i]; - if (card->base_addr) { - /* clear interrupt */ - cy_writeb(card->base_addr + Cy_ClrIntr, 0); - iounmap(card->base_addr); - if (card->ctl_addr.p9050) - iounmap(card->ctl_addr.p9050); - if (card->irq -#ifndef CONFIG_CYZ_INTR - && !cy_is_Z(card) -#endif /* CONFIG_CYZ_INTR */ - ) - free_irq(card->irq, card); - for (e1 = card->first_line; e1 < card->first_line + - card->nports; e1++) - tty_unregister_device(cy_serial_driver, e1); - kfree(card->ports); - } - } - - put_tty_driver(cy_serial_driver); -} /* cy_cleanup_module */ - -module_init(cy_init); -module_exit(cy_cleanup_module); - -MODULE_LICENSE("GPL"); -MODULE_VERSION(CY_VERSION); -MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); -MODULE_FIRMWARE("cyzfirm.bin"); diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c deleted file mode 100644 index db1cf9c328d8..000000000000 --- a/drivers/char/isicom.c +++ /dev/null @@ -1,1736 +0,0 @@ -/* - * 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. - * - * Original driver code supplied by Multi-Tech - * - * Changes - * 1/9/98 alan@lxorguk.ukuu.org.uk - * Merge to 2.0.x kernel tree - * Obtain and use official major/minors - * Loader switched to a misc device - * (fixed range check bug as a side effect) - * Printk clean up - * 9/12/98 alan@lxorguk.ukuu.org.uk - * Rough port to 2.1.x - * - * 10/6/99 sameer Merged the ISA and PCI drivers to - * a new unified driver. - * - * 3/9/99 sameer Added support for ISI4616 cards. - * - * 16/9/99 sameer We do not force RTS low anymore. - * This is to prevent the firmware - * from getting confused. - * - * 26/10/99 sameer Cosmetic changes:The driver now - * dumps the Port Count information - * along with I/O address and IRQ. - * - * 13/12/99 sameer Fixed the problem with IRQ sharing. - * - * 10/5/00 sameer Fixed isicom_shutdown_board() - * to not lower DTR on all the ports - * when the last port on the card is - * closed. - * - * 10/5/00 sameer Signal mask setup command added - * to isicom_setup_port and - * isicom_shutdown_port. - * - * 24/5/00 sameer The driver is now SMP aware. - * - * - * 27/11/00 Vinayak P Risbud Fixed the Driver Crash Problem - * - * - * 03/01/01 anil .s Added support for resetting the - * internal modems on ISI cards. - * - * 08/02/01 anil .s Upgraded the driver for kernel - * 2.4.x - * - * 11/04/01 Kevin Fixed firmware load problem with - * ISIHP-4X card - * - * 30/04/01 anil .s Fixed the remote login through - * ISI port problem. Now the link - * does not go down before password - * prompt. - * - * 03/05/01 anil .s Fixed the problem with IRQ sharing - * among ISI-PCI cards. - * - * 03/05/01 anil .s Added support to display the version - * info during insmod as well as module - * listing by lsmod. - * - * 10/05/01 anil .s Done the modifications to the source - * file and Install script so that the - * same installation can be used for - * 2.2.x and 2.4.x kernel. - * - * 06/06/01 anil .s Now we drop both dtr and rts during - * shutdown_port as well as raise them - * during isicom_config_port. - * - * 09/06/01 acme@conectiva.com.br use capable, not suser, do - * restore_flags on failure in - * isicom_send_break, verify put_user - * result - * - * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps - * Baud index extended to 21 - * - * 20/03/03 ranjeeth Made to work for Linux Advanced server. - * Taken care of license warning. - * - * 10/12/03 Ravindra Made to work for Fedora Core 1 of - * Red Hat Distribution - * - * 06/01/05 Alan Cox Merged the ISI and base kernel strands - * into a single 2.6 driver - * - * *********************************************************** - * - * To use this driver you also need the support package. You - * can find this in RPM format on - * ftp://ftp.linux.org.uk/pub/linux/alan - * - * You can find the original tools for this direct from Multitech - * ftp://ftp.multitech.com/ISI-Cards/ - * - * Having installed the cards the module options (/etc/modprobe.conf) - * - * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4 - * - * Omit those entries for boards you don't have installed. - * - * TODO - * Merge testing - * 64-bit verification - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#define InterruptTheCard(base) outw(0, (base) + 0xc) -#define ClearInterrupt(base) inw((base) + 0x0a) - -#ifdef DEBUG -#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) -#else -#define isicom_paranoia_check(a, b, c) 0 -#endif - -static int isicom_probe(struct pci_dev *, const struct pci_device_id *); -static void __devexit isicom_remove(struct pci_dev *); - -static struct pci_device_id isicom_pci_tbl[] = { - { PCI_DEVICE(VENDOR_ID, 0x2028) }, - { PCI_DEVICE(VENDOR_ID, 0x2051) }, - { PCI_DEVICE(VENDOR_ID, 0x2052) }, - { PCI_DEVICE(VENDOR_ID, 0x2053) }, - { PCI_DEVICE(VENDOR_ID, 0x2054) }, - { PCI_DEVICE(VENDOR_ID, 0x2055) }, - { PCI_DEVICE(VENDOR_ID, 0x2056) }, - { PCI_DEVICE(VENDOR_ID, 0x2057) }, - { PCI_DEVICE(VENDOR_ID, 0x2058) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, isicom_pci_tbl); - -static struct pci_driver isicom_driver = { - .name = "isicom", - .id_table = isicom_pci_tbl, - .probe = isicom_probe, - .remove = __devexit_p(isicom_remove) -}; - -static int prev_card = 3; /* start servicing isi_card[0] */ -static struct tty_driver *isicom_normal; - -static void isicom_tx(unsigned long _data); -static void isicom_start(struct tty_struct *tty); - -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, 20, 21 -}; - -struct isi_board { - unsigned long base; - int irq; - unsigned char port_count; - unsigned short status; - unsigned short port_status; /* each bit for each port */ - unsigned short shift_count; - struct isi_port *ports; - signed char count; - spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */ - unsigned long flags; - unsigned int index; -}; - -struct isi_port { - unsigned short magic; - struct tty_port port; - u16 channel; - u16 status; - struct isi_board *card; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; -}; - -static struct isi_board isi_card[BOARD_COUNT]; -static struct isi_port isi_ports[PORT_COUNT]; - -/* - * Locking functions for card level locking. We need to own both - * the kernel lock for the card and have the card in a position that - * it wants to talk. - */ - -static inline int WaitTillCardIsFree(unsigned long base) -{ - unsigned int count = 0; - unsigned int a = in_atomic(); /* do we run under spinlock? */ - - while (!(inw(base + 0xe) & 0x1) && count++ < 100) - if (a) - mdelay(1); - else - msleep(1); - - return !(inw(base + 0xe) & 0x1); -} - -static int lock_card(struct isi_board *card) -{ - unsigned long base = card->base; - unsigned int retries, a; - - for (retries = 0; retries < 10; retries++) { - spin_lock_irqsave(&card->card_lock, card->flags); - for (a = 0; a < 10; a++) { - if (inw(base + 0xe) & 0x1) - return 1; - udelay(10); - } - spin_unlock_irqrestore(&card->card_lock, card->flags); - msleep(10); - } - pr_warning("Failed to lock Card (0x%lx)\n", card->base); - - return 0; /* Failed to acquire the card! */ -} - -static void unlock_card(struct isi_board *card) -{ - spin_unlock_irqrestore(&card->card_lock, card->flags); -} - -/* - * ISI Card specific ops ... - */ - -/* card->lock HAS to be held */ -static void raise_dtr(struct isi_port *port) -{ - struct isi_board *card = port->card; - unsigned long base = card->base; - u16 channel = port->channel; - - if (WaitTillCardIsFree(base)) - return; - - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0504, base); - InterruptTheCard(base); - port->status |= ISI_DTR; -} - -/* card->lock HAS to be held */ -static inline void drop_dtr(struct isi_port *port) -{ - struct isi_board *card = port->card; - unsigned long base = card->base; - u16 channel = port->channel; - - if (WaitTillCardIsFree(base)) - return; - - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0404, base); - InterruptTheCard(base); - port->status &= ~ISI_DTR; -} - -/* card->lock HAS to be held */ -static inline void raise_rts(struct isi_port *port) -{ - struct isi_board *card = port->card; - unsigned long base = card->base; - u16 channel = port->channel; - - if (WaitTillCardIsFree(base)) - return; - - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0a04, base); - InterruptTheCard(base); - port->status |= ISI_RTS; -} - -/* card->lock HAS to be held */ -static inline void drop_rts(struct isi_port *port) -{ - struct isi_board *card = port->card; - unsigned long base = card->base; - u16 channel = port->channel; - - if (WaitTillCardIsFree(base)) - return; - - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0804, base); - InterruptTheCard(base); - port->status &= ~ISI_RTS; -} - -/* card->lock MUST NOT be held */ - -static void isicom_dtr_rts(struct tty_port *port, int on) -{ - struct isi_port *ip = container_of(port, struct isi_port, port); - struct isi_board *card = ip->card; - unsigned long base = card->base; - u16 channel = ip->channel; - - if (!lock_card(card)) - return; - - if (on) { - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0f04, base); - InterruptTheCard(base); - ip->status |= (ISI_DTR | ISI_RTS); - } else { - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0C04, base); - InterruptTheCard(base); - ip->status &= ~(ISI_DTR | ISI_RTS); - } - unlock_card(card); -} - -/* card->lock HAS to be held */ -static void drop_dtr_rts(struct isi_port *port) -{ - struct isi_board *card = port->card; - unsigned long base = card->base; - u16 channel = port->channel; - - if (WaitTillCardIsFree(base)) - return; - - outw(0x8000 | (channel << card->shift_count) | 0x02, base); - outw(0x0c04, base); - InterruptTheCard(base); - port->status &= ~(ISI_RTS | ISI_DTR); -} - -/* - * ISICOM Driver specific routines ... - * - */ - -static inline int __isicom_paranoia_check(struct isi_port const *port, - char *name, const char *routine) -{ - if (!port) { - pr_warning("Warning: bad isicom magic for dev %s in %s.\n", - name, routine); - return 1; - } - if (port->magic != ISICOM_MAGIC) { - pr_warning("Warning: NULL isicom port for dev %s in %s.\n", - name, routine); - return 1; - } - - return 0; -} - -/* - * Transmitter. - * - * We shovel data into the card buffers on a regular basis. The card - * will do the rest of the work for us. - */ - -static void isicom_tx(unsigned long _data) -{ - unsigned long flags, base; - unsigned int retries; - short count = (BOARD_COUNT-1), card; - short txcount, wrd, residue, word_count, cnt; - struct isi_port *port; - struct tty_struct *tty; - - /* find next active board */ - card = (prev_card + 1) & 0x0003; - while (count-- > 0) { - if (isi_card[card].status & BOARD_ACTIVE) - break; - card = (card + 1) & 0x0003; - } - if (!(isi_card[card].status & BOARD_ACTIVE)) - goto sched_again; - - prev_card = card; - - count = isi_card[card].port_count; - port = isi_card[card].ports; - base = isi_card[card].base; - - spin_lock_irqsave(&isi_card[card].card_lock, flags); - for (retries = 0; retries < 100; retries++) { - if (inw(base + 0xe) & 0x1) - break; - udelay(2); - } - if (retries >= 100) - goto unlock; - - tty = tty_port_tty_get(&port->port); - if (tty == NULL) - goto put_unlock; - - for (; count > 0; count--, port++) { - /* port not active or tx disabled to force flow control */ - if (!(port->port.flags & ASYNC_INITIALIZED) || - !(port->status & ISI_TXOK)) - continue; - - txcount = min_t(short, TX_SIZE, port->xmit_cnt); - if (txcount <= 0 || tty->stopped || tty->hw_stopped) - continue; - - if (!(inw(base + 0x02) & (1 << port->channel))) - continue; - - pr_debug("txing %d bytes, port%d.\n", - txcount, port->channel + 1); - outw((port->channel << isi_card[card].shift_count) | txcount, - base); - residue = NO; - wrd = 0; - while (1) { - cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - - port->xmit_tail)); - if (residue == YES) { - residue = NO; - if (cnt > 0) { - wrd |= (port->port.xmit_buf[port->xmit_tail] - << 8); - port->xmit_tail = (port->xmit_tail + 1) - & (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt--; - txcount--; - cnt--; - outw(wrd, base); - } else { - outw(wrd, base); - break; - } - } - if (cnt <= 0) - break; - word_count = cnt >> 1; - outsw(base, port->port.xmit_buf+port->xmit_tail, word_count); - port->xmit_tail = (port->xmit_tail - + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1); - txcount -= (word_count << 1); - port->xmit_cnt -= (word_count << 1); - if (cnt & 0x0001) { - residue = YES; - wrd = port->port.xmit_buf[port->xmit_tail]; - port->xmit_tail = (port->xmit_tail + 1) - & (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt--; - txcount--; - } - } - - InterruptTheCard(base); - if (port->xmit_cnt <= 0) - port->status &= ~ISI_TXOK; - if (port->xmit_cnt <= WAKEUP_CHARS) - tty_wakeup(tty); - } - -put_unlock: - tty_kref_put(tty); -unlock: - spin_unlock_irqrestore(&isi_card[card].card_lock, flags); - /* schedule another tx for hopefully in about 10ms */ -sched_again: - mod_timer(&tx, jiffies + msecs_to_jiffies(10)); -} - -/* - * Main interrupt handler routine - */ - -static irqreturn_t isicom_interrupt(int irq, void *dev_id) -{ - struct isi_board *card = dev_id; - struct isi_port *port; - struct tty_struct *tty; - unsigned long base; - u16 header, word_count, count, channel; - short byte_count; - unsigned char *rp; - - if (!card || !(card->status & FIRMWARE_LOADED)) - return IRQ_NONE; - - base = card->base; - - /* did the card interrupt us? */ - if (!(inw(base + 0x0e) & 0x02)) - return IRQ_NONE; - - spin_lock(&card->card_lock); - - /* - * disable any interrupts from the PCI card and lower the - * interrupt line - */ - outw(0x8000, base+0x04); - ClearInterrupt(base); - - inw(base); /* get the dummy word out */ - header = inw(base); - channel = (header & 0x7800) >> card->shift_count; - byte_count = header & 0xff; - - if (channel + 1 > card->port_count) { - pr_warning("%s(0x%lx): %d(channel) > port_count.\n", - __func__, base, channel+1); - outw(0x0000, base+0x04); /* enable interrupts */ - spin_unlock(&card->card_lock); - return IRQ_HANDLED; - } - port = card->ports + channel; - if (!(port->port.flags & ASYNC_INITIALIZED)) { - outw(0x0000, base+0x04); /* enable interrupts */ - spin_unlock(&card->card_lock); - return IRQ_HANDLED; - } - - tty = tty_port_tty_get(&port->port); - if (tty == NULL) { - word_count = byte_count >> 1; - while (byte_count > 1) { - inw(base); - byte_count -= 2; - } - if (byte_count & 0x01) - inw(base); - outw(0x0000, base+0x04); /* enable interrupts */ - spin_unlock(&card->card_lock); - return IRQ_HANDLED; - } - - if (header & 0x8000) { /* Status Packet */ - header = inw(base); - switch (header & 0xff) { - case 0: /* Change in EIA signals */ - if (port->port.flags & ASYNC_CHECK_CD) { - if (port->status & ISI_DCD) { - if (!(header & ISI_DCD)) { - /* Carrier has been lost */ - pr_debug("%s: DCD->low.\n", - __func__); - port->status &= ~ISI_DCD; - tty_hangup(tty); - } - } else if (header & ISI_DCD) { - /* Carrier has been detected */ - pr_debug("%s: DCD->high.\n", - __func__); - port->status |= ISI_DCD; - wake_up_interruptible(&port->port.open_wait); - } - } else { - if (header & ISI_DCD) - port->status |= ISI_DCD; - else - port->status &= ~ISI_DCD; - } - - if (port->port.flags & ASYNC_CTS_FLOW) { - if (tty->hw_stopped) { - if (header & ISI_CTS) { - port->port.tty->hw_stopped = 0; - /* start tx ing */ - port->status |= (ISI_TXOK - | ISI_CTS); - tty_wakeup(tty); - } - } else if (!(header & ISI_CTS)) { - tty->hw_stopped = 1; - /* stop tx ing */ - port->status &= ~(ISI_TXOK | ISI_CTS); - } - } else { - if (header & ISI_CTS) - port->status |= ISI_CTS; - else - port->status &= ~ISI_CTS; - } - - if (header & ISI_DSR) - port->status |= ISI_DSR; - else - port->status &= ~ISI_DSR; - - if (header & ISI_RI) - port->status |= ISI_RI; - else - port->status &= ~ISI_RI; - - break; - - case 1: /* Received Break !!! */ - tty_insert_flip_char(tty, 0, TTY_BREAK); - if (port->port.flags & ASYNC_SAK) - do_SAK(tty); - tty_flip_buffer_push(tty); - break; - - case 2: /* Statistics */ - pr_debug("%s: stats!!!\n", __func__); - break; - - default: - pr_debug("%s: Unknown code in status packet.\n", - __func__); - break; - } - } else { /* Data Packet */ - - count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); - pr_debug("%s: Can rx %d of %d bytes.\n", - __func__, count, byte_count); - word_count = count >> 1; - insw(base, rp, word_count); - byte_count -= (word_count << 1); - if (count & 0x0001) { - tty_insert_flip_char(tty, inw(base) & 0xff, - TTY_NORMAL); - byte_count -= 2; - } - if (byte_count > 0) { - pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n", - __func__, base, channel + 1); - /* drain out unread xtra data */ - while (byte_count > 0) { - inw(base); - byte_count -= 2; - } - } - tty_flip_buffer_push(tty); - } - outw(0x0000, base+0x04); /* enable interrupts */ - spin_unlock(&card->card_lock); - tty_kref_put(tty); - - return IRQ_HANDLED; -} - -static void isicom_config_port(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - unsigned long baud; - unsigned long base = card->base; - u16 channel_setup, channel = port->channel, - shift_count = card->shift_count; - unsigned char flow_ctrl; - - /* FIXME: Switch to new tty baud API */ - baud = C_BAUD(tty); - if (baud & CBAUDEX) { - baud &= ~CBAUDEX; - - /* if CBAUDEX bit is on and the baud is set to either 50 or 75 - * then the card is programmed for 57.6Kbps or 115Kbps - * respectively. - */ - - /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ - if (baud < 1 || baud > 4) - tty->termios->c_cflag &= ~CBAUDEX; - else - baud += 15; - } - if (baud == 15) { - - /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set - * by the set_serial_info ioctl ... this is done by - * the 'setserial' utility. - */ - - if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baud++; /* 57.6 Kbps */ - if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baud += 2; /* 115 Kbps */ - if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baud += 3; /* 230 kbps*/ - if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baud += 4; /* 460 kbps*/ - } - if (linuxb_to_isib[baud] == -1) { - /* hang up */ - drop_dtr(port); - return; - } else - raise_dtr(port); - - if (WaitTillCardIsFree(base) == 0) { - outw(0x8000 | (channel << shift_count) | 0x03, base); - outw(linuxb_to_isib[baud] << 8 | 0x03, base); - channel_setup = 0; - switch (C_CSIZE(tty)) { - case CS5: - channel_setup |= ISICOM_CS5; - break; - case CS6: - channel_setup |= ISICOM_CS6; - break; - case CS7: - channel_setup |= ISICOM_CS7; - break; - case CS8: - channel_setup |= ISICOM_CS8; - break; - } - - if (C_CSTOPB(tty)) - channel_setup |= ISICOM_2SB; - if (C_PARENB(tty)) { - channel_setup |= ISICOM_EVPAR; - if (C_PARODD(tty)) - channel_setup |= ISICOM_ODPAR; - } - outw(channel_setup, base); - InterruptTheCard(base); - } - if (C_CLOCAL(tty)) - port->port.flags &= ~ASYNC_CHECK_CD; - else - port->port.flags |= ASYNC_CHECK_CD; - - /* flow control settings ...*/ - flow_ctrl = 0; - port->port.flags &= ~ASYNC_CTS_FLOW; - if (C_CRTSCTS(tty)) { - port->port.flags |= ASYNC_CTS_FLOW; - flow_ctrl |= ISICOM_CTSRTS; - } - if (I_IXON(tty)) - flow_ctrl |= ISICOM_RESPOND_XONXOFF; - if (I_IXOFF(tty)) - flow_ctrl |= ISICOM_INITIATE_XONXOFF; - - if (WaitTillCardIsFree(base) == 0) { - outw(0x8000 | (channel << shift_count) | 0x04, base); - outw(flow_ctrl << 8 | 0x05, base); - outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base); - InterruptTheCard(base); - } - - /* rx enabled -> enable port for rx on the card */ - if (C_CREAD(tty)) { - card->port_status |= (1 << channel); - outw(card->port_status, base + 0x02); - } -} - -/* open et all */ - -static inline void isicom_setup_board(struct isi_board *bp) -{ - int channel; - struct isi_port *port; - - bp->count++; - if (!(bp->status & BOARD_INIT)) { - port = bp->ports; - for (channel = 0; channel < bp->port_count; channel++, port++) - drop_dtr_rts(port); - } - bp->status |= BOARD_ACTIVE | BOARD_INIT; -} - -/* Activate and thus setup board are protected from races against shutdown - by the tty_port mutex */ - -static int isicom_activate(struct tty_port *tport, struct tty_struct *tty) -{ - struct isi_port *port = container_of(tport, struct isi_port, port); - struct isi_board *card = port->card; - unsigned long flags; - - if (tty_port_alloc_xmit_buf(tport) < 0) - return -ENOMEM; - - spin_lock_irqsave(&card->card_lock, flags); - isicom_setup_board(card); - - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - - /* discard any residual data */ - if (WaitTillCardIsFree(card->base) == 0) { - outw(0x8000 | (port->channel << card->shift_count) | 0x02, - card->base); - outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); - InterruptTheCard(card->base); - } - isicom_config_port(tty); - spin_unlock_irqrestore(&card->card_lock, flags); - - return 0; -} - -static int isicom_carrier_raised(struct tty_port *port) -{ - struct isi_port *ip = container_of(port, struct isi_port, port); - return (ip->status & ISI_DCD)?1 : 0; -} - -static struct tty_port *isicom_find_port(struct tty_struct *tty) -{ - struct isi_port *port; - struct isi_board *card; - unsigned int board; - int line = tty->index; - - if (line < 0 || line > PORT_COUNT-1) - return NULL; - board = BOARD(line); - card = &isi_card[board]; - - if (!(card->status & FIRMWARE_LOADED)) - return NULL; - - /* open on a port greater than the port count for the card !!! */ - if (line > ((board * 16) + card->port_count - 1)) - return NULL; - - port = &isi_ports[line]; - if (isicom_paranoia_check(port, tty->name, "isicom_open")) - return NULL; - - return &port->port; -} - -static int isicom_open(struct tty_struct *tty, struct file *filp) -{ - struct isi_port *port; - struct tty_port *tport; - - tport = isicom_find_port(tty); - if (tport == NULL) - return -ENODEV; - port = container_of(tport, struct isi_port, port); - - tty->driver_data = port; - return tty_port_open(tport, tty, filp); -} - -/* close et all */ - -/* card->lock HAS to be held */ -static void isicom_shutdown_port(struct isi_port *port) -{ - struct isi_board *card = port->card; - - if (--card->count < 0) { - pr_debug("%s: bad board(0x%lx) count %d.\n", - __func__, card->base, card->count); - card->count = 0; - } - /* last port was closed, shutdown that board too */ - if (!card->count) - card->status &= BOARD_ACTIVE; -} - -static void isicom_flush_buffer(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - unsigned long flags; - - if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer")) - return; - - spin_lock_irqsave(&card->card_lock, flags); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - spin_unlock_irqrestore(&card->card_lock, flags); - - tty_wakeup(tty); -} - -static void isicom_shutdown(struct tty_port *port) -{ - struct isi_port *ip = container_of(port, struct isi_port, port); - struct isi_board *card = ip->card; - unsigned long flags; - - /* indicate to the card that no more data can be received - on this port */ - spin_lock_irqsave(&card->card_lock, flags); - card->port_status &= ~(1 << ip->channel); - outw(card->port_status, card->base + 0x02); - isicom_shutdown_port(ip); - spin_unlock_irqrestore(&card->card_lock, flags); - tty_port_free_xmit_buf(port); -} - -static void isicom_close(struct tty_struct *tty, struct file *filp) -{ - struct isi_port *ip = tty->driver_data; - struct tty_port *port; - - if (ip == NULL) - return; - - port = &ip->port; - if (isicom_paranoia_check(ip, tty->name, "isicom_close")) - return; - tty_port_close(port, tty, filp); -} - -/* write et all */ -static int isicom_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - unsigned long flags; - int cnt, total = 0; - - if (isicom_paranoia_check(port, tty->name, "isicom_write")) - return 0; - - spin_lock_irqsave(&card->card_lock, flags); - - while (1) { - cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - - 1, SERIAL_XMIT_SIZE - port->xmit_head)); - if (cnt <= 0) - break; - - memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt); - port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - - 1); - port->xmit_cnt += cnt; - buf += cnt; - count -= cnt; - total += cnt; - } - if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped) - port->status |= ISI_TXOK; - spin_unlock_irqrestore(&card->card_lock, flags); - return total; -} - -/* put_char et all */ -static int isicom_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - unsigned long flags; - - if (isicom_paranoia_check(port, tty->name, "isicom_put_char")) - return 0; - - spin_lock_irqsave(&card->card_lock, flags); - if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - spin_unlock_irqrestore(&card->card_lock, flags); - return 0; - } - - port->port.xmit_buf[port->xmit_head++] = ch; - port->xmit_head &= (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt++; - spin_unlock_irqrestore(&card->card_lock, flags); - return 1; -} - -/* flush_chars et all */ -static void isicom_flush_chars(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - - if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars")) - return; - - if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !port->port.xmit_buf) - return; - - /* this tells the transmitter to consider this port for - data output to the card ... that's the best we can do. */ - port->status |= ISI_TXOK; -} - -/* write_room et all */ -static int isicom_write_room(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - int free; - - if (isicom_paranoia_check(port, tty->name, "isicom_write_room")) - return 0; - - free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; - if (free < 0) - free = 0; - return free; -} - -/* chars_in_buffer et all */ -static int isicom_chars_in_buffer(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer")) - return 0; - return port->xmit_cnt; -} - -/* ioctl et all */ -static int isicom_send_break(struct tty_struct *tty, int length) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - unsigned long base = card->base; - - if (length == -1) - return -EOPNOTSUPP; - - if (!lock_card(card)) - return -EINVAL; - - outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base); - outw((length & 0xff) << 8 | 0x00, base); - outw((length & 0xff00), base); - InterruptTheCard(base); - - unlock_card(card); - return 0; -} - -static int isicom_tiocmget(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - /* just send the port status */ - u16 status = port->status; - - if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) - return -ENODEV; - - return ((status & ISI_RTS) ? TIOCM_RTS : 0) | - ((status & ISI_DTR) ? TIOCM_DTR : 0) | - ((status & ISI_DCD) ? TIOCM_CAR : 0) | - ((status & ISI_DSR) ? TIOCM_DSR : 0) | - ((status & ISI_CTS) ? TIOCM_CTS : 0) | - ((status & ISI_RI ) ? TIOCM_RI : 0); -} - -static int isicom_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct isi_port *port = tty->driver_data; - unsigned long flags; - - if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) - return -ENODEV; - - spin_lock_irqsave(&port->card->card_lock, flags); - if (set & TIOCM_RTS) - raise_rts(port); - if (set & TIOCM_DTR) - raise_dtr(port); - - if (clear & TIOCM_RTS) - drop_rts(port); - if (clear & TIOCM_DTR) - drop_dtr(port); - spin_unlock_irqrestore(&port->card->card_lock, flags); - - return 0; -} - -static int isicom_set_serial_info(struct tty_struct *tty, - struct serial_struct __user *info) -{ - struct isi_port *port = tty->driver_data; - struct serial_struct newinfo; - int reconfig_port; - - if (copy_from_user(&newinfo, info, sizeof(newinfo))) - return -EFAULT; - - mutex_lock(&port->port.mutex); - reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != - (newinfo.flags & ASYNC_SPD_MASK)); - - if (!capable(CAP_SYS_ADMIN)) { - if ((newinfo.close_delay != port->port.close_delay) || - (newinfo.closing_wait != port->port.closing_wait) || - ((newinfo.flags & ~ASYNC_USR_MASK) != - (port->port.flags & ~ASYNC_USR_MASK))) { - mutex_unlock(&port->port.mutex); - return -EPERM; - } - port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | - (newinfo.flags & ASYNC_USR_MASK)); - } else { - port->port.close_delay = newinfo.close_delay; - port->port.closing_wait = newinfo.closing_wait; - port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | - (newinfo.flags & ASYNC_FLAGS)); - } - if (reconfig_port) { - unsigned long flags; - spin_lock_irqsave(&port->card->card_lock, flags); - isicom_config_port(tty); - spin_unlock_irqrestore(&port->card->card_lock, flags); - } - mutex_unlock(&port->port.mutex); - return 0; -} - -static int isicom_get_serial_info(struct isi_port *port, - struct serial_struct __user *info) -{ - struct serial_struct out_info; - - mutex_lock(&port->port.mutex); - memset(&out_info, 0, sizeof(out_info)); -/* out_info.type = ? */ - out_info.line = port - isi_ports; - out_info.port = port->card->base; - out_info.irq = port->card->irq; - out_info.flags = port->port.flags; -/* out_info.baud_base = ? */ - out_info.close_delay = port->port.close_delay; - out_info.closing_wait = port->port.closing_wait; - mutex_unlock(&port->port.mutex); - if (copy_to_user(info, &out_info, sizeof(out_info))) - return -EFAULT; - return 0; -} - -static int isicom_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct isi_port *port = tty->driver_data; - void __user *argp = (void __user *)arg; - - if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) - return -ENODEV; - - switch (cmd) { - case TIOCGSERIAL: - return isicom_get_serial_info(port, argp); - - case TIOCSSERIAL: - return isicom_set_serial_info(tty, argp); - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -/* set_termios et all */ -static void isicom_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct isi_port *port = tty->driver_data; - unsigned long flags; - - if (isicom_paranoia_check(port, tty->name, "isicom_set_termios")) - return; - - if (tty->termios->c_cflag == old_termios->c_cflag && - tty->termios->c_iflag == old_termios->c_iflag) - return; - - spin_lock_irqsave(&port->card->card_lock, flags); - isicom_config_port(tty); - spin_unlock_irqrestore(&port->card->card_lock, flags); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - isicom_start(tty); - } -} - -/* throttle et all */ -static void isicom_throttle(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - - if (isicom_paranoia_check(port, tty->name, "isicom_throttle")) - return; - - /* tell the card that this port cannot handle any more data for now */ - card->port_status &= ~(1 << port->channel); - outw(card->port_status, card->base + 0x02); -} - -/* unthrottle et all */ -static void isicom_unthrottle(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; - - if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle")) - return; - - /* tell the card that this port is ready to accept more data */ - card->port_status |= (1 << port->channel); - outw(card->port_status, card->base + 0x02); -} - -/* stop et all */ -static void isicom_stop(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - - if (isicom_paranoia_check(port, tty->name, "isicom_stop")) - return; - - /* this tells the transmitter not to consider this port for - data output to the card. */ - port->status &= ~ISI_TXOK; -} - -/* start et all */ -static void isicom_start(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - - if (isicom_paranoia_check(port, tty->name, "isicom_start")) - return; - - /* this tells the transmitter to consider this port for - data output to the card. */ - port->status |= ISI_TXOK; -} - -static void isicom_hangup(struct tty_struct *tty) -{ - struct isi_port *port = tty->driver_data; - - if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) - return; - tty_port_hangup(&port->port); -} - - -/* - * Driver init and deinit functions - */ - -static const struct tty_operations isicom_ops = { - .open = isicom_open, - .close = isicom_close, - .write = isicom_write, - .put_char = isicom_put_char, - .flush_chars = isicom_flush_chars, - .write_room = isicom_write_room, - .chars_in_buffer = isicom_chars_in_buffer, - .ioctl = isicom_ioctl, - .set_termios = isicom_set_termios, - .throttle = isicom_throttle, - .unthrottle = isicom_unthrottle, - .stop = isicom_stop, - .start = isicom_start, - .hangup = isicom_hangup, - .flush_buffer = isicom_flush_buffer, - .tiocmget = isicom_tiocmget, - .tiocmset = isicom_tiocmset, - .break_ctl = isicom_send_break, -}; - -static const struct tty_port_operations isicom_port_ops = { - .carrier_raised = isicom_carrier_raised, - .dtr_rts = isicom_dtr_rts, - .activate = isicom_activate, - .shutdown = isicom_shutdown, -}; - -static int __devinit reset_card(struct pci_dev *pdev, - const unsigned int card, unsigned int *signature) -{ - struct isi_board *board = pci_get_drvdata(pdev); - unsigned long base = board->base; - unsigned int sig, portcount = 0; - int retval = 0; - - dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, - base); - - inw(base + 0x8); - - msleep(10); - - outw(0, base + 0x8); /* Reset */ - - msleep(1000); - - 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 && portcount != 16)) { - dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n", - card + 1); - retval = -EIO; - goto end; - } - - switch (sig) { - case 0xa5: - case 0xbb: - case 0xdd: - board->port_count = (portcount == 4) ? 4 : 8; - board->shift_count = 12; - break; - case 0xcc: - case 0xee: - board->port_count = 16; - board->shift_count = 11; - break; - } - dev_info(&pdev->dev, "-Done\n"); - *signature = sig; - -end: - return retval; -} - -static int __devinit load_firmware(struct pci_dev *pdev, - const unsigned int index, const unsigned int signature) -{ - struct isi_board *board = pci_get_drvdata(pdev); - const struct firmware *fw; - unsigned long base = board->base; - unsigned int a; - u16 word_count, status; - int retval = -EIO; - char *name; - u8 *data; - - struct stframe { - u16 addr; - u16 count; - u8 data[0]; - } *frame; - - switch (signature) { - case 0xa5: - name = "isi608.bin"; - break; - case 0xbb: - name = "isi608em.bin"; - break; - case 0xcc: - name = "isi616em.bin"; - break; - case 0xdd: - name = "isi4608.bin"; - break; - case 0xee: - name = "isi4616.bin"; - break; - default: - dev_err(&pdev->dev, "Unknown signature.\n"); - goto end; - } - - retval = request_firmware(&fw, name, &pdev->dev); - if (retval) - goto end; - - retval = -EIO; - - for (frame = (struct stframe *)fw->data; - frame < (struct stframe *)(fw->data + fw->size); - frame = (struct stframe *)((u8 *)(frame + 1) + - frame->count)) { - if (WaitTillCardIsFree(base)) - goto errrelfw; - - outw(0xf0, base); /* start upload sequence */ - outw(0x00, base); - outw(frame->addr, base); /* lsb of address */ - - word_count = frame->count / 2 + frame->count % 2; - outw(word_count, base); - InterruptTheCard(base); - - udelay(100); /* 0x2f */ - - if (WaitTillCardIsFree(base)) - goto errrelfw; - - status = inw(base + 0x4); - if (status != 0) { - dev_warn(&pdev->dev, "Card%d rejected load header:\n" - "Address:0x%x\n" - "Count:0x%x\n" - "Status:0x%x\n", - index + 1, frame->addr, frame->count, status); - goto errrelfw; - } - outsw(base, frame->data, word_count); - - InterruptTheCard(base); - - udelay(50); /* 0x0f */ - - if (WaitTillCardIsFree(base)) - goto errrelfw; - - status = inw(base + 0x4); - if (status != 0) { - dev_err(&pdev->dev, "Card%d got out of sync.Card " - "Status:0x%x\n", index + 1, status); - goto errrelfw; - } - } - -/* XXX: should we test it by reading it back and comparing with original like - * in load firmware package? */ - for (frame = (struct stframe *)fw->data; - frame < (struct stframe *)(fw->data + fw->size); - frame = (struct stframe *)((u8 *)(frame + 1) + - frame->count)) { - if (WaitTillCardIsFree(base)) - goto errrelfw; - - outw(0xf1, base); /* start download sequence */ - outw(0x00, base); - outw(frame->addr, base); /* lsb of address */ - - word_count = (frame->count >> 1) + frame->count % 2; - outw(word_count + 1, base); - InterruptTheCard(base); - - udelay(50); /* 0xf */ - - if (WaitTillCardIsFree(base)) - goto errrelfw; - - status = inw(base + 0x4); - if (status != 0) { - dev_warn(&pdev->dev, "Card%d rejected verify header:\n" - "Address:0x%x\n" - "Count:0x%x\n" - "Status: 0x%x\n", - index + 1, frame->addr, frame->count, status); - goto errrelfw; - } - - data = kmalloc(word_count * 2, GFP_KERNEL); - if (data == NULL) { - dev_err(&pdev->dev, "Card%d, firmware upload " - "failed, not enough memory\n", index + 1); - goto errrelfw; - } - inw(base); - insw(base, data, word_count); - InterruptTheCard(base); - - for (a = 0; a < frame->count; a++) - if (data[a] != frame->data[a]) { - kfree(data); - dev_err(&pdev->dev, "Card%d, firmware upload " - "failed\n", index + 1); - goto errrelfw; - } - kfree(data); - - udelay(50); /* 0xf */ - - if (WaitTillCardIsFree(base)) - goto errrelfw; - - status = inw(base + 0x4); - if (status != 0) { - dev_err(&pdev->dev, "Card%d verify got out of sync. " - "Card Status:0x%x\n", index + 1, status); - goto errrelfw; - } - } - - /* xfer ctrl */ - if (WaitTillCardIsFree(base)) - goto errrelfw; - - outw(0xf2, base); - outw(0x800, base); - outw(0x0, base); - outw(0x0, base); - InterruptTheCard(base); - outw(0x0, base + 0x4); /* for ISI4608 cards */ - - board->status |= FIRMWARE_LOADED; - retval = 0; - -errrelfw: - release_firmware(fw); -end: - return retval; -} - -/* - * Insmod can set static symbols so keep these static - */ -static unsigned int card_count; - -static int __devinit isicom_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - unsigned int uninitialized_var(signature), index; - int retval = -EPERM; - struct isi_board *board = NULL; - - if (card_count >= BOARD_COUNT) - goto err; - - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "failed to enable\n"); - goto err; - } - - dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); - - /* allot the first empty slot in the array */ - for (index = 0; index < BOARD_COUNT; index++) { - if (isi_card[index].base == 0) { - board = &isi_card[index]; - break; - } - } - if (index == BOARD_COUNT) { - retval = -ENODEV; - goto err_disable; - } - - board->index = index; - board->base = pci_resource_start(pdev, 3); - board->irq = pdev->irq; - card_count++; - - pci_set_drvdata(pdev, board); - - retval = pci_request_region(pdev, 3, ISICOM_NAME); - if (retval) { - dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " - "will be disabled.\n", board->base, board->base + 15, - index + 1); - retval = -EBUSY; - goto errdec; - } - - retval = request_irq(board->irq, isicom_interrupt, - IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); - if (retval < 0) { - dev_err(&pdev->dev, "Could not install handler at Irq %d. " - "Card%d will be disabled.\n", board->irq, index + 1); - goto errunrr; - } - - retval = reset_card(pdev, index, &signature); - if (retval < 0) - goto errunri; - - retval = load_firmware(pdev, index, signature); - if (retval < 0) - goto errunri; - - for (index = 0; index < board->port_count; index++) - tty_register_device(isicom_normal, board->index * 16 + index, - &pdev->dev); - - return 0; - -errunri: - free_irq(board->irq, board); -errunrr: - pci_release_region(pdev, 3); -errdec: - board->base = 0; - card_count--; -err_disable: - pci_disable_device(pdev); -err: - return retval; -} - -static void __devexit isicom_remove(struct pci_dev *pdev) -{ - struct isi_board *board = pci_get_drvdata(pdev); - unsigned int i; - - for (i = 0; i < board->port_count; i++) - tty_unregister_device(isicom_normal, board->index * 16 + i); - - free_irq(board->irq, board); - pci_release_region(pdev, 3); - board->base = 0; - card_count--; - pci_disable_device(pdev); -} - -static int __init isicom_init(void) -{ - int retval, idx, channel; - struct isi_port *port; - - for (idx = 0; idx < BOARD_COUNT; idx++) { - port = &isi_ports[idx * 16]; - isi_card[idx].ports = port; - spin_lock_init(&isi_card[idx].card_lock); - for (channel = 0; channel < 16; channel++, port++) { - tty_port_init(&port->port); - port->port.ops = &isicom_port_ops; - port->magic = ISICOM_MAGIC; - port->card = &isi_card[idx]; - port->channel = channel; - port->port.close_delay = 50 * HZ/100; - port->port.closing_wait = 3000 * HZ/100; - port->status = 0; - /* . . . */ - } - isi_card[idx].base = 0; - isi_card[idx].irq = 0; - } - - /* tty driver structure initialization */ - isicom_normal = alloc_tty_driver(PORT_COUNT); - if (!isicom_normal) { - retval = -ENOMEM; - goto error; - } - - isicom_normal->owner = THIS_MODULE; - isicom_normal->name = "ttyM"; - isicom_normal->major = ISICOM_NMAJOR; - isicom_normal->minor_start = 0; - isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; - isicom_normal->subtype = SERIAL_TYPE_NORMAL; - isicom_normal->init_termios = tty_std_termios; - isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | - CLOCAL; - isicom_normal->flags = TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK; - tty_set_operations(isicom_normal, &isicom_ops); - - retval = tty_register_driver(isicom_normal); - if (retval) { - pr_debug("Couldn't register the dialin driver\n"); - goto err_puttty; - } - - retval = pci_register_driver(&isicom_driver); - if (retval < 0) { - pr_err("Unable to register pci driver.\n"); - goto err_unrtty; - } - - mod_timer(&tx, jiffies + 1); - - return 0; -err_unrtty: - tty_unregister_driver(isicom_normal); -err_puttty: - put_tty_driver(isicom_normal); -error: - return retval; -} - -static void __exit isicom_exit(void) -{ - del_timer_sync(&tx); - - pci_unregister_driver(&isicom_driver); - tty_unregister_driver(isicom_normal); - put_tty_driver(isicom_normal); -} - -module_init(isicom_init); -module_exit(isicom_exit); - -MODULE_AUTHOR("MultiTech"); -MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("isi608.bin"); -MODULE_FIRMWARE("isi608em.bin"); -MODULE_FIRMWARE("isi616em.bin"); -MODULE_FIRMWARE("isi4608.bin"); -MODULE_FIRMWARE("isi4616.bin"); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c deleted file mode 100644 index 35b0c38590e6..000000000000 --- a/drivers/char/moxa.c +++ /dev/null @@ -1,2092 +0,0 @@ -/*****************************************************************************/ -/* - * moxa.c -- MOXA Intellio family multiport serial driver. - * - * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com). - * Copyright (c) 2007 Jiri Slaby - * - * This code is loosely based on the Linux serial driver, written by - * Linus Torvalds, Theodore T'so and others. - * - * 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. - */ - -/* - * MOXA Intellio Series Driver - * for : LINUX - * date : 1999/1/7 - * version : 5.1 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "moxa.h" - -#define MOXA_VERSION "6.0k" - -#define MOXA_FW_HDRLEN 32 - -#define MOXAMAJOR 172 - -#define MAX_BOARDS 4 /* Don't change this value */ -#define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ -#define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) - -#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \ - (brd)->boardType == MOXA_BOARD_C320_PCI) - -/* - * Define the Moxa PCI vendor and device IDs. - */ -#define MOXA_BUS_TYPE_ISA 0 -#define MOXA_BUS_TYPE_PCI 1 - -enum { - MOXA_BOARD_C218_PCI = 1, - MOXA_BOARD_C218_ISA, - MOXA_BOARD_C320_PCI, - MOXA_BOARD_C320_ISA, - MOXA_BOARD_CP204J, -}; - -static char *moxa_brdname[] = -{ - "C218 Turbo PCI series", - "C218 Turbo ISA series", - "C320 Turbo PCI series", - "C320 Turbo ISA series", - "CP-204J series", -}; - -#ifdef CONFIG_PCI -static struct pci_device_id moxa_pcibrds[] = { - { 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 */ - -struct moxa_port; - -static struct moxa_board_conf { - int boardType; - int numPorts; - int busType; - - unsigned int ready; - - struct moxa_port *ports; - - 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_port { - struct tty_port port; - struct moxa_board_conf *board; - void __iomem *tableAddr; - - int type; - int cflag; - unsigned long statusflags; - - u8 DCDState; /* Protected by the port lock */ - u8 lineCtrl; - u8 lowChkFlag; -}; - -struct mon_str { - int tick; - int rxcnt[MAX_PORTS]; - int txcnt[MAX_PORTS]; -}; - -/* statusflags */ -#define TXSTOPPED 1 -#define LOWWAIT 2 -#define EMPTYWAIT 3 - -#define SERIAL_DO_RESTART - -#define WAKEUP_CHARS 256 - -static int ttymajor = MOXAMAJOR; -static struct mon_str moxaLog; -static unsigned int moxaFuncTout = HZ / 2; -static unsigned int moxaLowWaterChk; -static DEFINE_MUTEX(moxa_openlock); -static DEFINE_SPINLOCK(moxa_lock); - -static unsigned long baseaddr[MAX_BOARDS]; -static unsigned int type[MAX_BOARDS]; -static unsigned int numports[MAX_BOARDS]; - -MODULE_AUTHOR("William Chen"); -MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("c218tunx.cod"); -MODULE_FIRMWARE("cp204unx.cod"); -MODULE_FIRMWARE("c320tunx.cod"); - -module_param_array(type, uint, NULL, 0); -MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); -module_param_array(baseaddr, ulong, NULL, 0); -MODULE_PARM_DESC(baseaddr, "base address"); -module_param_array(numports, uint, NULL, 0); -MODULE_PARM_DESC(numports, "numports (ignored for C218)"); - -module_param(ttymajor, int, 0); - -/* - * static functions: - */ -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); -static int moxa_write_room(struct tty_struct *); -static void moxa_flush_buffer(struct tty_struct *); -static int moxa_chars_in_buffer(struct tty_struct *); -static void moxa_set_termios(struct tty_struct *, struct ktermios *); -static void moxa_stop(struct tty_struct *); -static void moxa_start(struct tty_struct *); -static void moxa_hangup(struct tty_struct *); -static int moxa_tiocmget(struct tty_struct *tty); -static int moxa_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear); -static void moxa_poll(unsigned long); -static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); -static void moxa_shutdown(struct tty_port *); -static int moxa_carrier_raised(struct tty_port *); -static void moxa_dtr_rts(struct tty_port *, int); -/* - * moxa board interface functions: - */ -static void MoxaPortEnable(struct moxa_port *); -static void MoxaPortDisable(struct moxa_port *); -static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t); -static int MoxaPortGetLineOut(struct moxa_port *, int *, int *); -static void MoxaPortLineCtrl(struct moxa_port *, int, int); -static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); -static int MoxaPortLineStatus(struct moxa_port *); -static void MoxaPortFlushData(struct moxa_port *, int); -static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int); -static int MoxaPortReadData(struct moxa_port *); -static int MoxaPortTxQueue(struct moxa_port *); -static int MoxaPortRxQueue(struct moxa_port *); -static int MoxaPortTxFree(struct moxa_port *); -static void MoxaPortTxDisable(struct moxa_port *); -static void MoxaPortTxEnable(struct moxa_port *); -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(struct moxa_port *port, int enable); - -/* - * I/O functions - */ - -static DEFINE_SPINLOCK(moxafunc_lock); - -static void moxa_wait_finish(void __iomem *ofsAddr) -{ - unsigned long end = jiffies + moxaFuncTout; - - while (readw(ofsAddr + FuncCode) != 0) - if (time_after(jiffies, end)) - return; - if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit()) - printk(KERN_WARNING "moxa function expired\n"); -} - -static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) -{ - unsigned long flags; - spin_lock_irqsave(&moxafunc_lock, flags); - writew(arg, ofsAddr + FuncArg); - writew(cmd, ofsAddr + FuncCode); - moxa_wait_finish(ofsAddr); - spin_unlock_irqrestore(&moxafunc_lock, flags); -} - -static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) -{ - unsigned long flags; - u16 ret; - spin_lock_irqsave(&moxafunc_lock, flags); - writew(arg, ofsAddr + FuncArg); - writew(cmd, ofsAddr + FuncCode); - moxa_wait_finish(ofsAddr); - ret = readw(ofsAddr + FuncArg); - spin_unlock_irqrestore(&moxafunc_lock, flags); - return ret; -} - -static void moxa_low_water_check(void __iomem *ofsAddr) -{ - u16 rptr, wptr, mask, len; - - if (readb(ofsAddr + FlagStat) & Xoff_state) { - rptr = readw(ofsAddr + RXrptr); - wptr = readw(ofsAddr + RXwptr); - mask = readw(ofsAddr + RX_mask); - len = (wptr - rptr) & mask; - if (len <= Low_water) - moxafunc(ofsAddr, FC_SendXon, 0); - } -} - -/* - * TTY operations - */ - -static int moxa_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct moxa_port *ch = tty->driver_data; - void __user *argp = (void __user *)arg; - int status, ret = 0; - - if (tty->index == MAX_PORTS) { - if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE && - cmd != MOXA_GETMSTATUS) - return -EINVAL; - } else if (!ch) - return -ENODEV; - - switch (cmd) { - case MOXA_GETDATACOUNT: - moxaLog.tick = jiffies; - if (copy_to_user(argp, &moxaLog, sizeof(moxaLog))) - ret = -EFAULT; - break; - case MOXA_FLUSH_QUEUE: - MoxaPortFlushData(ch, arg); - break; - case MOXA_GET_IOQUEUE: { - struct moxaq_str __user *argm = argp; - struct moxaq_str tmp; - struct moxa_port *p; - unsigned int i, j; - - for (i = 0; i < MAX_BOARDS; i++) { - p = moxa_boards[i].ports; - for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { - memset(&tmp, 0, sizeof(tmp)); - spin_lock_bh(&moxa_lock); - if (moxa_boards[i].ready) { - tmp.inq = MoxaPortRxQueue(p); - tmp.outq = MoxaPortTxQueue(p); - } - spin_unlock_bh(&moxa_lock); - if (copy_to_user(argm, &tmp, sizeof(tmp))) - return -EFAULT; - } - } - break; - } case MOXA_GET_OQUEUE: - status = MoxaPortTxQueue(ch); - ret = put_user(status, (unsigned long __user *)argp); - break; - case MOXA_GET_IQUEUE: - status = MoxaPortRxQueue(ch); - ret = put_user(status, (unsigned long __user *)argp); - break; - case MOXA_GETMSTATUS: { - struct mxser_mstatus __user *argm = argp; - struct mxser_mstatus tmp; - struct moxa_port *p; - unsigned int i, j; - - for (i = 0; i < MAX_BOARDS; i++) { - p = moxa_boards[i].ports; - for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { - struct tty_struct *ttyp; - memset(&tmp, 0, sizeof(tmp)); - spin_lock_bh(&moxa_lock); - if (!moxa_boards[i].ready) { - spin_unlock_bh(&moxa_lock); - goto copy; - } - - status = MoxaPortLineStatus(p); - spin_unlock_bh(&moxa_lock); - - if (status & 1) - tmp.cts = 1; - if (status & 2) - tmp.dsr = 1; - if (status & 4) - tmp.dcd = 1; - - ttyp = tty_port_tty_get(&p->port); - if (!ttyp || !ttyp->termios) - tmp.cflag = p->cflag; - else - tmp.cflag = ttyp->termios->c_cflag; - tty_kref_put(tty); -copy: - if (copy_to_user(argm, &tmp, sizeof(tmp))) - return -EFAULT; - } - } - break; - } - case TIOCGSERIAL: - mutex_lock(&ch->port.mutex); - ret = moxa_get_serial_info(ch, argp); - mutex_unlock(&ch->port.mutex); - break; - case TIOCSSERIAL: - mutex_lock(&ch->port.mutex); - ret = moxa_set_serial_info(ch, argp); - mutex_unlock(&ch->port.mutex); - break; - default: - ret = -ENOIOCTLCMD; - } - return ret; -} - -static int moxa_break_ctl(struct tty_struct *tty, int state) -{ - struct moxa_port *port = tty->driver_data; - - moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, - Magic_code); - return 0; -} - -static const struct tty_operations moxa_ops = { - .open = moxa_open, - .close = moxa_close, - .write = moxa_write, - .write_room = moxa_write_room, - .flush_buffer = moxa_flush_buffer, - .chars_in_buffer = moxa_chars_in_buffer, - .ioctl = moxa_ioctl, - .set_termios = moxa_set_termios, - .stop = moxa_stop, - .start = moxa_start, - .hangup = moxa_hangup, - .break_ctl = moxa_break_ctl, - .tiocmget = moxa_tiocmget, - .tiocmset = moxa_tiocmset, -}; - -static const struct tty_port_operations moxa_port_ops = { - .carrier_raised = moxa_carrier_raised, - .dtr_rts = moxa_dtr_rts, - .shutdown = moxa_shutdown, -}; - -static struct tty_driver *moxaDriver; -static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); - -/* - * HW init - */ - -static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) -{ - switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: - case MOXA_BOARD_C218_PCI: - if (model != 1) - goto err; - break; - case MOXA_BOARD_CP204J: - if (model != 3) - goto err; - break; - default: - if (model != 2) - goto err; - break; - } - return 0; -err: - return -EINVAL; -} - -static int moxa_check_fw(const void *ptr) -{ - const __le16 *lptr = ptr; - - if (*lptr != cpu_to_le16(0x7980)) - return -EINVAL; - - return 0; -} - -static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, - size_t len) -{ - void __iomem *baseAddr = brd->basemem; - u16 tmp; - - writeb(HW_reset, baseAddr + Control_reg); /* reset */ - msleep(10); - memset_io(baseAddr, 0, 4096); - memcpy_toio(baseAddr, buf, len); /* download BIOS */ - writeb(0, baseAddr + Control_reg); /* restart */ - - msleep(2000); - - switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: - case MOXA_BOARD_C218_PCI: - tmp = readw(baseAddr + C218_key); - if (tmp != C218_KeyCode) - goto err; - break; - case MOXA_BOARD_CP204J: - tmp = readw(baseAddr + C218_key); - if (tmp != CP204J_KeyCode) - goto err; - break; - default: - tmp = readw(baseAddr + C320_key); - if (tmp != C320_KeyCode) - goto err; - tmp = readw(baseAddr + C320_status); - if (tmp != STS_init) { - printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic " - "module not found\n"); - return -EIO; - } - break; - } - - return 0; -err: - printk(KERN_ERR "MOXA: bios upload failed -- board not found\n"); - return -EIO; -} - -static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr, - size_t len) -{ - void __iomem *baseAddr = brd->basemem; - - if (len < 7168) { - printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n"); - return -EINVAL; - } - - writew(len - 7168 - 2, baseAddr + C320bapi_len); - writeb(1, baseAddr + Control_reg); /* Select Page 1 */ - memcpy_toio(baseAddr + DynPage_addr, ptr, 7168); - writeb(2, baseAddr + Control_reg); /* Select Page 2 */ - memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168); - - return 0; -} - -static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, - size_t len) -{ - void __iomem *baseAddr = brd->basemem; - const __le16 *uptr = ptr; - size_t wlen, len2, j; - unsigned long key, loadbuf, loadlen, checksum, checksum_ok; - unsigned int i, retry; - u16 usum, keycode; - - keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode : - C218_KeyCode; - - switch (brd->boardType) { - case MOXA_BOARD_CP204J: - case MOXA_BOARD_C218_ISA: - case MOXA_BOARD_C218_PCI: - key = C218_key; - loadbuf = C218_LoadBuf; - loadlen = C218DLoad_len; - checksum = C218check_sum; - checksum_ok = C218chksum_ok; - break; - default: - key = C320_key; - keycode = C320_KeyCode; - loadbuf = C320_LoadBuf; - loadlen = C320DLoad_len; - checksum = C320check_sum; - checksum_ok = C320chksum_ok; - break; - } - - usum = 0; - wlen = len >> 1; - for (i = 0; i < wlen; i++) - usum += le16_to_cpu(uptr[i]); - retry = 0; - do { - wlen = len >> 1; - j = 0; - while (wlen) { - len2 = (wlen > 2048) ? 2048 : wlen; - wlen -= len2; - memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1); - j += len2 << 1; - - writew(len2, baseAddr + loadlen); - writew(0, baseAddr + key); - for (i = 0; i < 100; i++) { - if (readw(baseAddr + key) == keycode) - break; - msleep(10); - } - if (readw(baseAddr + key) != keycode) - return -EIO; - } - writew(0, baseAddr + loadlen); - writew(usum, baseAddr + checksum); - writew(0, baseAddr + key); - for (i = 0; i < 100; i++) { - if (readw(baseAddr + key) == keycode) - break; - msleep(10); - } - retry++; - } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3)); - if (readb(baseAddr + checksum_ok) != 1) - return -EIO; - - writew(0, baseAddr + key); - for (i = 0; i < 600; i++) { - if (readw(baseAddr + Magic_no) == Magic_code) - break; - msleep(10); - } - if (readw(baseAddr + Magic_no) != Magic_code) - return -EIO; - - if (MOXA_IS_320(brd)) { - if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ - writew(0x3800, baseAddr + TMS320_PORT1); - writew(0x3900, baseAddr + TMS320_PORT2); - writew(28499, baseAddr + TMS320_CLOCK); - } else { - writew(0x3200, baseAddr + TMS320_PORT1); - writew(0x3400, baseAddr + TMS320_PORT2); - writew(19999, baseAddr + TMS320_CLOCK); - } - } - writew(1, baseAddr + Disable_IRQ); - writew(0, baseAddr + Magic_no); - for (i = 0; i < 500; i++) { - if (readw(baseAddr + Magic_no) == Magic_code) - break; - msleep(10); - } - if (readw(baseAddr + Magic_no) != Magic_code) - return -EIO; - - if (MOXA_IS_320(brd)) { - j = readw(baseAddr + Module_cnt); - if (j <= 0) - return -EIO; - brd->numPorts = j * 8; - writew(j, baseAddr + Module_no); - writew(0, baseAddr + Magic_no); - for (i = 0; i < 600; i++) { - if (readw(baseAddr + Magic_no) == Magic_code) - break; - msleep(10); - } - if (readw(baseAddr + Magic_no) != Magic_code) - return -EIO; - } - brd->intNdx = baseAddr + IRQindex; - brd->intPend = baseAddr + IRQpending; - brd->intTable = baseAddr + IRQtable; - - return 0; -} - -static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, - size_t len) -{ - void __iomem *ofsAddr, *baseAddr = brd->basemem; - struct moxa_port *port; - int retval, i; - - if (len % 2) { - printk(KERN_ERR "MOXA: bios length is not even\n"); - return -EINVAL; - } - - retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */ - if (retval) - return retval; - - switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: - case MOXA_BOARD_C218_PCI: - case MOXA_BOARD_CP204J: - port = brd->ports; - for (i = 0; i < brd->numPorts; i++, port++) { - port->board = brd; - port->DCDState = 0; - port->tableAddr = baseAddr + Extern_table + - Extern_size * i; - ofsAddr = port->tableAddr; - writew(C218rx_mask, ofsAddr + RX_mask); - writew(C218tx_mask, ofsAddr + TX_mask); - writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); - writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); - - writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); - writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); - - } - break; - default: - port = brd->ports; - for (i = 0; i < brd->numPorts; i++, port++) { - port->board = brd; - port->DCDState = 0; - port->tableAddr = baseAddr + Extern_table + - Extern_size * i; - ofsAddr = port->tableAddr; - switch (brd->numPorts) { - case 8: - writew(C320p8rx_mask, ofsAddr + RX_mask); - writew(C320p8tx_mask, ofsAddr + TX_mask); - writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); - writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); - writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); - writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); - - break; - case 16: - writew(C320p16rx_mask, ofsAddr + RX_mask); - writew(C320p16tx_mask, ofsAddr + TX_mask); - writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); - writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); - writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); - writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); - break; - - case 24: - writew(C320p24rx_mask, ofsAddr + RX_mask); - writew(C320p24tx_mask, ofsAddr + TX_mask); - writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); - writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); - writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); - writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); - break; - case 32: - writew(C320p32rx_mask, ofsAddr + RX_mask); - writew(C320p32tx_mask, ofsAddr + TX_mask); - writew(C320p32tx_ofs, ofsAddr + Ofs_txb); - writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); - writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); - writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); - writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); - break; - } - } - break; - } - return 0; -} - -static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw) -{ - const void *ptr = fw->data; - char rsn[64]; - u16 lens[5]; - size_t len; - unsigned int a, lenp, lencnt; - int ret = -EINVAL; - struct { - __le32 magic; /* 0x34303430 */ - u8 reserved1[2]; - u8 type; /* UNIX = 3 */ - u8 model; /* C218T=1, C320T=2, CP204=3 */ - u8 reserved2[8]; - __le16 len[5]; - } const *hdr = ptr; - - BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens)); - - if (fw->size < MOXA_FW_HDRLEN) { - strcpy(rsn, "too short (even header won't fit)"); - goto err; - } - if (hdr->magic != cpu_to_le32(0x30343034)) { - sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic)); - goto err; - } - if (hdr->type != 3) { - sprintf(rsn, "not for linux, type is %u", hdr->type); - goto err; - } - if (moxa_check_fw_model(brd, hdr->model)) { - sprintf(rsn, "not for this card, model is %u", hdr->model); - goto err; - } - - len = MOXA_FW_HDRLEN; - lencnt = hdr->model == 2 ? 5 : 3; - for (a = 0; a < ARRAY_SIZE(lens); a++) { - lens[a] = le16_to_cpu(hdr->len[a]); - if (lens[a] && len + lens[a] <= fw->size && - moxa_check_fw(&fw->data[len])) - printk(KERN_WARNING "MOXA firmware: unexpected input " - "at offset %u, but going on\n", (u32)len); - if (!lens[a] && a < lencnt) { - sprintf(rsn, "too few entries in fw file"); - goto err; - } - len += lens[a]; - } - - if (len != fw->size) { - sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size, - (u32)len); - goto err; - } - - ptr += MOXA_FW_HDRLEN; - lenp = 0; /* bios */ - - strcpy(rsn, "read above"); - - ret = moxa_load_bios(brd, ptr, lens[lenp]); - if (ret) - goto err; - - /* we skip the tty section (lens[1]), since we don't need it */ - ptr += lens[lenp] + lens[lenp + 1]; - lenp += 2; /* comm */ - - if (hdr->model == 2) { - ret = moxa_load_320b(brd, ptr, lens[lenp]); - if (ret) - goto err; - /* skip another tty */ - ptr += lens[lenp] + lens[lenp + 1]; - lenp += 2; - } - - ret = moxa_load_code(brd, ptr, lens[lenp]); - if (ret) - goto err; - - return 0; -err: - printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn); - return ret; -} - -static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) -{ - const struct firmware *fw; - const char *file; - struct moxa_port *p; - unsigned int i; - int ret; - - brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports), - GFP_KERNEL); - if (brd->ports == NULL) { - printk(KERN_ERR "cannot allocate memory for ports\n"); - ret = -ENOMEM; - goto err; - } - - for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { - tty_port_init(&p->port); - p->port.ops = &moxa_port_ops; - p->type = PORT_16550A; - p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; - } - - switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: - case MOXA_BOARD_C218_PCI: - file = "c218tunx.cod"; - break; - case MOXA_BOARD_CP204J: - file = "cp204unx.cod"; - break; - default: - file = "c320tunx.cod"; - break; - } - - ret = request_firmware(&fw, file, dev); - if (ret) { - printk(KERN_ERR "MOXA: request_firmware failed. Make sure " - "you've placed '%s' file into your firmware " - "loader directory (e.g. /lib/firmware)\n", - file); - goto err_free; - } - - ret = moxa_load_fw(brd, fw); - - release_firmware(fw); - - if (ret) - goto err_free; - - spin_lock_bh(&moxa_lock); - brd->ready = 1; - if (!timer_pending(&moxaTimer)) - mod_timer(&moxaTimer, jiffies + HZ / 50); - spin_unlock_bh(&moxa_lock); - - return 0; -err_free: - kfree(brd->ports); -err: - return ret; -} - -static void moxa_board_deinit(struct moxa_board_conf *brd) -{ - unsigned int a, opened; - - mutex_lock(&moxa_openlock); - spin_lock_bh(&moxa_lock); - brd->ready = 0; - spin_unlock_bh(&moxa_lock); - - /* pci hot-un-plug support */ - for (a = 0; a < brd->numPorts; a++) - if (brd->ports[a].port.flags & ASYNC_INITIALIZED) { - struct tty_struct *tty = tty_port_tty_get( - &brd->ports[a].port); - if (tty) { - tty_hangup(tty); - tty_kref_put(tty); - } - } - while (1) { - opened = 0; - for (a = 0; a < brd->numPorts; a++) - if (brd->ports[a].port.flags & ASYNC_INITIALIZED) - opened++; - mutex_unlock(&moxa_openlock); - if (!opened) - break; - msleep(50); - mutex_lock(&moxa_openlock); - } - - iounmap(brd->basemem); - brd->basemem = NULL; - kfree(brd->ports); -} - -#ifdef CONFIG_PCI -static int __devinit moxa_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct moxa_board_conf *board; - unsigned int i; - int board_type = ent->driver_data; - int retval; - - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "can't enable pci device\n"); - goto err; - } - - for (i = 0; i < MAX_BOARDS; i++) - if (moxa_boards[i].basemem == NULL) - break; - - retval = -ENODEV; - if (i >= MAX_BOARDS) { - dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards " - "found. Board is ignored.\n", MAX_BOARDS); - goto err; - } - - board = &moxa_boards[i]; - - retval = pci_request_region(pdev, 2, "moxa-base"); - if (retval) { - dev_err(&pdev->dev, "can't request pci region 2\n"); - goto err; - } - - board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000); - if (board->basemem == NULL) { - dev_err(&pdev->dev, "can't remap io space 2\n"); - goto err_reg; - } - - board->boardType = board_type; - switch (board_type) { - case MOXA_BOARD_C218_ISA: - case MOXA_BOARD_C218_PCI: - board->numPorts = 8; - break; - - case MOXA_BOARD_CP204J: - board->numPorts = 4; - break; - default: - board->numPorts = 0; - break; - } - board->busType = MOXA_BUS_TYPE_PCI; - - retval = moxa_init_board(board, &pdev->dev); - if (retval) - goto err_base; - - pci_set_drvdata(pdev, board); - - dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n", - moxa_brdname[board_type - 1], board->numPorts); - - return 0; -err_base: - iounmap(board->basemem); - board->basemem = NULL; -err_reg: - pci_release_region(pdev, 2); -err: - return retval; -} - -static void __devexit moxa_pci_remove(struct pci_dev *pdev) -{ - struct moxa_board_conf *brd = pci_get_drvdata(pdev); - - moxa_board_deinit(brd); - - pci_release_region(pdev, 2); -} - -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) -{ - unsigned int isabrds = 0; - int retval = 0; - struct moxa_board_conf *brd = moxa_boards; - unsigned int i; - - printk(KERN_INFO "MOXA Intellio family driver version %s\n", - MOXA_VERSION); - moxaDriver = alloc_tty_driver(MAX_PORTS + 1); - if (!moxaDriver) - return -ENOMEM; - - moxaDriver->owner = THIS_MODULE; - moxaDriver->name = "ttyMX"; - moxaDriver->major = ttymajor; - moxaDriver->minor_start = 0; - moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; - moxaDriver->subtype = SERIAL_TYPE_NORMAL; - moxaDriver->init_termios = tty_std_termios; - moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; - moxaDriver->init_termios.c_ispeed = 9600; - moxaDriver->init_termios.c_ospeed = 9600; - moxaDriver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(moxaDriver, &moxa_ops); - - if (tty_register_driver(moxaDriver)) { - printk(KERN_ERR "can't register MOXA Smartio tty driver!\n"); - put_tty_driver(moxaDriver); - return -1; - } - - /* Find the boards defined from module args. */ - - for (i = 0; i < MAX_BOARDS; i++) { - if (!baseaddr[i]) - break; - if (type[i] == MOXA_BOARD_C218_ISA || - type[i] == MOXA_BOARD_C320_ISA) { - pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n", - isabrds + 1, moxa_brdname[type[i] - 1], - baseaddr[i]); - brd->boardType = type[i]; - brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : - numports[i]; - brd->busType = MOXA_BUS_TYPE_ISA; - brd->basemem = ioremap_nocache(baseaddr[i], 0x4000); - if (!brd->basemem) { - printk(KERN_ERR "MOXA: can't remap %lx\n", - baseaddr[i]); - continue; - } - if (moxa_init_board(brd, NULL)) { - iounmap(brd->basemem); - brd->basemem = NULL; - continue; - } - - printk(KERN_INFO "MOXA isa board found at 0x%.8lu and " - "ready (%u ports, firmware loaded)\n", - baseaddr[i], brd->numPorts); - - brd++; - isabrds++; - } - } - -#ifdef CONFIG_PCI - retval = pci_register_driver(&moxa_pci_driver); - if (retval) { - printk(KERN_ERR "Can't register MOXA pci driver!\n"); - if (isabrds) - retval = 0; - } -#endif - - return retval; -} - -static void __exit moxa_exit(void) -{ - unsigned int i; - -#ifdef CONFIG_PCI - pci_unregister_driver(&moxa_pci_driver); -#endif - - for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */ - if (moxa_boards[i].ready) - moxa_board_deinit(&moxa_boards[i]); - - del_timer_sync(&moxaTimer); - - if (tty_unregister_driver(moxaDriver)) - printk(KERN_ERR "Couldn't unregister MOXA Intellio family " - "serial driver\n"); - put_tty_driver(moxaDriver); -} - -module_init(moxa_init); -module_exit(moxa_exit); - -static void moxa_shutdown(struct tty_port *port) -{ - struct moxa_port *ch = container_of(port, struct moxa_port, port); - MoxaPortDisable(ch); - MoxaPortFlushData(ch, 2); - clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); -} - -static int moxa_carrier_raised(struct tty_port *port) -{ - struct moxa_port *ch = container_of(port, struct moxa_port, port); - int dcd; - - spin_lock_irq(&port->lock); - dcd = ch->DCDState; - spin_unlock_irq(&port->lock); - return dcd; -} - -static void moxa_dtr_rts(struct tty_port *port, int onoff) -{ - struct moxa_port *ch = container_of(port, struct moxa_port, port); - MoxaPortLineCtrl(ch, onoff, onoff); -} - - -static int moxa_open(struct tty_struct *tty, struct file *filp) -{ - struct moxa_board_conf *brd; - struct moxa_port *ch; - int port; - int retval; - - port = tty->index; - if (port == MAX_PORTS) { - return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; - } - if (mutex_lock_interruptible(&moxa_openlock)) - return -ERESTARTSYS; - brd = &moxa_boards[port / MAX_PORTS_PER_BOARD]; - if (!brd->ready) { - mutex_unlock(&moxa_openlock); - return -ENODEV; - } - - if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) { - mutex_unlock(&moxa_openlock); - return -ENODEV; - } - - ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; - ch->port.count++; - tty->driver_data = ch; - tty_port_tty_set(&ch->port, tty); - mutex_lock(&ch->port.mutex); - if (!(ch->port.flags & ASYNC_INITIALIZED)) { - ch->statusflags = 0; - moxa_set_tty_param(tty, tty->termios); - MoxaPortLineCtrl(ch, 1, 1); - MoxaPortEnable(ch); - MoxaSetFifo(ch, ch->type == PORT_16550A); - ch->port.flags |= ASYNC_INITIALIZED; - } - mutex_unlock(&ch->port.mutex); - mutex_unlock(&moxa_openlock); - - retval = tty_port_block_til_ready(&ch->port, tty, filp); - if (retval == 0) - set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); - return retval; -} - -static void moxa_close(struct tty_struct *tty, struct file *filp) -{ - struct moxa_port *ch = tty->driver_data; - ch->cflag = tty->termios->c_cflag; - tty_port_close(&ch->port, tty, filp); -} - -static int moxa_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - struct moxa_port *ch = tty->driver_data; - int len; - - if (ch == NULL) - return 0; - - spin_lock_bh(&moxa_lock); - len = MoxaPortWriteData(tty, buf, count); - spin_unlock_bh(&moxa_lock); - - set_bit(LOWWAIT, &ch->statusflags); - return len; -} - -static int moxa_write_room(struct tty_struct *tty) -{ - struct moxa_port *ch; - - if (tty->stopped) - return 0; - ch = tty->driver_data; - if (ch == NULL) - return 0; - return MoxaPortTxFree(ch); -} - -static void moxa_flush_buffer(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - if (ch == NULL) - return; - MoxaPortFlushData(ch, 1); - tty_wakeup(tty); -} - -static int moxa_chars_in_buffer(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - int chars; - - chars = MoxaPortTxQueue(ch); - if (chars) - /* - * Make it possible to wakeup anything waiting for output - * in tty_ioctl.c, etc. - */ - set_bit(EMPTYWAIT, &ch->statusflags); - return chars; -} - -static int moxa_tiocmget(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - int flag = 0, dtr, rts; - - MoxaPortGetLineOut(ch, &dtr, &rts); - if (dtr) - flag |= TIOCM_DTR; - if (rts) - flag |= TIOCM_RTS; - dtr = MoxaPortLineStatus(ch); - if (dtr & 1) - flag |= TIOCM_CTS; - if (dtr & 2) - flag |= TIOCM_DSR; - if (dtr & 4) - flag |= TIOCM_CD; - return flag; -} - -static int moxa_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct moxa_port *ch; - int port; - int dtr, rts; - - port = tty->index; - mutex_lock(&moxa_openlock); - ch = tty->driver_data; - if (!ch) { - mutex_unlock(&moxa_openlock); - return -EINVAL; - } - - MoxaPortGetLineOut(ch, &dtr, &rts); - if (set & TIOCM_RTS) - rts = 1; - if (set & TIOCM_DTR) - dtr = 1; - if (clear & TIOCM_RTS) - rts = 0; - if (clear & TIOCM_DTR) - dtr = 0; - MoxaPortLineCtrl(ch, dtr, rts); - mutex_unlock(&moxa_openlock); - return 0; -} - -static void moxa_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct moxa_port *ch = tty->driver_data; - - if (ch == NULL) - return; - moxa_set_tty_param(tty, old_termios); - if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) - wake_up_interruptible(&ch->port.open_wait); -} - -static void moxa_stop(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - if (ch == NULL) - return; - MoxaPortTxDisable(ch); - set_bit(TXSTOPPED, &ch->statusflags); -} - - -static void moxa_start(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - - if (ch == NULL) - return; - - if (!(ch->statusflags & TXSTOPPED)) - return; - - MoxaPortTxEnable(ch); - clear_bit(TXSTOPPED, &ch->statusflags); -} - -static void moxa_hangup(struct tty_struct *tty) -{ - struct moxa_port *ch = tty->driver_data; - tty_port_hangup(&ch->port); -} - -static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) -{ - struct tty_struct *tty; - unsigned long flags; - dcd = !!dcd; - - spin_lock_irqsave(&p->port.lock, flags); - if (dcd != p->DCDState) { - p->DCDState = dcd; - spin_unlock_irqrestore(&p->port.lock, flags); - tty = tty_port_tty_get(&p->port); - if (tty && C_CLOCAL(tty) && !dcd) - tty_hangup(tty); - tty_kref_put(tty); - } - else - spin_unlock_irqrestore(&p->port.lock, flags); -} - -static int moxa_poll_port(struct moxa_port *p, unsigned int handle, - u16 __iomem *ip) -{ - struct tty_struct *tty = tty_port_tty_get(&p->port); - void __iomem *ofsAddr; - unsigned int inited = p->port.flags & ASYNC_INITIALIZED; - u16 intr; - - if (tty) { - if (test_bit(EMPTYWAIT, &p->statusflags) && - MoxaPortTxQueue(p) == 0) { - clear_bit(EMPTYWAIT, &p->statusflags); - tty_wakeup(tty); - } - if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && - MoxaPortTxQueue(p) <= WAKEUP_CHARS) { - clear_bit(LOWWAIT, &p->statusflags); - tty_wakeup(tty); - } - - if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && - MoxaPortRxQueue(p) > 0) { /* RX */ - MoxaPortReadData(p); - tty_schedule_flip(tty); - } - } else { - clear_bit(EMPTYWAIT, &p->statusflags); - MoxaPortFlushData(p, 0); /* flush RX */ - } - - if (!handle) /* nothing else to do */ - goto put; - - intr = readw(ip); /* port irq status */ - if (intr == 0) - goto put; - - writew(0, ip); /* ACK port */ - ofsAddr = p->tableAddr; - if (intr & IntrTx) /* disable tx intr */ - writew(readw(ofsAddr + HostStat) & ~WakeupTx, - ofsAddr + HostStat); - - if (!inited) - goto put; - - if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ - tty_insert_flip_char(tty, 0, TTY_BREAK); - tty_schedule_flip(tty); - } - - if (intr & IntrLine) - moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); -put: - tty_kref_put(tty); - - return 0; -} - -static void moxa_poll(unsigned long ignored) -{ - struct moxa_board_conf *brd; - u16 __iomem *ip; - unsigned int card, port, served = 0; - - spin_lock(&moxa_lock); - for (card = 0; card < MAX_BOARDS; card++) { - brd = &moxa_boards[card]; - if (!brd->ready) - continue; - - served++; - - ip = NULL; - if (readb(brd->intPend) == 0xff) - ip = brd->intTable + readb(brd->intNdx); - - for (port = 0; port < brd->numPorts; port++) - moxa_poll_port(&brd->ports[port], !!ip, ip + port); - - if (ip) - writeb(0, brd->intPend); /* ACK */ - - if (moxaLowWaterChk) { - struct moxa_port *p = brd->ports; - for (port = 0; port < brd->numPorts; port++, p++) - if (p->lowChkFlag) { - p->lowChkFlag = 0; - moxa_low_water_check(p->tableAddr); - } - } - } - moxaLowWaterChk = 0; - - if (served) - mod_timer(&moxaTimer, jiffies + HZ / 50); - spin_unlock(&moxa_lock); -} - -/******************************************************************************/ - -static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios) -{ - register struct ktermios *ts = tty->termios; - struct moxa_port *ch = tty->driver_data; - int rts, cts, txflow, rxflow, xany, baud; - - rts = cts = txflow = rxflow = xany = 0; - if (ts->c_cflag & CRTSCTS) - rts = cts = 1; - if (ts->c_iflag & IXON) - txflow = 1; - if (ts->c_iflag & IXOFF) - rxflow = 1; - if (ts->c_iflag & IXANY) - xany = 1; - - /* Clear the features we don't support */ - ts->c_cflag &= ~CMSPAR; - MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany); - baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty)); - if (baud == -1) - baud = tty_termios_baud_rate(old_termios); - /* Not put the baud rate into the termios data */ - tty_encode_baud_rate(tty, baud, baud); -} - -/***************************************************************************** - * Driver level functions: * - *****************************************************************************/ - -static void MoxaPortFlushData(struct moxa_port *port, int mode) -{ - void __iomem *ofsAddr; - if (mode < 0 || mode > 2) - return; - ofsAddr = port->tableAddr; - moxafunc(ofsAddr, FC_FlushQueue, mode); - if (mode != 1) { - port->lowChkFlag = 0; - moxa_low_water_check(ofsAddr); - } -} - -/* - * Moxa Port Number Description: - * - * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And, - * the port number using in MOXA driver functions will be 0 to 31 for - * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96 - * to 127 for fourth. For example, if you setup three MOXA boards, - * first board is C218, second board is C320-16 and third board is - * C320-32. The port number of first board (C218 - 8 ports) is from - * 0 to 7. The port number of second board (C320 - 16 ports) is form - * 32 to 47. The port number of third board (C320 - 32 ports) is from - * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to - * 127 will be invalid. - * - * - * Moxa Functions Description: - * - * Function 1: Driver initialization routine, this routine must be - * called when initialized driver. - * Syntax: - * void MoxaDriverInit(); - * - * - * Function 2: Moxa driver private IOCTL command processing. - * Syntax: - * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); - * - * unsigned int cmd : IOCTL command - * unsigned long arg : IOCTL argument - * int port : port number (0 - 127) - * - * return: 0 (OK) - * -EINVAL - * -ENOIOCTLCMD - * - * - * Function 6: Enable this port to start Tx/Rx data. - * Syntax: - * void MoxaPortEnable(int port); - * int port : port number (0 - 127) - * - * - * Function 7: Disable this port - * Syntax: - * void MoxaPortDisable(int port); - * int port : port number (0 - 127) - * - * - * Function 10: Setting baud rate of this port. - * Syntax: - * speed_t MoxaPortSetBaud(int port, speed_t baud); - * int port : port number (0 - 127) - * long baud : baud rate (50 - 115200) - * - * return: 0 : this port is invalid or baud < 50 - * 50 - 115200 : the real baud rate set to the port, if - * the argument baud is large than maximun - * available baud rate, the real setting - * baud rate will be the maximun baud rate. - * - * - * Function 12: Configure the port. - * Syntax: - * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); - * int port : port number (0 - 127) - * struct ktermios * termio : termio structure pointer - * speed_t baud : baud rate - * - * return: -1 : this port is invalid or termio == NULL - * 0 : setting O.K. - * - * - * Function 13: Get the DTR/RTS state of this port. - * Syntax: - * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); - * int port : port number (0 - 127) - * int * dtrState : pointer to INT to receive the current DTR - * state. (if NULL, this function will not - * write to this address) - * int * rtsState : pointer to INT to receive the current RTS - * state. (if NULL, this function will not - * write to this address) - * - * return: -1 : this port is invalid - * 0 : O.K. - * - * - * Function 14: Setting the DTR/RTS output state of this port. - * Syntax: - * void MoxaPortLineCtrl(int port, int dtrState, int rtsState); - * int port : port number (0 - 127) - * int dtrState : DTR output state (0: off, 1: on) - * int rtsState : RTS output state (0: off, 1: on) - * - * - * Function 15: Setting the flow control of this port. - * Syntax: - * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow, - * int txFlow,int xany); - * int port : port number (0 - 127) - * int rtsFlow : H/W RTS flow control (0: no, 1: yes) - * int ctsFlow : H/W CTS flow control (0: no, 1: yes) - * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes) - * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes) - * int xany : S/W XANY flow control (0: no, 1: yes) - * - * - * Function 16: Get ths line status of this port - * Syntax: - * int MoxaPortLineStatus(int port); - * int port : port number (0 - 127) - * - * return: Bit 0 - CTS state (0: off, 1: on) - * Bit 1 - DSR state (0: off, 1: on) - * Bit 2 - DCD state (0: off, 1: on) - * - * - * Function 19: Flush the Rx/Tx buffer data of this port. - * Syntax: - * void MoxaPortFlushData(int port, int mode); - * int port : port number (0 - 127) - * int mode - * 0 : flush the Rx buffer - * 1 : flush the Tx buffer - * 2 : flush the Rx and Tx buffer - * - * - * Function 20: Write data. - * Syntax: - * int MoxaPortWriteData(int port, unsigned char * buffer, int length); - * int port : port number (0 - 127) - * unsigned char * buffer : pointer to write data buffer. - * int length : write data length - * - * return: 0 - length : real write data length - * - * - * Function 21: Read data. - * Syntax: - * int MoxaPortReadData(int port, struct tty_struct *tty); - * int port : port number (0 - 127) - * struct tty_struct *tty : tty for data - * - * return: 0 - length : real read data length - * - * - * Function 24: Get the Tx buffer current queued data bytes - * Syntax: - * int MoxaPortTxQueue(int port); - * int port : port number (0 - 127) - * - * return: .. : Tx buffer current queued data bytes - * - * - * Function 25: Get the Tx buffer current free space - * Syntax: - * int MoxaPortTxFree(int port); - * int port : port number (0 - 127) - * - * return: .. : Tx buffer current free space - * - * - * Function 26: Get the Rx buffer current queued data bytes - * Syntax: - * int MoxaPortRxQueue(int port); - * int port : port number (0 - 127) - * - * return: .. : Rx buffer current queued data bytes - * - * - * Function 28: Disable port data transmission. - * Syntax: - * void MoxaPortTxDisable(int port); - * int port : port number (0 - 127) - * - * - * Function 29: Enable port data transmission. - * Syntax: - * void MoxaPortTxEnable(int port); - * int port : port number (0 - 127) - * - * - * Function 31: Get the received BREAK signal count and reset it. - * Syntax: - * int MoxaPortResetBrkCnt(int port); - * int port : port number (0 - 127) - * - * return: 0 - .. : BREAK signal count - * - * - */ - -static void MoxaPortEnable(struct moxa_port *port) -{ - void __iomem *ofsAddr; - u16 lowwater = 512; - - ofsAddr = port->tableAddr; - writew(lowwater, ofsAddr + Low_water); - if (MOXA_IS_320(port->board)) - moxafunc(ofsAddr, FC_SetBreakIrq, 0); - else - writew(readw(ofsAddr + HostStat) | WakeupBreak, - ofsAddr + HostStat); - - moxafunc(ofsAddr, FC_SetLineIrq, Magic_code); - moxafunc(ofsAddr, FC_FlushQueue, 2); - - moxafunc(ofsAddr, FC_EnableCH, Magic_code); - MoxaPortLineStatus(port); -} - -static void MoxaPortDisable(struct moxa_port *port) -{ - void __iomem *ofsAddr = port->tableAddr; - - moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ - moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); - writew(0, ofsAddr + HostStat); - moxafunc(ofsAddr, FC_DisableCH, Magic_code); -} - -static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud) -{ - void __iomem *ofsAddr = port->tableAddr; - unsigned int clock, val; - speed_t max; - - max = MOXA_IS_320(port->board) ? 460800 : 921600; - if (baud < 50) - return 0; - if (baud > max) - baud = max; - clock = 921600; - val = clock / baud; - moxafunc(ofsAddr, FC_SetBaud, val); - baud = clock / val; - return baud; -} - -static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, - speed_t baud) -{ - void __iomem *ofsAddr; - tcflag_t cflag; - tcflag_t mode = 0; - - ofsAddr = port->tableAddr; - cflag = termio->c_cflag; /* termio->c_cflag */ - - mode = termio->c_cflag & CSIZE; - if (mode == CS5) - mode = MX_CS5; - else if (mode == CS6) - mode = MX_CS6; - else if (mode == CS7) - mode = MX_CS7; - else if (mode == CS8) - mode = MX_CS8; - - if (termio->c_cflag & CSTOPB) { - if (mode == MX_CS5) - mode |= MX_STOP15; - else - mode |= MX_STOP2; - } else - mode |= MX_STOP1; - - if (termio->c_cflag & PARENB) { - if (termio->c_cflag & PARODD) - mode |= MX_PARODD; - else - mode |= MX_PAREVEN; - } else - mode |= MX_PARNONE; - - moxafunc(ofsAddr, FC_SetDataMode, (u16)mode); - - if (MOXA_IS_320(port->board) && baud >= 921600) - return -1; - - baud = MoxaPortSetBaud(port, baud); - - if (termio->c_iflag & (IXON | IXOFF | IXANY)) { - spin_lock_irq(&moxafunc_lock); - writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); - writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); - writeb(FC_SetXonXoff, ofsAddr + FuncCode); - moxa_wait_finish(ofsAddr); - spin_unlock_irq(&moxafunc_lock); - - } - return baud; -} - -static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState, - int *rtsState) -{ - if (dtrState) - *dtrState = !!(port->lineCtrl & DTR_ON); - if (rtsState) - *rtsState = !!(port->lineCtrl & RTS_ON); - - return 0; -} - -static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts) -{ - u8 mode = 0; - - if (dtr) - mode |= DTR_ON; - if (rts) - mode |= RTS_ON; - port->lineCtrl = mode; - moxafunc(port->tableAddr, FC_LineControl, mode); -} - -static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts, - int txflow, int rxflow, int txany) -{ - int mode = 0; - - if (rts) - mode |= RTS_FlowCtl; - if (cts) - mode |= CTS_FlowCtl; - if (txflow) - mode |= Tx_FlowCtl; - if (rxflow) - mode |= Rx_FlowCtl; - if (txany) - mode |= IXM_IXANY; - moxafunc(port->tableAddr, FC_SetFlowCtl, mode); -} - -static int MoxaPortLineStatus(struct moxa_port *port) -{ - void __iomem *ofsAddr; - int val; - - ofsAddr = port->tableAddr; - if (MOXA_IS_320(port->board)) - val = moxafuncret(ofsAddr, FC_LineStatus, 0); - else - val = readw(ofsAddr + FlagStat) >> 4; - val &= 0x0B; - if (val & 8) - val |= 4; - moxa_new_dcdstate(port, val & 8); - val &= 7; - return val; -} - -static int MoxaPortWriteData(struct tty_struct *tty, - const unsigned char *buffer, int len) -{ - struct moxa_port *port = tty->driver_data; - void __iomem *baseAddr, *ofsAddr, *ofs; - unsigned int c, total; - u16 head, tail, tx_mask, spage, epage; - u16 pageno, pageofs, bufhead; - - ofsAddr = port->tableAddr; - baseAddr = port->board->basemem; - tx_mask = readw(ofsAddr + TX_mask); - spage = readw(ofsAddr + Page_txb); - epage = readw(ofsAddr + EndPage_txb); - tail = readw(ofsAddr + TXwptr); - head = readw(ofsAddr + TXrptr); - c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask); - if (c > len) - c = len; - moxaLog.txcnt[port->port.tty->index] += c; - total = c; - if (spage == epage) { - bufhead = readw(ofsAddr + Ofs_txb); - writew(spage, baseAddr + Control_reg); - while (c > 0) { - if (head > tail) - len = head - tail - 1; - else - len = tx_mask + 1 - tail; - len = (c > len) ? len : c; - ofs = baseAddr + DynPage_addr + bufhead + tail; - memcpy_toio(ofs, buffer, len); - buffer += len; - tail = (tail + len) & tx_mask; - c -= len; - } - } else { - pageno = spage + (tail >> 13); - pageofs = tail & Page_mask; - while (c > 0) { - len = Page_size - pageofs; - if (len > c) - len = c; - writeb(pageno, baseAddr + Control_reg); - ofs = baseAddr + DynPage_addr + pageofs; - memcpy_toio(ofs, buffer, len); - buffer += len; - if (++pageno == epage) - pageno = spage; - pageofs = 0; - c -= len; - } - tail = (tail + total) & tx_mask; - } - writew(tail, ofsAddr + TXwptr); - writeb(1, ofsAddr + CD180TXirq); /* start to send */ - return total; -} - -static int MoxaPortReadData(struct moxa_port *port) -{ - struct tty_struct *tty = port->port.tty; - unsigned char *dst; - void __iomem *baseAddr, *ofsAddr, *ofs; - unsigned int count, len, total; - u16 tail, rx_mask, spage, epage; - u16 pageno, pageofs, bufhead, head; - - ofsAddr = port->tableAddr; - baseAddr = port->board->basemem; - head = readw(ofsAddr + RXrptr); - tail = readw(ofsAddr + RXwptr); - rx_mask = readw(ofsAddr + RX_mask); - spage = readw(ofsAddr + Page_rxb); - epage = readw(ofsAddr + EndPage_rxb); - count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1); - if (count == 0) - return 0; - - total = count; - moxaLog.rxcnt[tty->index] += total; - if (spage == epage) { - bufhead = readw(ofsAddr + Ofs_rxb); - writew(spage, baseAddr + Control_reg); - while (count > 0) { - ofs = baseAddr + DynPage_addr + bufhead + head; - len = (tail >= head) ? (tail - head) : - (rx_mask + 1 - head); - len = tty_prepare_flip_string(tty, &dst, - min(len, count)); - memcpy_fromio(dst, ofs, len); - head = (head + len) & rx_mask; - count -= len; - } - } else { - pageno = spage + (head >> 13); - pageofs = head & Page_mask; - while (count > 0) { - writew(pageno, baseAddr + Control_reg); - ofs = baseAddr + DynPage_addr + pageofs; - len = tty_prepare_flip_string(tty, &dst, - min(Page_size - pageofs, count)); - memcpy_fromio(dst, ofs, len); - - count -= len; - pageofs = (pageofs + len) & Page_mask; - if (pageofs == 0 && ++pageno == epage) - pageno = spage; - } - head = (head + total) & rx_mask; - } - writew(head, ofsAddr + RXrptr); - if (readb(ofsAddr + FlagStat) & Xoff_state) { - moxaLowWaterChk = 1; - port->lowChkFlag = 1; - } - return total; -} - - -static int MoxaPortTxQueue(struct moxa_port *port) -{ - void __iomem *ofsAddr = port->tableAddr; - u16 rptr, wptr, mask; - - rptr = readw(ofsAddr + TXrptr); - wptr = readw(ofsAddr + TXwptr); - mask = readw(ofsAddr + TX_mask); - return (wptr - rptr) & mask; -} - -static int MoxaPortTxFree(struct moxa_port *port) -{ - void __iomem *ofsAddr = port->tableAddr; - u16 rptr, wptr, mask; - - rptr = readw(ofsAddr + TXrptr); - wptr = readw(ofsAddr + TXwptr); - mask = readw(ofsAddr + TX_mask); - return mask - ((wptr - rptr) & mask); -} - -static int MoxaPortRxQueue(struct moxa_port *port) -{ - void __iomem *ofsAddr = port->tableAddr; - u16 rptr, wptr, mask; - - rptr = readw(ofsAddr + RXrptr); - wptr = readw(ofsAddr + RXwptr); - mask = readw(ofsAddr + RX_mask); - return (wptr - rptr) & mask; -} - -static void MoxaPortTxDisable(struct moxa_port *port) -{ - moxafunc(port->tableAddr, FC_SetXoffState, Magic_code); -} - -static void MoxaPortTxEnable(struct moxa_port *port) -{ - moxafunc(port->tableAddr, FC_SetXonState, Magic_code); -} - -static int moxa_get_serial_info(struct moxa_port *info, - struct serial_struct __user *retinfo) -{ - struct serial_struct tmp = { - .type = info->type, - .line = info->port.tty->index, - .flags = info->port.flags, - .baud_base = 921600, - .close_delay = info->port.close_delay - }; - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; -} - - -static int moxa_set_serial_info(struct moxa_port *info, - struct serial_struct __user *new_info) -{ - struct serial_struct new_serial; - - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - - if (new_serial.irq != 0 || new_serial.port != 0 || - new_serial.custom_divisor != 0 || - new_serial.baud_base != 921600) - return -EPERM; - - if (!capable(CAP_SYS_ADMIN)) { - if (((new_serial.flags & ~ASYNC_USR_MASK) != - (info->port.flags & ~ASYNC_USR_MASK))) - return -EPERM; - } else - info->port.close_delay = new_serial.close_delay * HZ / 100; - - new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS); - new_serial.flags |= (info->port.flags & ASYNC_FLAGS); - - MoxaSetFifo(info, new_serial.type == PORT_16550A); - - info->type = new_serial.type; - return 0; -} - - - -/***************************************************************************** - * Static local functions: * - *****************************************************************************/ - -static void MoxaSetFifo(struct moxa_port *port, int enable) -{ - void __iomem *ofsAddr = port->tableAddr; - - if (!enable) { - moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); - moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1); - } else { - moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3); - moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); - } -} diff --git a/drivers/char/moxa.h b/drivers/char/moxa.h deleted file mode 100644 index 87d16ce57be7..000000000000 --- a/drivers/char/moxa.h +++ /dev/null @@ -1,304 +0,0 @@ -#ifndef MOXA_H_FILE -#define MOXA_H_FILE - -#define MOXA 0x400 -#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ -#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ -#define MOXA_GETDATACOUNT (MOXA + 23) -#define MOXA_GET_IOQUEUE (MOXA + 27) -#define MOXA_FLUSH_QUEUE (MOXA + 28) -#define MOXA_GETMSTATUS (MOXA + 65) - -/* - * System Configuration - */ - -#define Magic_code 0x404 - -/* - * for C218 BIOS initialization - */ -#define C218_ConfBase 0x800 -#define C218_status (C218_ConfBase + 0) /* BIOS running status */ -#define C218_diag (C218_ConfBase + 2) /* diagnostic status */ -#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */ -#define C218DLoad_len (C218_ConfBase + 6) /* WORD */ -#define C218check_sum (C218_ConfBase + 8) /* BYTE */ -#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */ -#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */ -#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */ -#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */ -#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */ - -#define C218_LoadBuf 0x0F00 -#define C218_KeyCode 0x218 -#define CP204J_KeyCode 0x204 - -/* - * for C320 BIOS initialization - */ -#define C320_ConfBase 0x800 -#define C320_LoadBuf 0x0f00 -#define STS_init 0x05 /* for C320_status */ - -#define C320_status C320_ConfBase + 0 /* BIOS running status */ -#define C320_diag C320_ConfBase + 2 /* diagnostic status */ -#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */ -#define C320DLoad_len C320_ConfBase + 6 /* WORD */ -#define C320check_sum C320_ConfBase + 8 /* WORD */ -#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */ -#define C320bapi_len C320_ConfBase + 0x0c /* WORD */ -#define C320UART_no C320_ConfBase + 0x0e /* WORD */ - -#define C320_KeyCode 0x320 - -#define FixPage_addr 0x0000 /* starting addr of static page */ -#define DynPage_addr 0x2000 /* starting addr of dynamic page */ -#define C218_start 0x3000 /* starting addr of C218 BIOS prg */ -#define Control_reg 0x1ff0 /* select page and reset control */ -#define HW_reset 0x80 - -/* - * Function Codes - */ -#define FC_CardReset 0x80 -#define FC_ChannelReset 1 /* C320 firmware not supported */ -#define FC_EnableCH 2 -#define FC_DisableCH 3 -#define FC_SetParam 4 -#define FC_SetMode 5 -#define FC_SetRate 6 -#define FC_LineControl 7 -#define FC_LineStatus 8 -#define FC_XmitControl 9 -#define FC_FlushQueue 10 -#define FC_SendBreak 11 -#define FC_StopBreak 12 -#define FC_LoopbackON 13 -#define FC_LoopbackOFF 14 -#define FC_ClrIrqTable 15 -#define FC_SendXon 16 -#define FC_SetTermIrq 17 /* C320 firmware not supported */ -#define FC_SetCntIrq 18 /* C320 firmware not supported */ -#define FC_SetBreakIrq 19 -#define FC_SetLineIrq 20 -#define FC_SetFlowCtl 21 -#define FC_GenIrq 22 -#define FC_InCD180 23 -#define FC_OutCD180 24 -#define FC_InUARTreg 23 -#define FC_OutUARTreg 24 -#define FC_SetXonXoff 25 -#define FC_OutCD180CCR 26 -#define FC_ExtIQueue 27 -#define FC_ExtOQueue 28 -#define FC_ClrLineIrq 29 -#define FC_HWFlowCtl 30 -#define FC_GetClockRate 35 -#define FC_SetBaud 36 -#define FC_SetDataMode 41 -#define FC_GetCCSR 43 -#define FC_GetDataError 45 -#define FC_RxControl 50 -#define FC_ImmSend 51 -#define FC_SetXonState 52 -#define FC_SetXoffState 53 -#define FC_SetRxFIFOTrig 54 -#define FC_SetTxFIFOCnt 55 -#define FC_UnixRate 56 -#define FC_UnixResetTimer 57 - -#define RxFIFOTrig1 0 -#define RxFIFOTrig4 1 -#define RxFIFOTrig8 2 -#define RxFIFOTrig14 3 - -/* - * Dual-Ported RAM - */ -#define DRAM_global 0 -#define INT_data (DRAM_global + 0) -#define Config_base (DRAM_global + 0x108) - -#define IRQindex (INT_data + 0) -#define IRQpending (INT_data + 4) -#define IRQtable (INT_data + 8) - -/* - * Interrupt Status - */ -#define IntrRx 0x01 /* receiver data O.K. */ -#define IntrTx 0x02 /* transmit buffer empty */ -#define IntrFunc 0x04 /* function complete */ -#define IntrBreak 0x08 /* received break */ -#define IntrLine 0x10 /* line status change - for transmitter */ -#define IntrIntr 0x20 /* received INTR code */ -#define IntrQuit 0x40 /* received QUIT code */ -#define IntrEOF 0x80 /* received EOF code */ - -#define IntrRxTrigger 0x100 /* rx data count reach tigger value */ -#define IntrTxTrigger 0x200 /* tx data count below trigger value */ - -#define Magic_no (Config_base + 0) -#define Card_model_no (Config_base + 2) -#define Total_ports (Config_base + 4) -#define Module_cnt (Config_base + 8) -#define Module_no (Config_base + 10) -#define Timer_10ms (Config_base + 14) -#define Disable_IRQ (Config_base + 20) -#define TMS320_PORT1 (Config_base + 22) -#define TMS320_PORT2 (Config_base + 24) -#define TMS320_CLOCK (Config_base + 26) - -/* - * DATA BUFFER in DRAM - */ -#define Extern_table 0x400 /* Base address of the external table - (24 words * 64) total 3K bytes - (24 words * 128) total 6K bytes */ -#define Extern_size 0x60 /* 96 bytes */ -#define RXrptr 0x00 /* read pointer for RX buffer */ -#define RXwptr 0x02 /* write pointer for RX buffer */ -#define TXrptr 0x04 /* read pointer for TX buffer */ -#define TXwptr 0x06 /* write pointer for TX buffer */ -#define HostStat 0x08 /* IRQ flag and general flag */ -#define FlagStat 0x0A -#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */ - /* x x x x | | | | */ - /* | | | + CTS flow */ - /* | | +--- RTS flow */ - /* | +------ TX Xon/Xoff */ - /* +--------- RX Xon/Xoff */ -#define Break_cnt 0x0E /* received break count */ -#define CD180TXirq 0x10 /* if non-0: enable TX irq */ -#define RX_mask 0x12 -#define TX_mask 0x14 -#define Ofs_rxb 0x16 -#define Ofs_txb 0x18 -#define Page_rxb 0x1A -#define Page_txb 0x1C -#define EndPage_rxb 0x1E -#define EndPage_txb 0x20 -#define Data_error 0x22 -#define RxTrigger 0x28 -#define TxTrigger 0x2a - -#define rRXwptr 0x34 -#define Low_water 0x36 - -#define FuncCode 0x40 -#define FuncArg 0x42 -#define FuncArg1 0x44 - -#define C218rx_size 0x2000 /* 8K bytes */ -#define C218tx_size 0x8000 /* 32K bytes */ - -#define C218rx_mask (C218rx_size - 1) -#define C218tx_mask (C218tx_size - 1) - -#define C320p8rx_size 0x2000 -#define C320p8tx_size 0x8000 -#define C320p8rx_mask (C320p8rx_size - 1) -#define C320p8tx_mask (C320p8tx_size - 1) - -#define C320p16rx_size 0x2000 -#define C320p16tx_size 0x4000 -#define C320p16rx_mask (C320p16rx_size - 1) -#define C320p16tx_mask (C320p16tx_size - 1) - -#define C320p24rx_size 0x2000 -#define C320p24tx_size 0x2000 -#define C320p24rx_mask (C320p24rx_size - 1) -#define C320p24tx_mask (C320p24tx_size - 1) - -#define C320p32rx_size 0x1000 -#define C320p32tx_size 0x1000 -#define C320p32rx_mask (C320p32rx_size - 1) -#define C320p32tx_mask (C320p32tx_size - 1) - -#define Page_size 0x2000U -#define Page_mask (Page_size - 1) -#define C218rx_spage 3 -#define C218tx_spage 4 -#define C218rx_pageno 1 -#define C218tx_pageno 4 -#define C218buf_pageno 5 - -#define C320p8rx_spage 3 -#define C320p8tx_spage 4 -#define C320p8rx_pgno 1 -#define C320p8tx_pgno 4 -#define C320p8buf_pgno 5 - -#define C320p16rx_spage 3 -#define C320p16tx_spage 4 -#define C320p16rx_pgno 1 -#define C320p16tx_pgno 2 -#define C320p16buf_pgno 3 - -#define C320p24rx_spage 3 -#define C320p24tx_spage 4 -#define C320p24rx_pgno 1 -#define C320p24tx_pgno 1 -#define C320p24buf_pgno 2 - -#define C320p32rx_spage 3 -#define C320p32tx_ofs C320p32rx_size -#define C320p32tx_spage 3 -#define C320p32buf_pgno 1 - -/* - * Host Status - */ -#define WakeupRx 0x01 -#define WakeupTx 0x02 -#define WakeupBreak 0x08 -#define WakeupLine 0x10 -#define WakeupIntr 0x20 -#define WakeupQuit 0x40 -#define WakeupEOF 0x80 /* used in VTIME control */ -#define WakeupRxTrigger 0x100 -#define WakeupTxTrigger 0x200 -/* - * Flag status - */ -#define Rx_over 0x01 -#define Xoff_state 0x02 -#define Tx_flowOff 0x04 -#define Tx_enable 0x08 -#define CTS_state 0x10 -#define DSR_state 0x20 -#define DCD_state 0x80 -/* - * FlowControl - */ -#define CTS_FlowCtl 1 -#define RTS_FlowCtl 2 -#define Tx_FlowCtl 4 -#define Rx_FlowCtl 8 -#define IXM_IXANY 0x10 - -#define LowWater 128 - -#define DTR_ON 1 -#define RTS_ON 2 -#define CTS_ON 1 -#define DSR_ON 2 -#define DCD_ON 8 - -/* mode definition */ -#define MX_CS8 0x03 -#define MX_CS7 0x02 -#define MX_CS6 0x01 -#define MX_CS5 0x00 - -#define MX_STOP1 0x00 -#define MX_STOP15 0x04 -#define MX_STOP2 0x08 - -#define MX_PARNONE 0x00 -#define MX_PAREVEN 0x40 -#define MX_PARODD 0xC0 - -#endif diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c deleted file mode 100644 index d188f378684d..000000000000 --- a/drivers/char/mxser.c +++ /dev/null @@ -1,2757 +0,0 @@ -/* - * mxser.c -- MOXA Smartio/Industio family multiport serial driver. - * - * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com). - * Copyright (C) 2006-2008 Jiri Slaby - * - * This code is loosely based on the 1.8 moxa driver which is based on - * Linux serial driver, written by Linus Torvalds, Theodore T'so and - * others. - * - * 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. - * - * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox - * . The original 1.8 code is available on - * www.moxa.com. - * - Fixed x86_64 cleanness - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "mxser.h" - -#define MXSER_VERSION "2.0.5" /* 1.14 */ -#define MXSERMAJOR 174 - -#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 100 - -/*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 -#define UART_LSR_SPECIAL 0x1E - -#define PCI_DEVICE_ID_POS104UL 0x1044 -#define PCI_DEVICE_ID_CB108 0x1080 -#define PCI_DEVICE_ID_CP102UF 0x1023 -#define PCI_DEVICE_ID_CP112UL 0x1120 -#define PCI_DEVICE_ID_CB114 0x1142 -#define PCI_DEVICE_ID_CP114UL 0x1143 -#define PCI_DEVICE_ID_CB134I 0x1341 -#define PCI_DEVICE_ID_CP138U 0x1380 - - -#define C168_ASIC_ID 1 -#define C104_ASIC_ID 2 -#define C102_ASIC_ID 0xB -#define CI132_ASIC_ID 4 -#define CI134_ASIC_ID 3 -#define CI104J_ASIC_ID 5 - -#define MXSER_HIGHBAUD 1 -#define MXSER_HAS2 2 - -/* This is only for PCI */ -static const struct { - int type; - int tx_fifo; - int rx_fifo; - int xmit_fifo_size; - int rx_high_water; - int rx_trigger; - int rx_low_water; - long max_baud; -} Gpci_uart_info[] = { - {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, - {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, - {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} -}; -#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) - -struct mxser_cardinfo { - char *name; - unsigned int nports; - unsigned int flags; -}; - -static const struct mxser_cardinfo mxser_cards[] = { -/* 0*/ { "C168 series", 8, }, - { "C104 series", 4, }, - { "CI-104J series", 4, }, - { "C168H/PCI series", 8, }, - { "C104H/PCI series", 4, }, -/* 5*/ { "C102 series", 4, MXSER_HAS2 }, /* C102-ISA */ - { "CI-132 series", 4, MXSER_HAS2 }, - { "CI-134 series", 4, }, - { "CP-132 series", 2, }, - { "CP-114 series", 4, }, -/*10*/ { "CT-114 series", 4, }, - { "CP-102 series", 2, MXSER_HIGHBAUD }, - { "CP-104U series", 4, }, - { "CP-168U series", 8, }, - { "CP-132U series", 2, }, -/*15*/ { "CP-134U series", 4, }, - { "CP-104JU series", 4, }, - { "Moxa UC7000 Serial", 8, }, /* RC7000 */ - { "CP-118U series", 8, }, - { "CP-102UL series", 2, }, -/*20*/ { "CP-102U series", 2, }, - { "CP-118EL series", 8, }, - { "CP-168EL series", 8, }, - { "CP-104EL series", 4, }, - { "CB-108 series", 8, }, -/*25*/ { "CB-114 series", 4, }, - { "CB-134I series", 4, }, - { "CP-138U series", 8, }, - { "POS-104UL series", 4, }, - { "CP-114UL series", 4, }, -/*30*/ { "CP-102UF series", 2, }, - { "CP-112UL series", 2, }, -}; - -/* driver_data correspond to the lines in the structure above - see also ISA probe function before you change something */ -static struct pci_device_id mxser_pcibrds[] = { - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 31 }, - { } -}; -MODULE_DEVICE_TABLE(pci, mxser_pcibrds); - -static unsigned long ioaddr[MXSER_BOARDS]; -static int ttymajor = MXSERMAJOR; - -/* Variables for insmod */ - -MODULE_AUTHOR("Casper Yang"); -MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); -module_param_array(ioaddr, ulong, NULL, 0); -MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); -module_param(ttymajor, int, 0); -MODULE_LICENSE("GPL"); - -struct mxser_log { - int tick; - unsigned long rxcnt[MXSER_PORTS]; - unsigned long txcnt[MXSER_PORTS]; -}; - -struct mxser_mon { - unsigned long rxcnt; - unsigned long txcnt; - unsigned long up_rxcnt; - unsigned long up_txcnt; - int modem_status; - unsigned char hold_reason; -}; - -struct mxser_mon_ext { - unsigned long rx_cnt[32]; - unsigned long tx_cnt[32]; - unsigned long up_rxcnt[32]; - unsigned long up_txcnt[32]; - int modem_status[32]; - - long baudrate[32]; - int databits[32]; - int stopbits[32]; - int parity[32]; - int flowctrl[32]; - int fifo[32]; - int iftype[32]; -}; - -struct mxser_board; - -struct mxser_port { - struct tty_port port; - struct mxser_board *board; - - unsigned long ioaddr; - unsigned long opmode_ioaddr; - int max_baud; - - int rx_high_water; - int rx_trigger; /* Rx fifo trigger level */ - int rx_low_water; - int baud_base; /* max. speed */ - int type; /* UART type */ - - int x_char; /* xon/xoff character */ - int IER; /* Interrupt Enable Register */ - int MCR; /* Modem control register */ - - unsigned char stop_rx; - unsigned char ldisc_stop_rx; - - int custom_divisor; - unsigned char err_shadow; - - struct async_icount icount; /* kernel counters for 4 input interrupts */ - int timeout; - - int read_status_mask; - int ignore_status_mask; - int xmit_fifo_size; - int xmit_head; - int xmit_tail; - int xmit_cnt; - - struct ktermios normal_termios; - - struct mxser_mon mon_data; - - spinlock_t slock; -}; - -struct mxser_board { - unsigned int idx; - int irq; - const struct mxser_cardinfo *info; - unsigned long vector; - unsigned long vector_mask; - - int chip_flag; - int uart_type; - - struct mxser_port ports[MXSER_PORTS_PER_BOARD]; -}; - -struct mxser_mstatus { - tcflag_t cflag; - int cts; - int dsr; - int ri; - int dcd; -}; - -static struct mxser_board mxser_boards[MXSER_BOARDS]; -static struct tty_driver *mxvar_sdriver; -static struct mxser_log mxvar_log; -static int mxser_set_baud_method[MXSER_PORTS + 1]; - -static void mxser_enable_must_enchance_mode(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} - -#ifdef CONFIG_PCI -static void mxser_disable_must_enchance_mode(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} -#endif - -static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) -{ - u8 oldlcr; - u8 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(value, baseio + MOXA_MUST_XON1_REGISTER); - outb(oldlcr, baseio + UART_LCR); -} - -static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value) -{ - u8 oldlcr; - u8 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(value, baseio + MOXA_MUST_XOFF1_REGISTER); - outb(oldlcr, baseio + UART_LCR); -} - -static void mxser_set_must_fifo_value(struct mxser_port *info) -{ - u8 oldlcr; - u8 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; - - 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); -} - -static void mxser_set_must_enum_value(unsigned long baseio, u8 value) -{ - u8 oldlcr; - u8 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); - outb(value, baseio + MOXA_MUST_ENUM_REGISTER); - outb(oldlcr, baseio + UART_LCR); -} - -#ifdef CONFIG_PCI -static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) -{ - u8 oldlcr; - u8 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); -} -#endif - -static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} - -static void mxser_enable_must_tx_software_flow_control(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} - -static void mxser_disable_must_tx_software_flow_control(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} - -static void mxser_enable_must_rx_software_flow_control(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} - -static void mxser_disable_must_rx_software_flow_control(unsigned long baseio) -{ - u8 oldlcr; - u8 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); -} - -#ifdef CONFIG_PCI -static int __devinit CheckIsMoxaMust(unsigned long io) -{ - u8 oldmcr, hwid; - int i; - - outb(0, io + UART_LCR); - mxser_disable_must_enchance_mode(io); - oldmcr = inb(io + UART_MCR); - outb(0, io + UART_MCR); - mxser_set_must_xon1_value(io, 0x11); - if ((hwid = inb(io + UART_MCR)) != 0) { - outb(oldmcr, io + UART_MCR); - return MOXA_OTHER_UART; - } - - mxser_get_must_hardware_id(io, &hwid); - for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ - if (hwid == Gpci_uart_info[i].type) - return (int)hwid; - } - return MOXA_OTHER_UART; -} -#endif - -static void process_txrx_fifo(struct mxser_port *info) -{ - int i; - - if ((info->type == PORT_16450) || (info->type == PORT_8250)) { - info->rx_trigger = 1; - info->rx_high_water = 1; - info->rx_low_water = 1; - info->xmit_fifo_size = 1; - } else - for (i = 0; i < UART_INFO_NUM; i++) - if (info->board->chip_flag == Gpci_uart_info[i].type) { - info->rx_trigger = Gpci_uart_info[i].rx_trigger; - info->rx_low_water = Gpci_uart_info[i].rx_low_water; - info->rx_high_water = Gpci_uart_info[i].rx_high_water; - info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; - break; - } -} - -static unsigned char mxser_get_msr(int baseaddr, int mode, int port) -{ - static unsigned char mxser_msr[MXSER_PORTS + 1]; - unsigned char status = 0; - - status = inb(baseaddr + UART_MSR); - - mxser_msr[port] &= 0x0F; - mxser_msr[port] |= status; - status = mxser_msr[port]; - if (mode) - mxser_msr[port] = 0; - - return status; -} - -static int mxser_carrier_raised(struct tty_port *port) -{ - struct mxser_port *mp = container_of(port, struct mxser_port, port); - return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; -} - -static void mxser_dtr_rts(struct tty_port *port, int on) -{ - struct mxser_port *mp = container_of(port, struct mxser_port, port); - unsigned long flags; - - spin_lock_irqsave(&mp->slock, flags); - if (on) - outb(inb(mp->ioaddr + UART_MCR) | - UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); - else - outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS), - mp->ioaddr + UART_MCR); - spin_unlock_irqrestore(&mp->slock, flags); -} - -static int mxser_set_baud(struct tty_struct *tty, long newspd) -{ - struct mxser_port *info = tty->driver_data; - int quot = 0, baud; - unsigned char cval; - - if (!info->ioaddr) - return -1; - - if (newspd > info->max_baud) - return -1; - - if (newspd == 134) { - quot = 2 * info->baud_base / 269; - tty_encode_baud_rate(tty, 134, 134); - } else if (newspd) { - quot = info->baud_base / newspd; - if (quot == 0) - quot = 1; - baud = info->baud_base/quot; - tty_encode_baud_rate(tty, baud, baud); - } 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) { - info->MCR |= UART_MCR_DTR; - outb(info->MCR, info->ioaddr + UART_MCR); - } else { - info->MCR &= ~UART_MCR_DTR; - outb(info->MCR, info->ioaddr + UART_MCR); - return 0; - } - - cval = inb(info->ioaddr + UART_LCR); - - outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */ - - outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */ - outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ - outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ - -#ifdef BOTHER - if (C_BAUD(tty) == BOTHER) { - quot = info->baud_base % newspd; - quot *= 8; - if (quot % newspd > newspd / 2) { - quot /= newspd; - quot++; - } else - quot /= newspd; - - mxser_set_must_enum_value(info->ioaddr, quot); - } else -#endif - mxser_set_must_enum_value(info->ioaddr, 0); - - return 0; -} - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static int mxser_change_speed(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct mxser_port *info = tty->driver_data; - unsigned cflag, cval, fcr; - int ret = 0; - unsigned char status; - - cflag = tty->termios->c_cflag; - if (!info->ioaddr) - return ret; - - if (mxser_set_baud_method[tty->index] == 0) - mxser_set_baud(tty, tty_get_baud_rate(tty)); - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: - cval = 0x00; - break; - case CS6: - cval = 0x01; - break; - case CS7: - cval = 0x02; - break; - case CS8: - cval = 0x03; - break; - default: - cval = 0x00; - break; /* too keep GCC shut... */ - } - if (cflag & CSTOPB) - cval |= 0x04; - if (cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; - if (cflag & CMSPAR) - cval |= UART_LCR_SPAR; - - if ((info->type == PORT_8250) || (info->type == PORT_16450)) { - if (info->board->chip_flag) { - fcr = UART_FCR_ENABLE_FIFO; - fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; - mxser_set_must_fifo_value(info); - } else - fcr = 0; - } else { - fcr = UART_FCR_ENABLE_FIFO; - if (info->board->chip_flag) { - fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; - mxser_set_must_fifo_value(info); - } else { - switch (info->rx_trigger) { - case 1: - fcr |= UART_FCR_TRIGGER_1; - break; - case 4: - fcr |= UART_FCR_TRIGGER_4; - break; - case 8: - fcr |= UART_FCR_TRIGGER_8; - break; - default: - fcr |= UART_FCR_TRIGGER_14; - break; - } - } - } - - /* CTS flow control flag and modem status interrupts */ - info->IER &= ~UART_IER_MSI; - info->MCR &= ~UART_MCR_AFE; - if (cflag & CRTSCTS) { - info->port.flags |= ASYNC_CTS_FLOW; - info->IER |= UART_IER_MSI; - if ((info->type == PORT_16550A) || (info->board->chip_flag)) { - info->MCR |= UART_MCR_AFE; - } else { - status = inb(info->ioaddr + UART_MSR); - if (tty->hw_stopped) { - if (status & UART_MSR_CTS) { - tty->hw_stopped = 0; - if (info->type != PORT_16550A && - !info->board->chip_flag) { - outb(info->IER & ~UART_IER_THRI, - info->ioaddr + - UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + - UART_IER); - } - tty_wakeup(tty); - } - } else { - if (!(status & UART_MSR_CTS)) { - tty->hw_stopped = 1; - if ((info->type != PORT_16550A) && - (!info->board->chip_flag)) { - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->ioaddr + - UART_IER); - } - } - } - } - } else { - info->port.flags &= ~ASYNC_CTS_FLOW; - } - outb(info->MCR, info->ioaddr + UART_MCR); - if (cflag & CLOCAL) { - info->port.flags &= ~ASYNC_CHECK_CD; - } else { - info->port.flags |= ASYNC_CHECK_CD; - info->IER |= UART_IER_MSI; - } - outb(info->IER, info->ioaddr + UART_IER); - - /* - * Set up parity check flag - */ - info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (I_INPCK(tty)) - info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (I_BRKINT(tty) || I_PARMRK(tty)) - info->read_status_mask |= UART_LSR_BI; - - info->ignore_status_mask = 0; - - if (I_IGNBRK(tty)) { - info->ignore_status_mask |= UART_LSR_BI; - info->read_status_mask |= UART_LSR_BI; - /* - * If we're ignore parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(tty)) { - info->ignore_status_mask |= - UART_LSR_OE | - UART_LSR_PE | - UART_LSR_FE; - info->read_status_mask |= - UART_LSR_OE | - UART_LSR_PE | - UART_LSR_FE; - } - } - if (info->board->chip_flag) { - mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty)); - mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty)); - if (I_IXON(tty)) { - mxser_enable_must_rx_software_flow_control( - info->ioaddr); - } else { - mxser_disable_must_rx_software_flow_control( - info->ioaddr); - } - if (I_IXOFF(tty)) { - mxser_enable_must_tx_software_flow_control( - info->ioaddr); - } else { - mxser_disable_must_tx_software_flow_control( - info->ioaddr); - } - } - - - outb(fcr, info->ioaddr + UART_FCR); /* set fcr */ - outb(cval, info->ioaddr + UART_LCR); - - return ret; -} - -static void mxser_check_modem_status(struct tty_struct *tty, - struct mxser_port *port, int status) -{ - /* update input line counters */ - if (status & UART_MSR_TERI) - port->icount.rng++; - if (status & UART_MSR_DDSR) - port->icount.dsr++; - if (status & UART_MSR_DDCD) - port->icount.dcd++; - if (status & UART_MSR_DCTS) - port->icount.cts++; - port->mon_data.modem_status = status; - wake_up_interruptible(&port->port.delta_msr_wait); - - if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { - if (status & UART_MSR_DCD) - wake_up_interruptible(&port->port.open_wait); - } - - if (port->port.flags & ASYNC_CTS_FLOW) { - if (tty->hw_stopped) { - if (status & UART_MSR_CTS) { - tty->hw_stopped = 0; - - if ((port->type != PORT_16550A) && - (!port->board->chip_flag)) { - outb(port->IER & ~UART_IER_THRI, - port->ioaddr + UART_IER); - port->IER |= UART_IER_THRI; - outb(port->IER, port->ioaddr + - UART_IER); - } - tty_wakeup(tty); - } - } else { - if (!(status & UART_MSR_CTS)) { - tty->hw_stopped = 1; - if (port->type != PORT_16550A && - !port->board->chip_flag) { - port->IER &= ~UART_IER_THRI; - outb(port->IER, port->ioaddr + - UART_IER); - } - } - } - } -} - -static int mxser_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct mxser_port *info = container_of(port, struct mxser_port, port); - unsigned long page; - unsigned long flags; - - page = __get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - spin_lock_irqsave(&info->slock, flags); - - if (!info->ioaddr || !info->type) { - set_bit(TTY_IO_ERROR, &tty->flags); - free_page(page); - spin_unlock_irqrestore(&info->slock, flags); - return 0; - } - info->port.xmit_buf = (unsigned char *) page; - - /* - * Clear the FIFO buffers and disable them - * (they will be reenabled in mxser_change_speed()) - */ - if (info->board->chip_flag) - outb((UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT | - MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); - else - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), - info->ioaddr + UART_FCR); - - /* - * At this point there's no way the LSR could still be 0xFF; - * if it is, then bail out, because there's likely no UART - * here. - */ - if (inb(info->ioaddr + UART_LSR) == 0xff) { - spin_unlock_irqrestore(&info->slock, flags); - if (capable(CAP_SYS_ADMIN)) { - set_bit(TTY_IO_ERROR, &tty->flags); - return 0; - } else - return -ENODEV; - } - - /* - * Clear the interrupt registers. - */ - (void) inb(info->ioaddr + UART_LSR); - (void) inb(info->ioaddr + UART_RX); - (void) inb(info->ioaddr + UART_IIR); - (void) inb(info->ioaddr + UART_MSR); - - /* - * Now, initialize the UART - */ - outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */ - info->MCR = UART_MCR_DTR | UART_MCR_RTS; - outb(info->MCR, info->ioaddr + UART_MCR); - - /* - * Finally, enable interrupts - */ - info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - - if (info->board->chip_flag) - info->IER |= MOXA_MUST_IER_EGDAI; - outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ - - /* - * And clear the interrupt registers again for luck. - */ - (void) inb(info->ioaddr + UART_LSR); - (void) inb(info->ioaddr + UART_RX); - (void) inb(info->ioaddr + UART_IIR); - (void) inb(info->ioaddr + UART_MSR); - - clear_bit(TTY_IO_ERROR, &tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* - * and set the speed of the serial port - */ - mxser_change_speed(tty, NULL); - spin_unlock_irqrestore(&info->slock, flags); - - return 0; -} - -/* - * This routine will shutdown a serial port - */ -static void mxser_shutdown_port(struct tty_port *port) -{ - struct mxser_port *info = container_of(port, struct mxser_port, port); - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be waken up - */ - wake_up_interruptible(&info->port.delta_msr_wait); - - /* - * Free the xmit buffer, if necessary - */ - if (info->port.xmit_buf) { - free_page((unsigned long) info->port.xmit_buf); - info->port.xmit_buf = NULL; - } - - info->IER = 0; - outb(0x00, info->ioaddr + UART_IER); - - /* clear Rx/Tx FIFO's */ - if (info->board->chip_flag) - outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | - MOXA_MUST_FCR_GDA_MODE_ENABLE, - info->ioaddr + UART_FCR); - else - outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, - info->ioaddr + UART_FCR); - - /* read data port to reset things */ - (void) inb(info->ioaddr + UART_RX); - - - if (info->board->chip_flag) - SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); - - spin_unlock_irqrestore(&info->slock, flags); -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int mxser_open(struct tty_struct *tty, struct file *filp) -{ - struct mxser_port *info; - int line; - - line = tty->index; - if (line == MXSER_PORTS) - return 0; - if (line < 0 || line > MXSER_PORTS) - return -ENODEV; - info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; - if (!info->ioaddr) - return -ENODEV; - - tty->driver_data = info; - return tty_port_open(&info->port, tty, filp); -} - -static void mxser_flush_buffer(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - char fcr; - unsigned long flags; - - - spin_lock_irqsave(&info->slock, flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - fcr = inb(info->ioaddr + UART_FCR); - outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), - info->ioaddr + UART_FCR); - outb(fcr, info->ioaddr + UART_FCR); - - spin_unlock_irqrestore(&info->slock, flags); - - tty_wakeup(tty); -} - - -static void mxser_close_port(struct tty_port *port) -{ - struct mxser_port *info = container_of(port, struct mxser_port, port); - unsigned long timeout; - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - info->IER &= ~UART_IER_RLSI; - if (info->board->chip_flag) - info->IER &= ~MOXA_MUST_RECV_ISR; - - outb(info->IER, info->ioaddr + UART_IER); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies + HZ; - while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { - schedule_timeout_interruptible(5); - if (time_after(jiffies, timeout)) - break; - } -} - -/* - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - */ -static void mxser_close(struct tty_struct *tty, struct file *filp) -{ - struct mxser_port *info = tty->driver_data; - struct tty_port *port = &info->port; - - if (tty->index == MXSER_PORTS || info == NULL) - return; - if (tty_port_close_start(port, tty, filp) == 0) - return; - mutex_lock(&port->mutex); - mxser_close_port(port); - mxser_flush_buffer(tty); - mxser_shutdown_port(port); - clear_bit(ASYNCB_INITIALIZED, &port->flags); - mutex_unlock(&port->mutex); - /* Right now the tty_port set is done outside of the close_end helper - as we don't yet have everyone using refcounts */ - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); -} - -static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - int c, total = 0; - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - if (!info->port.xmit_buf) - return 0; - - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - memcpy(info->port.xmit_buf + info->xmit_head, buf, c); - spin_lock_irqsave(&info->slock, flags); - info->xmit_head = (info->xmit_head + c) & - (SERIAL_XMIT_SIZE - 1); - info->xmit_cnt += c; - spin_unlock_irqrestore(&info->slock, flags); - - buf += c; - count -= c; - total += c; - } - - if (info->xmit_cnt && !tty->stopped) { - if (!tty->hw_stopped || - (info->type == PORT_16550A) || - (info->board->chip_flag)) { - spin_lock_irqsave(&info->slock, flags); - outb(info->IER & ~UART_IER_THRI, info->ioaddr + - UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - spin_unlock_irqrestore(&info->slock, flags); - } - } - return total; -} - -static int mxser_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - if (!info->port.xmit_buf) - return 0; - - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) - return 0; - - spin_lock_irqsave(&info->slock, flags); - info->port.xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE - 1; - info->xmit_cnt++; - spin_unlock_irqrestore(&info->slock, flags); - if (!tty->stopped) { - if (!tty->hw_stopped || - (info->type == PORT_16550A) || - info->board->chip_flag) { - spin_lock_irqsave(&info->slock, flags); - outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - spin_unlock_irqrestore(&info->slock, flags); - } - } - return 1; -} - - -static void mxser_flush_chars(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || - (tty->hw_stopped && info->type != PORT_16550A && - !info->board->chip_flag)) - return; - - spin_lock_irqsave(&info->slock, flags); - - outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - - spin_unlock_irqrestore(&info->slock, flags); -} - -static int mxser_write_room(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - int ret; - - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - return ret < 0 ? 0 : ret; -} - -static int mxser_chars_in_buffer(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - return info->xmit_cnt; -} - -/* - * ------------------------------------------------------------ - * friends of mxser_ioctl() - * ------------------------------------------------------------ - */ -static int mxser_get_serial_info(struct tty_struct *tty, - struct serial_struct __user *retinfo) -{ - struct mxser_port *info = tty->driver_data; - struct serial_struct tmp = { - .type = info->type, - .line = tty->index, - .port = info->ioaddr, - .irq = info->board->irq, - .flags = info->port.flags, - .baud_base = info->baud_base, - .close_delay = info->port.close_delay, - .closing_wait = info->port.closing_wait, - .custom_divisor = info->custom_divisor, - .hub6 = 0 - }; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int mxser_set_serial_info(struct tty_struct *tty, - struct serial_struct __user *new_info) -{ - struct mxser_port *info = tty->driver_data; - struct tty_port *port = &info->port; - struct serial_struct new_serial; - speed_t baud; - unsigned long sl_flags; - unsigned int flags; - int retval = 0; - - if (!new_info || !info->ioaddr) - return -ENODEV; - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - - if (new_serial.irq != info->board->irq || - new_serial.port != info->ioaddr) - return -EINVAL; - - flags = port->flags & ASYNC_SPD_MASK; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.baud_base != info->baud_base) || - (new_serial.close_delay != info->port.close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) - return -EPERM; - info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - } else { - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - port->flags = ((port->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - port->close_delay = new_serial.close_delay * HZ / 100; - port->closing_wait = new_serial.closing_wait * HZ / 100; - tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && - (new_serial.baud_base != info->baud_base || - new_serial.custom_divisor != - info->custom_divisor)) { - if (new_serial.custom_divisor == 0) - return -EINVAL; - baud = new_serial.baud_base / new_serial.custom_divisor; - tty_encode_baud_rate(tty, baud, baud); - } - } - - info->type = new_serial.type; - - process_txrx_fifo(info); - - if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { - if (flags != (port->flags & ASYNC_SPD_MASK)) { - spin_lock_irqsave(&info->slock, sl_flags); - mxser_change_speed(tty, NULL); - spin_unlock_irqrestore(&info->slock, sl_flags); - } - } else { - retval = mxser_activate(port, tty); - if (retval == 0) - set_bit(ASYNCB_INITIALIZED, &port->flags); - } - return retval; -} - -/* - * mxser_get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int mxser_get_lsr_info(struct mxser_port *info, - unsigned int __user *value) -{ - unsigned char status; - unsigned int result; - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - status = inb(info->ioaddr + UART_LSR); - spin_unlock_irqrestore(&info->slock, flags); - result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - return put_user(result, value); -} - -static int mxser_tiocmget(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - unsigned char control, status; - unsigned long flags; - - - if (tty->index == MXSER_PORTS) - return -ENOIOCTLCMD; - if (test_bit(TTY_IO_ERROR, &tty->flags)) - return -EIO; - - control = info->MCR; - - spin_lock_irqsave(&info->slock, flags); - status = inb(info->ioaddr + UART_MSR); - if (status & UART_MSR_ANY_DELTA) - mxser_check_modem_status(tty, info, status); - spin_unlock_irqrestore(&info->slock, flags); - return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | - ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | - ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | - ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | - ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | - ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); -} - -static int mxser_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - - if (tty->index == MXSER_PORTS) - return -ENOIOCTLCMD; - if (test_bit(TTY_IO_ERROR, &tty->flags)) - return -EIO; - - spin_lock_irqsave(&info->slock, flags); - - if (set & TIOCM_RTS) - info->MCR |= UART_MCR_RTS; - if (set & TIOCM_DTR) - info->MCR |= UART_MCR_DTR; - - if (clear & TIOCM_RTS) - info->MCR &= ~UART_MCR_RTS; - if (clear & TIOCM_DTR) - info->MCR &= ~UART_MCR_DTR; - - outb(info->MCR, info->ioaddr + UART_MCR); - spin_unlock_irqrestore(&info->slock, flags); - return 0; -} - -static int __init mxser_program_mode(int port) -{ - int id, i, j, n; - - outb(0, port); - outb(0, port); - outb(0, port); - (void)inb(port); - (void)inb(port); - outb(0, port); - (void)inb(port); - - id = inb(port + 1) & 0x1F; - if ((id != C168_ASIC_ID) && - (id != C104_ASIC_ID) && - (id != C102_ASIC_ID) && - (id != CI132_ASIC_ID) && - (id != CI134_ASIC_ID) && - (id != CI104J_ASIC_ID)) - return -1; - for (i = 0, j = 0; i < 4; i++) { - n = inb(port + 2); - if (n == 'M') { - j = 1; - } else if ((j == 1) && (n == 1)) { - j = 2; - break; - } else - j = 0; - } - if (j != 2) - id = -2; - return id; -} - -static void __init mxser_normal_mode(int port) -{ - int i, n; - - outb(0xA5, port + 1); - outb(0x80, port + 3); - outb(12, port + 0); /* 9600 bps */ - outb(0, port + 1); - outb(0x03, port + 3); /* 8 data bits */ - outb(0x13, port + 4); /* loop back mode */ - for (i = 0; i < 16; i++) { - n = inb(port + 5); - if ((n & 0x61) == 0x60) - break; - if ((n & 1) == 1) - (void)inb(port); - } - outb(0x00, port + 4); -} - -#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ -#define CHIP_DO 0x02 /* Serial Data Output in Eprom */ -#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ -#define CHIP_DI 0x08 /* Serial Data Input in Eprom */ -#define EN_CCMD 0x000 /* Chip's command register */ -#define EN0_RSARLO 0x008 /* Remote start address reg 0 */ -#define EN0_RSARHI 0x009 /* Remote start address reg 1 */ -#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ -#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ -#define EN0_DCFG 0x00E /* Data configuration reg WR */ -#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 __init mxser_read_register(int port, unsigned short *regs) -{ - int i, k, value, id; - unsigned int j; - - id = mxser_program_mode(port); - if (id < 0) - return id; - for (i = 0; i < 14; i++) { - k = (i & 0x3F) | 0x180; - for (j = 0x100; j > 0; j >>= 1) { - outb(CHIP_CS, port); - if (k & j) { - outb(CHIP_CS | CHIP_DO, port); - outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ - } else { - outb(CHIP_CS, port); - outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ - } - } - (void)inb(port); - value = 0; - for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { - outb(CHIP_CS, port); - outb(CHIP_CS | CHIP_SK, port); - if (inb(port) & CHIP_DI) - value |= j; - } - regs[i] = value; - outb(0, port); - } - mxser_normal_mode(port); - return id; -} - -static int mxser_ioctl_special(unsigned int cmd, void __user *argp) -{ - struct mxser_port *ip; - struct tty_port *port; - struct tty_struct *tty; - int result, status; - unsigned int i, j; - int ret = 0; - - switch (cmd) { - case MOXA_GET_MAJOR: - if (printk_ratelimit()) - printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl " - "%x (GET_MAJOR), fix your userspace\n", - current->comm, cmd); - return put_user(ttymajor, (int __user *)argp); - - case MOXA_CHKPORTENABLE: - result = 0; - for (i = 0; i < MXSER_BOARDS; i++) - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) - if (mxser_boards[i].ports[j].ioaddr) - result |= (1 << i); - return put_user(result, (unsigned long __user *)argp); - case MOXA_GETDATACOUNT: - /* The receive side is locked by port->slock but it isn't - clear that an exact snapshot is worth copying here */ - if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) - ret = -EFAULT; - return ret; - case MOXA_GETMSTATUS: { - struct mxser_mstatus ms, __user *msu = argp; - for (i = 0; i < MXSER_BOARDS; i++) - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { - ip = &mxser_boards[i].ports[j]; - port = &ip->port; - memset(&ms, 0, sizeof(ms)); - - mutex_lock(&port->mutex); - if (!ip->ioaddr) - goto copy; - - tty = tty_port_tty_get(port); - - if (!tty || !tty->termios) - ms.cflag = ip->normal_termios.c_cflag; - else - ms.cflag = tty->termios->c_cflag; - tty_kref_put(tty); - spin_lock_irq(&ip->slock); - status = inb(ip->ioaddr + UART_MSR); - spin_unlock_irq(&ip->slock); - if (status & UART_MSR_DCD) - ms.dcd = 1; - if (status & UART_MSR_DSR) - ms.dsr = 1; - if (status & UART_MSR_CTS) - ms.cts = 1; - copy: - mutex_unlock(&port->mutex); - if (copy_to_user(msu, &ms, sizeof(ms))) - return -EFAULT; - msu++; - } - return 0; - } - case MOXA_ASPP_MON_EXT: { - struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ - unsigned int cflag, iflag, p; - u8 opmode; - - me = kzalloc(sizeof(*me), GFP_KERNEL); - if (!me) - return -ENOMEM; - - for (i = 0, p = 0; i < MXSER_BOARDS; i++) { - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { - if (p >= ARRAY_SIZE(me->rx_cnt)) { - i = MXSER_BOARDS; - break; - } - ip = &mxser_boards[i].ports[j]; - port = &ip->port; - - mutex_lock(&port->mutex); - if (!ip->ioaddr) { - mutex_unlock(&port->mutex); - continue; - } - - spin_lock_irq(&ip->slock); - status = mxser_get_msr(ip->ioaddr, 0, p); - - if (status & UART_MSR_TERI) - ip->icount.rng++; - if (status & UART_MSR_DDSR) - ip->icount.dsr++; - if (status & UART_MSR_DDCD) - ip->icount.dcd++; - if (status & UART_MSR_DCTS) - ip->icount.cts++; - - ip->mon_data.modem_status = status; - me->rx_cnt[p] = ip->mon_data.rxcnt; - me->tx_cnt[p] = ip->mon_data.txcnt; - me->up_rxcnt[p] = ip->mon_data.up_rxcnt; - me->up_txcnt[p] = ip->mon_data.up_txcnt; - me->modem_status[p] = - ip->mon_data.modem_status; - spin_unlock_irq(&ip->slock); - - tty = tty_port_tty_get(&ip->port); - - if (!tty || !tty->termios) { - cflag = ip->normal_termios.c_cflag; - iflag = ip->normal_termios.c_iflag; - me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); - } else { - cflag = tty->termios->c_cflag; - iflag = tty->termios->c_iflag; - me->baudrate[p] = tty_get_baud_rate(tty); - } - tty_kref_put(tty); - - me->databits[p] = cflag & CSIZE; - me->stopbits[p] = cflag & CSTOPB; - me->parity[p] = cflag & (PARENB | PARODD | - CMSPAR); - - if (cflag & CRTSCTS) - me->flowctrl[p] |= 0x03; - - if (iflag & (IXON | IXOFF)) - me->flowctrl[p] |= 0x0C; - - if (ip->type == PORT_16550A) - me->fifo[p] = 1; - - opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); - opmode &= OP_MODE_MASK; - me->iftype[p] = opmode; - mutex_unlock(&port->mutex); - } - } - if (copy_to_user(argp, me, sizeof(*me))) - ret = -EFAULT; - kfree(me); - return ret; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg, - struct async_icount *cprev) -{ - struct async_icount cnow; - unsigned long flags; - int ret; - - spin_lock_irqsave(&info->slock, flags); - cnow = info->icount; /* atomic copy */ - spin_unlock_irqrestore(&info->slock, flags); - - ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); - - *cprev = cnow; - - return ret; -} - -static int mxser_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct mxser_port *info = tty->driver_data; - struct tty_port *port = &info->port; - struct async_icount cnow; - unsigned long flags; - void __user *argp = (void __user *)arg; - int retval; - - if (tty->index == MXSER_PORTS) - return mxser_ioctl_special(cmd, argp); - - if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { - int p; - unsigned long opmode; - static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; - int shiftbit; - unsigned char val, mask; - - p = tty->index % 4; - if (cmd == MOXA_SET_OP_MODE) { - if (get_user(opmode, (int __user *) argp)) - return -EFAULT; - if (opmode != RS232_MODE && - opmode != RS485_2WIRE_MODE && - opmode != RS422_MODE && - opmode != RS485_4WIRE_MODE) - return -EFAULT; - mask = ModeMask[p]; - shiftbit = p * 2; - spin_lock_irq(&info->slock); - val = inb(info->opmode_ioaddr); - val &= mask; - val |= (opmode << shiftbit); - outb(val, info->opmode_ioaddr); - spin_unlock_irq(&info->slock); - } else { - shiftbit = p * 2; - spin_lock_irq(&info->slock); - opmode = inb(info->opmode_ioaddr) >> shiftbit; - spin_unlock_irq(&info->slock); - opmode &= OP_MODE_MASK; - if (put_user(opmode, (int __user *)argp)) - return -EFAULT; - } - return 0; - } - - if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && - test_bit(TTY_IO_ERROR, &tty->flags)) - return -EIO; - - switch (cmd) { - case TIOCGSERIAL: - mutex_lock(&port->mutex); - retval = mxser_get_serial_info(tty, argp); - mutex_unlock(&port->mutex); - return retval; - case TIOCSSERIAL: - mutex_lock(&port->mutex); - retval = mxser_set_serial_info(tty, argp); - mutex_unlock(&port->mutex); - return retval; - case TIOCSERGETLSR: /* Get line status register */ - return mxser_get_lsr_info(info, argp); - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - spin_lock_irqsave(&info->slock, flags); - cnow = info->icount; /* note the counters on entry */ - spin_unlock_irqrestore(&info->slock, flags); - - return wait_event_interruptible(info->port.delta_msr_wait, - mxser_cflags_changed(info, arg, &cnow)); - case MOXA_HighSpeedOn: - return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); - case MOXA_SDS_RSTICOUNTER: - spin_lock_irq(&info->slock); - info->mon_data.rxcnt = 0; - info->mon_data.txcnt = 0; - spin_unlock_irq(&info->slock); - return 0; - - case MOXA_ASPP_OQUEUE:{ - int len, lsr; - - len = mxser_chars_in_buffer(tty); - spin_lock_irq(&info->slock); - lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; - spin_unlock_irq(&info->slock); - len += (lsr ? 0 : 1); - - return put_user(len, (int __user *)argp); - } - case MOXA_ASPP_MON: { - int mcr, status; - - spin_lock_irq(&info->slock); - status = mxser_get_msr(info->ioaddr, 1, tty->index); - mxser_check_modem_status(tty, info, status); - - mcr = inb(info->ioaddr + UART_MCR); - spin_unlock_irq(&info->slock); - - if (mcr & MOXA_MUST_MCR_XON_FLAG) - info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; - else - info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; - - if (mcr & MOXA_MUST_MCR_TX_XON) - info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; - else - info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; - - if (tty->hw_stopped) - info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; - else - info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; - - if (copy_to_user(argp, &info->mon_data, - sizeof(struct mxser_mon))) - return -EFAULT; - - return 0; - } - case MOXA_ASPP_LSTATUS: { - if (put_user(info->err_shadow, (unsigned char __user *)argp)) - return -EFAULT; - - info->err_shadow = 0; - return 0; - } - case MOXA_SET_BAUD_METHOD: { - int method; - - if (get_user(method, (int __user *)argp)) - return -EFAULT; - mxser_set_baud_method[tty->index] = method; - return put_user(method, (int __user *)argp); - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - -static int mxser_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) - -{ - struct mxser_port *info = tty->driver_data; - struct async_icount cnow; - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->slock, flags); - - icount->frame = cnow.frame; - icount->brk = cnow.brk; - icount->overrun = cnow.overrun; - icount->buf_overrun = cnow.buf_overrun; - icount->parity = cnow.parity; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - return 0; -} - -static void mxser_stoprx(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - - info->ldisc_stop_rx = 1; - if (I_IXOFF(tty)) { - if (info->board->chip_flag) { - info->IER &= ~MOXA_MUST_RECV_ISR; - outb(info->IER, info->ioaddr + UART_IER); - } else { - info->x_char = STOP_CHAR(tty); - outb(0, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - } - } - - if (tty->termios->c_cflag & CRTSCTS) { - info->MCR &= ~UART_MCR_RTS; - outb(info->MCR, info->ioaddr + UART_MCR); - } -} - -/* - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - */ -static void mxser_throttle(struct tty_struct *tty) -{ - mxser_stoprx(tty); -} - -static void mxser_unthrottle(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - - /* startrx */ - info->ldisc_stop_rx = 0; - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else { - if (info->board->chip_flag) { - info->IER |= MOXA_MUST_RECV_ISR; - outb(info->IER, info->ioaddr + UART_IER); - } else { - info->x_char = START_CHAR(tty); - outb(0, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - } - } - } - - if (tty->termios->c_cflag & CRTSCTS) { - info->MCR |= UART_MCR_RTS; - outb(info->MCR, info->ioaddr + UART_MCR); - } -} - -/* - * mxser_stop() and mxser_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - */ -static void mxser_stop(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - } - spin_unlock_irqrestore(&info->slock, flags); -} - -static void mxser_start(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - if (info->xmit_cnt && info->port.xmit_buf) { - outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - } - spin_unlock_irqrestore(&info->slock, flags); -} - -static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - mxser_change_speed(tty, old_termios); - spin_unlock_irqrestore(&info->slock, flags); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - mxser_start(tty); - } - - /* Handle sw stopped */ - if ((old_termios->c_iflag & IXON) && - !(tty->termios->c_iflag & IXON)) { - tty->stopped = 0; - - if (info->board->chip_flag) { - spin_lock_irqsave(&info->slock, flags); - mxser_disable_must_rx_software_flow_control( - info->ioaddr); - spin_unlock_irqrestore(&info->slock, flags); - } - - mxser_start(tty); - } -} - -/* - * mxser_wait_until_sent() --- wait until the transmitter is empty - */ -static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct mxser_port *info = tty->driver_data; - unsigned long orig_jiffies, char_time; - unsigned long flags; - int lsr; - - if (info->type == PORT_UNKNOWN) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2 * info->timeout) - timeout = 2 * info->timeout; -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", - timeout, char_time); - printk("jiff=%lu...", jiffies); -#endif - spin_lock_irqsave(&info->slock, flags); - while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...", lsr, jiffies); -#endif - spin_unlock_irqrestore(&info->slock, flags); - schedule_timeout_interruptible(char_time); - spin_lock_irqsave(&info->slock, flags); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - spin_unlock_irqrestore(&info->slock, flags); - set_current_state(TASK_RUNNING); - -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); -#endif -} - -/* - * This routine is called by tty_hangup() when a hangup is signaled. - */ -static void mxser_hangup(struct tty_struct *tty) -{ - struct mxser_port *info = tty->driver_data; - - mxser_flush_buffer(tty); - tty_port_hangup(&info->port); -} - -/* - * mxser_rs_break() --- routine which turns the break handling on or off - */ -static int mxser_rs_break(struct tty_struct *tty, int break_state) -{ - struct mxser_port *info = tty->driver_data; - unsigned long flags; - - spin_lock_irqsave(&info->slock, flags); - if (break_state == -1) - outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, - info->ioaddr + UART_LCR); - else - outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, - info->ioaddr + UART_LCR); - spin_unlock_irqrestore(&info->slock, flags); - return 0; -} - -static void mxser_receive_chars(struct tty_struct *tty, - struct mxser_port *port, int *status) -{ - unsigned char ch, gdl; - int ignored = 0; - int cnt = 0; - int recv_room; - int max = 256; - - recv_room = tty->receive_room; - if (recv_room == 0 && !port->ldisc_stop_rx) - mxser_stoprx(tty); - if (port->board->chip_flag != MOXA_OTHER_UART) { - - if (*status & UART_LSR_SPECIAL) - goto intr_old; - if (port->board->chip_flag == MOXA_MUST_MU860_HWID && - (*status & MOXA_MUST_LSR_RERR)) - goto intr_old; - if (*status & MOXA_MUST_LSR_RERR) - goto intr_old; - - gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); - - if (port->board->chip_flag == MOXA_MUST_MU150_HWID) - gdl &= MOXA_MUST_GDL_MASK; - if (gdl >= recv_room) { - if (!port->ldisc_stop_rx) - mxser_stoprx(tty); - } - while (gdl--) { - ch = inb(port->ioaddr + UART_RX); - tty_insert_flip_char(tty, ch, 0); - cnt++; - } - goto end_intr; - } -intr_old: - - do { - if (max-- < 0) - break; - - ch = inb(port->ioaddr + UART_RX); - if (port->board->chip_flag && (*status & UART_LSR_OE)) - outb(0x23, port->ioaddr + UART_FCR); - *status &= port->read_status_mask; - if (*status & port->ignore_status_mask) { - if (++ignored > 100) - break; - } else { - char flag = 0; - if (*status & UART_LSR_SPECIAL) { - if (*status & UART_LSR_BI) { - flag = TTY_BREAK; - port->icount.brk++; - - if (port->port.flags & ASYNC_SAK) - do_SAK(tty); - } else if (*status & UART_LSR_PE) { - flag = TTY_PARITY; - port->icount.parity++; - } else if (*status & UART_LSR_FE) { - flag = TTY_FRAME; - port->icount.frame++; - } else if (*status & UART_LSR_OE) { - flag = TTY_OVERRUN; - port->icount.overrun++; - } else - flag = TTY_BREAK; - } - tty_insert_flip_char(tty, ch, flag); - cnt++; - if (cnt >= recv_room) { - if (!port->ldisc_stop_rx) - mxser_stoprx(tty); - break; - } - - } - - if (port->board->chip_flag) - break; - - *status = inb(port->ioaddr + UART_LSR); - } while (*status & UART_LSR_DR); - -end_intr: - mxvar_log.rxcnt[tty->index] += cnt; - port->mon_data.rxcnt += cnt; - port->mon_data.up_rxcnt += cnt; - - /* - * We are called from an interrupt context with &port->slock - * being held. Drop it temporarily in order to prevent - * recursive locking. - */ - spin_unlock(&port->slock); - tty_flip_buffer_push(tty); - spin_lock(&port->slock); -} - -static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port) -{ - int count, cnt; - - if (port->x_char) { - outb(port->x_char, port->ioaddr + UART_TX); - port->x_char = 0; - mxvar_log.txcnt[tty->index]++; - port->mon_data.txcnt++; - port->mon_data.up_txcnt++; - port->icount.tx++; - return; - } - - if (port->port.xmit_buf == NULL) - return; - - if (port->xmit_cnt <= 0 || tty->stopped || - (tty->hw_stopped && - (port->type != PORT_16550A) && - (!port->board->chip_flag))) { - port->IER &= ~UART_IER_THRI; - outb(port->IER, port->ioaddr + UART_IER); - return; - } - - cnt = port->xmit_cnt; - count = port->xmit_fifo_size; - do { - outb(port->port.xmit_buf[port->xmit_tail++], - port->ioaddr + UART_TX); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); - if (--port->xmit_cnt <= 0) - break; - } while (--count > 0); - mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt); - - port->mon_data.txcnt += (cnt - port->xmit_cnt); - port->mon_data.up_txcnt += (cnt - port->xmit_cnt); - port->icount.tx += (cnt - port->xmit_cnt); - - if (port->xmit_cnt < WAKEUP_CHARS) - tty_wakeup(tty); - - if (port->xmit_cnt <= 0) { - port->IER &= ~UART_IER_THRI; - outb(port->IER, port->ioaddr + UART_IER); - } -} - -/* - * This is the serial driver's generic interrupt routine - */ -static irqreturn_t mxser_interrupt(int irq, void *dev_id) -{ - int status, iir, i; - struct mxser_board *brd = NULL; - struct mxser_port *port; - int max, irqbits, bits, msr; - unsigned int int_cnt, pass_counter = 0; - int handled = IRQ_NONE; - struct tty_struct *tty; - - for (i = 0; i < MXSER_BOARDS; i++) - if (dev_id == &mxser_boards[i]) { - brd = dev_id; - break; - } - - if (i == MXSER_BOARDS) - goto irq_stop; - if (brd == NULL) - goto irq_stop; - max = brd->info->nports; - while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { - irqbits = inb(brd->vector) & brd->vector_mask; - if (irqbits == brd->vector_mask) - break; - - handled = IRQ_HANDLED; - for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { - if (irqbits == brd->vector_mask) - break; - if (bits & irqbits) - continue; - 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; - tty = tty_port_tty_get(&port->port); - if (!tty || - (port->port.flags & ASYNC_CLOSING) || - !(port->port.flags & - ASYNC_INITIALIZED)) { - status = inb(port->ioaddr + UART_LSR); - outb(0x27, port->ioaddr + UART_FCR); - inb(port->ioaddr + UART_MSR); - tty_kref_put(tty); - break; - } - - status = inb(port->ioaddr + UART_LSR); - - if (status & UART_LSR_PE) - port->err_shadow |= NPPI_NOTIFY_PARITY; - if (status & UART_LSR_FE) - port->err_shadow |= NPPI_NOTIFY_FRAMING; - if (status & UART_LSR_OE) - port->err_shadow |= - NPPI_NOTIFY_HW_OVERRUN; - if (status & UART_LSR_BI) - port->err_shadow |= NPPI_NOTIFY_BREAK; - - if (port->board->chip_flag) { - if (iir == MOXA_MUST_IIR_GDA || - iir == MOXA_MUST_IIR_RDA || - iir == MOXA_MUST_IIR_RTO || - iir == MOXA_MUST_IIR_LSR) - mxser_receive_chars(tty, port, - &status); - - } else { - status &= port->read_status_mask; - if (status & UART_LSR_DR) - mxser_receive_chars(tty, port, - &status); - } - msr = inb(port->ioaddr + UART_MSR); - if (msr & UART_MSR_ANY_DELTA) - mxser_check_modem_status(tty, port, msr); - - if (port->board->chip_flag) { - if (iir == 0x02 && (status & - UART_LSR_THRE)) - mxser_transmit_chars(tty, port); - } else { - if (status & UART_LSR_THRE) - mxser_transmit_chars(tty, port); - } - tty_kref_put(tty); - } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); - spin_unlock(&port->slock); - } - } - -irq_stop: - return handled; -} - -static const struct tty_operations mxser_ops = { - .open = mxser_open, - .close = mxser_close, - .write = mxser_write, - .put_char = mxser_put_char, - .flush_chars = mxser_flush_chars, - .write_room = mxser_write_room, - .chars_in_buffer = mxser_chars_in_buffer, - .flush_buffer = mxser_flush_buffer, - .ioctl = mxser_ioctl, - .throttle = mxser_throttle, - .unthrottle = mxser_unthrottle, - .set_termios = mxser_set_termios, - .stop = mxser_stop, - .start = mxser_start, - .hangup = mxser_hangup, - .break_ctl = mxser_rs_break, - .wait_until_sent = mxser_wait_until_sent, - .tiocmget = mxser_tiocmget, - .tiocmset = mxser_tiocmset, - .get_icount = mxser_get_icount, -}; - -struct tty_port_operations mxser_port_ops = { - .carrier_raised = mxser_carrier_raised, - .dtr_rts = mxser_dtr_rts, - .activate = mxser_activate, - .shutdown = mxser_shutdown_port, -}; - -/* - * The MOXA Smartio/Industio serial driver boot-time initialization code! - */ - -static void mxser_release_ISA_res(struct mxser_board *brd) -{ - free_irq(brd->irq, brd); - release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - release_region(brd->vector, 1); -} - -static int __devinit mxser_initbrd(struct mxser_board *brd, - struct pci_dev *pdev) -{ - struct mxser_port *info; - unsigned int i; - int retval; - - printk(KERN_INFO "mxser: max. baud rate = %d bps\n", - brd->ports[0].max_baud); - - for (i = 0; i < brd->info->nports; i++) { - info = &brd->ports[i]; - tty_port_init(&info->port); - info->port.ops = &mxser_port_ops; - info->board = brd; - info->stop_rx = 0; - info->ldisc_stop_rx = 0; - - /* Enhance mode enabled here */ - if (brd->chip_flag != MOXA_OTHER_UART) - mxser_enable_must_enchance_mode(info->ioaddr); - - info->port.flags = ASYNC_SHARE_IRQ; - info->type = brd->uart_type; - - process_txrx_fifo(info); - - info->custom_divisor = info->baud_base * 16; - info->port.close_delay = 5 * HZ / 10; - info->port.closing_wait = 30 * HZ; - info->normal_termios = mxvar_sdriver->init_termios; - memset(&info->mon_data, 0, sizeof(struct mxser_mon)); - info->err_shadow = 0; - spin_lock_init(&info->slock); - - /* before set INT ISR, disable all int */ - outb(inb(info->ioaddr + UART_IER) & 0xf0, - info->ioaddr + UART_IER); - } - - 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); - - return retval; -} - -static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) -{ - int id, i, bits; - unsigned short regs[16], irq; - unsigned char scratch, scratch2; - - brd->chip_flag = MOXA_OTHER_UART; - - id = mxser_read_register(cap, regs); - switch (id) { - case C168_ASIC_ID: - brd->info = &mxser_cards[0]; - break; - case C104_ASIC_ID: - brd->info = &mxser_cards[1]; - break; - case CI104J_ASIC_ID: - brd->info = &mxser_cards[2]; - break; - case C102_ASIC_ID: - brd->info = &mxser_cards[5]; - break; - case CI132_ASIC_ID: - brd->info = &mxser_cards[6]; - break; - case CI134_ASIC_ID: - brd->info = &mxser_cards[7]; - break; - default: - return 0; - } - - irq = 0; - /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) - Flag-hack checks if configuration should be read as 2-port here. */ - if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { - irq = regs[9] & 0xF000; - irq = irq | (irq >> 4); - if (irq != (regs[9] & 0xFF00)) - goto err_irqconflict; - } else if (brd->info->nports == 4) { - irq = regs[9] & 0xF000; - irq = irq | (irq >> 4); - irq = irq | (irq >> 8); - if (irq != regs[9]) - goto err_irqconflict; - } else if (brd->info->nports == 8) { - irq = regs[9] & 0xF000; - irq = irq | (irq >> 4); - irq = irq | (irq >> 8); - if ((irq != regs[9]) || (irq != regs[10])) - goto err_irqconflict; - } - - if (!irq) { - printk(KERN_ERR "mxser: interrupt number unset\n"); - return -EIO; - } - brd->irq = ((int)(irq & 0xF000) >> 12); - for (i = 0; i < 8; i++) - brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; - if ((regs[12] & 0x80) == 0) { - printk(KERN_ERR "mxser: invalid interrupt vector\n"); - return -EIO; - } - brd->vector = (int)regs[11]; /* interrupt vector */ - if (id == 1) - brd->vector_mask = 0x00FF; - else - brd->vector_mask = 0x000F; - for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { - if (regs[12] & bits) { - brd->ports[i].baud_base = 921600; - brd->ports[i].max_baud = 921600; - } else { - brd->ports[i].baud_base = 115200; - brd->ports[i].max_baud = 115200; - } - } - scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); - outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); - outb(0, cap + UART_EFR); /* EFR is the same as FCR */ - outb(scratch2, cap + UART_LCR); - outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); - scratch = inb(cap + UART_IIR); - - if (scratch & 0xC0) - brd->uart_type = PORT_16550A; - else - brd->uart_type = PORT_16450; - if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, - "mxser(IO)")) { - printk(KERN_ERR "mxser: can't request ports I/O region: " - "0x%.8lx-0x%.8lx\n", - brd->ports[0].ioaddr, brd->ports[0].ioaddr + - 8 * brd->info->nports - 1); - return -EIO; - } - if (!request_region(brd->vector, 1, "mxser(vector)")) { - release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - printk(KERN_ERR "mxser: can't request interrupt vector region: " - "0x%.8lx-0x%.8lx\n", - brd->ports[0].ioaddr, brd->ports[0].ioaddr + - 8 * brd->info->nports - 1); - return -EIO; - } - return brd->info->nports; - -err_irqconflict: - printk(KERN_ERR "mxser: invalid interrupt number\n"); - return -EIO; -} - -static int __devinit mxser_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ -#ifdef CONFIG_PCI - struct mxser_board *brd; - unsigned int i, j; - unsigned long ioaddress; - int retval = -EINVAL; - - for (i = 0; i < MXSER_BOARDS; i++) - if (mxser_boards[i].info == NULL) - break; - - if (i >= MXSER_BOARDS) { - dev_err(&pdev->dev, "too many boards found (maximum %d), board " - "not configured\n", MXSER_BOARDS); - goto err; - } - - brd = &mxser_boards[i]; - brd->idx = i * MXSER_PORTS_PER_BOARD; - dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", - mxser_cards[ent->driver_data].name, - pdev->bus->number, PCI_SLOT(pdev->devfn)); - - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "PCI enable failed\n"); - goto err; - } - - /* io address */ - ioaddress = pci_resource_start(pdev, 2); - retval = pci_request_region(pdev, 2, "mxser(IO)"); - if (retval) - goto err_dis; - - brd->info = &mxser_cards[ent->driver_data]; - for (i = 0; i < brd->info->nports; i++) - brd->ports[i].ioaddr = ioaddress + 8 * i; - - /* vector */ - ioaddress = pci_resource_start(pdev, 3); - retval = pci_request_region(pdev, 3, "mxser(vector)"); - if (retval) - goto err_zero; - brd->vector = ioaddress; - - /* irq */ - brd->irq = pdev->irq; - - brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); - brd->uart_type = PORT_16550A; - brd->vector_mask = 0; - - for (i = 0; i < brd->info->nports; i++) { - for (j = 0; j < UART_INFO_NUM; j++) { - if (Gpci_uart_info[j].type == brd->chip_flag) { - brd->ports[i].max_baud = - Gpci_uart_info[j].max_baud; - - /* exception....CP-102 */ - if (brd->info->flags & MXSER_HIGHBAUD) - brd->ports[i].max_baud = 921600; - break; - } - } - } - - if (brd->chip_flag == MOXA_MUST_MU860_HWID) { - for (i = 0; i < brd->info->nports; i++) { - if (i < 4) - brd->ports[i].opmode_ioaddr = ioaddress + 4; - else - brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; - } - outb(0, ioaddress + 4); /* default set to RS232 mode */ - outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ - } - - for (i = 0; i < brd->info->nports; i++) { - brd->vector_mask |= (1 << i); - brd->ports[i].baud_base = 921600; - } - - /* mxser_initbrd will hook ISR. */ - retval = mxser_initbrd(brd, pdev); - if (retval) - goto err_rel3; - - for (i = 0; i < brd->info->nports; i++) - tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); - - pci_set_drvdata(pdev, brd); - - return 0; -err_rel3: - pci_release_region(pdev, 3); -err_zero: - brd->info = NULL; - pci_release_region(pdev, 2); -err_dis: - pci_disable_device(pdev); -err: - return retval; -#else - return -ENODEV; -#endif -} - -static void __devexit mxser_remove(struct pci_dev *pdev) -{ -#ifdef CONFIG_PCI - struct mxser_board *brd = pci_get_drvdata(pdev); - unsigned int i; - - for (i = 0; i < brd->info->nports; i++) - tty_unregister_device(mxvar_sdriver, brd->idx + i); - - free_irq(pdev->irq, brd); - pci_release_region(pdev, 2); - pci_release_region(pdev, 3); - pci_disable_device(pdev); - brd->info = NULL; -#endif -} - -static struct pci_driver mxser_driver = { - .name = "mxser", - .id_table = mxser_pcibrds, - .probe = mxser_probe, - .remove = __devexit_p(mxser_remove) -}; - -static int __init mxser_module_init(void) -{ - struct mxser_board *brd; - unsigned int b, i, m; - int retval; - - mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); - if (!mxvar_sdriver) - return -ENOMEM; - - printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", - MXSER_VERSION); - - /* Initialize the tty_driver structure */ - mxvar_sdriver->owner = THIS_MODULE; - mxvar_sdriver->magic = TTY_DRIVER_MAGIC; - mxvar_sdriver->name = "ttyMI"; - mxvar_sdriver->major = ttymajor; - mxvar_sdriver->minor_start = 0; - mxvar_sdriver->num = MXSER_PORTS + 1; - mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; - mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; - mxvar_sdriver->init_termios = tty_std_termios; - mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; - mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV; - tty_set_operations(mxvar_sdriver, &mxser_ops); - - retval = tty_register_driver(mxvar_sdriver); - if (retval) { - printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family " - "tty driver !\n"); - goto err_put; - } - - /* Start finding ISA boards here */ - for (m = 0, b = 0; b < MXSER_BOARDS; b++) { - if (!ioaddr[b]) - continue; - - brd = &mxser_boards[m]; - retval = mxser_get_ISA_conf(ioaddr[b], brd); - if (retval <= 0) { - brd->info = NULL; - continue; - } - - printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", - brd->info->name, ioaddr[b]); - - /* mxser_initbrd will hook ISR. */ - if (mxser_initbrd(brd, NULL) < 0) { - brd->info = NULL; - continue; - } - - brd->idx = m * MXSER_PORTS_PER_BOARD; - for (i = 0; i < brd->info->nports; i++) - tty_register_device(mxvar_sdriver, brd->idx + i, NULL); - - m++; - } - - retval = pci_register_driver(&mxser_driver); - if (retval) { - printk(KERN_ERR "mxser: can't register pci driver\n"); - if (!m) { - retval = -ENODEV; - goto err_unr; - } /* else: we have some ISA cards under control */ - } - - return 0; -err_unr: - tty_unregister_driver(mxvar_sdriver); -err_put: - put_tty_driver(mxvar_sdriver); - return retval; -} - -static void __exit mxser_module_exit(void) -{ - unsigned int i, j; - - pci_unregister_driver(&mxser_driver); - - for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ - if (mxser_boards[i].info != NULL) - for (j = 0; j < mxser_boards[i].info->nports; j++) - tty_unregister_device(mxvar_sdriver, - mxser_boards[i].idx + j); - tty_unregister_driver(mxvar_sdriver); - put_tty_driver(mxvar_sdriver); - - for (i = 0; i < MXSER_BOARDS; i++) - if (mxser_boards[i].info != NULL) - mxser_release_ISA_res(&mxser_boards[i]); -} - -module_init(mxser_module_init); -module_exit(mxser_module_exit); diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h deleted file mode 100644 index 41878a69203d..000000000000 --- a/drivers/char/mxser.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef _MXSER_H -#define _MXSER_H - -/* - * Semi-public control interfaces - */ - -/* - * MOXA ioctls - */ - -#define MOXA 0x400 -#define MOXA_GETDATACOUNT (MOXA + 23) -#define MOXA_DIAGNOSE (MOXA + 50) -#define MOXA_CHKPORTENABLE (MOXA + 60) -#define MOXA_HighSpeedOn (MOXA + 61) -#define MOXA_GET_MAJOR (MOXA + 63) -#define MOXA_GETMSTATUS (MOXA + 65) -#define MOXA_SET_OP_MODE (MOXA + 66) -#define MOXA_GET_OP_MODE (MOXA + 67) - -#define RS232_MODE 0 -#define RS485_2WIRE_MODE 1 -#define RS422_MODE 2 -#define RS485_4WIRE_MODE 3 -#define OP_MODE_MASK 3 - -#define MOXA_SDS_RSTICOUNTER (MOXA + 69) -#define MOXA_ASPP_OQUEUE (MOXA + 70) -#define MOXA_ASPP_MON (MOXA + 73) -#define MOXA_ASPP_LSTATUS (MOXA + 74) -#define MOXA_ASPP_MON_EXT (MOXA + 75) -#define MOXA_SET_BAUD_METHOD (MOXA + 76) - -/* --------------------------------------------------- */ - -#define NPPI_NOTIFY_PARITY 0x01 -#define NPPI_NOTIFY_FRAMING 0x02 -#define NPPI_NOTIFY_HW_OVERRUN 0x04 -#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 */ - -/* 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 */ -#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_EFR_REGISTER 0x02 -/* enchance mode enable */ -#define MOXA_MUST_EFR_EFRB_ENABLE 0x10 -/* 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 */ -#define MOXA_MUST_XON1_REGISTER 0x04 - -/* 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 */ -#define MOXA_MUST_XOFF1_REGISTER 0x06 - -/* set XOFF2 value register, when LCR=0xBF and change to bank0 */ -#define MOXA_MUST_XOFF2_REGISTER 0x07 - -#define MOXA_MUST_RBRTL_REGISTER 0x04 -#define MOXA_MUST_RBRTH_REGISTER 0x05 -#define MOXA_MUST_RBRTI_REGISTER 0x06 -#define MOXA_MUST_THRTL_REGISTER 0x07 -#define MOXA_MUST_ENUM_REGISTER 0x04 -#define MOXA_MUST_HWID_REGISTER 0x05 -#define MOXA_MUST_ECR_REGISTER 0x06 -#define MOXA_MUST_CSR_REGISTER 0x07 - -/* good data mode enable */ -#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 -/* only good data put into RxFIFO */ -#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 - -/* enable CTS interrupt */ -#define MOXA_MUST_IER_ECTSI 0x80 -/* enable RTS interrupt */ -#define MOXA_MUST_IER_ERTSI 0x40 -/* enable Xon/Xoff interrupt */ -#define MOXA_MUST_IER_XINT 0x20 -/* enable GDA interrupt */ -#define MOXA_MUST_IER_EGDAI 0x10 - -#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) - -/* 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 */ -#define MOXA_MUST_IIR_XSC 0x10 - -/* RTS/CTS change state interrupt pending */ -#define MOXA_MUST_IIR_RTSCTS 0x20 -#define MOXA_MUST_IIR_MASK 0x3E - -#define MOXA_MUST_MCR_XON_FLAG 0x40 -#define MOXA_MUST_MCR_XON_ANY 0x80 -#define MOXA_MUST_MCR_TX_XON 0x08 - -/* software flow control on chip mask value */ -#define MOXA_MUST_EFR_SF_MASK 0x0F -/* send Xon1/Xoff1 */ -#define MOXA_MUST_EFR_SF_TX1 0x08 -/* send Xon2/Xoff2 */ -#define MOXA_MUST_EFR_SF_TX2 0x04 -/* send Xon1,Xon2/Xoff1,Xoff2 */ -#define MOXA_MUST_EFR_SF_TX12 0x0C -/* don't send Xon/Xoff */ -#define MOXA_MUST_EFR_SF_TX_NO 0x00 -/* Tx software flow control mask */ -#define MOXA_MUST_EFR_SF_TX_MASK 0x0C -/* don't receive Xon/Xoff */ -#define MOXA_MUST_EFR_SF_RX_NO 0x00 -/* receive Xon1/Xoff1 */ -#define MOXA_MUST_EFR_SF_RX1 0x02 -/* receive Xon2/Xoff2 */ -#define MOXA_MUST_EFR_SF_RX2 0x01 -/* receive Xon1,Xon2/Xoff1,Xoff2 */ -#define MOXA_MUST_EFR_SF_RX12 0x03 -/* Rx software flow control mask */ -#define MOXA_MUST_EFR_SF_RX_MASK 0x03 - -#endif diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c deleted file mode 100644 index 513ba12064ea..000000000000 --- a/drivers/char/nozomi.c +++ /dev/null @@ -1,1993 +0,0 @@ -/* - * nozomi.c -- HSDPA driver Broadband Wireless Data Card - Globe Trotter - * - * Written by: Ulf Jakobsson, - * Jan Ã…kerfeldt, - * Stefan Thomasson, - * - * Maintained by: Paul Hardwick (p.hardwick@option.com) - * - * Patches: - * Locking code changes for Vodafone by Sphere Systems Ltd, - * Andrew Bird (ajb@spheresystems.co.uk ) - * & Phil Sanderson - * - * Source has been ported from an implementation made by Filip Aben @ Option - * - * -------------------------------------------------------------------------- - * - * Copyright (c) 2005,2006 Option Wireless Sweden AB - * Copyright (c) 2006 Sphere Systems Ltd - * Copyright (c) 2006 Option Wireless n/v - * All rights Reserved. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * -------------------------------------------------------------------------- - */ - -/* Enable this to have a lot of debug printouts */ -#define DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \ - __DATE__ " " __TIME__ ")" - -/* Macros definitions */ - -/* Default debug printout level */ -#define NOZOMI_DEBUG_LEVEL 0x00 - -#define P_BUF_SIZE 128 -#define NFO(_err_flag_, args...) \ -do { \ - char tmp[P_BUF_SIZE]; \ - snprintf(tmp, sizeof(tmp), ##args); \ - printk(_err_flag_ "[%d] %s(): %s\n", __LINE__, \ - __func__, tmp); \ -} while (0) - -#define DBG1(args...) D_(0x01, ##args) -#define DBG2(args...) D_(0x02, ##args) -#define DBG3(args...) D_(0x04, ##args) -#define DBG4(args...) D_(0x08, ##args) -#define DBG5(args...) D_(0x10, ##args) -#define DBG6(args...) D_(0x20, ##args) -#define DBG7(args...) D_(0x40, ##args) -#define DBG8(args...) D_(0x80, ##args) - -#ifdef DEBUG -/* Do we need this settable at runtime? */ -static int debug = NOZOMI_DEBUG_LEVEL; - -#define D(lvl, args...) do \ - {if (lvl & debug) NFO(KERN_DEBUG, ##args); } \ - while (0) -#define D_(lvl, args...) D(lvl, ##args) - -/* These printouts are always printed */ - -#else -static int debug; -#define D_(lvl, args...) -#endif - -/* TODO: rewrite to optimize macros... */ - -#define TMP_BUF_MAX 256 - -#define DUMP(buf__,len__) \ - do { \ - char tbuf[TMP_BUF_MAX] = {0};\ - if (len__ > 1) {\ - snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\ - if (tbuf[len__-2] == '\r') {\ - tbuf[len__-2] = 'r';\ - } \ - DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\ - } else {\ - DBG1("SENDING: '%s' (%d)", tbuf, len__);\ - } \ -} while (0) - -/* Defines */ -#define NOZOMI_NAME "nozomi" -#define NOZOMI_NAME_TTY "nozomi_tty" -#define DRIVER_DESC "Nozomi driver" - -#define NTTY_TTY_MAXMINORS 256 -#define NTTY_FIFO_BUFFER_SIZE 8192 - -/* Must be power of 2 */ -#define FIFO_BUFFER_SIZE_UL 8192 - -/* Size of tmp send buffer to card */ -#define SEND_BUF_MAX 1024 -#define RECEIVE_BUF_MAX 4 - - -#define R_IIR 0x0000 /* Interrupt Identity Register */ -#define R_FCR 0x0000 /* Flow Control Register */ -#define R_IER 0x0004 /* Interrupt Enable Register */ - -#define CONFIG_MAGIC 0xEFEFFEFE -#define TOGGLE_VALID 0x0000 - -/* Definition of interrupt tokens */ -#define MDM_DL1 0x0001 -#define MDM_UL1 0x0002 -#define MDM_DL2 0x0004 -#define MDM_UL2 0x0008 -#define DIAG_DL1 0x0010 -#define DIAG_DL2 0x0020 -#define DIAG_UL 0x0040 -#define APP1_DL 0x0080 -#define APP1_UL 0x0100 -#define APP2_DL 0x0200 -#define APP2_UL 0x0400 -#define CTRL_DL 0x0800 -#define CTRL_UL 0x1000 -#define RESET 0x8000 - -#define MDM_DL (MDM_DL1 | MDM_DL2) -#define MDM_UL (MDM_UL1 | MDM_UL2) -#define DIAG_DL (DIAG_DL1 | DIAG_DL2) - -/* modem signal definition */ -#define CTRL_DSR 0x0001 -#define CTRL_DCD 0x0002 -#define CTRL_RI 0x0004 -#define CTRL_CTS 0x0008 - -#define CTRL_DTR 0x0001 -#define CTRL_RTS 0x0002 - -#define MAX_PORT 4 -#define NOZOMI_MAX_PORTS 5 -#define NOZOMI_MAX_CARDS (NTTY_TTY_MAXMINORS / MAX_PORT) - -/* Type definitions */ - -/* - * There are two types of nozomi cards, - * one with 2048 memory and with 8192 memory - */ -enum card_type { - F32_2 = 2048, /* 512 bytes downlink + uplink * 2 -> 2048 */ - F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */ -}; - -/* Initialization states a card can be in */ -enum card_state { - NOZOMI_STATE_UKNOWN = 0, - NOZOMI_STATE_ENABLED = 1, /* pci device enabled */ - NOZOMI_STATE_ALLOCATED = 2, /* config setup done */ - NOZOMI_STATE_READY = 3, /* flowcontrols received */ -}; - -/* Two different toggle channels exist */ -enum channel_type { - CH_A = 0, - CH_B = 1, -}; - -/* Port definition for the card regarding flow control */ -enum ctrl_port_type { - CTRL_CMD = 0, - CTRL_MDM = 1, - CTRL_DIAG = 2, - CTRL_APP1 = 3, - CTRL_APP2 = 4, - CTRL_ERROR = -1, -}; - -/* Ports that the nozomi has */ -enum port_type { - PORT_MDM = 0, - PORT_DIAG = 1, - PORT_APP1 = 2, - PORT_APP2 = 3, - PORT_CTRL = 4, - PORT_ERROR = -1, -}; - -#ifdef __BIG_ENDIAN -/* Big endian */ - -struct toggles { - unsigned int enabled:5; /* - * Toggle fields are valid if enabled is 0, - * else A-channels must always be used. - */ - unsigned int diag_dl:1; - unsigned int mdm_dl:1; - unsigned int mdm_ul:1; -} __attribute__ ((packed)); - -/* Configuration table to read at startup of card */ -/* Is for now only needed during initialization phase */ -struct config_table { - u32 signature; - u16 product_information; - u16 version; - u8 pad3[3]; - struct toggles toggle; - u8 pad1[4]; - u16 dl_mdm_len1; /* - * If this is 64, it can hold - * 60 bytes + 4 that is length field - */ - u16 dl_start; - - u16 dl_diag_len1; - u16 dl_mdm_len2; /* - * If this is 64, it can hold - * 60 bytes + 4 that is length field - */ - u16 dl_app1_len; - - u16 dl_diag_len2; - u16 dl_ctrl_len; - u16 dl_app2_len; - u8 pad2[16]; - u16 ul_mdm_len1; - u16 ul_start; - u16 ul_diag_len; - u16 ul_mdm_len2; - u16 ul_app1_len; - u16 ul_app2_len; - u16 ul_ctrl_len; -} __attribute__ ((packed)); - -/* This stores all control downlink flags */ -struct ctrl_dl { - u8 port; - unsigned int reserved:4; - unsigned int CTS:1; - unsigned int RI:1; - unsigned int DCD:1; - unsigned int DSR:1; -} __attribute__ ((packed)); - -/* This stores all control uplink flags */ -struct ctrl_ul { - u8 port; - unsigned int reserved:6; - unsigned int RTS:1; - unsigned int DTR:1; -} __attribute__ ((packed)); - -#else -/* Little endian */ - -/* This represents the toggle information */ -struct toggles { - unsigned int mdm_ul:1; - unsigned int mdm_dl:1; - unsigned int diag_dl:1; - unsigned int enabled:5; /* - * Toggle fields are valid if enabled is 0, - * else A-channels must always be used. - */ -} __attribute__ ((packed)); - -/* Configuration table to read at startup of card */ -struct config_table { - u32 signature; - u16 version; - u16 product_information; - struct toggles toggle; - u8 pad1[7]; - u16 dl_start; - u16 dl_mdm_len1; /* - * If this is 64, it can hold - * 60 bytes + 4 that is length field - */ - u16 dl_mdm_len2; - u16 dl_diag_len1; - u16 dl_diag_len2; - u16 dl_app1_len; - u16 dl_app2_len; - u16 dl_ctrl_len; - u8 pad2[16]; - u16 ul_start; - u16 ul_mdm_len2; - u16 ul_mdm_len1; - u16 ul_diag_len; - u16 ul_app1_len; - u16 ul_app2_len; - u16 ul_ctrl_len; -} __attribute__ ((packed)); - -/* This stores all control downlink flags */ -struct ctrl_dl { - unsigned int DSR:1; - unsigned int DCD:1; - unsigned int RI:1; - unsigned int CTS:1; - unsigned int reserverd:4; - u8 port; -} __attribute__ ((packed)); - -/* This stores all control uplink flags */ -struct ctrl_ul { - unsigned int DTR:1; - unsigned int RTS:1; - unsigned int reserved:6; - u8 port; -} __attribute__ ((packed)); -#endif - -/* This holds all information that is needed regarding a port */ -struct port { - struct tty_port port; - u8 update_flow_control; - struct ctrl_ul ctrl_ul; - struct ctrl_dl ctrl_dl; - struct kfifo fifo_ul; - void __iomem *dl_addr[2]; - u32 dl_size[2]; - u8 toggle_dl; - void __iomem *ul_addr[2]; - u32 ul_size[2]; - u8 toggle_ul; - u16 token_dl; - - /* mutex to ensure one access patch to this port */ - struct mutex tty_sem; - wait_queue_head_t tty_wait; - struct async_icount tty_icount; - - struct nozomi *dc; -}; - -/* Private data one for each card in the system */ -struct nozomi { - void __iomem *base_addr; - unsigned long flip; - - /* Pointers to registers */ - void __iomem *reg_iir; - void __iomem *reg_fcr; - void __iomem *reg_ier; - - u16 last_ier; - enum card_type card_type; - struct config_table config_table; /* Configuration table */ - struct pci_dev *pdev; - struct port port[NOZOMI_MAX_PORTS]; - u8 *send_buf; - - spinlock_t spin_mutex; /* secures access to registers and tty */ - - unsigned int index_start; - enum card_state state; - u32 open_ttys; -}; - -/* This is a data packet that is read or written to/from card */ -struct buffer { - u32 size; /* size is the length of the data buffer */ - u8 *data; -} __attribute__ ((packed)); - -/* Global variables */ -static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { - {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ - {}, -}; - -MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); - -static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; -static struct tty_driver *ntty_driver; - -static const struct tty_port_operations noz_tty_port_ops; - -/* - * find card by tty_index - */ -static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty) -{ - return tty ? ndevs[tty->index / MAX_PORT] : NULL; -} - -static inline struct port *get_port_by_tty(const struct tty_struct *tty) -{ - struct nozomi *ndev = get_dc_by_tty(tty); - return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL; -} - -/* - * TODO: - * -Optimize - * -Rewrite cleaner - */ - -static void read_mem32(u32 *buf, const void __iomem *mem_addr_start, - u32 size_bytes) -{ - u32 i = 0; - const u32 __iomem *ptr = mem_addr_start; - u16 *buf16; - - if (unlikely(!ptr || !buf)) - goto out; - - /* shortcut for extremely often used cases */ - switch (size_bytes) { - case 2: /* 2 bytes */ - buf16 = (u16 *) buf; - *buf16 = __le16_to_cpu(readw(ptr)); - goto out; - break; - case 4: /* 4 bytes */ - *(buf) = __le32_to_cpu(readl(ptr)); - goto out; - break; - } - - while (i < size_bytes) { - if (size_bytes - i == 2) { - /* Handle 2 bytes in the end */ - buf16 = (u16 *) buf; - *(buf16) = __le16_to_cpu(readw(ptr)); - i += 2; - } else { - /* Read 4 bytes */ - *(buf) = __le32_to_cpu(readl(ptr)); - i += 4; - } - buf++; - ptr++; - } -out: - return; -} - -/* - * TODO: - * -Optimize - * -Rewrite cleaner - */ -static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, - u32 size_bytes) -{ - u32 i = 0; - u32 __iomem *ptr = mem_addr_start; - const u16 *buf16; - - if (unlikely(!ptr || !buf)) - return 0; - - /* shortcut for extremely often used cases */ - switch (size_bytes) { - case 2: /* 2 bytes */ - buf16 = (const u16 *)buf; - writew(__cpu_to_le16(*buf16), ptr); - return 2; - break; - case 1: /* - * also needs to write 4 bytes in this case - * so falling through.. - */ - case 4: /* 4 bytes */ - writel(__cpu_to_le32(*buf), ptr); - return 4; - break; - } - - while (i < size_bytes) { - if (size_bytes - i == 2) { - /* 2 bytes */ - buf16 = (const u16 *)buf; - writew(__cpu_to_le16(*buf16), ptr); - i += 2; - } else { - /* 4 bytes */ - writel(__cpu_to_le32(*buf), ptr); - i += 4; - } - buf++; - ptr++; - } - return i; -} - -/* Setup pointers to different channels and also setup buffer sizes. */ -static void setup_memory(struct nozomi *dc) -{ - void __iomem *offset = dc->base_addr + dc->config_table.dl_start; - /* The length reported is including the length field of 4 bytes, - * hence subtract with 4. - */ - const u16 buff_offset = 4; - - /* Modem port dl configuration */ - dc->port[PORT_MDM].dl_addr[CH_A] = offset; - dc->port[PORT_MDM].dl_addr[CH_B] = - (offset += dc->config_table.dl_mdm_len1); - dc->port[PORT_MDM].dl_size[CH_A] = - dc->config_table.dl_mdm_len1 - buff_offset; - dc->port[PORT_MDM].dl_size[CH_B] = - dc->config_table.dl_mdm_len2 - buff_offset; - - /* Diag port dl configuration */ - dc->port[PORT_DIAG].dl_addr[CH_A] = - (offset += dc->config_table.dl_mdm_len2); - dc->port[PORT_DIAG].dl_size[CH_A] = - dc->config_table.dl_diag_len1 - buff_offset; - dc->port[PORT_DIAG].dl_addr[CH_B] = - (offset += dc->config_table.dl_diag_len1); - dc->port[PORT_DIAG].dl_size[CH_B] = - dc->config_table.dl_diag_len2 - buff_offset; - - /* App1 port dl configuration */ - dc->port[PORT_APP1].dl_addr[CH_A] = - (offset += dc->config_table.dl_diag_len2); - dc->port[PORT_APP1].dl_size[CH_A] = - dc->config_table.dl_app1_len - buff_offset; - - /* App2 port dl configuration */ - dc->port[PORT_APP2].dl_addr[CH_A] = - (offset += dc->config_table.dl_app1_len); - dc->port[PORT_APP2].dl_size[CH_A] = - dc->config_table.dl_app2_len - buff_offset; - - /* Ctrl dl configuration */ - dc->port[PORT_CTRL].dl_addr[CH_A] = - (offset += dc->config_table.dl_app2_len); - dc->port[PORT_CTRL].dl_size[CH_A] = - dc->config_table.dl_ctrl_len - buff_offset; - - offset = dc->base_addr + dc->config_table.ul_start; - - /* Modem Port ul configuration */ - dc->port[PORT_MDM].ul_addr[CH_A] = offset; - dc->port[PORT_MDM].ul_size[CH_A] = - dc->config_table.ul_mdm_len1 - buff_offset; - dc->port[PORT_MDM].ul_addr[CH_B] = - (offset += dc->config_table.ul_mdm_len1); - dc->port[PORT_MDM].ul_size[CH_B] = - dc->config_table.ul_mdm_len2 - buff_offset; - - /* Diag port ul configuration */ - dc->port[PORT_DIAG].ul_addr[CH_A] = - (offset += dc->config_table.ul_mdm_len2); - dc->port[PORT_DIAG].ul_size[CH_A] = - dc->config_table.ul_diag_len - buff_offset; - - /* App1 port ul configuration */ - dc->port[PORT_APP1].ul_addr[CH_A] = - (offset += dc->config_table.ul_diag_len); - dc->port[PORT_APP1].ul_size[CH_A] = - dc->config_table.ul_app1_len - buff_offset; - - /* App2 port ul configuration */ - dc->port[PORT_APP2].ul_addr[CH_A] = - (offset += dc->config_table.ul_app1_len); - dc->port[PORT_APP2].ul_size[CH_A] = - dc->config_table.ul_app2_len - buff_offset; - - /* Ctrl ul configuration */ - dc->port[PORT_CTRL].ul_addr[CH_A] = - (offset += dc->config_table.ul_app2_len); - dc->port[PORT_CTRL].ul_size[CH_A] = - dc->config_table.ul_ctrl_len - buff_offset; -} - -/* Dump config table under initalization phase */ -#ifdef DEBUG -static void dump_table(const struct nozomi *dc) -{ - DBG3("signature: 0x%08X", dc->config_table.signature); - DBG3("version: 0x%04X", dc->config_table.version); - DBG3("product_information: 0x%04X", \ - dc->config_table.product_information); - DBG3("toggle enabled: %d", dc->config_table.toggle.enabled); - DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul); - DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl); - DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl); - - DBG3("dl_start: 0x%04X", dc->config_table.dl_start); - DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1, - dc->config_table.dl_mdm_len1); - DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2, - dc->config_table.dl_mdm_len2); - DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1, - dc->config_table.dl_diag_len1); - DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2, - dc->config_table.dl_diag_len2); - DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len, - dc->config_table.dl_app1_len); - DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len, - dc->config_table.dl_app2_len); - DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len, - dc->config_table.dl_ctrl_len); - DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start, - dc->config_table.ul_start); - DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1, - dc->config_table.ul_mdm_len1); - DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2, - dc->config_table.ul_mdm_len2); - DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len, - dc->config_table.ul_diag_len); - DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len, - dc->config_table.ul_app1_len); - DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len, - dc->config_table.ul_app2_len); - DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len, - dc->config_table.ul_ctrl_len); -} -#else -static inline void dump_table(const struct nozomi *dc) { } -#endif - -/* - * Read configuration table from card under intalization phase - * Returns 1 if ok, else 0 - */ -static int nozomi_read_config_table(struct nozomi *dc) -{ - read_mem32((u32 *) &dc->config_table, dc->base_addr + 0, - sizeof(struct config_table)); - - if (dc->config_table.signature != CONFIG_MAGIC) { - dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n", - dc->config_table.signature, CONFIG_MAGIC); - return 0; - } - - if ((dc->config_table.version == 0) - || (dc->config_table.toggle.enabled == TOGGLE_VALID)) { - int i; - DBG1("Second phase, configuring card"); - - setup_memory(dc); - - dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul; - dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl; - dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl; - DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d", - dc->port[PORT_MDM].toggle_ul, - dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl); - - dump_table(dc); - - for (i = PORT_MDM; i < MAX_PORT; i++) { - memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); - memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); - } - - /* Enable control channel */ - dc->last_ier = dc->last_ier | CTRL_DL; - writew(dc->last_ier, dc->reg_ier); - - dc->state = NOZOMI_STATE_ALLOCATED; - dev_info(&dc->pdev->dev, "Initialization OK!\n"); - return 1; - } - - if ((dc->config_table.version > 0) - && (dc->config_table.toggle.enabled != TOGGLE_VALID)) { - u32 offset = 0; - DBG1("First phase: pushing upload buffers, clearing download"); - - dev_info(&dc->pdev->dev, "Version of card: %d\n", - dc->config_table.version); - - /* Here we should disable all I/O over F32. */ - setup_memory(dc); - - /* - * We should send ALL channel pair tokens back along - * with reset token - */ - - /* push upload modem buffers */ - write_mem32(dc->port[PORT_MDM].ul_addr[CH_A], - (u32 *) &offset, 4); - write_mem32(dc->port[PORT_MDM].ul_addr[CH_B], - (u32 *) &offset, 4); - - writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr); - - DBG1("First phase done"); - } - - return 1; -} - -/* Enable uplink interrupts */ -static void enable_transmit_ul(enum port_type port, struct nozomi *dc) -{ - static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL}; - - if (port < NOZOMI_MAX_PORTS) { - dc->last_ier |= mask[port]; - writew(dc->last_ier, dc->reg_ier); - } else { - dev_err(&dc->pdev->dev, "Called with wrong port?\n"); - } -} - -/* Disable uplink interrupts */ -static void disable_transmit_ul(enum port_type port, struct nozomi *dc) -{ - static const u16 mask[] = - {~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL}; - - if (port < NOZOMI_MAX_PORTS) { - dc->last_ier &= mask[port]; - writew(dc->last_ier, dc->reg_ier); - } else { - dev_err(&dc->pdev->dev, "Called with wrong port?\n"); - } -} - -/* Enable downlink interrupts */ -static void enable_transmit_dl(enum port_type port, struct nozomi *dc) -{ - static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL}; - - if (port < NOZOMI_MAX_PORTS) { - dc->last_ier |= mask[port]; - writew(dc->last_ier, dc->reg_ier); - } else { - dev_err(&dc->pdev->dev, "Called with wrong port?\n"); - } -} - -/* Disable downlink interrupts */ -static void disable_transmit_dl(enum port_type port, struct nozomi *dc) -{ - static const u16 mask[] = - {~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL}; - - if (port < NOZOMI_MAX_PORTS) { - dc->last_ier &= mask[port]; - writew(dc->last_ier, dc->reg_ier); - } else { - dev_err(&dc->pdev->dev, "Called with wrong port?\n"); - } -} - -/* - * Return 1 - send buffer to card and ack. - * Return 0 - don't ack, don't send buffer to card. - */ -static int send_data(enum port_type index, struct nozomi *dc) -{ - u32 size = 0; - struct port *port = &dc->port[index]; - const u8 toggle = port->toggle_ul; - void __iomem *addr = port->ul_addr[toggle]; - const u32 ul_size = port->ul_size[toggle]; - struct tty_struct *tty = tty_port_tty_get(&port->port); - - /* Get data from tty and place in buf for now */ - size = kfifo_out(&port->fifo_ul, dc->send_buf, - ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); - - if (size == 0) { - DBG4("No more data to send, disable link:"); - tty_kref_put(tty); - return 0; - } - - /* DUMP(buf, size); */ - - /* Write length + data */ - write_mem32(addr, (u32 *) &size, 4); - write_mem32(addr + 4, (u32 *) dc->send_buf, size); - - if (tty) - tty_wakeup(tty); - - tty_kref_put(tty); - return 1; -} - -/* If all data has been read, return 1, else 0 */ -static int receive_data(enum port_type index, struct nozomi *dc) -{ - u8 buf[RECEIVE_BUF_MAX] = { 0 }; - int size; - u32 offset = 4; - struct port *port = &dc->port[index]; - void __iomem *addr = port->dl_addr[port->toggle_dl]; - struct tty_struct *tty = tty_port_tty_get(&port->port); - int i, ret; - - if (unlikely(!tty)) { - DBG1("tty not open for port: %d?", index); - return 1; - } - - read_mem32((u32 *) &size, addr, 4); - /* DBG1( "%d bytes port: %d", size, index); */ - - if (test_bit(TTY_THROTTLED, &tty->flags)) { - DBG1("No room in tty, don't read data, don't ack interrupt, " - "disable interrupt"); - - /* disable interrupt in downlink... */ - disable_transmit_dl(index, dc); - ret = 0; - goto put; - } - - if (unlikely(size == 0)) { - dev_err(&dc->pdev->dev, "size == 0?\n"); - ret = 1; - goto put; - } - - while (size > 0) { - read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); - - if (size == 1) { - tty_insert_flip_char(tty, buf[0], TTY_NORMAL); - size = 0; - } else if (size < RECEIVE_BUF_MAX) { - size -= tty_insert_flip_string(tty, (char *) buf, size); - } else { - i = tty_insert_flip_string(tty, \ - (char *) buf, RECEIVE_BUF_MAX); - size -= i; - offset += i; - } - } - - set_bit(index, &dc->flip); - ret = 1; -put: - tty_kref_put(tty); - return ret; -} - -/* Debug for interrupts */ -#ifdef DEBUG -static char *interrupt2str(u16 interrupt) -{ - static char buf[TMP_BUF_MAX]; - char *p = buf; - - interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL; - interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "MDM_DL2 ") : NULL; - - interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "MDM_UL1 ") : NULL; - interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "MDM_UL2 ") : NULL; - - interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "DIAG_DL1 ") : NULL; - interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "DIAG_DL2 ") : NULL; - - interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "DIAG_UL ") : NULL; - - interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "APP1_DL ") : NULL; - interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "APP2_DL ") : NULL; - - interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "APP1_UL ") : NULL; - interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "APP2_UL ") : NULL; - - interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "CTRL_DL ") : NULL; - interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "CTRL_UL ") : NULL; - - interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf), - "RESET ") : NULL; - - return buf; -} -#endif - -/* - * Receive flow control - * Return 1 - If ok, else 0 - */ -static int receive_flow_control(struct nozomi *dc) -{ - enum port_type port = PORT_MDM; - struct ctrl_dl ctrl_dl; - struct ctrl_dl old_ctrl; - u16 enable_ier = 0; - - read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2); - - switch (ctrl_dl.port) { - case CTRL_CMD: - DBG1("The Base Band sends this value as a response to a " - "request for IMSI detach sent over the control " - "channel uplink (see section 7.6.1)."); - break; - case CTRL_MDM: - port = PORT_MDM; - enable_ier = MDM_DL; - break; - case CTRL_DIAG: - port = PORT_DIAG; - enable_ier = DIAG_DL; - break; - case CTRL_APP1: - port = PORT_APP1; - enable_ier = APP1_DL; - break; - case CTRL_APP2: - port = PORT_APP2; - enable_ier = APP2_DL; - if (dc->state == NOZOMI_STATE_ALLOCATED) { - /* - * After card initialization the flow control - * received for APP2 is always the last - */ - dc->state = NOZOMI_STATE_READY; - dev_info(&dc->pdev->dev, "Device READY!\n"); - } - break; - default: - dev_err(&dc->pdev->dev, - "ERROR: flow control received for non-existing port\n"); - return 0; - }; - - DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl), - *((u16 *)&ctrl_dl)); - - old_ctrl = dc->port[port].ctrl_dl; - dc->port[port].ctrl_dl = ctrl_dl; - - if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) { - DBG1("Disable interrupt (0x%04X) on port: %d", - enable_ier, port); - disable_transmit_ul(port, dc); - - } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { - - if (kfifo_len(&dc->port[port].fifo_ul)) { - DBG1("Enable interrupt (0x%04X) on port: %d", - enable_ier, port); - DBG1("Data in buffer [%d], enable transmit! ", - kfifo_len(&dc->port[port].fifo_ul)); - enable_transmit_ul(port, dc); - } else { - DBG1("No data in buffer..."); - } - } - - if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) { - DBG1(" No change in mctrl"); - return 1; - } - /* Update statistics */ - if (old_ctrl.CTS != ctrl_dl.CTS) - dc->port[port].tty_icount.cts++; - if (old_ctrl.DSR != ctrl_dl.DSR) - dc->port[port].tty_icount.dsr++; - if (old_ctrl.RI != ctrl_dl.RI) - dc->port[port].tty_icount.rng++; - if (old_ctrl.DCD != ctrl_dl.DCD) - dc->port[port].tty_icount.dcd++; - - wake_up_interruptible(&dc->port[port].tty_wait); - - DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)", - port, - dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts, - dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr); - - return 1; -} - -static enum ctrl_port_type port2ctrl(enum port_type port, - const struct nozomi *dc) -{ - switch (port) { - case PORT_MDM: - return CTRL_MDM; - case PORT_DIAG: - return CTRL_DIAG; - case PORT_APP1: - return CTRL_APP1; - case PORT_APP2: - return CTRL_APP2; - default: - dev_err(&dc->pdev->dev, - "ERROR: send flow control " \ - "received for non-existing port\n"); - }; - return CTRL_ERROR; -} - -/* - * Send flow control, can only update one channel at a time - * Return 0 - If we have updated all flow control - * Return 1 - If we need to update more flow control, ack current enable more - */ -static int send_flow_control(struct nozomi *dc) -{ - u32 i, more_flow_control_to_be_updated = 0; - u16 *ctrl; - - for (i = PORT_MDM; i < MAX_PORT; i++) { - if (dc->port[i].update_flow_control) { - if (more_flow_control_to_be_updated) { - /* We have more flow control to be updated */ - return 1; - } - dc->port[i].ctrl_ul.port = port2ctrl(i, dc); - ctrl = (u16 *)&dc->port[i].ctrl_ul; - write_mem32(dc->port[PORT_CTRL].ul_addr[0], \ - (u32 *) ctrl, 2); - dc->port[i].update_flow_control = 0; - more_flow_control_to_be_updated = 1; - } - } - return 0; -} - -/* - * Handle downlink data, ports that are handled are modem and diagnostics - * Return 1 - ok - * Return 0 - toggle fields are out of sync - */ -static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle, - u16 read_iir, u16 mask1, u16 mask2) -{ - if (*toggle == 0 && read_iir & mask1) { - if (receive_data(port, dc)) { - writew(mask1, dc->reg_fcr); - *toggle = !(*toggle); - } - - if (read_iir & mask2) { - if (receive_data(port, dc)) { - writew(mask2, dc->reg_fcr); - *toggle = !(*toggle); - } - } - } else if (*toggle == 1 && read_iir & mask2) { - if (receive_data(port, dc)) { - writew(mask2, dc->reg_fcr); - *toggle = !(*toggle); - } - - if (read_iir & mask1) { - if (receive_data(port, dc)) { - writew(mask1, dc->reg_fcr); - *toggle = !(*toggle); - } - } - } else { - dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n", - *toggle); - return 0; - } - return 1; -} - -/* - * Handle uplink data, this is currently for the modem port - * Return 1 - ok - * Return 0 - toggle field are out of sync - */ -static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir) -{ - u8 *toggle = &(dc->port[port].toggle_ul); - - if (*toggle == 0 && read_iir & MDM_UL1) { - dc->last_ier &= ~MDM_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(port, dc)) { - writew(MDM_UL1, dc->reg_fcr); - dc->last_ier = dc->last_ier | MDM_UL; - writew(dc->last_ier, dc->reg_ier); - *toggle = !*toggle; - } - - if (read_iir & MDM_UL2) { - dc->last_ier &= ~MDM_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(port, dc)) { - writew(MDM_UL2, dc->reg_fcr); - dc->last_ier = dc->last_ier | MDM_UL; - writew(dc->last_ier, dc->reg_ier); - *toggle = !*toggle; - } - } - - } else if (*toggle == 1 && read_iir & MDM_UL2) { - dc->last_ier &= ~MDM_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(port, dc)) { - writew(MDM_UL2, dc->reg_fcr); - dc->last_ier = dc->last_ier | MDM_UL; - writew(dc->last_ier, dc->reg_ier); - *toggle = !*toggle; - } - - if (read_iir & MDM_UL1) { - dc->last_ier &= ~MDM_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(port, dc)) { - writew(MDM_UL1, dc->reg_fcr); - dc->last_ier = dc->last_ier | MDM_UL; - writew(dc->last_ier, dc->reg_ier); - *toggle = !*toggle; - } - } - } else { - writew(read_iir & MDM_UL, dc->reg_fcr); - dev_err(&dc->pdev->dev, "port out of sync!\n"); - return 0; - } - return 1; -} - -static irqreturn_t interrupt_handler(int irq, void *dev_id) -{ - struct nozomi *dc = dev_id; - unsigned int a; - u16 read_iir; - - if (!dc) - return IRQ_NONE; - - spin_lock(&dc->spin_mutex); - read_iir = readw(dc->reg_iir); - - /* Card removed */ - if (read_iir == (u16)-1) - goto none; - /* - * Just handle interrupt enabled in IER - * (by masking with dc->last_ier) - */ - read_iir &= dc->last_ier; - - if (read_iir == 0) - goto none; - - - DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir, - dc->last_ier); - - if (read_iir & RESET) { - if (unlikely(!nozomi_read_config_table(dc))) { - dc->last_ier = 0x0; - writew(dc->last_ier, dc->reg_ier); - dev_err(&dc->pdev->dev, "Could not read status from " - "card, we should disable interface\n"); - } else { - writew(RESET, dc->reg_fcr); - } - /* No more useful info if this was the reset interrupt. */ - goto exit_handler; - } - if (read_iir & CTRL_UL) { - DBG1("CTRL_UL"); - dc->last_ier &= ~CTRL_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_flow_control(dc)) { - writew(CTRL_UL, dc->reg_fcr); - dc->last_ier = dc->last_ier | CTRL_UL; - writew(dc->last_ier, dc->reg_ier); - } - } - if (read_iir & CTRL_DL) { - receive_flow_control(dc); - writew(CTRL_DL, dc->reg_fcr); - } - if (read_iir & MDM_DL) { - if (!handle_data_dl(dc, PORT_MDM, - &(dc->port[PORT_MDM].toggle_dl), read_iir, - MDM_DL1, MDM_DL2)) { - dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n"); - goto exit_handler; - } - } - if (read_iir & MDM_UL) { - if (!handle_data_ul(dc, PORT_MDM, read_iir)) { - dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n"); - goto exit_handler; - } - } - if (read_iir & DIAG_DL) { - if (!handle_data_dl(dc, PORT_DIAG, - &(dc->port[PORT_DIAG].toggle_dl), read_iir, - DIAG_DL1, DIAG_DL2)) { - dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n"); - goto exit_handler; - } - } - if (read_iir & DIAG_UL) { - dc->last_ier &= ~DIAG_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(PORT_DIAG, dc)) { - writew(DIAG_UL, dc->reg_fcr); - dc->last_ier = dc->last_ier | DIAG_UL; - writew(dc->last_ier, dc->reg_ier); - } - } - if (read_iir & APP1_DL) { - if (receive_data(PORT_APP1, dc)) - writew(APP1_DL, dc->reg_fcr); - } - if (read_iir & APP1_UL) { - dc->last_ier &= ~APP1_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(PORT_APP1, dc)) { - writew(APP1_UL, dc->reg_fcr); - dc->last_ier = dc->last_ier | APP1_UL; - writew(dc->last_ier, dc->reg_ier); - } - } - if (read_iir & APP2_DL) { - if (receive_data(PORT_APP2, dc)) - writew(APP2_DL, dc->reg_fcr); - } - if (read_iir & APP2_UL) { - dc->last_ier &= ~APP2_UL; - writew(dc->last_ier, dc->reg_ier); - if (send_data(PORT_APP2, dc)) { - writew(APP2_UL, dc->reg_fcr); - dc->last_ier = dc->last_ier | APP2_UL; - writew(dc->last_ier, dc->reg_ier); - } - } - -exit_handler: - spin_unlock(&dc->spin_mutex); - for (a = 0; a < NOZOMI_MAX_PORTS; a++) { - struct tty_struct *tty; - if (test_and_clear_bit(a, &dc->flip)) { - tty = tty_port_tty_get(&dc->port[a].port); - if (tty) - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } - } - return IRQ_HANDLED; -none: - spin_unlock(&dc->spin_mutex); - return IRQ_NONE; -} - -static void nozomi_get_card_type(struct nozomi *dc) -{ - int i; - u32 size = 0; - - for (i = 0; i < 6; i++) - size += pci_resource_len(dc->pdev, i); - - /* Assume card type F32_8 if no match */ - dc->card_type = size == 2048 ? F32_2 : F32_8; - - dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type); -} - -static void nozomi_setup_private_data(struct nozomi *dc) -{ - void __iomem *offset = dc->base_addr + dc->card_type / 2; - unsigned int i; - - dc->reg_fcr = (void __iomem *)(offset + R_FCR); - dc->reg_iir = (void __iomem *)(offset + R_IIR); - dc->reg_ier = (void __iomem *)(offset + R_IER); - dc->last_ier = 0; - dc->flip = 0; - - dc->port[PORT_MDM].token_dl = MDM_DL; - dc->port[PORT_DIAG].token_dl = DIAG_DL; - dc->port[PORT_APP1].token_dl = APP1_DL; - dc->port[PORT_APP2].token_dl = APP2_DL; - - for (i = 0; i < MAX_PORT; i++) - init_waitqueue_head(&dc->port[i].tty_wait); -} - -static ssize_t card_type_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev)); - - return sprintf(buf, "%d\n", dc->card_type); -} -static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL); - -static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev)); - - return sprintf(buf, "%u\n", dc->open_ttys); -} -static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL); - -static void make_sysfs_files(struct nozomi *dc) -{ - if (device_create_file(&dc->pdev->dev, &dev_attr_card_type)) - dev_err(&dc->pdev->dev, - "Could not create sysfs file for card_type\n"); - if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys)) - dev_err(&dc->pdev->dev, - "Could not create sysfs file for open_ttys\n"); -} - -static void remove_sysfs_files(struct nozomi *dc) -{ - device_remove_file(&dc->pdev->dev, &dev_attr_card_type); - device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys); -} - -/* Allocate memory for one device */ -static int __devinit nozomi_card_init(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - resource_size_t start; - int ret; - struct nozomi *dc = NULL; - int ndev_idx; - int i; - - dev_dbg(&pdev->dev, "Init, new card found\n"); - - for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++) - if (!ndevs[ndev_idx]) - break; - - if (ndev_idx >= ARRAY_SIZE(ndevs)) { - dev_err(&pdev->dev, "no free tty range for this card left\n"); - ret = -EIO; - goto err; - } - - dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL); - if (unlikely(!dc)) { - dev_err(&pdev->dev, "Could not allocate memory\n"); - ret = -ENOMEM; - goto err_free; - } - - dc->pdev = pdev; - - ret = pci_enable_device(dc->pdev); - if (ret) { - dev_err(&pdev->dev, "Failed to enable PCI Device\n"); - goto err_free; - } - - ret = pci_request_regions(dc->pdev, NOZOMI_NAME); - if (ret) { - dev_err(&pdev->dev, "I/O address 0x%04x already in use\n", - (int) /* nozomi_private.io_addr */ 0); - goto err_disable_device; - } - - start = pci_resource_start(dc->pdev, 0); - if (start == 0) { - dev_err(&pdev->dev, "No I/O address for card detected\n"); - ret = -ENODEV; - goto err_rel_regs; - } - - /* Find out what card type it is */ - nozomi_get_card_type(dc); - - dc->base_addr = ioremap_nocache(start, dc->card_type); - if (!dc->base_addr) { - dev_err(&pdev->dev, "Unable to map card MMIO\n"); - ret = -ENODEV; - goto err_rel_regs; - } - - dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL); - if (!dc->send_buf) { - dev_err(&pdev->dev, "Could not allocate send buffer?\n"); - ret = -ENOMEM; - goto err_free_sbuf; - } - - for (i = PORT_MDM; i < MAX_PORT; i++) { - if (kfifo_alloc(&dc->port[i].fifo_ul, - FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { - dev_err(&pdev->dev, - "Could not allocate kfifo buffer\n"); - ret = -ENOMEM; - goto err_free_kfifo; - } - } - - spin_lock_init(&dc->spin_mutex); - - nozomi_setup_private_data(dc); - - /* Disable all interrupts */ - dc->last_ier = 0; - writew(dc->last_ier, dc->reg_ier); - - ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED, - NOZOMI_NAME, dc); - if (unlikely(ret)) { - dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); - goto err_free_kfifo; - } - - DBG1("base_addr: %p", dc->base_addr); - - make_sysfs_files(dc); - - dc->index_start = ndev_idx * MAX_PORT; - ndevs[ndev_idx] = dc; - - pci_set_drvdata(pdev, dc); - - /* Enable RESET interrupt */ - dc->last_ier = RESET; - iowrite16(dc->last_ier, dc->reg_ier); - - dc->state = NOZOMI_STATE_ENABLED; - - for (i = 0; i < MAX_PORT; i++) { - struct device *tty_dev; - struct port *port = &dc->port[i]; - port->dc = dc; - mutex_init(&port->tty_sem); - tty_port_init(&port->port); - port->port.ops = &noz_tty_port_ops; - tty_dev = tty_register_device(ntty_driver, dc->index_start + i, - &pdev->dev); - - if (IS_ERR(tty_dev)) { - ret = PTR_ERR(tty_dev); - dev_err(&pdev->dev, "Could not allocate tty?\n"); - goto err_free_tty; - } - } - - return 0; - -err_free_tty: - for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) - tty_unregister_device(ntty_driver, i); -err_free_kfifo: - for (i = 0; i < MAX_PORT; i++) - kfifo_free(&dc->port[i].fifo_ul); -err_free_sbuf: - kfree(dc->send_buf); - iounmap(dc->base_addr); -err_rel_regs: - pci_release_regions(pdev); -err_disable_device: - pci_disable_device(pdev); -err_free: - kfree(dc); -err: - return ret; -} - -static void __devexit tty_exit(struct nozomi *dc) -{ - unsigned int i; - - DBG1(" "); - - flush_scheduled_work(); - - for (i = 0; i < MAX_PORT; ++i) { - struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port); - if (tty && list_empty(&tty->hangup_work.entry)) - tty_hangup(tty); - tty_kref_put(tty); - } - /* Racy below - surely should wait for scheduled work to be done or - complete off a hangup method ? */ - while (dc->open_ttys) - msleep(1); - for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) - tty_unregister_device(ntty_driver, i); -} - -/* Deallocate memory for one device */ -static void __devexit nozomi_card_exit(struct pci_dev *pdev) -{ - int i; - struct ctrl_ul ctrl; - struct nozomi *dc = pci_get_drvdata(pdev); - - /* Disable all interrupts */ - dc->last_ier = 0; - writew(dc->last_ier, dc->reg_ier); - - tty_exit(dc); - - /* Send 0x0001, command card to resend the reset token. */ - /* This is to get the reset when the module is reloaded. */ - ctrl.port = 0x00; - ctrl.reserved = 0; - ctrl.RTS = 0; - ctrl.DTR = 1; - DBG1("sending flow control 0x%04X", *((u16 *)&ctrl)); - - /* Setup dc->reg addresses to we can use defines here */ - write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2); - writew(CTRL_UL, dc->reg_fcr); /* push the token to the card. */ - - remove_sysfs_files(dc); - - free_irq(pdev->irq, dc); - - for (i = 0; i < MAX_PORT; i++) - kfifo_free(&dc->port[i].fifo_ul); - - kfree(dc->send_buf); - - iounmap(dc->base_addr); - - pci_release_regions(pdev); - - pci_disable_device(pdev); - - ndevs[dc->index_start / MAX_PORT] = NULL; - - kfree(dc); -} - -static void set_rts(const struct tty_struct *tty, int rts) -{ - struct port *port = get_port_by_tty(tty); - - port->ctrl_ul.RTS = rts; - port->update_flow_control = 1; - enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty)); -} - -static void set_dtr(const struct tty_struct *tty, int dtr) -{ - struct port *port = get_port_by_tty(tty); - - DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr); - - port->ctrl_ul.DTR = dtr; - port->update_flow_control = 1; - enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty)); -} - -/* - * ---------------------------------------------------------------------------- - * TTY code - * ---------------------------------------------------------------------------- - */ - -static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct port *port = get_port_by_tty(tty); - struct nozomi *dc = get_dc_by_tty(tty); - int ret; - if (!port || !dc || dc->state != NOZOMI_STATE_READY) - return -ENODEV; - ret = tty_init_termios(tty); - if (ret == 0) { - tty_driver_kref_get(driver); - tty->count++; - tty->driver_data = port; - driver->ttys[tty->index] = tty; - } - return ret; -} - -static void ntty_cleanup(struct tty_struct *tty) -{ - tty->driver_data = NULL; -} - -static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) -{ - struct port *port = container_of(tport, struct port, port); - struct nozomi *dc = port->dc; - unsigned long flags; - - DBG1("open: %d", port->token_dl); - spin_lock_irqsave(&dc->spin_mutex, flags); - dc->last_ier = dc->last_ier | port->token_dl; - writew(dc->last_ier, dc->reg_ier); - dc->open_ttys++; - spin_unlock_irqrestore(&dc->spin_mutex, flags); - printk("noz: activated %d: %p\n", tty->index, tport); - return 0; -} - -static int ntty_open(struct tty_struct *tty, struct file *filp) -{ - struct port *port = tty->driver_data; - return tty_port_open(&port->port, tty, filp); -} - -static void ntty_shutdown(struct tty_port *tport) -{ - struct port *port = container_of(tport, struct port, port); - struct nozomi *dc = port->dc; - unsigned long flags; - - DBG1("close: %d", port->token_dl); - spin_lock_irqsave(&dc->spin_mutex, flags); - dc->last_ier &= ~(port->token_dl); - writew(dc->last_ier, dc->reg_ier); - dc->open_ttys--; - spin_unlock_irqrestore(&dc->spin_mutex, flags); - printk("noz: shutdown %p\n", tport); -} - -static void ntty_close(struct tty_struct *tty, struct file *filp) -{ - struct port *port = tty->driver_data; - if (port) - tty_port_close(&port->port, tty, filp); -} - -static void ntty_hangup(struct tty_struct *tty) -{ - struct port *port = tty->driver_data; - tty_port_hangup(&port->port); -} - -/* - * called when the userspace process writes to the tty (/dev/noz*). - * Data is inserted into a fifo, which is then read and transfered to the modem. - */ -static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, - int count) -{ - int rval = -EINVAL; - struct nozomi *dc = get_dc_by_tty(tty); - struct port *port = tty->driver_data; - unsigned long flags; - - /* DBG1( "WRITEx: %d, index = %d", count, index); */ - - if (!dc || !port) - return -ENODEV; - - mutex_lock(&port->tty_sem); - - if (unlikely(!port->port.count)) { - DBG1(" "); - goto exit; - } - - rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); - - /* notify card */ - if (unlikely(dc == NULL)) { - DBG1("No device context?"); - goto exit; - } - - spin_lock_irqsave(&dc->spin_mutex, flags); - /* CTS is only valid on the modem channel */ - if (port == &(dc->port[PORT_MDM])) { - if (port->ctrl_dl.CTS) { - DBG4("Enable interrupt"); - enable_transmit_ul(tty->index % MAX_PORT, dc); - } else { - dev_err(&dc->pdev->dev, - "CTS not active on modem port?\n"); - } - } else { - enable_transmit_ul(tty->index % MAX_PORT, dc); - } - spin_unlock_irqrestore(&dc->spin_mutex, flags); - -exit: - mutex_unlock(&port->tty_sem); - return rval; -} - -/* - * Calculate how much is left in device - * This method is called by the upper tty layer. - * #according to sources N_TTY.c it expects a value >= 0 and - * does not check for negative values. - * - * If the port is unplugged report lots of room and let the bits - * dribble away so we don't block anything. - */ -static int ntty_write_room(struct tty_struct *tty) -{ - struct port *port = tty->driver_data; - int room = 4096; - const struct nozomi *dc = get_dc_by_tty(tty); - - if (dc) { - mutex_lock(&port->tty_sem); - if (port->port.count) - room = kfifo_avail(&port->fifo_ul); - mutex_unlock(&port->tty_sem); - } - return room; -} - -/* Gets io control parameters */ -static int ntty_tiocmget(struct tty_struct *tty) -{ - const struct port *port = tty->driver_data; - const struct ctrl_dl *ctrl_dl = &port->ctrl_dl; - const struct ctrl_ul *ctrl_ul = &port->ctrl_ul; - - /* Note: these could change under us but it is not clear this - matters if so */ - return (ctrl_ul->RTS ? TIOCM_RTS : 0) | - (ctrl_ul->DTR ? TIOCM_DTR : 0) | - (ctrl_dl->DCD ? TIOCM_CAR : 0) | - (ctrl_dl->RI ? TIOCM_RNG : 0) | - (ctrl_dl->DSR ? TIOCM_DSR : 0) | - (ctrl_dl->CTS ? TIOCM_CTS : 0); -} - -/* Sets io controls parameters */ -static int ntty_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct nozomi *dc = get_dc_by_tty(tty); - unsigned long flags; - - spin_lock_irqsave(&dc->spin_mutex, flags); - if (set & TIOCM_RTS) - set_rts(tty, 1); - else if (clear & TIOCM_RTS) - set_rts(tty, 0); - - if (set & TIOCM_DTR) - set_dtr(tty, 1); - else if (clear & TIOCM_DTR) - set_dtr(tty, 0); - spin_unlock_irqrestore(&dc->spin_mutex, flags); - - return 0; -} - -static int ntty_cflags_changed(struct port *port, unsigned long flags, - struct async_icount *cprev) -{ - const struct async_icount cnow = port->tty_icount; - int ret; - - ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) || - ((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || - ((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || - ((flags & TIOCM_CTS) && (cnow.cts != cprev->cts)); - - *cprev = cnow; - - return ret; -} - -static int ntty_tiocgicount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct port *port = tty->driver_data; - const struct async_icount cnow = port->tty_icount; - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - return 0; -} - -static int ntty_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct port *port = tty->driver_data; - int rval = -ENOIOCTLCMD; - - DBG1("******** IOCTL, cmd: %d", cmd); - - switch (cmd) { - case TIOCMIWAIT: { - struct async_icount cprev = port->tty_icount; - - rval = wait_event_interruptible(port->tty_wait, - ntty_cflags_changed(port, arg, &cprev)); - break; - } - default: - DBG1("ERR: 0x%08X, %d", cmd, cmd); - break; - }; - - return rval; -} - -/* - * Called by the upper tty layer when tty buffers are ready - * to receive data again after a call to throttle. - */ -static void ntty_unthrottle(struct tty_struct *tty) -{ - struct nozomi *dc = get_dc_by_tty(tty); - unsigned long flags; - - DBG1("UNTHROTTLE"); - spin_lock_irqsave(&dc->spin_mutex, flags); - enable_transmit_dl(tty->index % MAX_PORT, dc); - set_rts(tty, 1); - - spin_unlock_irqrestore(&dc->spin_mutex, flags); -} - -/* - * Called by the upper tty layer when the tty buffers are almost full. - * The driver should stop send more data. - */ -static void ntty_throttle(struct tty_struct *tty) -{ - struct nozomi *dc = get_dc_by_tty(tty); - unsigned long flags; - - DBG1("THROTTLE"); - spin_lock_irqsave(&dc->spin_mutex, flags); - set_rts(tty, 0); - spin_unlock_irqrestore(&dc->spin_mutex, flags); -} - -/* Returns number of chars in buffer, called by tty layer */ -static s32 ntty_chars_in_buffer(struct tty_struct *tty) -{ - struct port *port = tty->driver_data; - struct nozomi *dc = get_dc_by_tty(tty); - s32 rval = 0; - - if (unlikely(!dc || !port)) { - goto exit_in_buffer; - } - - if (unlikely(!port->port.count)) { - dev_err(&dc->pdev->dev, "No tty open?\n"); - goto exit_in_buffer; - } - - rval = kfifo_len(&port->fifo_ul); - -exit_in_buffer: - return rval; -} - -static const struct tty_port_operations noz_tty_port_ops = { - .activate = ntty_activate, - .shutdown = ntty_shutdown, -}; - -static const struct tty_operations tty_ops = { - .ioctl = ntty_ioctl, - .open = ntty_open, - .close = ntty_close, - .hangup = ntty_hangup, - .write = ntty_write, - .write_room = ntty_write_room, - .unthrottle = ntty_unthrottle, - .throttle = ntty_throttle, - .chars_in_buffer = ntty_chars_in_buffer, - .tiocmget = ntty_tiocmget, - .tiocmset = ntty_tiocmset, - .get_icount = ntty_tiocgicount, - .install = ntty_install, - .cleanup = ntty_cleanup, -}; - -/* Module initialization */ -static struct pci_driver nozomi_driver = { - .name = NOZOMI_NAME, - .id_table = nozomi_pci_tbl, - .probe = nozomi_card_init, - .remove = __devexit_p(nozomi_card_exit), -}; - -static __init int nozomi_init(void) -{ - int ret; - - printk(KERN_INFO "Initializing %s\n", VERSION_STRING); - - ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS); - if (!ntty_driver) - return -ENOMEM; - - ntty_driver->owner = THIS_MODULE; - ntty_driver->driver_name = NOZOMI_NAME_TTY; - ntty_driver->name = "noz"; - ntty_driver->major = 0; - ntty_driver->type = TTY_DRIVER_TYPE_SERIAL; - ntty_driver->subtype = SERIAL_TYPE_NORMAL; - ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - ntty_driver->init_termios = tty_std_termios; - ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \ - HUPCL | CLOCAL; - ntty_driver->init_termios.c_ispeed = 115200; - ntty_driver->init_termios.c_ospeed = 115200; - tty_set_operations(ntty_driver, &tty_ops); - - ret = tty_register_driver(ntty_driver); - if (ret) { - printk(KERN_ERR "Nozomi: failed to register ntty driver\n"); - goto free_tty; - } - - ret = pci_register_driver(&nozomi_driver); - if (ret) { - printk(KERN_ERR "Nozomi: can't register pci driver\n"); - goto unr_tty; - } - - return 0; -unr_tty: - tty_unregister_driver(ntty_driver); -free_tty: - put_tty_driver(ntty_driver); - return ret; -} - -static __exit void nozomi_exit(void) -{ - printk(KERN_INFO "Unloading %s\n", DRIVER_DESC); - pci_unregister_driver(&nozomi_driver); - tty_unregister_driver(ntty_driver); - put_tty_driver(ntty_driver); -} - -module_init(nozomi_init); -module_exit(nozomi_exit); - -module_param(debug, int, S_IRUGO | S_IWUSR); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c deleted file mode 100644 index 3780da8ad12d..000000000000 --- a/drivers/char/rocket.c +++ /dev/null @@ -1,3199 +0,0 @@ -/* - * RocketPort device driver for Linux - * - * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Kernel Synchronization: - * - * This driver has 2 kernel control paths - exception handlers (calls into the driver - * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts - * are not used. - * - * Critical data: - * - rp_table[], accessed through passed "info" pointers, is a global (static) array of - * serial port state information and the xmit_buf circular buffer. Protected by - * a per port spinlock. - * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there - * is data to be transmitted. Protected by atomic bit operations. - * - rp_num_ports, int indicating number of open ports, protected by atomic operations. - * - * rp_write() and rp_write_char() functions use a per port semaphore to protect against - * simultaneous access to the same port by more than one process. - */ - -/****** Defines ******/ -#define ROCKET_PARANOIA_CHECK -#define ROCKET_DISABLE_SIMUSAGE - -#undef ROCKET_SOFT_FLOW -#undef ROCKET_DEBUG_OPEN -#undef ROCKET_DEBUG_INTR -#undef ROCKET_DEBUG_WRITE -#undef ROCKET_DEBUG_FLOW -#undef ROCKET_DEBUG_THROTTLE -#undef ROCKET_DEBUG_WAIT_UNTIL_SENT -#undef ROCKET_DEBUG_RECEIVE -#undef ROCKET_DEBUG_HANGUP -#undef REV_PCI_ORDER -#undef ROCKET_DEBUG_IO - -#define POLL_PERIOD HZ/100 /* Polling period .01 seconds (10ms) */ - -/****** Kernel includes ******/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/****** RocketPort includes ******/ - -#include "rocket_int.h" -#include "rocket.h" - -#define ROCKET_VERSION "2.09" -#define ROCKET_DATE "12-June-2003" - -/****** RocketPort Local Variables ******/ - -static void rp_do_poll(unsigned long dummy); - -static struct tty_driver *rocket_driver; - -static struct rocket_version driver_version = { - ROCKET_VERSION, ROCKET_DATE -}; - -static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of serial port state information. */ -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 DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0); - -static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */ -static unsigned long board2; -static unsigned long board3; -static unsigned long board4; -static unsigned long controller; -static int support_low_speed; -static unsigned long modem1; -static unsigned long modem2; -static unsigned long modem3; -static unsigned long modem4; -static unsigned long pc104_1[8]; -static unsigned long pc104_2[8]; -static unsigned long pc104_3[8]; -static unsigned long pc104_4[8]; -static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 }; - -static int rp_baud_base[NUM_BOARDS]; /* Board config info (Someday make a per-board structure) */ -static unsigned long rcktpt_io_addr[NUM_BOARDS]; -static int rcktpt_type[NUM_BOARDS]; -static int is_PCI[NUM_BOARDS]; -static rocketModel_t rocketModel[NUM_BOARDS]; -static int max_board; -static const struct tty_port_operations rocket_port_ops; - -/* - * The following arrays define the interrupt bits corresponding to each AIOP. - * These bits are different between the ISA and regular PCI boards and the - * Universal PCI boards. - */ - -static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = { - AIOP_INTR_BIT_0, - AIOP_INTR_BIT_1, - AIOP_INTR_BIT_2, - AIOP_INTR_BIT_3 -}; - -static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = { - UPCI_AIOP_INTR_BIT_0, - UPCI_AIOP_INTR_BIT_1, - UPCI_AIOP_INTR_BIT_2, - UPCI_AIOP_INTR_BIT_3 -}; - -static Byte_t RData[RDATASIZE] = { - 0x00, 0x09, 0xf6, 0x82, - 0x02, 0x09, 0x86, 0xfb, - 0x04, 0x09, 0x00, 0x0a, - 0x06, 0x09, 0x01, 0x0a, - 0x08, 0x09, 0x8a, 0x13, - 0x0a, 0x09, 0xc5, 0x11, - 0x0c, 0x09, 0x86, 0x85, - 0x0e, 0x09, 0x20, 0x0a, - 0x10, 0x09, 0x21, 0x0a, - 0x12, 0x09, 0x41, 0xff, - 0x14, 0x09, 0x82, 0x00, - 0x16, 0x09, 0x82, 0x7b, - 0x18, 0x09, 0x8a, 0x7d, - 0x1a, 0x09, 0x88, 0x81, - 0x1c, 0x09, 0x86, 0x7a, - 0x1e, 0x09, 0x84, 0x81, - 0x20, 0x09, 0x82, 0x7c, - 0x22, 0x09, 0x0a, 0x0a -}; - -static Byte_t RRegData[RREGDATASIZE] = { - 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ - 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ - 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ - 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ - 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ - 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ - 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ - 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ - 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ - 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ - 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ - 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ - 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ -}; - -static CONTROLLER_T sController[CTL_SIZE] = { - {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, - {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}, - {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, - {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}, - {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, - {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}, - {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, - {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}} -}; - -static Byte_t sBitMapClrTbl[8] = { - 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f -}; - -static Byte_t sBitMapSetTbl[8] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 -}; - -static int sClockPrescale = 0x14; - -/* - * Line number is the ttySIx number (x), the Minor number. We - * assign them sequentially, starting at zero. The following - * array keeps track of the line number assigned to a given board/aiop/channel. - */ -static unsigned char lineNumbers[MAX_RP_PORTS]; -static unsigned long nextLineNumber; - -/***** RocketPort Static Prototypes *********/ -static int __init init_ISA(int i); -static void rp_wait_until_sent(struct tty_struct *tty, int timeout); -static void rp_flush_buffer(struct tty_struct *tty); -static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model); -static unsigned char GetLineNumber(int ctrl, int aiop, int ch); -static unsigned char SetLineNumber(int ctrl, int aiop, int ch); -static void rp_start(struct tty_struct *tty); -static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, - int ChanNum); -static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode); -static void sFlushRxFIFO(CHANNEL_T * ChP); -static void sFlushTxFIFO(CHANNEL_T * ChP); -static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags); -static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags); -static void sModemReset(CONTROLLER_T * CtlP, int chan, int on); -static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on); -static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data); -static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, - ByteIO_t * AiopIOList, int AiopIOListSize, - WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, - int PeriodicOnly, int altChanRingIndicator, - int UPCIRingInd); -static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, - ByteIO_t * AiopIOList, int AiopIOListSize, - int IRQNum, Byte_t Frequency, int PeriodicOnly); -static int sReadAiopID(ByteIO_t io); -static int sReadAiopNumChan(WordIO_t io); - -MODULE_AUTHOR("Theodore Ts'o"); -MODULE_DESCRIPTION("Comtrol RocketPort driver"); -module_param(board1, ulong, 0); -MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1"); -module_param(board2, ulong, 0); -MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2"); -module_param(board3, ulong, 0); -MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3"); -module_param(board4, ulong, 0); -MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4"); -module_param(controller, ulong, 0); -MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller"); -module_param(support_low_speed, bool, 0); -MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud"); -module_param(modem1, ulong, 0); -MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem"); -module_param(modem2, ulong, 0); -MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem"); -module_param(modem3, ulong, 0); -MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem"); -module_param(modem4, ulong, 0); -MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem"); -module_param_array(pc104_1, ulong, NULL, 0); -MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,..."); -module_param_array(pc104_2, ulong, NULL, 0); -MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,..."); -module_param_array(pc104_3, ulong, NULL, 0); -MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,..."); -module_param_array(pc104_4, ulong, NULL, 0); -MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,..."); - -static int rp_init(void); -static void rp_cleanup_module(void); - -module_init(rp_init); -module_exit(rp_cleanup_module); - - -MODULE_LICENSE("Dual BSD/GPL"); - -/*************************************************************************/ -/* Module code starts here */ - -static inline int rocket_paranoia_check(struct r_port *info, - const char *routine) -{ -#ifdef ROCKET_PARANOIA_CHECK - if (!info) - return 1; - if (info->magic != RPORT_MAGIC) { - printk(KERN_WARNING "Warning: bad magic number for rocketport " - "struct in %s\n", routine); - return 1; - } -#endif - return 0; -} - - -/* Serial port receive data function. Called (from timer poll) when an AIOPIC signals - * that receive data is present on a serial port. Pulls data from FIFO, moves it into the - * tty layer. - */ -static void rp_do_receive(struct r_port *info, - struct tty_struct *tty, - CHANNEL_t * cp, unsigned int ChanStatus) -{ - unsigned int CharNStat; - int ToRecv, wRecv, space; - unsigned char *cbuf; - - ToRecv = sGetRxCnt(cp); -#ifdef ROCKET_DEBUG_INTR - printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv); -#endif - if (ToRecv == 0) - return; - - /* - * if status indicates there are errored characters in the - * FIFO, then enter status mode (a word in FIFO holds - * character and status). - */ - if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { - if (!(ChanStatus & STATMODE)) { -#ifdef ROCKET_DEBUG_RECEIVE - printk(KERN_INFO "Entering STATMODE...\n"); -#endif - ChanStatus |= STATMODE; - sEnRxStatusMode(cp); - } - } - - /* - * if we previously entered status mode, then read down the - * FIFO one word at a time, pulling apart the character and - * the status. Update error counters depending on status - */ - if (ChanStatus & STATMODE) { -#ifdef ROCKET_DEBUG_RECEIVE - printk(KERN_INFO "Ignore %x, read %x...\n", - info->ignore_status_mask, info->read_status_mask); -#endif - while (ToRecv) { - char flag; - - CharNStat = sInW(sGetTxRxDataIO(cp)); -#ifdef ROCKET_DEBUG_RECEIVE - printk(KERN_INFO "%x...\n", CharNStat); -#endif - if (CharNStat & STMBREAKH) - CharNStat &= ~(STMFRAMEH | STMPARITYH); - if (CharNStat & info->ignore_status_mask) { - ToRecv--; - continue; - } - CharNStat &= info->read_status_mask; - if (CharNStat & STMBREAKH) - flag = TTY_BREAK; - else if (CharNStat & STMPARITYH) - flag = TTY_PARITY; - else if (CharNStat & STMFRAMEH) - flag = TTY_FRAME; - else if (CharNStat & STMRCVROVRH) - flag = TTY_OVERRUN; - else - flag = TTY_NORMAL; - tty_insert_flip_char(tty, CharNStat & 0xff, flag); - ToRecv--; - } - - /* - * after we've emptied the FIFO in status mode, turn - * status mode back off - */ - if (sGetRxCnt(cp) == 0) { -#ifdef ROCKET_DEBUG_RECEIVE - printk(KERN_INFO "Status mode off.\n"); -#endif - sDisRxStatusMode(cp); - } - } else { - /* - * we aren't in status mode, so read down the FIFO two - * characters at time by doing repeated word IO - * transfer. - */ - space = tty_prepare_flip_string(tty, &cbuf, ToRecv); - if (space < ToRecv) { -#ifdef ROCKET_DEBUG_RECEIVE - printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space); -#endif - if (space <= 0) - return; - ToRecv = space; - } - wRecv = ToRecv >> 1; - if (wRecv) - sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv); - if (ToRecv & 1) - cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp)); - } - /* Push the data up to the tty layer */ - tty_flip_buffer_push(tty); -} - -/* - * Serial port transmit data function. Called from the timer polling loop as a - * result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready - * to be sent out the serial port. Data is buffered in rp_table[line].xmit_buf, it is - * moved to the port's xmit FIFO. *info is critical data, protected by spinlocks. - */ -static void rp_do_transmit(struct r_port *info) -{ - int c; - CHANNEL_t *cp = &info->channel; - struct tty_struct *tty; - unsigned long flags; - -#ifdef ROCKET_DEBUG_INTR - printk(KERN_DEBUG "%s\n", __func__); -#endif - if (!info) - return; - tty = tty_port_tty_get(&info->port); - - if (tty == NULL) { - printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__); - clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - return; - } - - spin_lock_irqsave(&info->slock, flags); - info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - - /* Loop sending data to FIFO until done or FIFO full */ - while (1) { - if (tty->stopped || tty->hw_stopped) - break; - c = min(info->xmit_fifo_room, info->xmit_cnt); - c = min(c, XMIT_BUF_SIZE - info->xmit_tail); - if (c <= 0 || info->xmit_fifo_room <= 0) - break; - sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2); - if (c & 1) - sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]); - info->xmit_tail += c; - info->xmit_tail &= XMIT_BUF_SIZE - 1; - info->xmit_cnt -= c; - info->xmit_fifo_room -= c; -#ifdef ROCKET_DEBUG_INTR - printk(KERN_INFO "tx %d chars...\n", c); -#endif - } - - if (info->xmit_cnt == 0) - clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - - if (info->xmit_cnt < WAKEUP_CHARS) { - tty_wakeup(tty); -#ifdef ROCKETPORT_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - } - - spin_unlock_irqrestore(&info->slock, flags); - tty_kref_put(tty); - -#ifdef ROCKET_DEBUG_INTR - printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, - info->xmit_tail, info->xmit_fifo_room); -#endif -} - -/* - * Called when a serial port signals it has read data in it's RX FIFO. - * It checks what interrupts are pending and services them, including - * receiving serial data. - */ -static void rp_handle_port(struct r_port *info) -{ - CHANNEL_t *cp; - struct tty_struct *tty; - unsigned int IntMask, ChanStatus; - - if (!info) - return; - - if ((info->port.flags & ASYNC_INITIALIZED) == 0) { - printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " - "info->flags & NOT_INIT\n"); - return; - } - tty = tty_port_tty_get(&info->port); - if (!tty) { - printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " - "tty==NULL\n"); - return; - } - cp = &info->channel; - - IntMask = sGetChanIntID(cp) & info->intmask; -#ifdef ROCKET_DEBUG_INTR - printk(KERN_INFO "rp_interrupt %02x...\n", IntMask); -#endif - ChanStatus = sGetChanStatus(cp); - if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */ - rp_do_receive(info, tty, cp, ChanStatus); - } - if (IntMask & DELTA_CD) { /* CD change */ -#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP)) - printk(KERN_INFO "ttyR%d CD now %s...\n", info->line, - (ChanStatus & CD_ACT) ? "on" : "off"); -#endif - if (!(ChanStatus & CD_ACT) && info->cd_status) { -#ifdef ROCKET_DEBUG_HANGUP - printk(KERN_INFO "CD drop, calling hangup.\n"); -#endif - tty_hangup(tty); - } - info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0; - wake_up_interruptible(&info->port.open_wait); - } -#ifdef ROCKET_DEBUG_INTR - if (IntMask & DELTA_CTS) { /* CTS change */ - printk(KERN_INFO "CTS change...\n"); - } - if (IntMask & DELTA_DSR) { /* DSR change */ - printk(KERN_INFO "DSR change...\n"); - } -#endif - tty_kref_put(tty); -} - -/* - * The top level polling routine. Repeats every 1/100 HZ (10ms). - */ -static void rp_do_poll(unsigned long dummy) -{ - CONTROLLER_t *ctlp; - int ctrl, aiop, ch, line; - unsigned int xmitmask, i; - unsigned int CtlMask; - unsigned char AiopMask; - Word_t bit; - - /* Walk through all the boards (ctrl's) */ - for (ctrl = 0; ctrl < max_board; ctrl++) { - if (rcktpt_io_addr[ctrl] <= 0) - continue; - - /* Get a ptr to the board's control struct */ - ctlp = sCtlNumToCtlPtr(ctrl); - - /* Get the interrupt status from the board */ -#ifdef CONFIG_PCI - if (ctlp->BusType == isPCI) - CtlMask = sPCIGetControllerIntStatus(ctlp); - else -#endif - CtlMask = sGetControllerIntStatus(ctlp); - - /* Check if any AIOP read bits are set */ - for (aiop = 0; CtlMask; aiop++) { - bit = ctlp->AiopIntrBits[aiop]; - if (CtlMask & bit) { - CtlMask &= ~bit; - AiopMask = sGetAiopIntStatus(ctlp, aiop); - - /* Check if any port read bits are set */ - for (ch = 0; AiopMask; AiopMask >>= 1, ch++) { - if (AiopMask & 1) { - - /* Get the line number (/dev/ttyRx number). */ - /* Read the data from the port. */ - line = GetLineNumber(ctrl, aiop, ch); - rp_handle_port(rp_table[line]); - } - } - } - } - - xmitmask = xmit_flags[ctrl]; - - /* - * xmit_flags contains bit-significant flags, indicating there is data - * to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port - * 1, ... (32 total possible). The variable i has the aiop and ch - * numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc). - */ - if (xmitmask) { - for (i = 0; i < rocketModel[ctrl].numPorts; i++) { - if (xmitmask & (1 << i)) { - aiop = (i & 0x18) >> 3; - ch = i & 0x07; - line = GetLineNumber(ctrl, aiop, ch); - rp_do_transmit(rp_table[line]); - } - } - } - } - - /* - * Reset the timer so we get called at the next clock tick (10ms). - */ - if (atomic_read(&rp_num_ports_open)) - mod_timer(&rocket_timer, jiffies + POLL_PERIOD); -} - -/* - * Initializes the r_port structure for a port, as well as enabling the port on - * the board. - * Inputs: board, aiop, chan numbers - */ -static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) -{ - unsigned rocketMode; - struct r_port *info; - int line; - CONTROLLER_T *ctlp; - - /* Get the next available line number */ - line = SetLineNumber(board, aiop, chan); - - ctlp = sCtlNumToCtlPtr(board); - - /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */ - info = kzalloc(sizeof (struct r_port), GFP_KERNEL); - if (!info) { - printk(KERN_ERR "Couldn't allocate info struct for line #%d\n", - line); - return; - } - - info->magic = RPORT_MAGIC; - info->line = line; - info->ctlp = ctlp; - info->board = board; - info->aiop = aiop; - info->chan = chan; - tty_port_init(&info->port); - info->port.ops = &rocket_port_ops; - init_completion(&info->close_wait); - info->flags &= ~ROCKET_MODE_MASK; - switch (pc104[board][line]) { - case 422: - info->flags |= ROCKET_MODE_RS422; - break; - case 485: - info->flags |= ROCKET_MODE_RS485; - break; - case 232: - default: - info->flags |= ROCKET_MODE_RS232; - break; - } - - info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR; - if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { - printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n", - board, aiop, chan); - kfree(info); - return; - } - - rocketMode = info->flags & ROCKET_MODE_MASK; - - if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485)) - sEnRTSToggle(&info->channel); - else - sDisRTSToggle(&info->channel); - - if (ctlp->boardType == ROCKET_TYPE_PC104) { - switch (rocketMode) { - case ROCKET_MODE_RS485: - sSetInterfaceMode(&info->channel, InterfaceModeRS485); - break; - case ROCKET_MODE_RS422: - sSetInterfaceMode(&info->channel, InterfaceModeRS422); - break; - case ROCKET_MODE_RS232: - default: - if (info->flags & ROCKET_RTS_TOGGLE) - sSetInterfaceMode(&info->channel, InterfaceModeRS232T); - else - sSetInterfaceMode(&info->channel, InterfaceModeRS232); - break; - } - } - spin_lock_init(&info->slock); - mutex_init(&info->write_mtx); - rp_table[line] = info; - tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev : - NULL); -} - -/* - * Configures a rocketport port according to its termio settings. Called from - * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. - */ -static void configure_r_port(struct tty_struct *tty, struct r_port *info, - struct ktermios *old_termios) -{ - unsigned cflag; - unsigned long flags; - unsigned rocketMode; - int bits, baud, divisor; - CHANNEL_t *cp; - struct ktermios *t = tty->termios; - - cp = &info->channel; - cflag = t->c_cflag; - - /* Byte size and parity */ - if ((cflag & CSIZE) == CS8) { - sSetData8(cp); - bits = 10; - } else { - sSetData7(cp); - bits = 9; - } - if (cflag & CSTOPB) { - sSetStop2(cp); - bits++; - } else { - sSetStop1(cp); - } - - if (cflag & PARENB) { - sEnParity(cp); - bits++; - if (cflag & PARODD) { - sSetOddParity(cp); - } else { - sSetEvenParity(cp); - } - } else { - sDisParity(cp); - } - - /* baud rate */ - baud = tty_get_baud_rate(tty); - if (!baud) - baud = 9600; - divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1; - if ((divisor >= 8192 || divisor < 0) && old_termios) { - baud = tty_termios_baud_rate(old_termios); - if (!baud) - baud = 9600; - divisor = (rp_baud_base[info->board] / baud) - 1; - } - if (divisor >= 8192 || divisor < 0) { - baud = 9600; - divisor = (rp_baud_base[info->board] / baud) - 1; - } - info->cps = baud / bits; - sSetBaud(cp, divisor); - - /* FIXME: Should really back compute a baud rate from the divisor */ - tty_encode_baud_rate(tty, baud, baud); - - if (cflag & CRTSCTS) { - info->intmask |= DELTA_CTS; - sEnCTSFlowCtl(cp); - } else { - info->intmask &= ~DELTA_CTS; - sDisCTSFlowCtl(cp); - } - if (cflag & CLOCAL) { - info->intmask &= ~DELTA_CD; - } else { - spin_lock_irqsave(&info->slock, flags); - if (sGetChanStatus(cp) & CD_ACT) - info->cd_status = 1; - else - info->cd_status = 0; - info->intmask |= DELTA_CD; - spin_unlock_irqrestore(&info->slock, flags); - } - - /* - * Handle software flow control in the board - */ -#ifdef ROCKET_SOFT_FLOW - if (I_IXON(tty)) { - sEnTxSoftFlowCtl(cp); - if (I_IXANY(tty)) { - sEnIXANY(cp); - } else { - sDisIXANY(cp); - } - sSetTxXONChar(cp, START_CHAR(tty)); - sSetTxXOFFChar(cp, STOP_CHAR(tty)); - } else { - sDisTxSoftFlowCtl(cp); - sDisIXANY(cp); - sClrTxXOFF(cp); - } -#endif - - /* - * Set up ignore/read mask words - */ - info->read_status_mask = STMRCVROVRH | 0xFF; - if (I_INPCK(tty)) - info->read_status_mask |= STMFRAMEH | STMPARITYH; - if (I_BRKINT(tty) || I_PARMRK(tty)) - info->read_status_mask |= STMBREAKH; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(tty)) - info->ignore_status_mask |= STMFRAMEH | STMPARITYH; - if (I_IGNBRK(tty)) { - info->ignore_status_mask |= STMBREAKH; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too. (For real raw support). - */ - if (I_IGNPAR(tty)) - info->ignore_status_mask |= STMRCVROVRH; - } - - rocketMode = info->flags & ROCKET_MODE_MASK; - - if ((info->flags & ROCKET_RTS_TOGGLE) - || (rocketMode == ROCKET_MODE_RS485)) - sEnRTSToggle(cp); - else - sDisRTSToggle(cp); - - sSetRTS(&info->channel); - - if (cp->CtlP->boardType == ROCKET_TYPE_PC104) { - switch (rocketMode) { - case ROCKET_MODE_RS485: - sSetInterfaceMode(cp, InterfaceModeRS485); - break; - case ROCKET_MODE_RS422: - sSetInterfaceMode(cp, InterfaceModeRS422); - break; - case ROCKET_MODE_RS232: - default: - if (info->flags & ROCKET_RTS_TOGGLE) - sSetInterfaceMode(cp, InterfaceModeRS232T); - else - sSetInterfaceMode(cp, InterfaceModeRS232); - break; - } - } -} - -static int carrier_raised(struct tty_port *port) -{ - struct r_port *info = container_of(port, struct r_port, port); - return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; -} - -static void dtr_rts(struct tty_port *port, int on) -{ - struct r_port *info = container_of(port, struct r_port, port); - if (on) { - sSetDTR(&info->channel); - sSetRTS(&info->channel); - } else { - sClrDTR(&info->channel); - sClrRTS(&info->channel); - } -} - -/* - * Exception handler that opens a serial port. Creates xmit_buf storage, fills in - * port's r_port struct. Initializes the port hardware. - */ -static int rp_open(struct tty_struct *tty, struct file *filp) -{ - struct r_port *info; - struct tty_port *port; - int line = 0, retval; - CHANNEL_t *cp; - unsigned long page; - - line = tty->index; - if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL)) - return -ENXIO; - port = &info->port; - - page = __get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - if (port->flags & ASYNC_CLOSING) { - retval = wait_for_completion_interruptible(&info->close_wait); - free_page(page); - if (retval) - return retval; - return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); - } - - /* - * We must not sleep from here until the port is marked fully in use. - */ - if (info->xmit_buf) - free_page(page); - else - info->xmit_buf = (unsigned char *) page; - - tty->driver_data = info; - tty_port_tty_set(port, tty); - - if (port->count++ == 0) { - atomic_inc(&rp_num_ports_open); - -#ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "rocket mod++ = %d...\n", - atomic_read(&rp_num_ports_open)); -#endif - } -#ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count); -#endif - - /* - * Info->count is now 1; so it's safe to sleep now. - */ - if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { - cp = &info->channel; - sSetRxTrigger(cp, TRIG_1); - if (sGetChanStatus(cp) & CD_ACT) - info->cd_status = 1; - else - info->cd_status = 0; - sDisRxStatusMode(cp); - sFlushRxFIFO(cp); - sFlushTxFIFO(cp); - - sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN)); - sSetRxTrigger(cp, TRIG_1); - - sGetChanStatus(cp); - sDisRxStatusMode(cp); - sClrTxXOFF(cp); - - sDisCTSFlowCtl(cp); - sDisTxSoftFlowCtl(cp); - - sEnRxFIFO(cp); - sEnTransmit(cp); - - set_bit(ASYNCB_INITIALIZED, &info->port.flags); - - /* - * Set up the tty->alt_speed kludge - */ - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) - tty->alt_speed = 57600; - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) - tty->alt_speed = 115200; - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) - tty->alt_speed = 230400; - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) - tty->alt_speed = 460800; - - configure_r_port(tty, info, NULL); - if (tty->termios->c_cflag & CBAUD) { - sSetDTR(cp); - sSetRTS(cp); - } - } - /* Starts (or resets) the maint polling loop */ - mod_timer(&rocket_timer, jiffies + POLL_PERIOD); - - retval = tty_port_block_til_ready(port, tty, filp); - if (retval) { -#ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval); -#endif - return retval; - } - return 0; -} - -/* - * Exception handler that closes a serial port. info->port.count is considered critical. - */ -static void rp_close(struct tty_struct *tty, struct file *filp) -{ - struct r_port *info = tty->driver_data; - struct tty_port *port = &info->port; - int timeout; - CHANNEL_t *cp; - - if (rocket_paranoia_check(info, "rp_close")) - return; - -#ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count); -#endif - - if (tty_port_close_start(port, tty, filp) == 0) - return; - - mutex_lock(&port->mutex); - cp = &info->channel; - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps; - if (timeout == 0) - timeout = 1; - rp_wait_until_sent(tty, timeout); - clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - - sDisTransmit(cp); - sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN)); - sDisCTSFlowCtl(cp); - sDisTxSoftFlowCtl(cp); - sClrTxXOFF(cp); - sFlushRxFIFO(cp); - sFlushTxFIFO(cp); - sClrRTS(cp); - if (C_HUPCL(tty)) - sClrDTR(cp); - - rp_flush_buffer(tty); - - tty_ldisc_flush(tty); - - clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - - /* We can't yet use tty_port_close_end as the buffer handling in this - driver is a bit different to the usual */ - - if (port->blocked_open) { - if (port->close_delay) { - msleep_interruptible(jiffies_to_msecs(port->close_delay)); - } - wake_up_interruptible(&port->open_wait); - } else { - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = NULL; - } - } - spin_lock_irq(&port->lock); - info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); - tty->closing = 0; - spin_unlock_irq(&port->lock); - mutex_unlock(&port->mutex); - tty_port_tty_set(port, NULL); - - wake_up_interruptible(&port->close_wait); - complete_all(&info->close_wait); - atomic_dec(&rp_num_ports_open); - -#ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "rocket mod-- = %d...\n", - atomic_read(&rp_num_ports_open)); - printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line); -#endif - -} - -static void rp_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - unsigned cflag; - - if (rocket_paranoia_check(info, "rp_set_termios")) - return; - - cflag = tty->termios->c_cflag; - - /* - * This driver doesn't support CS5 or CS6 - */ - if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6)) - tty->termios->c_cflag = - ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE)); - /* Or CMSPAR */ - tty->termios->c_cflag &= ~CMSPAR; - - configure_r_port(tty, info, old_termios); - - cp = &info->channel; - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) { - sClrDTR(cp); - sClrRTS(cp); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) { - if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS)) - sSetRTS(cp); - sSetDTR(cp); - } - - if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rp_start(tty); - } -} - -static int rp_break(struct tty_struct *tty, int break_state) -{ - struct r_port *info = tty->driver_data; - unsigned long flags; - - if (rocket_paranoia_check(info, "rp_break")) - return -EINVAL; - - spin_lock_irqsave(&info->slock, flags); - if (break_state == -1) - sSendBreak(&info->channel); - else - sClrBreak(&info->channel); - spin_unlock_irqrestore(&info->slock, flags); - return 0; -} - -/* - * sGetChanRI used to be a macro in rocket_int.h. When the functionality for - * the UPCI boards was added, it was decided to make this a function because - * the macro was getting too complicated. All cases except the first one - * (UPCIRingInd) are taken directly from the original macro. - */ -static int sGetChanRI(CHANNEL_T * ChP) -{ - CONTROLLER_t *CtlP = ChP->CtlP; - int ChanNum = ChP->ChanNum; - int RingInd = 0; - - if (CtlP->UPCIRingInd) - RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]); - else if (CtlP->AltChanRingIndicator) - RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT; - else if (CtlP->boardType == ROCKET_TYPE_PC104) - RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]); - - return RingInd; -} - -/********************************************************************************************/ -/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */ - -/* - * Returns the state of the serial modem control lines. These next 2 functions - * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs. - */ -static int rp_tiocmget(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - unsigned int control, result, ChanStatus; - - ChanStatus = sGetChanStatusLo(&info->channel); - control = info->channel.TxControl[3]; - result = ((control & SET_RTS) ? TIOCM_RTS : 0) | - ((control & SET_DTR) ? TIOCM_DTR : 0) | - ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) | - (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) | - ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) | - ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0); - - return result; -} - -/* - * Sets the modem control lines - */ -static int rp_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct r_port *info = tty->driver_data; - - if (set & TIOCM_RTS) - info->channel.TxControl[3] |= SET_RTS; - if (set & TIOCM_DTR) - info->channel.TxControl[3] |= SET_DTR; - if (clear & TIOCM_RTS) - info->channel.TxControl[3] &= ~SET_RTS; - if (clear & TIOCM_DTR) - info->channel.TxControl[3] &= ~SET_DTR; - - out32(info->channel.IndexAddr, info->channel.TxControl); - return 0; -} - -static int get_config(struct r_port *info, struct rocket_config __user *retinfo) -{ - struct rocket_config tmp; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof (tmp)); - mutex_lock(&info->port.mutex); - tmp.line = info->line; - tmp.flags = info->flags; - tmp.close_delay = info->port.close_delay; - tmp.closing_wait = info->port.closing_wait; - tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; - mutex_unlock(&info->port.mutex); - - if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) - return -EFAULT; - return 0; -} - -static int set_config(struct tty_struct *tty, struct r_port *info, - struct rocket_config __user *new_info) -{ - struct rocket_config new_serial; - - if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) - return -EFAULT; - - mutex_lock(&info->port.mutex); - if (!capable(CAP_SYS_ADMIN)) - { - if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) { - mutex_unlock(&info->port.mutex); - return -EPERM; - } - info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); - configure_r_port(tty, info, NULL); - mutex_unlock(&info->port.mutex); - return 0; - } - - info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS)); - info->port.close_delay = new_serial.close_delay; - info->port.closing_wait = new_serial.closing_wait; - - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) - tty->alt_speed = 57600; - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) - tty->alt_speed = 115200; - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) - tty->alt_speed = 230400; - if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) - tty->alt_speed = 460800; - mutex_unlock(&info->port.mutex); - - configure_r_port(tty, info, NULL); - return 0; -} - -/* - * This function fills in a rocket_ports struct with information - * about what boards/ports are in the system. This info is passed - * to user space. See setrocket.c where the info is used to create - * the /dev/ttyRx ports. - */ -static int get_ports(struct r_port *info, struct rocket_ports __user *retports) -{ - struct rocket_ports tmp; - int board; - - if (!retports) - return -EFAULT; - memset(&tmp, 0, sizeof (tmp)); - tmp.tty_major = rocket_driver->major; - - for (board = 0; board < 4; board++) { - tmp.rocketModel[board].model = rocketModel[board].model; - strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString); - tmp.rocketModel[board].numPorts = rocketModel[board].numPorts; - tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2; - tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber; - } - if (copy_to_user(retports, &tmp, sizeof (*retports))) - return -EFAULT; - return 0; -} - -static int reset_rm2(struct r_port *info, void __user *arg) -{ - int reset; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&reset, arg, sizeof (int))) - return -EFAULT; - if (reset) - reset = 1; - - if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII && - rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII) - return -EINVAL; - - if (info->ctlp->BusType == isISA) - sModemReset(info->ctlp, info->chan, reset); - else - sPCIModemReset(info->ctlp, info->chan, reset); - - return 0; -} - -static int get_version(struct r_port *info, struct rocket_version __user *retvers) -{ - if (copy_to_user(retvers, &driver_version, sizeof (*retvers))) - return -EFAULT; - return 0; -} - -/* IOCTL call handler into the driver */ -static int rp_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct r_port *info = tty->driver_data; - void __user *argp = (void __user *)arg; - int ret = 0; - - if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) - return -ENXIO; - - switch (cmd) { - case RCKP_GET_STRUCT: - if (copy_to_user(argp, info, sizeof (struct r_port))) - ret = -EFAULT; - break; - case RCKP_GET_CONFIG: - ret = get_config(info, argp); - break; - case RCKP_SET_CONFIG: - ret = set_config(tty, info, argp); - break; - case RCKP_GET_PORTS: - ret = get_ports(info, argp); - break; - case RCKP_RESET_RM2: - ret = reset_rm2(info, argp); - break; - case RCKP_GET_VERSION: - ret = get_version(info, argp); - break; - default: - ret = -ENOIOCTLCMD; - } - return ret; -} - -static void rp_send_xchar(struct tty_struct *tty, char ch) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - - if (rocket_paranoia_check(info, "rp_send_xchar")) - return; - - cp = &info->channel; - if (sGetTxCnt(cp)) - sWriteTxPrioByte(cp, ch); - else - sWriteTxByte(sGetTxRxDataIO(cp), ch); -} - -static void rp_throttle(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - -#ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "throttle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (rocket_paranoia_check(info, "rp_throttle")) - return; - - cp = &info->channel; - if (I_IXOFF(tty)) - rp_send_xchar(tty, STOP_CHAR(tty)); - - sClrRTS(&info->channel); -} - -static void rp_unthrottle(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; -#ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (rocket_paranoia_check(info, "rp_throttle")) - return; - - cp = &info->channel; - if (I_IXOFF(tty)) - rp_send_xchar(tty, START_CHAR(tty)); - - sSetRTS(&info->channel); -} - -/* - * ------------------------------------------------------------ - * rp_stop() and rp_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rp_stop(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - -#ifdef ROCKET_DEBUG_FLOW - printk(KERN_INFO "stop %s: %d %d....\n", tty->name, - info->xmit_cnt, info->xmit_fifo_room); -#endif - - if (rocket_paranoia_check(info, "rp_stop")) - return; - - if (sGetTxCnt(&info->channel)) - sDisTransmit(&info->channel); -} - -static void rp_start(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - -#ifdef ROCKET_DEBUG_FLOW - printk(KERN_INFO "start %s: %d %d....\n", tty->name, - info->xmit_cnt, info->xmit_fifo_room); -#endif - - if (rocket_paranoia_check(info, "rp_stop")) - return; - - sEnTransmit(&info->channel); - set_bit((info->aiop * 8) + info->chan, - (void *) &xmit_flags[info->board]); -} - -/* - * rp_wait_until_sent() --- wait until the transmitter is empty - */ -static void rp_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - unsigned long orig_jiffies; - int check_time, exit_time; - int txcnt; - - if (rocket_paranoia_check(info, "rp_wait_until_sent")) - return; - - cp = &info->channel; - - orig_jiffies = jiffies; -#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT - printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout, - jiffies); - printk(KERN_INFO "cps=%d...\n", info->cps); -#endif - while (1) { - txcnt = sGetTxCnt(cp); - if (!txcnt) { - if (sGetChanStatusLo(cp) & TXSHRMT) - break; - check_time = (HZ / info->cps) / 5; - } else { - check_time = HZ * txcnt / info->cps; - } - if (timeout) { - exit_time = orig_jiffies + timeout - jiffies; - if (exit_time <= 0) - break; - if (exit_time < check_time) - check_time = exit_time; - } - if (check_time == 0) - check_time = 1; -#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT - printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt, - jiffies, check_time); -#endif - msleep_interruptible(jiffies_to_msecs(check_time)); - if (signal_pending(current)) - break; - } - __set_current_state(TASK_RUNNING); -#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT - printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); -#endif -} - -/* - * rp_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void rp_hangup(struct tty_struct *tty) -{ - CHANNEL_t *cp; - struct r_port *info = tty->driver_data; - unsigned long flags; - - if (rocket_paranoia_check(info, "rp_hangup")) - return; - -#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP)) - printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); -#endif - rp_flush_buffer(tty); - spin_lock_irqsave(&info->port.lock, flags); - if (info->port.flags & ASYNC_CLOSING) { - spin_unlock_irqrestore(&info->port.lock, flags); - return; - } - if (info->port.count) - atomic_dec(&rp_num_ports_open); - clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - spin_unlock_irqrestore(&info->port.lock, flags); - - tty_port_hangup(&info->port); - - cp = &info->channel; - sDisRxFIFO(cp); - sDisTransmit(cp); - sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN)); - sDisCTSFlowCtl(cp); - sDisTxSoftFlowCtl(cp); - sClrTxXOFF(cp); - clear_bit(ASYNCB_INITIALIZED, &info->port.flags); - - wake_up_interruptible(&info->port.open_wait); -} - -/* - * Exception handler - write char routine. The RocketPort driver uses a - * double-buffering strategy, with the twist that if the in-memory CPU - * buffer is empty, and there's space in the transmit FIFO, the - * writing routines will write directly to transmit FIFO. - * Write buffer and counters protected by spinlocks - */ -static int rp_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - unsigned long flags; - - if (rocket_paranoia_check(info, "rp_put_char")) - return 0; - - /* - * Grab the port write mutex, locking out other processes that try to - * write to this port - */ - mutex_lock(&info->write_mtx); - -#ifdef ROCKET_DEBUG_WRITE - printk(KERN_INFO "rp_put_char %c...\n", ch); -#endif - - spin_lock_irqsave(&info->slock, flags); - cp = &info->channel; - - if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0) - info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - - if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) { - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= XMIT_BUF_SIZE - 1; - info->xmit_cnt++; - set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - } else { - sOutB(sGetTxRxDataIO(cp), ch); - info->xmit_fifo_room--; - } - spin_unlock_irqrestore(&info->slock, flags); - mutex_unlock(&info->write_mtx); - return 1; -} - -/* - * Exception handler - write routine, called when user app writes to the device. - * A per port write mutex is used to protect from another process writing to - * this port at the same time. This other process could be running on the other CPU - * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). - * Spinlocks protect the info xmit members. - */ -static int rp_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - const unsigned char *b; - int c, retval = 0; - unsigned long flags; - - if (count <= 0 || rocket_paranoia_check(info, "rp_write")) - return 0; - - if (mutex_lock_interruptible(&info->write_mtx)) - return -ERESTARTSYS; - -#ifdef ROCKET_DEBUG_WRITE - printk(KERN_INFO "rp_write %d chars...\n", count); -#endif - cp = &info->channel; - - if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count) - info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - - /* - * If the write queue for the port is empty, and there is FIFO space, stuff bytes - * into FIFO. Use the write queue for temp storage. - */ - if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) { - c = min(count, info->xmit_fifo_room); - b = buf; - - /* Push data into FIFO, 2 bytes at a time */ - sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2); - - /* If there is a byte remaining, write it */ - if (c & 1) - sOutB(sGetTxRxDataIO(cp), b[c - 1]); - - retval += c; - buf += c; - count -= c; - - spin_lock_irqsave(&info->slock, flags); - info->xmit_fifo_room -= c; - spin_unlock_irqrestore(&info->slock, flags); - } - - /* If count is zero, we wrote it all and are done */ - if (!count) - goto end; - - /* Write remaining data into the port's xmit_buf */ - while (1) { - /* Hung up ? */ - if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags)) - goto end; - c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); - c = min(c, XMIT_BUF_SIZE - info->xmit_head); - if (c <= 0) - break; - - b = buf; - memcpy(info->xmit_buf + info->xmit_head, b, c); - - spin_lock_irqsave(&info->slock, flags); - info->xmit_head = - (info->xmit_head + c) & (XMIT_BUF_SIZE - 1); - info->xmit_cnt += c; - spin_unlock_irqrestore(&info->slock, flags); - - buf += c; - count -= c; - retval += c; - } - - if ((retval > 0) && !tty->stopped && !tty->hw_stopped) - set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); - -end: - if (info->xmit_cnt < WAKEUP_CHARS) { - tty_wakeup(tty); -#ifdef ROCKETPORT_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - } - mutex_unlock(&info->write_mtx); - return retval; -} - -/* - * Return the number of characters that can be sent. We estimate - * only using the in-memory transmit buffer only, and ignore the - * potential space in the transmit FIFO. - */ -static int rp_write_room(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - int ret; - - if (rocket_paranoia_check(info, "rp_write_room")) - return 0; - - ret = XMIT_BUF_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; -#ifdef ROCKET_DEBUG_WRITE - printk(KERN_INFO "rp_write_room returns %d...\n", ret); -#endif - return ret; -} - -/* - * Return the number of characters in the buffer. Again, this only - * counts those characters in the in-memory transmit buffer. - */ -static int rp_chars_in_buffer(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - - if (rocket_paranoia_check(info, "rp_chars_in_buffer")) - return 0; - - cp = &info->channel; - -#ifdef ROCKET_DEBUG_WRITE - printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt); -#endif - return info->xmit_cnt; -} - -/* - * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the - * r_port struct for the port. Note that spinlock are used to protect info members, - * do not call this function if the spinlock is already held. - */ -static void rp_flush_buffer(struct tty_struct *tty) -{ - struct r_port *info = tty->driver_data; - CHANNEL_t *cp; - unsigned long flags; - - if (rocket_paranoia_check(info, "rp_flush_buffer")) - return; - - spin_lock_irqsave(&info->slock, flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - spin_unlock_irqrestore(&info->slock, flags); - -#ifdef ROCKETPORT_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - tty_wakeup(tty); - - cp = &info->channel; - sFlushTxFIFO(cp); -} - -#ifdef CONFIG_PCI - -static struct pci_device_id __devinitdata __used rocket_pci_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) }, - { } -}; -MODULE_DEVICE_TABLE(pci, rocket_pci_ids); - -/* - * Called when a PCI card is found. Retrieves and stores model information, - * init's aiopic and serial port hardware. - * Inputs: i is the board number (0-n) - */ -static __init int register_PCI(int i, struct pci_dev *dev) -{ - int num_aiops, aiop, max_num_aiops, num_chan, chan; - unsigned int aiopio[MAX_AIOPS_PER_BOARD]; - char *str, *board_type; - CONTROLLER_t *ctlp; - - int fast_clock = 0; - int altChanRingIndicator = 0; - int ports_per_aiop = 8; - WordIO_t ConfigIO = 0; - ByteIO_t UPCIRingInd = 0; - - if (!dev || pci_enable_device(dev)) - return 0; - - rcktpt_io_addr[i] = pci_resource_start(dev, 0); - - rcktpt_type[i] = ROCKET_TYPE_NORMAL; - rocketModel[i].loadrm2 = 0; - rocketModel[i].startingPortNumber = nextLineNumber; - - /* Depending on the model, set up some config variables */ - switch (dev->device) { - case PCI_DEVICE_ID_RP4QUAD: - str = "Quadcable"; - max_num_aiops = 1; - ports_per_aiop = 4; - rocketModel[i].model = MODEL_RP4QUAD; - strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable"); - rocketModel[i].numPorts = 4; - break; - case PCI_DEVICE_ID_RP8OCTA: - str = "Octacable"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_RP8OCTA; - strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_URP8OCTA: - str = "Octacable"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_UPCI_RP8OCTA; - strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_RP8INTF: - str = "8"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_RP8INTF; - strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_URP8INTF: - str = "8"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_UPCI_RP8INTF; - strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_RP8J: - str = "8J"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_RP8J; - strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_RP4J: - str = "4J"; - max_num_aiops = 1; - ports_per_aiop = 4; - rocketModel[i].model = MODEL_RP4J; - strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors"); - rocketModel[i].numPorts = 4; - break; - case PCI_DEVICE_ID_RP8SNI: - str = "8 (DB78 Custom)"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_RP8SNI; - strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_RP16SNI: - str = "16 (DB78 Custom)"; - max_num_aiops = 2; - rocketModel[i].model = MODEL_RP16SNI; - strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78"); - rocketModel[i].numPorts = 16; - break; - case PCI_DEVICE_ID_RP16INTF: - str = "16"; - max_num_aiops = 2; - rocketModel[i].model = MODEL_RP16INTF; - strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F"); - rocketModel[i].numPorts = 16; - break; - case PCI_DEVICE_ID_URP16INTF: - str = "16"; - max_num_aiops = 2; - rocketModel[i].model = MODEL_UPCI_RP16INTF; - strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F"); - rocketModel[i].numPorts = 16; - break; - case PCI_DEVICE_ID_CRP16INTF: - str = "16"; - max_num_aiops = 2; - rocketModel[i].model = MODEL_CPCI_RP16INTF; - strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F"); - rocketModel[i].numPorts = 16; - break; - case PCI_DEVICE_ID_RP32INTF: - str = "32"; - max_num_aiops = 4; - rocketModel[i].model = MODEL_RP32INTF; - strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F"); - rocketModel[i].numPorts = 32; - break; - case PCI_DEVICE_ID_URP32INTF: - str = "32"; - max_num_aiops = 4; - rocketModel[i].model = MODEL_UPCI_RP32INTF; - strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F"); - rocketModel[i].numPorts = 32; - break; - case PCI_DEVICE_ID_RPP4: - str = "Plus Quadcable"; - max_num_aiops = 1; - ports_per_aiop = 4; - altChanRingIndicator++; - fast_clock++; - rocketModel[i].model = MODEL_RPP4; - strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port"); - rocketModel[i].numPorts = 4; - break; - case PCI_DEVICE_ID_RPP8: - str = "Plus Octacable"; - max_num_aiops = 2; - ports_per_aiop = 4; - altChanRingIndicator++; - fast_clock++; - rocketModel[i].model = MODEL_RPP8; - strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port"); - rocketModel[i].numPorts = 8; - break; - case PCI_DEVICE_ID_RP2_232: - str = "Plus 2 (RS-232)"; - max_num_aiops = 1; - ports_per_aiop = 2; - altChanRingIndicator++; - fast_clock++; - rocketModel[i].model = MODEL_RP2_232; - strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232"); - rocketModel[i].numPorts = 2; - break; - case PCI_DEVICE_ID_RP2_422: - str = "Plus 2 (RS-422)"; - max_num_aiops = 1; - ports_per_aiop = 2; - altChanRingIndicator++; - fast_clock++; - rocketModel[i].model = MODEL_RP2_422; - strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422"); - rocketModel[i].numPorts = 2; - break; - case PCI_DEVICE_ID_RP6M: - - max_num_aiops = 1; - ports_per_aiop = 6; - str = "6-port"; - - /* If revision is 1, the rocketmodem flash must be loaded. - * If it is 2 it is a "socketed" version. */ - if (dev->revision == 1) { - rcktpt_type[i] = ROCKET_TYPE_MODEMII; - rocketModel[i].loadrm2 = 1; - } else { - rcktpt_type[i] = ROCKET_TYPE_MODEM; - } - - rocketModel[i].model = MODEL_RP6M; - strcpy(rocketModel[i].modelString, "RocketModem 6 port"); - rocketModel[i].numPorts = 6; - break; - case PCI_DEVICE_ID_RP4M: - max_num_aiops = 1; - ports_per_aiop = 4; - str = "4-port"; - if (dev->revision == 1) { - rcktpt_type[i] = ROCKET_TYPE_MODEMII; - rocketModel[i].loadrm2 = 1; - } else { - rcktpt_type[i] = ROCKET_TYPE_MODEM; - } - - rocketModel[i].model = MODEL_RP4M; - strcpy(rocketModel[i].modelString, "RocketModem 4 port"); - rocketModel[i].numPorts = 4; - break; - default: - str = "(unknown/unsupported)"; - max_num_aiops = 0; - break; - } - - /* - * Check for UPCI boards. - */ - - switch (dev->device) { - case PCI_DEVICE_ID_URP32INTF: - case PCI_DEVICE_ID_URP8INTF: - case PCI_DEVICE_ID_URP16INTF: - case PCI_DEVICE_ID_CRP16INTF: - case PCI_DEVICE_ID_URP8OCTA: - rcktpt_io_addr[i] = pci_resource_start(dev, 2); - ConfigIO = pci_resource_start(dev, 1); - if (dev->device == PCI_DEVICE_ID_URP8OCTA) { - UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND; - - /* - * Check for octa or quad cable. - */ - if (! - (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) & - PCI_GPIO_CTRL_8PORT)) { - str = "Quadcable"; - ports_per_aiop = 4; - rocketModel[i].numPorts = 4; - } - } - break; - case PCI_DEVICE_ID_UPCI_RM3_8PORT: - str = "8 ports"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_UPCI_RM3_8PORT; - strcpy(rocketModel[i].modelString, "RocketModem III 8 port"); - rocketModel[i].numPorts = 8; - rcktpt_io_addr[i] = pci_resource_start(dev, 2); - UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND; - ConfigIO = pci_resource_start(dev, 1); - rcktpt_type[i] = ROCKET_TYPE_MODEMIII; - break; - case PCI_DEVICE_ID_UPCI_RM3_4PORT: - str = "4 ports"; - max_num_aiops = 1; - rocketModel[i].model = MODEL_UPCI_RM3_4PORT; - strcpy(rocketModel[i].modelString, "RocketModem III 4 port"); - rocketModel[i].numPorts = 4; - rcktpt_io_addr[i] = pci_resource_start(dev, 2); - UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND; - ConfigIO = pci_resource_start(dev, 1); - rcktpt_type[i] = ROCKET_TYPE_MODEMIII; - break; - default: - break; - } - - switch (rcktpt_type[i]) { - case ROCKET_TYPE_MODEM: - board_type = "RocketModem"; - break; - case ROCKET_TYPE_MODEMII: - board_type = "RocketModem II"; - break; - case ROCKET_TYPE_MODEMIII: - board_type = "RocketModem III"; - break; - default: - board_type = "RocketPort"; - break; - } - - if (fast_clock) { - sClockPrescale = 0x12; /* mod 2 (divide by 3) */ - rp_baud_base[i] = 921600; - } else { - /* - * If support_low_speed is set, use the slow clock - * prescale, which supports 50 bps - */ - if (support_low_speed) { - /* mod 9 (divide by 10) prescale */ - sClockPrescale = 0x19; - rp_baud_base[i] = 230400; - } else { - /* mod 4 (devide by 5) prescale */ - sClockPrescale = 0x14; - rp_baud_base[i] = 460800; - } - } - - for (aiop = 0; aiop < max_num_aiops; aiop++) - aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40); - ctlp = sCtlNumToCtlPtr(i); - num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd); - for (aiop = 0; aiop < max_num_aiops; aiop++) - ctlp->AiopNumChan[aiop] = ports_per_aiop; - - dev_info(&dev->dev, "comtrol PCI controller #%d found at " - "address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n", - i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString, - rocketModel[i].startingPortNumber, - rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1); - - if (num_aiops <= 0) { - rcktpt_io_addr[i] = 0; - return (0); - } - is_PCI[i] = 1; - - /* Reset the AIOPIC, init the serial ports */ - for (aiop = 0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - num_chan = ports_per_aiop; - for (chan = 0; chan < num_chan; chan++) - init_r_port(i, aiop, chan, dev); - } - - /* Rocket modems must be reset */ - if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || - (rcktpt_type[i] == ROCKET_TYPE_MODEMII) || - (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) { - num_chan = ports_per_aiop; - for (chan = 0; chan < num_chan; chan++) - sPCIModemReset(ctlp, chan, 1); - msleep(500); - for (chan = 0; chan < num_chan; chan++) - sPCIModemReset(ctlp, chan, 0); - msleep(500); - rmSpeakerReset(ctlp, rocketModel[i].model); - } - return (1); -} - -/* - * Probes for PCI cards, inits them if found - * Input: board_found = number of ISA boards already found, or the - * starting board number - * Returns: Number of PCI boards found - */ -static int __init init_PCI(int boards_found) -{ - struct pci_dev *dev = NULL; - int count = 0; - - /* Work through the PCI device list, pulling out ours */ - while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { - if (register_PCI(count + boards_found, dev)) - count++; - } - return (count); -} - -#endif /* CONFIG_PCI */ - -/* - * Probes for ISA cards - * Input: i = the board number to look for - * Returns: 1 if board found, 0 else - */ -static int __init init_ISA(int i) -{ - int num_aiops, num_chan = 0, total_num_chan = 0; - int aiop, chan; - unsigned int aiopio[MAX_AIOPS_PER_BOARD]; - CONTROLLER_t *ctlp; - char *type_string; - - /* If io_addr is zero, no board configured */ - if (rcktpt_io_addr[i] == 0) - return (0); - - /* Reserve the IO region */ - if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) { - printk(KERN_ERR "Unable to reserve IO region for configured " - "ISA RocketPort at address 0x%lx, board not " - "installed...\n", rcktpt_io_addr[i]); - rcktpt_io_addr[i] = 0; - return (0); - } - - ctlp = sCtlNumToCtlPtr(i); - - ctlp->boardType = rcktpt_type[i]; - - switch (rcktpt_type[i]) { - case ROCKET_TYPE_PC104: - type_string = "(PC104)"; - break; - case ROCKET_TYPE_MODEM: - type_string = "(RocketModem)"; - break; - case ROCKET_TYPE_MODEMII: - type_string = "(RocketModem II)"; - break; - default: - type_string = ""; - break; - } - - /* - * If support_low_speed is set, use the slow clock prescale, - * which supports 50 bps - */ - if (support_low_speed) { - sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */ - rp_baud_base[i] = 230400; - } else { - sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */ - rp_baud_base[i] = 460800; - } - - for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++) - aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400); - - num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0); - - if (ctlp->boardType == ROCKET_TYPE_PC104) { - sEnAiop(ctlp, 2); /* only one AIOPIC, but these */ - sEnAiop(ctlp, 3); /* CSels used for other stuff */ - } - - /* If something went wrong initing the AIOP's release the ISA IO memory */ - if (num_aiops <= 0) { - release_region(rcktpt_io_addr[i], 64); - rcktpt_io_addr[i] = 0; - return (0); - } - - rocketModel[i].startingPortNumber = nextLineNumber; - - for (aiop = 0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - sEnAiop(ctlp, aiop); - num_chan = sGetAiopNumChan(ctlp, aiop); - total_num_chan += num_chan; - for (chan = 0; chan < num_chan; chan++) - init_r_port(i, aiop, chan, NULL); - } - is_PCI[i] = 0; - if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) { - num_chan = sGetAiopNumChan(ctlp, 0); - total_num_chan = num_chan; - for (chan = 0; chan < num_chan; chan++) - sModemReset(ctlp, chan, 1); - msleep(500); - for (chan = 0; chan < num_chan; chan++) - sModemReset(ctlp, chan, 0); - msleep(500); - strcpy(rocketModel[i].modelString, "RocketModem ISA"); - } else { - strcpy(rocketModel[i].modelString, "RocketPort ISA"); - } - rocketModel[i].numPorts = total_num_chan; - rocketModel[i].model = MODEL_ISA; - - printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n", - i, rcktpt_io_addr[i], num_aiops, type_string); - - printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n", - rocketModel[i].modelString, - rocketModel[i].startingPortNumber, - rocketModel[i].startingPortNumber + - rocketModel[i].numPorts - 1); - - return (1); -} - -static const struct tty_operations rocket_ops = { - .open = rp_open, - .close = rp_close, - .write = rp_write, - .put_char = rp_put_char, - .write_room = rp_write_room, - .chars_in_buffer = rp_chars_in_buffer, - .flush_buffer = rp_flush_buffer, - .ioctl = rp_ioctl, - .throttle = rp_throttle, - .unthrottle = rp_unthrottle, - .set_termios = rp_set_termios, - .stop = rp_stop, - .start = rp_start, - .hangup = rp_hangup, - .break_ctl = rp_break, - .send_xchar = rp_send_xchar, - .wait_until_sent = rp_wait_until_sent, - .tiocmget = rp_tiocmget, - .tiocmset = rp_tiocmset, -}; - -static const struct tty_port_operations rocket_port_ops = { - .carrier_raised = carrier_raised, - .dtr_rts = dtr_rts, -}; - -/* - * The module "startup" routine; it's run when the module is loaded. - */ -static int __init rp_init(void) -{ - int ret = -ENOMEM, pci_boards_found, isa_boards_found, i; - - printk(KERN_INFO "RocketPort device driver module, version %s, %s\n", - ROCKET_VERSION, ROCKET_DATE); - - rocket_driver = alloc_tty_driver(MAX_RP_PORTS); - if (!rocket_driver) - goto err; - - /* - * If board 1 is non-zero, there is at least one ISA configured. If controller is - * zero, use the default controller IO address of board1 + 0x40. - */ - if (board1) { - if (controller == 0) - controller = board1 + 0x40; - } else { - controller = 0; /* Used as a flag, meaning no ISA boards */ - } - - /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */ - if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) { - printk(KERN_ERR "Unable to reserve IO region for first " - "configured ISA RocketPort controller 0x%lx. " - "Driver exiting\n", controller); - ret = -EBUSY; - goto err_tty; - } - - /* Store ISA variable retrieved from command line or .conf file. */ - rcktpt_io_addr[0] = board1; - rcktpt_io_addr[1] = board2; - rcktpt_io_addr[2] = board3; - rcktpt_io_addr[3] = board4; - - rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; - rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0]; - rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; - rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1]; - rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; - rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2]; - rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; - rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3]; - - /* - * Set up the tty driver structure and then register this - * driver with the tty layer. - */ - - rocket_driver->owner = THIS_MODULE; - rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV; - rocket_driver->name = "ttyR"; - rocket_driver->driver_name = "Comtrol RocketPort"; - rocket_driver->major = TTY_ROCKET_MAJOR; - rocket_driver->minor_start = 0; - rocket_driver->type = TTY_DRIVER_TYPE_SERIAL; - rocket_driver->subtype = SERIAL_TYPE_NORMAL; - rocket_driver->init_termios = tty_std_termios; - rocket_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - rocket_driver->init_termios.c_ispeed = 9600; - rocket_driver->init_termios.c_ospeed = 9600; -#ifdef ROCKET_SOFT_FLOW - rocket_driver->flags |= TTY_DRIVER_REAL_RAW; -#endif - tty_set_operations(rocket_driver, &rocket_ops); - - ret = tty_register_driver(rocket_driver); - if (ret < 0) { - printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); - goto err_controller; - } - -#ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major); -#endif - - /* - * OK, let's probe each of the controllers looking for boards. Any boards found - * will be initialized here. - */ - isa_boards_found = 0; - pci_boards_found = 0; - - for (i = 0; i < NUM_BOARDS; i++) { - if (init_ISA(i)) - isa_boards_found++; - } - -#ifdef CONFIG_PCI - if (isa_boards_found < NUM_BOARDS) - pci_boards_found = init_PCI(isa_boards_found); -#endif - - max_board = pci_boards_found + isa_boards_found; - - if (max_board == 0) { - printk(KERN_ERR "No rocketport ports found; unloading driver\n"); - ret = -ENXIO; - goto err_ttyu; - } - - return 0; -err_ttyu: - tty_unregister_driver(rocket_driver); -err_controller: - if (controller) - release_region(controller, 4); -err_tty: - put_tty_driver(rocket_driver); -err: - return ret; -} - - -static void rp_cleanup_module(void) -{ - int retval; - int i; - - del_timer_sync(&rocket_timer); - - retval = tty_unregister_driver(rocket_driver); - if (retval) - printk(KERN_ERR "Error %d while trying to unregister " - "rocketport driver\n", -retval); - - for (i = 0; i < MAX_RP_PORTS; i++) - if (rp_table[i]) { - tty_unregister_device(rocket_driver, i); - kfree(rp_table[i]); - } - - put_tty_driver(rocket_driver); - - for (i = 0; i < NUM_BOARDS; i++) { - if (rcktpt_io_addr[i] <= 0 || is_PCI[i]) - continue; - release_region(rcktpt_io_addr[i], 64); - } - if (controller) - release_region(controller, 4); -} - -/*************************************************************************** -Function: sInitController -Purpose: Initialization of controller global registers and controller - structure. -Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize, - IRQNum,Frequency,PeriodicOnly) - CONTROLLER_T *CtlP; Ptr to controller structure - int CtlNum; Controller number - ByteIO_t MudbacIO; Mudbac base I/O address. - ByteIO_t *AiopIOList; List of I/O addresses for each AIOP. - This list must be in the order the AIOPs will be found on the - controller. Once an AIOP in the list is not found, it is - assumed that there are no more AIOPs on the controller. - int AiopIOListSize; Number of addresses in AiopIOList - int IRQNum; Interrupt Request number. Can be any of the following: - 0: Disable global interrupts - 3: IRQ 3 - 4: IRQ 4 - 5: IRQ 5 - 9: IRQ 9 - 10: IRQ 10 - 11: IRQ 11 - 12: IRQ 12 - 15: IRQ 15 - Byte_t Frequency: A flag identifying the frequency - of the periodic interrupt, can be any one of the following: - FREQ_DIS - periodic interrupt disabled - FREQ_137HZ - 137 Hertz - FREQ_69HZ - 69 Hertz - FREQ_34HZ - 34 Hertz - FREQ_17HZ - 17 Hertz - FREQ_9HZ - 9 Hertz - FREQ_4HZ - 4 Hertz - If IRQNum is set to 0 the Frequency parameter is - overidden, it is forced to a value of FREQ_DIS. - int PeriodicOnly: 1 if all interrupts except the periodic - interrupt are to be blocked. - 0 is both the periodic interrupt and - other channel interrupts are allowed. - If IRQNum is set to 0 the PeriodicOnly parameter is - overidden, it is forced to a value of 0. -Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller - initialization failed. - -Comments: - If periodic interrupts are to be disabled but AIOP interrupts - are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0. - - If interrupts are to be completely disabled set IRQNum to 0. - - Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an - invalid combination. - - This function performs initialization of global interrupt modes, - but it does not actually enable global interrupts. To enable - and disable global interrupts use functions sEnGlobalInt() and - sDisGlobalInt(). Enabling of global interrupts is normally not - done until all other initializations are complete. - - Even if interrupts are globally enabled, they must also be - individually enabled for each channel that is to generate - interrupts. - -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. - - After this function all AIOPs on the controller are disabled, - they can be enabled with sEnAiop(). -*/ -static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, - ByteIO_t * AiopIOList, int AiopIOListSize, - int IRQNum, Byte_t Frequency, int PeriodicOnly) -{ - int i; - ByteIO_t io; - int done; - - CtlP->AiopIntrBits = aiop_intr_bits; - CtlP->AltChanRingIndicator = 0; - CtlP->CtlNum = CtlNum; - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - CtlP->BusType = isISA; - CtlP->MBaseIO = MudbacIO; - CtlP->MReg1IO = MudbacIO + 1; - CtlP->MReg2IO = MudbacIO + 2; - CtlP->MReg3IO = MudbacIO + 3; -#if 1 - CtlP->MReg2 = 0; /* interrupt disable */ - CtlP->MReg3 = 0; /* no periodic interrupts */ -#else - if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */ - CtlP->MReg2 = 0; /* interrupt disable */ - CtlP->MReg3 = 0; /* no periodic interrupts */ - } else { - CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ - CtlP->MReg3 = Frequency; /* set frequency */ - if (PeriodicOnly) { /* periodic interrupt only */ - CtlP->MReg3 |= PERIODIC_ONLY; - } - } -#endif - sOutB(CtlP->MReg2IO, CtlP->MReg2); - sOutB(CtlP->MReg3IO, CtlP->MReg3); - sControllerEOI(CtlP); /* clear EOI if warm init */ - /* Init AIOPs */ - CtlP->NumAiop = 0; - for (i = done = 0; i < AiopIOListSize; i++) { - io = AiopIOList[i]; - CtlP->AiopIO[i] = (WordIO_t) io; - CtlP->AiopIntChanIO[i] = io + _INT_CHAN; - sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */ - sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */ - if (done) - continue; - sEnAiop(CtlP, i); /* enable the AIOP */ - CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ - if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - done = 1; /* done looking for AIOPs */ - else { - CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */ - sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */ - sOutB(io + _INDX_DATA, sClockPrescale); - CtlP->NumAiop++; /* bump count of AIOPs */ - } - sDisAiop(CtlP, i); /* disable AIOP */ - } - - if (CtlP->NumAiop == 0) - return (-1); - else - return (CtlP->NumAiop); -} - -/*************************************************************************** -Function: sPCIInitController -Purpose: Initialization of controller global registers and controller - structure. -Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize, - IRQNum,Frequency,PeriodicOnly) - CONTROLLER_T *CtlP; Ptr to controller structure - int CtlNum; Controller number - ByteIO_t *AiopIOList; List of I/O addresses for each AIOP. - This list must be in the order the AIOPs will be found on the - controller. Once an AIOP in the list is not found, it is - assumed that there are no more AIOPs on the controller. - int AiopIOListSize; Number of addresses in AiopIOList - int IRQNum; Interrupt Request number. Can be any of the following: - 0: Disable global interrupts - 3: IRQ 3 - 4: IRQ 4 - 5: IRQ 5 - 9: IRQ 9 - 10: IRQ 10 - 11: IRQ 11 - 12: IRQ 12 - 15: IRQ 15 - Byte_t Frequency: A flag identifying the frequency - of the periodic interrupt, can be any one of the following: - FREQ_DIS - periodic interrupt disabled - FREQ_137HZ - 137 Hertz - FREQ_69HZ - 69 Hertz - FREQ_34HZ - 34 Hertz - FREQ_17HZ - 17 Hertz - FREQ_9HZ - 9 Hertz - FREQ_4HZ - 4 Hertz - If IRQNum is set to 0 the Frequency parameter is - overidden, it is forced to a value of FREQ_DIS. - int PeriodicOnly: 1 if all interrupts except the periodic - interrupt are to be blocked. - 0 is both the periodic interrupt and - other channel interrupts are allowed. - If IRQNum is set to 0 the PeriodicOnly parameter is - overidden, it is forced to a value of 0. -Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller - initialization failed. - -Comments: - If periodic interrupts are to be disabled but AIOP interrupts - are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0. - - If interrupts are to be completely disabled set IRQNum to 0. - - Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an - invalid combination. - - This function performs initialization of global interrupt modes, - but it does not actually enable global interrupts. To enable - and disable global interrupts use functions sEnGlobalInt() and - sDisGlobalInt(). Enabling of global interrupts is normally not - done until all other initializations are complete. - - Even if interrupts are globally enabled, they must also be - individually enabled for each channel that is to generate - interrupts. - -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. - - After this function all AIOPs on the controller are disabled, - they can be enabled with sEnAiop(). -*/ -static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, - ByteIO_t * AiopIOList, int AiopIOListSize, - WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, - int PeriodicOnly, int altChanRingIndicator, - int UPCIRingInd) -{ - int i; - ByteIO_t io; - - CtlP->AltChanRingIndicator = altChanRingIndicator; - CtlP->UPCIRingInd = UPCIRingInd; - CtlP->CtlNum = CtlNum; - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - CtlP->BusType = isPCI; /* controller release 1 */ - - if (ConfigIO) { - CtlP->isUPCI = 1; - CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL; - CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL; - CtlP->AiopIntrBits = upci_aiop_intr_bits; - } else { - CtlP->isUPCI = 0; - CtlP->PCIIO = - (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC); - CtlP->AiopIntrBits = aiop_intr_bits; - } - - sPCIControllerEOI(CtlP); /* clear EOI if warm init */ - /* Init AIOPs */ - CtlP->NumAiop = 0; - for (i = 0; i < AiopIOListSize; i++) { - io = AiopIOList[i]; - CtlP->AiopIO[i] = (WordIO_t) io; - CtlP->AiopIntChanIO[i] = io + _INT_CHAN; - - CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ - if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - break; /* done looking for AIOPs */ - - CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */ - sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */ - sOutB(io + _INDX_DATA, sClockPrescale); - CtlP->NumAiop++; /* bump count of AIOPs */ - } - - if (CtlP->NumAiop == 0) - return (-1); - else - return (CtlP->NumAiop); -} - -/*************************************************************************** -Function: sReadAiopID -Purpose: Read the AIOP idenfication number directly from an AIOP. -Call: sReadAiopID(io) - ByteIO_t io: AIOP base I/O address -Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X - is replace by an identifying number. - Flag AIOPID_NULL if no valid AIOP is found -Warnings: No context switches are allowed while executing this function. - -*/ -static int sReadAiopID(ByteIO_t io) -{ - Byte_t AiopID; /* ID byte from AIOP */ - - sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */ - sOutB(io + _CMD_REG, 0x0); - AiopID = sInW(io + _CHN_STAT0) & 0x07; - if (AiopID == 0x06) - return (1); - else /* AIOP does not exist */ - return (-1); -} - -/*************************************************************************** -Function: sReadAiopNumChan -Purpose: Read the number of channels available in an AIOP directly from - an AIOP. -Call: sReadAiopNumChan(io) - WordIO_t io: AIOP base I/O address -Return: int: The number of channels available -Comments: The number of channels is determined by write/reads from identical - offsets within the SRAM address spaces for channels 0 and 4. - If the channel 4 space is mirrored to channel 0 it is a 4 channel - AIOP, otherwise it is an 8 channel. -Warnings: No context switches are allowed while executing this function. -*/ -static int sReadAiopNumChan(WordIO_t io) -{ - Word_t x; - static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; - - /* write to chan 0 SRAM */ - out32((DWordIO_t) io + _INDX_ADDR, R); - sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */ - x = sInW(io + _INDX_DATA); - sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */ - if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */ - return (8); - else - return (4); -} - -/*************************************************************************** -Function: sInitChan -Purpose: Initialization of a channel and channel structure -Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) - CONTROLLER_T *CtlP; Ptr to controller structure - CHANNEL_T *ChP; Ptr to channel structure - int AiopNum; AIOP number within controller - int ChanNum; Channel number within AIOP -Return: int: 1 if initialization succeeded, 0 if it fails because channel - number exceeds number of channels available in AIOP. -Comments: This function must be called before a channel can be used. -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. -*/ -static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, - int ChanNum) -{ - int i; - WordIO_t AiopIO; - WordIO_t ChIOOff; - Byte_t *ChR; - Word_t ChOff; - static Byte_t R[4]; - int brd9600; - - if (ChanNum >= CtlP->AiopNumChan[AiopNum]) - return 0; /* exceeds num chans in AIOP */ - - /* Channel, AIOP, and controller identifiers */ - ChP->CtlP = CtlP; - ChP->ChanID = CtlP->AiopID[AiopNum]; - ChP->AiopNum = AiopNum; - ChP->ChanNum = ChanNum; - - /* Global direct addresses */ - AiopIO = CtlP->AiopIO[AiopNum]; - ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG; - ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN; - ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK; - ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR; - ChP->IndexData = AiopIO + _INDX_DATA; - - /* Channel direct addresses */ - ChIOOff = AiopIO + ChP->ChanNum * 2; - ChP->TxRxData = ChIOOff + _TD0; - ChP->ChanStat = ChIOOff + _CHN_STAT0; - ChP->TxRxCount = ChIOOff + _FIFO_CNT0; - ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0; - - /* Initialize the channel from the RData array */ - for (i = 0; i < RDATASIZE; i += 4) { - R[0] = RData[i]; - R[1] = RData[i + 1] + 0x10 * ChanNum; - R[2] = RData[i + 2]; - R[3] = RData[i + 3]; - out32(ChP->IndexAddr, R); - } - - ChR = ChP->R; - for (i = 0; i < RREGDATASIZE; i += 4) { - ChR[i] = RRegData[i]; - ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum; - ChR[i + 2] = RRegData[i + 2]; - ChR[i + 3] = RRegData[i + 3]; - } - - /* Indexed registers */ - ChOff = (Word_t) ChanNum *0x1000; - - if (sClockPrescale == 0x14) - brd9600 = 47; - else - brd9600 = 23; - - ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD); - ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8); - ChP->BaudDiv[2] = (Byte_t) brd9600; - ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8); - out32(ChP->IndexAddr, ChP->BaudDiv); - - ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL); - ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8); - ChP->TxControl[2] = 0; - ChP->TxControl[3] = 0; - out32(ChP->IndexAddr, ChP->TxControl); - - ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL); - ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8); - ChP->RxControl[2] = 0; - ChP->RxControl[3] = 0; - out32(ChP->IndexAddr, ChP->RxControl); - - ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS); - ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8); - ChP->TxEnables[2] = 0; - ChP->TxEnables[3] = 0; - out32(ChP->IndexAddr, ChP->TxEnables); - - ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1); - ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8); - ChP->TxCompare[2] = 0; - ChP->TxCompare[3] = 0; - out32(ChP->IndexAddr, ChP->TxCompare); - - ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1); - ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8); - ChP->TxReplace1[2] = 0; - ChP->TxReplace1[3] = 0; - out32(ChP->IndexAddr, ChP->TxReplace1); - - ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2); - ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8); - ChP->TxReplace2[2] = 0; - ChP->TxReplace2[3] = 0; - out32(ChP->IndexAddr, ChP->TxReplace2); - - ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; - ChP->TxFIFO = ChOff + _TX_FIFO; - - sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ - sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */ - sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - sOutW(ChP->IndexData, 0); - ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; - ChP->RxFIFO = ChOff + _RX_FIFO; - - sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ - sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */ - sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */ - sOutW(ChP->IndexData, 0); - sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - sOutW(ChP->IndexData, 0); - ChP->TxPrioCnt = ChOff + _TXP_CNT; - sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt); - sOutB(ChP->IndexData, 0); - ChP->TxPrioPtr = ChOff + _TXP_PNTR; - sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr); - sOutB(ChP->IndexData, 0); - ChP->TxPrioBuf = ChOff + _TXP_BUF; - sEnRxProcessor(ChP); /* start the Rx processor */ - - return 1; -} - -/*************************************************************************** -Function: sStopRxProcessor -Purpose: Stop the receive processor from processing a channel. -Call: sStopRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure - -Comments: The receive processor can be started again with sStartRxProcessor(). - This function causes the receive processor to skip over the - stopped channel. It does not stop it from processing other channels. - -Warnings: No context switches are allowed while executing this function. - - Do not leave the receive processor stopped for more than one - character time. - - After calling this function a delay of 4 uS is required to ensure - that the receive processor is no longer processing this channel. -*/ -static void sStopRxProcessor(CHANNEL_T * ChP) -{ - Byte_t R[4]; - - R[0] = ChP->R[0]; - R[1] = ChP->R[1]; - R[2] = 0x0a; - R[3] = ChP->R[3]; - out32(ChP->IndexAddr, R); -} - -/*************************************************************************** -Function: sFlushRxFIFO -Purpose: Flush the Rx FIFO -Call: sFlushRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -static void sFlushRxFIFO(CHANNEL_T * ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int RxFIFOEnabled; /* 1 if Rx FIFO enabled */ - - if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ - return; /* don't need to flush */ - - RxFIFOEnabled = 0; - if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */ - RxFIFOEnabled = 1; - sDisRxFIFO(ChP); /* disable it */ - for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */ - sInB(ChP->IntChan); /* depends on bus i/o timing */ - } - sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ - Ch = (Byte_t) sGetChanNum(ChP); - sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */ - sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */ - sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */ - sOutW(ChP->IndexData, 0); - sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - sOutW(ChP->IndexData, 0); - if (RxFIFOEnabled) - sEnRxFIFO(ChP); /* enable Rx FIFO */ -} - -/*************************************************************************** -Function: sFlushTxFIFO -Purpose: Flush the Tx FIFO -Call: sFlushTxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -static void sFlushTxFIFO(CHANNEL_T * ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int TxEnabled; /* 1 if transmitter enabled */ - - if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ - return; /* don't need to flush */ - - TxEnabled = 0; - if (ChP->TxControl[3] & TX_ENABLE) { - TxEnabled = 1; - sDisTransmit(ChP); /* disable transmitter */ - } - sStopRxProcessor(ChP); /* stop Rx processor */ - for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */ - sInB(ChP->IntChan); /* depends on bus i/o timing */ - Ch = (Byte_t) sGetChanNum(ChP); - sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */ - sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */ - sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - sOutW(ChP->IndexData, 0); - if (TxEnabled) - sEnTransmit(ChP); /* enable transmitter */ - sStartRxProcessor(ChP); /* restart Rx processor */ -} - -/*************************************************************************** -Function: sWriteTxPrioByte -Purpose: Write a byte of priority transmit data to a channel -Call: sWriteTxPrioByte(ChP,Data) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Data; The transmit data byte - -Return: int: 1 if the bytes is successfully written, otherwise 0. - -Comments: The priority byte is transmitted before any data in the Tx FIFO. - -Warnings: No context switches are allowed while executing this function. -*/ -static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) -{ - Byte_t DWBuf[4]; /* buffer for double word writes */ - Word_t *WordPtr; /* must be far because Win SS != DS */ - register DWordIO_t IndexAddr; - - if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */ - IndexAddr = ChP->IndexAddr; - sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */ - if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */ - return (0); /* nothing sent */ - - WordPtr = (Word_t *) (&DWBuf[0]); - *WordPtr = ChP->TxPrioBuf; /* data byte address */ - - DWBuf[2] = Data; /* data byte value */ - out32(IndexAddr, DWBuf); /* write it out */ - - *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ - - DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ - DWBuf[3] = 0; /* priority buffer pointer */ - out32(IndexAddr, DWBuf); /* write it out */ - } else { /* write it to Tx FIFO */ - - sWriteTxByte(sGetTxRxDataIO(ChP), Data); - } - return (1); /* 1 byte sent */ -} - -/*************************************************************************** -Function: sEnInterrupts -Purpose: Enable one or more interrupts for a channel -Call: sEnInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt enable flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Allow channel interrupt signal to the AIOP's - Interrupt Channel Register. -Return: void -Comments: If an interrupt enable flag is set in Flags, that interrupt will be - enabled. If an interrupt enable flag is not set in Flags, that - interrupt will not be changed. Interrupts can be disabled with - function sDisInterrupts(). - - This function sets the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This allows - this channel's bit to be set in the AIOP's Interrupt Channel Register. - - Interrupts must also be globally enabled before channel interrupts - will be passed on to the host. This is done with function - sEnGlobalInt(). - - In some cases it may be desirable to disable interrupts globally but - enable channel interrupts. This would allow the global interrupt - status register to be used to determine which AIOPs need service. -*/ -static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] |= - ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - - out32(ChP->IndexAddr, ChP->RxControl); - - ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN); - - out32(ChP->IndexAddr, ChP->TxControl); - - if (Flags & CHANINT_EN) { - Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum]; - sOutB(ChP->IntMask, Mask); - } -} - -/*************************************************************************** -Function: sDisInterrupts -Purpose: Disable one or more interrupts for a channel -Call: sDisInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Disable channel interrupt signal to the - AIOP's Interrupt Channel Register. -Return: void -Comments: If an interrupt flag is set in Flags, that interrupt will be - disabled. If an interrupt flag is not set in Flags, that - interrupt will not be changed. Interrupts can be enabled with - function sEnInterrupts(). - - This function clears the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This blocks - this channel's bit from being set in the AIOP's Interrupt Channel - Register. -*/ -static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] &= - ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - out32(ChP->IndexAddr, ChP->RxControl); - ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN); - out32(ChP->IndexAddr, ChP->TxControl); - - if (Flags & CHANINT_EN) { - Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum]; - sOutB(ChP->IntMask, Mask); - } -} - -static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) -{ - sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum); -} - -/* - * Not an official SSCI function, but how to reset RocketModems. - * ISA bus version - */ -static void sModemReset(CONTROLLER_T * CtlP, int chan, int on) -{ - ByteIO_t addr; - Byte_t val; - - addr = CtlP->AiopIO[0] + 0x400; - val = sInB(CtlP->MReg3IO); - /* if AIOP[1] is not enabled, enable it */ - if ((val & 2) == 0) { - val = sInB(CtlP->MReg2IO); - sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03)); - sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6)); - } - - sEnAiop(CtlP, 1); - if (!on) - addr += 8; - sOutB(addr + chan, 0); /* apply or remove reset */ - sDisAiop(CtlP, 1); -} - -/* - * Not an official SSCI function, but how to reset RocketModems. - * PCI bus version - */ -static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on) -{ - ByteIO_t addr; - - addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */ - if (!on) - addr += 8; - sOutB(addr + chan, 0); /* apply or remove reset */ -} - -/* Resets the speaker controller on RocketModem II and III devices */ -static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model) -{ - ByteIO_t addr; - - /* RocketModem II speaker control is at the 8th port location of offset 0x40 */ - if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) { - addr = CtlP->AiopIO[0] + 0x4F; - sOutB(addr, 0); - } - - /* RocketModem III speaker control is at the 1st port location of offset 0x80 */ - if ((model == MODEL_UPCI_RM3_8PORT) - || (model == MODEL_UPCI_RM3_4PORT)) { - addr = CtlP->AiopIO[0] + 0x88; - sOutB(addr, 0); - } -} - -/* Returns the line number given the controller (board), aiop and channel number */ -static unsigned char GetLineNumber(int ctrl, int aiop, int ch) -{ - return lineNumbers[(ctrl << 5) | (aiop << 3) | ch]; -} - -/* - * Stores the line number associated with a given controller (board), aiop - * and channel number. - * Returns: The line number assigned - */ -static unsigned char SetLineNumber(int ctrl, int aiop, int ch) -{ - lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++; - return (nextLineNumber - 1); -} diff --git a/drivers/char/rocket.h b/drivers/char/rocket.h deleted file mode 100644 index ec863f35f1a9..000000000000 --- a/drivers/char/rocket.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * rocket.h --- the exported interface of the rocket driver to its configuration program. - * - * Written by Theodore Ts'o, Copyright 1997. - * Copyright 1997 Comtrol Corporation. - * - */ - -/* Model Information Struct */ -typedef struct { - unsigned long model; - char modelString[80]; - unsigned long numPorts; - int loadrm2; - int startingPortNumber; -} rocketModel_t; - -struct rocket_config { - int line; - int flags; - int closing_wait; - int close_delay; - int port; - int reserved[32]; -}; - -struct rocket_ports { - int tty_major; - int callout_major; - rocketModel_t rocketModel[8]; -}; - -struct rocket_version { - char rocket_version[32]; - char rocket_date[32]; - char reserved[64]; -}; - -/* - * Rocketport flags - */ -/*#define ROCKET_CALLOUT_NOHUP 0x00000001 */ -#define ROCKET_FORCE_CD 0x00000002 -#define ROCKET_HUP_NOTIFY 0x00000004 -#define ROCKET_SPLIT_TERMIOS 0x00000008 -#define ROCKET_SPD_MASK 0x00000070 -#define ROCKET_SPD_HI 0x00000010 /* Use 56000 instead of 38400 bps */ -#define ROCKET_SPD_VHI 0x00000020 /* Use 115200 instead of 38400 bps */ -#define ROCKET_SPD_SHI 0x00000030 /* Use 230400 instead of 38400 bps */ -#define ROCKET_SPD_WARP 0x00000040 /* Use 460800 instead of 38400 bps */ -#define ROCKET_SAK 0x00000080 -#define ROCKET_SESSION_LOCKOUT 0x00000100 -#define ROCKET_PGRP_LOCKOUT 0x00000200 -#define ROCKET_RTS_TOGGLE 0x00000400 -#define ROCKET_MODE_MASK 0x00003000 -#define ROCKET_MODE_RS232 0x00000000 -#define ROCKET_MODE_RS485 0x00001000 -#define ROCKET_MODE_RS422 0x00002000 -#define ROCKET_FLAGS 0x00003FFF - -#define ROCKET_USR_MASK 0x0071 /* Legal flags that non-privileged - * users can set or reset */ - -/* - * For closing_wait and closing_wait2 - */ -#define ROCKET_CLOSING_WAIT_NONE ASYNC_CLOSING_WAIT_NONE -#define ROCKET_CLOSING_WAIT_INF ASYNC_CLOSING_WAIT_INF - -/* - * Rocketport ioctls -- "RP" - */ -#define RCKP_GET_STRUCT 0x00525001 -#define RCKP_GET_CONFIG 0x00525002 -#define RCKP_SET_CONFIG 0x00525003 -#define RCKP_GET_PORTS 0x00525004 -#define RCKP_RESET_RM2 0x00525005 -#define RCKP_GET_VERSION 0x00525006 - -/* Rocketport Models */ -#define MODEL_RP32INTF 0x0001 /* RP 32 port w/external I/F */ -#define MODEL_RP8INTF 0x0002 /* RP 8 port w/external I/F */ -#define MODEL_RP16INTF 0x0003 /* RP 16 port w/external I/F */ -#define MODEL_RP8OCTA 0x0005 /* RP 8 port w/octa cable */ -#define MODEL_RP4QUAD 0x0004 /* RP 4 port w/quad cable */ -#define MODEL_RP8J 0x0006 /* RP 8 port w/RJ11 connectors */ -#define MODEL_RP4J 0x0007 /* RP 4 port w/RJ45 connectors */ -#define MODEL_RP8SNI 0x0008 /* RP 8 port w/ DB78 SNI connector */ -#define MODEL_RP16SNI 0x0009 /* RP 16 port w/ DB78 SNI connector */ -#define MODEL_RPP4 0x000A /* RP Plus 4 port */ -#define MODEL_RPP8 0x000B /* RP Plus 8 port */ -#define MODEL_RP2_232 0x000E /* RP Plus 2 port RS232 */ -#define MODEL_RP2_422 0x000F /* RP Plus 2 port RS232 */ - -/* Rocketmodem II Models */ -#define MODEL_RP6M 0x000C /* RM 6 port */ -#define MODEL_RP4M 0x000D /* RM 4 port */ - -/* Universal PCI boards */ -#define MODEL_UPCI_RP32INTF 0x0801 /* RP UPCI 32 port w/external I/F */ -#define MODEL_UPCI_RP8INTF 0x0802 /* RP UPCI 8 port w/external I/F */ -#define MODEL_UPCI_RP16INTF 0x0803 /* RP UPCI 16 port w/external I/F */ -#define MODEL_UPCI_RP8OCTA 0x0805 /* RP UPCI 8 port w/octa cable */ -#define MODEL_UPCI_RM3_8PORT 0x080C /* RP UPCI Rocketmodem III 8 port */ -#define MODEL_UPCI_RM3_4PORT 0x080C /* RP UPCI Rocketmodem III 4 port */ - -/* Compact PCI 16 port */ -#define MODEL_CPCI_RP16INTF 0x0903 /* RP Compact PCI 16 port w/external I/F */ - -/* All ISA boards */ -#define MODEL_ISA 0x1000 diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h deleted file mode 100644 index 67e0f1e778a2..000000000000 --- a/drivers/char/rocket_int.h +++ /dev/null @@ -1,1214 +0,0 @@ -/* - * rocket_int.h --- internal header file for rocket.c - * - * Written by Theodore Ts'o, Copyright 1997. - * Copyright 1997 Comtrol Corporation. - * - */ - -/* - * Definition of the types in rcktpt_type - */ -#define ROCKET_TYPE_NORMAL 0 -#define ROCKET_TYPE_MODEM 1 -#define ROCKET_TYPE_MODEMII 2 -#define ROCKET_TYPE_MODEMIII 3 -#define ROCKET_TYPE_PC104 4 - -#include - -#include -#include - -typedef unsigned char Byte_t; -typedef unsigned int ByteIO_t; - -typedef unsigned int Word_t; -typedef unsigned int WordIO_t; - -typedef unsigned int DWordIO_t; - -/* - * Note! Normally the Linux I/O macros already take care of - * byte-swapping the I/O instructions. However, all accesses using - * sOutDW aren't really 32-bit accesses, but should be handled in byte - * order. Hence the use of the cpu_to_le32() macro to byte-swap - * things to no-op the byte swapping done by the big-endian outl() - * instruction. - */ - -static inline void sOutB(unsigned short port, unsigned char value) -{ -#ifdef ROCKET_DEBUG_IO - printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value); -#endif - outb_p(value, port); -} - -static inline void sOutW(unsigned short port, unsigned short value) -{ -#ifdef ROCKET_DEBUG_IO - printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value); -#endif - outw_p(value, port); -} - -static inline void out32(unsigned short port, Byte_t *p) -{ - u32 value = get_unaligned_le32(p); -#ifdef ROCKET_DEBUG_IO - printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value); -#endif - outl_p(value, port); -} - -static inline unsigned char sInB(unsigned short port) -{ - return inb_p(port); -} - -static inline unsigned short sInW(unsigned short port) -{ - return inw_p(port); -} - -/* This is used to move arrays of bytes so byte swapping isn't appropriate. */ -#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count) -#define sInStrW(port, addr, count) if (count) insw(port, addr, count) - -#define CTL_SIZE 8 -#define AIOP_CTL_SIZE 4 -#define CHAN_AIOP_SIZE 8 -#define MAX_PORTS_PER_AIOP 8 -#define MAX_AIOPS_PER_BOARD 4 -#define MAX_PORTS_PER_BOARD 32 - -/* Bus type ID */ -#define isISA 0 -#define isPCI 1 -#define isMC 2 - -/* Controller ID numbers */ -#define CTLID_NULL -1 /* no controller exists */ -#define CTLID_0001 0x0001 /* controller release 1 */ - -/* AIOP ID numbers, identifies AIOP type implementing channel */ -#define AIOPID_NULL -1 /* no AIOP or channel exists */ -#define AIOPID_0001 0x0001 /* AIOP release 1 */ - -/************************************************************************ - Global Register Offsets - Direct Access - Fixed values -************************************************************************/ - -#define _CMD_REG 0x38 /* Command Register 8 Write */ -#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */ -#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */ -#define _UNUSED 0x3B /* Unused 8 */ -#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */ -#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */ - -/************************************************************************ - Channel Register Offsets for 1st channel in AIOP - Direct Access -************************************************************************/ -#define _TD0 0x00 /* Transmit Data 16 Write */ -#define _RD0 0x00 /* Receive Data 16 Read */ -#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */ -#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */ -#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */ - -/************************************************************************ - Tx Control Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */ -#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */ -#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */ -#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */ -#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */ -#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */ - -/************************************************************************ -Memory Controller Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _RX_FIFO 0x000 /* Rx FIFO */ -#define _TX_FIFO 0x800 /* Tx FIFO */ -#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */ -#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */ -#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */ -#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */ -#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */ -#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */ - -#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */ -#define TXFIFO_SIZE 255 /* size of Tx FIFO */ -#define RXFIFO_SIZE 1023 /* size of Rx FIFO */ - -/************************************************************************ -Tx Priority Buffer - Indexed - External - Fixed -************************************************************************/ -#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */ -#define TXP_SIZE 0x20 /* 32 bytes */ - -/************************************************************************ -Channel Register Offsets - Indexed - Internal - Fixed -************************************************************************/ - -#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */ -#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */ -#define _BAUD 0xFF4 /* Baud Rate 16 Write */ -#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */ - -#define STMBREAK 0x08 /* BREAK */ -#define STMFRAME 0x04 /* framing error */ -#define STMRCVROVR 0x02 /* receiver over run error */ -#define STMPARITY 0x01 /* parity error */ -#define STMERROR (STMBREAK | STMFRAME | STMPARITY) -#define STMBREAKH 0x800 /* BREAK */ -#define STMFRAMEH 0x400 /* framing error */ -#define STMRCVROVRH 0x200 /* receiver over run error */ -#define STMPARITYH 0x100 /* parity error */ -#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH) - -#define CTS_ACT 0x20 /* CTS input asserted */ -#define DSR_ACT 0x10 /* DSR input asserted */ -#define CD_ACT 0x08 /* CD input asserted */ -#define TXFIFOMT 0x04 /* Tx FIFO is empty */ -#define TXSHRMT 0x02 /* Tx shift register is empty */ -#define RDA 0x01 /* Rx data available */ -#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */ - -#define STATMODE 0x8000 /* status mode enable bit */ -#define RXFOVERFL 0x2000 /* receive FIFO overflow */ -#define RX2MATCH 0x1000 /* receive compare byte 2 match */ -#define RX1MATCH 0x0800 /* receive compare byte 1 match */ -#define RXBREAK 0x0400 /* received BREAK */ -#define RXFRAME 0x0200 /* received framing error */ -#define RXPARITY 0x0100 /* received parity error */ -#define STATERROR (RXBREAK | RXFRAME | RXPARITY) - -#define CTSFC_EN 0x80 /* CTS flow control enable bit */ -#define RTSTOG_EN 0x40 /* RTS toggle enable bit */ -#define TXINT_EN 0x10 /* transmit interrupt enable */ -#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */ -#define PARITY_EN 0x04 /* enable parity (0 = no parity) */ -#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */ -#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */ - -#define SETBREAK 0x10 /* send break condition (must clear) */ -#define LOCALLOOP 0x08 /* local loopback set for test */ -#define SET_DTR 0x04 /* assert DTR */ -#define SET_RTS 0x02 /* assert RTS */ -#define TX_ENABLE 0x01 /* enable transmitter */ - -#define RTSFC_EN 0x40 /* RTS flow control enable */ -#define RXPROC_EN 0x20 /* receive processor enable */ -#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */ -#define TRIG_1 0x08 /* trigger level 1 char */ -#define TRIG_1_2 0x10 /* trigger level 1/2 */ -#define TRIG_7_8 0x18 /* trigger level 7/8 */ -#define TRIG_MASK 0x18 /* trigger level mask */ -#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */ -#define RXINT_EN 0x02 /* Rx interrupt enable */ -#define MCINT_EN 0x01 /* modem change interrupt enable */ - -#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */ -#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */ -#define SRC_INT 0x08 /* special receive condition interrupt */ -#define DELTA_CD 0x04 /* CD change interrupt */ -#define DELTA_CTS 0x02 /* CTS change interrupt */ -#define DELTA_DSR 0x01 /* DSR change interrupt */ - -#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */ -#define IGN2_EN 0x08 /* ignore byte 2 enable */ -#define IGN1_EN 0x04 /* ignore byte 1 enable */ -#define COMP2_EN 0x02 /* compare byte 2 enable */ -#define COMP1_EN 0x01 /* compare byte 1 enable */ - -#define RESET_ALL 0x80 /* reset AIOP (all channels) */ -#define TXOVERIDE 0x40 /* Transmit software off override */ -#define RESETUART 0x20 /* reset channel's UART */ -#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */ -#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */ - -#define INTSTAT0 0x01 /* AIOP 0 interrupt status */ -#define INTSTAT1 0x02 /* AIOP 1 interrupt status */ -#define INTSTAT2 0x04 /* AIOP 2 interrupt status */ -#define INTSTAT3 0x08 /* AIOP 3 interrupt status */ - -#define INTR_EN 0x08 /* allow interrupts to host */ -#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */ - -/************************************************************************** - MUDBAC remapped for PCI -**************************************************************************/ - -#define _CFG_INT_PCI 0x40 -#define _PCI_INT_FUNC 0x3A - -#define PCI_STROB 0x2000 /* bit 13 of int aiop register */ -#define INTR_EN_PCI 0x0010 /* allow interrupts to host */ - -/* - * Definitions for Universal PCI board registers - */ -#define _PCI_9030_INT_CTRL 0x4c /* Offsets from BAR1 */ -#define _PCI_9030_GPIO_CTRL 0x54 -#define PCI_INT_CTRL_AIOP 0x0001 -#define PCI_GPIO_CTRL_8PORT 0x4000 -#define _PCI_9030_RING_IND 0xc0 /* Offsets from BAR1 */ - -#define CHAN3_EN 0x08 /* enable AIOP 3 */ -#define CHAN2_EN 0x04 /* enable AIOP 2 */ -#define CHAN1_EN 0x02 /* enable AIOP 1 */ -#define CHAN0_EN 0x01 /* enable AIOP 0 */ -#define FREQ_DIS 0x00 -#define FREQ_274HZ 0x60 -#define FREQ_137HZ 0x50 -#define FREQ_69HZ 0x40 -#define FREQ_34HZ 0x30 -#define FREQ_17HZ 0x20 -#define FREQ_9HZ 0x10 -#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */ - -#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */ - -#define RDATASIZE 72 -#define RREGDATASIZE 52 - -/* - * AIOP interrupt bits for ISA/PCI boards and UPCI boards. - */ -#define AIOP_INTR_BIT_0 0x0001 -#define AIOP_INTR_BIT_1 0x0002 -#define AIOP_INTR_BIT_2 0x0004 -#define AIOP_INTR_BIT_3 0x0008 - -#define AIOP_INTR_BITS ( \ - AIOP_INTR_BIT_0 \ - | AIOP_INTR_BIT_1 \ - | AIOP_INTR_BIT_2 \ - | AIOP_INTR_BIT_3) - -#define UPCI_AIOP_INTR_BIT_0 0x0004 -#define UPCI_AIOP_INTR_BIT_1 0x0020 -#define UPCI_AIOP_INTR_BIT_2 0x0100 -#define UPCI_AIOP_INTR_BIT_3 0x0800 - -#define UPCI_AIOP_INTR_BITS ( \ - UPCI_AIOP_INTR_BIT_0 \ - | UPCI_AIOP_INTR_BIT_1 \ - | UPCI_AIOP_INTR_BIT_2 \ - | UPCI_AIOP_INTR_BIT_3) - -/* Controller level information structure */ -typedef struct { - int CtlID; - int CtlNum; - int BusType; - int boardType; - int isUPCI; - WordIO_t PCIIO; - WordIO_t PCIIO2; - ByteIO_t MBaseIO; - ByteIO_t MReg1IO; - ByteIO_t MReg2IO; - ByteIO_t MReg3IO; - Byte_t MReg2; - Byte_t MReg3; - int NumAiop; - int AltChanRingIndicator; - ByteIO_t UPCIRingInd; - WordIO_t AiopIO[AIOP_CTL_SIZE]; - ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE]; - int AiopID[AIOP_CTL_SIZE]; - int AiopNumChan[AIOP_CTL_SIZE]; - Word_t *AiopIntrBits; -} CONTROLLER_T; - -typedef CONTROLLER_T CONTROLLER_t; - -/* Channel level information structure */ -typedef struct { - CONTROLLER_T *CtlP; - int AiopNum; - int ChanID; - int ChanNum; - int rtsToggle; - - ByteIO_t Cmd; - ByteIO_t IntChan; - ByteIO_t IntMask; - DWordIO_t IndexAddr; - WordIO_t IndexData; - - WordIO_t TxRxData; - WordIO_t ChanStat; - WordIO_t TxRxCount; - ByteIO_t IntID; - - Word_t TxFIFO; - Word_t TxFIFOPtrs; - Word_t RxFIFO; - Word_t RxFIFOPtrs; - Word_t TxPrioCnt; - Word_t TxPrioPtr; - Word_t TxPrioBuf; - - Byte_t R[RREGDATASIZE]; - - Byte_t BaudDiv[4]; - Byte_t TxControl[4]; - Byte_t RxControl[4]; - Byte_t TxEnables[4]; - Byte_t TxCompare[4]; - Byte_t TxReplace1[4]; - Byte_t TxReplace2[4]; -} CHANNEL_T; - -typedef CHANNEL_T CHANNEL_t; -typedef CHANNEL_T *CHANPTR_T; - -#define InterfaceModeRS232 0x00 -#define InterfaceModeRS422 0x08 -#define InterfaceModeRS485 0x10 -#define InterfaceModeRS232T 0x18 - -/*************************************************************************** -Function: sClrBreak -Purpose: Stop sending a transmit BREAK signal -Call: sClrBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrBreak(ChP) \ -do { \ - (ChP)->TxControl[3] &= ~SETBREAK; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sClrDTR -Purpose: Clr the DTR output -Call: sClrDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrDTR(ChP) \ -do { \ - (ChP)->TxControl[3] &= ~SET_DTR; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sClrRTS -Purpose: Clr the RTS output -Call: sClrRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrRTS(ChP) \ -do { \ - if ((ChP)->rtsToggle) break; \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sClrTxXOFF -Purpose: Clear any existing transmit software flow control off condition -Call: sClrTxXOFF(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrTxXOFF(ChP) \ -do { \ - sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \ - sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \ -} while (0) - -/*************************************************************************** -Function: sCtlNumToCtlPtr -Purpose: Convert a controller number to controller structure pointer -Call: sCtlNumToCtlPtr(CtlNum) - int CtlNum; Controller number -Return: CONTROLLER_T *: Ptr to controller structure -*/ -#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM] - -/*************************************************************************** -Function: sControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sControllerEOI(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB) - -/*************************************************************************** -Function: sPCIControllerEOI -Purpose: Strobe the PCI End Of Interrupt bit. - For the UPCI boards, toggle the AIOP interrupt enable bit - (this was taken from the Windows driver). -Call: sPCIControllerEOI(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sPCIControllerEOI(CTLP) \ -do { \ - if ((CTLP)->isUPCI) { \ - Word_t w = sInW((CTLP)->PCIIO); \ - sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \ - sOutW((CTLP)->PCIIO, w); \ - } \ - else { \ - sOutW((CTLP)->PCIIO, PCI_STROB); \ - } \ -} while (0) - -/*************************************************************************** -Function: sDisAiop -Purpose: Disable I/O access to an AIOP -Call: sDisAiop(CltP) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sDisAiop(CTLP,AIOPNUM) \ -do { \ - (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \ - sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \ -} while (0) - -/*************************************************************************** -Function: sDisCTSFlowCtl -Purpose: Disable output flow control using CTS -Call: sDisCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisCTSFlowCtl(ChP) \ -do { \ - (ChP)->TxControl[2] &= ~CTSFC_EN; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sDisIXANY -Purpose: Disable IXANY Software Flow Control -Call: sDisIXANY(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisIXANY(ChP) \ -do { \ - (ChP)->R[0x0e] = 0x86; \ - out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ -} while (0) - -/*************************************************************************** -Function: DisParity -Purpose: Disable parity -Call: sDisParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). -*/ -#define sDisParity(ChP) \ -do { \ - (ChP)->TxControl[2] &= ~PARITY_EN; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sDisRTSToggle -Purpose: Disable RTS toggle -Call: sDisRTSToggle(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisRTSToggle(ChP) \ -do { \ - (ChP)->TxControl[2] &= ~RTSTOG_EN; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ - (ChP)->rtsToggle = 0; \ -} while (0) - -/*************************************************************************** -Function: sDisRxFIFO -Purpose: Disable Rx FIFO -Call: sDisRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisRxFIFO(ChP) \ -do { \ - (ChP)->R[0x32] = 0x0a; \ - out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ -} while (0) - -/*************************************************************************** -Function: sDisRxStatusMode -Purpose: Disable the Rx status mode -Call: sDisRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This takes the channel out of the receive status mode. All - subsequent reads of receive data using sReadRxWord() will return - two data bytes. -*/ -#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0) - -/*************************************************************************** -Function: sDisTransmit -Purpose: Disable transmit -Call: sDisTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure - This disables movement of Tx data from the Tx FIFO into the 1 byte - Tx buffer. Therefore there could be up to a 2 byte latency - between the time sDisTransmit() is called and the transmit buffer - and transmit shift register going completely empty. -*/ -#define sDisTransmit(ChP) \ -do { \ - (ChP)->TxControl[3] &= ~TX_ENABLE; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sDisTxSoftFlowCtl -Purpose: Disable Tx Software Flow Control -Call: sDisTxSoftFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisTxSoftFlowCtl(ChP) \ -do { \ - (ChP)->R[0x06] = 0x8a; \ - out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ -} while (0) - -/*************************************************************************** -Function: sEnAiop -Purpose: Enable I/O access to an AIOP -Call: sEnAiop(CltP) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sEnAiop(CTLP,AIOPNUM) \ -do { \ - (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \ - sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \ -} while (0) - -/*************************************************************************** -Function: sEnCTSFlowCtl -Purpose: Enable output flow control using CTS -Call: sEnCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnCTSFlowCtl(ChP) \ -do { \ - (ChP)->TxControl[2] |= CTSFC_EN; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sEnIXANY -Purpose: Enable IXANY Software Flow Control -Call: sEnIXANY(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnIXANY(ChP) \ -do { \ - (ChP)->R[0x0e] = 0x21; \ - out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ -} while (0) - -/*************************************************************************** -Function: EnParity -Purpose: Enable parity -Call: sEnParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: Before enabling parity odd or even parity should be chosen using - functions sSetOddParity() or sSetEvenParity(). -*/ -#define sEnParity(ChP) \ -do { \ - (ChP)->TxControl[2] |= PARITY_EN; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sEnRTSToggle -Purpose: Enable RTS toggle -Call: sEnRTSToggle(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function will disable RTS flow control and clear the RTS - line to allow operation of RTS toggle. -*/ -#define sEnRTSToggle(ChP) \ -do { \ - (ChP)->RxControl[2] &= ~RTSFC_EN; \ - out32((ChP)->IndexAddr,(ChP)->RxControl); \ - (ChP)->TxControl[2] |= RTSTOG_EN; \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ - (ChP)->rtsToggle = 1; \ -} while (0) - -/*************************************************************************** -Function: sEnRxFIFO -Purpose: Enable Rx FIFO -Call: sEnRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnRxFIFO(ChP) \ -do { \ - (ChP)->R[0x32] = 0x08; \ - out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ -} while (0) - -/*************************************************************************** -Function: sEnRxProcessor -Purpose: Enable the receive processor -Call: sEnRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start the receive processor. When - the channel is in the reset state the receive processor is not - running. This is done to prevent the receive processor from - executing invalid microcode instructions prior to the - downloading of the microcode. - -Warnings: This function must be called after valid microcode has been - downloaded to the AIOP, and it must not be called before the - microcode has been downloaded. -*/ -#define sEnRxProcessor(ChP) \ -do { \ - (ChP)->RxControl[2] |= RXPROC_EN; \ - out32((ChP)->IndexAddr,(ChP)->RxControl); \ -} while (0) - -/*************************************************************************** -Function: sEnRxStatusMode -Purpose: Enable the Rx status mode -Call: sEnRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This places the channel in the receive status mode. All subsequent - reads of receive data using sReadRxWord() will return a data byte - in the low word and a status byte in the high word. - -*/ -#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE) - -/*************************************************************************** -Function: sEnTransmit -Purpose: Enable transmit -Call: sEnTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnTransmit(ChP) \ -do { \ - (ChP)->TxControl[3] |= TX_ENABLE; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sEnTxSoftFlowCtl -Purpose: Enable Tx Software Flow Control -Call: sEnTxSoftFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnTxSoftFlowCtl(ChP) \ -do { \ - (ChP)->R[0x06] = 0xc5; \ - out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ -} while (0) - -/*************************************************************************** -Function: sGetAiopIntStatus -Purpose: Get the AIOP interrupt status -Call: sGetAiopIntStatus(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: Byte_t: The AIOP interrupt status. Bits 0 through 7 - represent channels 0 through 7 respectively. If a - bit is set that channel is interrupting. -*/ -#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM]) - -/*************************************************************************** -Function: sGetAiopNumChan -Purpose: Get the number of channels supported by an AIOP -Call: sGetAiopNumChan(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: int: The number of channels supported by the AIOP -*/ -#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM] - -/*************************************************************************** -Function: sGetChanIntID -Purpose: Get a channel's interrupt identification byte -Call: sGetChanIntID(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel interrupt ID. Can be any - combination of the following flags: - RXF_TRIG: Rx FIFO trigger level interrupt - TXFIFO_MT: Tx FIFO empty interrupt - SRC_INT: Special receive condition interrupt - DELTA_CD: CD change interrupt - DELTA_CTS: CTS change interrupt - DELTA_DSR: DSR change interrupt -*/ -#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR)) - -/*************************************************************************** -Function: sGetChanNum -Purpose: Get the number of a channel within an AIOP -Call: sGetChanNum(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: Channel number within AIOP, or NULLCHAN if channel does - not exist. -*/ -#define sGetChanNum(ChP) (ChP)->ChanNum - -/*************************************************************************** -Function: sGetChanStatus -Purpose: Get the channel status -Call: sGetChanStatus(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Word_t: The channel status. Can be any combination of - the following flags: - LOW BYTE FLAGS - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available - - HIGH BYTE FLAGS - STATMODE: status mode enable bit - RXFOVERFL: receive FIFO overflow - RX2MATCH: receive compare byte 2 match - RX1MATCH: receive compare byte 1 match - RXBREAK: received BREAK - RXFRAME: received framing error - RXPARITY: received parity error -Warnings: This function will clear the high byte flags in the Channel - Status Register. -*/ -#define sGetChanStatus(ChP) sInW((ChP)->ChanStat) - -/*************************************************************************** -Function: sGetChanStatusLo -Purpose: Get the low byte only of the channel status -Call: sGetChanStatusLo(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel status low byte. Can be any combination - of the following flags: - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available -*/ -#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat) - -/********************************************************************** - * Get RI status of channel - * Defined as a function in rocket.c -aes - */ -#if 0 -#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \ - (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \ - (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \ - (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \ - 0)) -#endif - -/*************************************************************************** -Function: sGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sGetControllerIntStatus(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f) - -/*************************************************************************** -Function: sPCIGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sPCIGetControllerIntStatus(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -Return: unsigned char: The controller interrupt status in the lower 4 - bits and bit 4. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. Bit 4 is set if the int - was generated from periodic. If a bit is set the - AIOP is interrupting. -*/ -#define sPCIGetControllerIntStatus(CTLP) \ - ((CTLP)->isUPCI ? \ - (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \ - ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS)) - -/*************************************************************************** - -Function: sGetRxCnt -Purpose: Get the number of data bytes in the Rx FIFO -Call: sGetRxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: The number of data bytes in the Rx FIFO. -Comments: Byte read of count register is required to obtain Rx count. - -*/ -#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount) - -/*************************************************************************** -Function: sGetTxCnt -Purpose: Get the number of data bytes in the Tx FIFO -Call: sGetTxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The number of data bytes in the Tx FIFO. -Comments: Byte read of count register is required to obtain Tx count. - -*/ -#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount) - -/***************************************************************************** -Function: sGetTxRxDataIO -Purpose: Get the I/O address of a channel's TxRx Data register -Call: sGetTxRxDataIO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: WordIO_t: I/O address of a channel's TxRx Data register -*/ -#define sGetTxRxDataIO(ChP) (ChP)->TxRxData - -/*************************************************************************** -Function: sInitChanDefaults -Purpose: Initialize a channel structure to it's default state. -Call: sInitChanDefaults(ChP) - CHANNEL_T *ChP; Ptr to the channel structure -Comments: This function must be called once for every channel structure - that exists before any other SSCI calls can be made. - -*/ -#define sInitChanDefaults(ChP) \ -do { \ - (ChP)->CtlP = NULLCTLPTR; \ - (ChP)->AiopNum = NULLAIOP; \ - (ChP)->ChanID = AIOPID_NULL; \ - (ChP)->ChanNum = NULLCHAN; \ -} while (0) - -/*************************************************************************** -Function: sResetAiopByNum -Purpose: Reset the AIOP by number -Call: sResetAiopByNum(CTLP,AIOPNUM) - CONTROLLER_T CTLP; Ptr to controller structure - AIOPNUM; AIOP index -*/ -#define sResetAiopByNum(CTLP,AIOPNUM) \ -do { \ - sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \ - sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \ -} while (0) - -/*************************************************************************** -Function: sSendBreak -Purpose: Send a transmit BREAK signal -Call: sSendBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSendBreak(ChP) \ -do { \ - (ChP)->TxControl[3] |= SETBREAK; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetBaud -Purpose: Set baud rate -Call: sSetBaud(ChP,Divisor) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Divisor; 16 bit baud rate divisor for channel -*/ -#define sSetBaud(ChP,DIVISOR) \ -do { \ - (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ - (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ - out32((ChP)->IndexAddr,(ChP)->BaudDiv); \ -} while (0) - -/*************************************************************************** -Function: sSetData7 -Purpose: Set data bits to 7 -Call: sSetData7(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData7(ChP) \ -do { \ - (ChP)->TxControl[2] &= ~DATA8BIT; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetData8 -Purpose: Set data bits to 8 -Call: sSetData8(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData8(ChP) \ -do { \ - (ChP)->TxControl[2] |= DATA8BIT; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetDTR -Purpose: Set the DTR output -Call: sSetDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetDTR(ChP) \ -do { \ - (ChP)->TxControl[3] |= SET_DTR; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetEvenParity -Purpose: Set even parity -Call: sSetEvenParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetEvenParity(ChP) \ -do { \ - (ChP)->TxControl[2] |= EVEN_PAR; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetOddParity -Purpose: Set odd parity -Call: sSetOddParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetOddParity(ChP) \ -do { \ - (ChP)->TxControl[2] &= ~EVEN_PAR; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetRTS -Purpose: Set the RTS output -Call: sSetRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetRTS(ChP) \ -do { \ - if ((ChP)->rtsToggle) break; \ - (ChP)->TxControl[3] |= SET_RTS; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetRxTrigger -Purpose: Set the Rx FIFO trigger level -Call: sSetRxProcessor(ChP,Level) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Level; Number of characters in Rx FIFO at which the - interrupt will be generated. Can be any of the following flags: - - TRIG_NO: no trigger - TRIG_1: 1 character in FIFO - TRIG_1_2: FIFO 1/2 full - TRIG_7_8: FIFO 7/8 full -Comments: An interrupt will be generated when the trigger level is reached - only if function sEnInterrupt() has been called with flag - RXINT_EN set. The RXF_TRIG flag in the Interrupt Idenfification - register will be set whenever the trigger level is reached - regardless of the setting of RXINT_EN. - -*/ -#define sSetRxTrigger(ChP,LEVEL) \ -do { \ - (ChP)->RxControl[2] &= ~TRIG_MASK; \ - (ChP)->RxControl[2] |= LEVEL; \ - out32((ChP)->IndexAddr,(ChP)->RxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetStop1 -Purpose: Set stop bits to 1 -Call: sSetStop1(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop1(ChP) \ -do { \ - (ChP)->TxControl[2] &= ~STOP2; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetStop2 -Purpose: Set stop bits to 2 -Call: sSetStop2(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop2(ChP) \ -do { \ - (ChP)->TxControl[2] |= STOP2; \ - out32((ChP)->IndexAddr,(ChP)->TxControl); \ -} while (0) - -/*************************************************************************** -Function: sSetTxXOFFChar -Purpose: Set the Tx XOFF flow control character -Call: sSetTxXOFFChar(ChP,Ch) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Ch; The value to set the Tx XOFF character to -*/ -#define sSetTxXOFFChar(ChP,CH) \ -do { \ - (ChP)->R[0x07] = (CH); \ - out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ -} while (0) - -/*************************************************************************** -Function: sSetTxXONChar -Purpose: Set the Tx XON flow control character -Call: sSetTxXONChar(ChP,Ch) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Ch; The value to set the Tx XON character to -*/ -#define sSetTxXONChar(ChP,CH) \ -do { \ - (ChP)->R[0x0b] = (CH); \ - out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \ -} while (0) - -/*************************************************************************** -Function: sStartRxProcessor -Purpose: Start a channel's receive processor -Call: sStartRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start a Rx processor after it was - stopped with sStopRxProcessor() or sStopSWInFlowCtl(). It - will restart both the Rx processor and software input flow control. - -*/ -#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0]) - -/*************************************************************************** -Function: sWriteTxByte -Purpose: Write a transmit data byte to a channel. - ByteIO_t io: Channel transmit register I/O address. This can - be obtained with sGetTxRxDataIO(). - Byte_t Data; The transmit data byte. -Warnings: This function writes the data byte without checking to see if - sMaxTxSize is exceeded in the Tx FIFO. -*/ -#define sWriteTxByte(IO,DATA) sOutB(IO,DATA) - -/* - * Begin Linux specific definitions for the Rocketport driver - * - * This code is Copyright Theodore Ts'o, 1995-1997 - */ - -struct r_port { - int magic; - struct tty_port port; - int line; - int flags; /* Don't yet match the ASY_ flags!! */ - unsigned int board:3; - unsigned int aiop:2; - unsigned int chan:3; - CONTROLLER_t *ctlp; - CHANNEL_t channel; - int intmask; - int xmit_fifo_room; /* room in xmit fifo */ - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; - int cd_status; - int ignore_status_mask; - int read_status_mask; - int cps; - - struct completion close_wait; /* Not yet matching the core */ - spinlock_t slock; - struct mutex write_mtx; -}; - -#define RPORT_MAGIC 0x525001 - -#define NUM_BOARDS 8 -#define MAX_RP_PORTS (32*NUM_BOARDS) - -/* - * The size of the xmit buffer is 1 page, or 4096 bytes - */ -#define XMIT_BUF_SIZE 4096 - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -/* - * Assigned major numbers for the Comtrol Rocketport - */ -#define TTY_ROCKET_MAJOR 46 -#define CUA_ROCKET_MAJOR 47 - -#ifdef PCI_VENDOR_ID_RP -#undef PCI_VENDOR_ID_RP -#undef PCI_DEVICE_ID_RP8OCTA -#undef PCI_DEVICE_ID_RP8INTF -#undef PCI_DEVICE_ID_RP16INTF -#undef PCI_DEVICE_ID_RP32INTF -#undef PCI_DEVICE_ID_URP8OCTA -#undef PCI_DEVICE_ID_URP8INTF -#undef PCI_DEVICE_ID_URP16INTF -#undef PCI_DEVICE_ID_CRP16INTF -#undef PCI_DEVICE_ID_URP32INTF -#endif - -/* Comtrol PCI Vendor ID */ -#define PCI_VENDOR_ID_RP 0x11fe - -/* Comtrol Device ID's */ -#define PCI_DEVICE_ID_RP32INTF 0x0001 /* Rocketport 32 port w/external I/F */ -#define PCI_DEVICE_ID_RP8INTF 0x0002 /* Rocketport 8 port w/external I/F */ -#define PCI_DEVICE_ID_RP16INTF 0x0003 /* Rocketport 16 port w/external I/F */ -#define PCI_DEVICE_ID_RP4QUAD 0x0004 /* Rocketport 4 port w/quad cable */ -#define PCI_DEVICE_ID_RP8OCTA 0x0005 /* Rocketport 8 port w/octa cable */ -#define PCI_DEVICE_ID_RP8J 0x0006 /* Rocketport 8 port w/RJ11 connectors */ -#define PCI_DEVICE_ID_RP4J 0x0007 /* Rocketport 4 port w/RJ11 connectors */ -#define PCI_DEVICE_ID_RP8SNI 0x0008 /* Rocketport 8 port w/ DB78 SNI (Siemens) connector */ -#define PCI_DEVICE_ID_RP16SNI 0x0009 /* Rocketport 16 port w/ DB78 SNI (Siemens) connector */ -#define PCI_DEVICE_ID_RPP4 0x000A /* Rocketport Plus 4 port */ -#define PCI_DEVICE_ID_RPP8 0x000B /* Rocketport Plus 8 port */ -#define PCI_DEVICE_ID_RP6M 0x000C /* RocketModem 6 port */ -#define PCI_DEVICE_ID_RP4M 0x000D /* RocketModem 4 port */ -#define PCI_DEVICE_ID_RP2_232 0x000E /* Rocketport Plus 2 port RS232 */ -#define PCI_DEVICE_ID_RP2_422 0x000F /* Rocketport Plus 2 port RS422 */ - -/* Universal PCI boards */ -#define PCI_DEVICE_ID_URP32INTF 0x0801 /* Rocketport UPCI 32 port w/external I/F */ -#define PCI_DEVICE_ID_URP8INTF 0x0802 /* Rocketport UPCI 8 port w/external I/F */ -#define PCI_DEVICE_ID_URP16INTF 0x0803 /* Rocketport UPCI 16 port w/external I/F */ -#define PCI_DEVICE_ID_URP8OCTA 0x0805 /* Rocketport UPCI 8 port w/octa cable */ -#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C /* Rocketmodem III 8 port */ -#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D /* Rocketmodem III 4 port */ - -/* Compact PCI device */ -#define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */ - diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c deleted file mode 100644 index 18888d005a0a..000000000000 --- a/drivers/char/synclink.c +++ /dev/null @@ -1,8119 +0,0 @@ -/* - * linux/drivers/char/synclink.c - * - * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ - * - * Device driver for Microgate SyncLink ISA and PCI - * high speed multiprotocol serial adapters. - * - * written by Paul Fulghum for Microgate Corporation - * paulkf@microgate.com - * - * Microgate and SyncLink are trademarks of Microgate Corporation - * - * Derived from serial.c written by Theodore Ts'o and Linus Torvalds - * - * Original release 01/11/99 - * - * This code is released under the GNU General Public License (GPL) - * - * This driver is primarily intended for use in synchronous - * HDLC mode. Asynchronous mode is also provided. - * - * When operating in synchronous mode, each call to mgsl_write() - * contains exactly one complete HDLC frame. Calling mgsl_put_char - * will start assembling an HDLC frame that will not be sent until - * mgsl_flush_chars or mgsl_write is called. - * - * Synchronous receive data is reported as complete frames. To accomplish - * this, the TTY flip buffer is bypassed (too small to hold largest - * frame and may fragment frames) and the line discipline - * receive entry point is called directly. - * - * This driver has been tested with a slightly modified ppp.c driver - * for synchronous PPP. - * - * 2000/02/16 - * Added interface for syncppp.c driver (an alternate synchronous PPP - * implementation that also supports Cisco HDLC). Each device instance - * registers as a tty device AND a network device (if dosyncppp option - * is set for the device). The functionality is determined by which - * device interface is opened. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(__i386__) -# define BREAKPOINT() asm(" int $3"); -#else -# define BREAKPOINT() { } -#endif - -#define MAX_ISA_DEVICES 10 -#define MAX_PCI_DEVICES 10 -#define MAX_TOTAL_DEVICES 20 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE)) -#define SYNCLINK_GENERIC_HDLC 1 -#else -#define SYNCLINK_GENERIC_HDLC 0 -#endif - -#define GET_USER(error,value,addr) error = get_user(value,addr) -#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 -#define PUT_USER(error,value,addr) error = put_user(value,addr) -#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 - -#include - -#define RCLRVALUE 0xffff - -static MGSL_PARAMS default_params = { - MGSL_MODE_HDLC, /* unsigned long mode */ - 0, /* unsigned char loopback; */ - HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */ - HDLC_ENCODING_NRZI_SPACE, /* unsigned char encoding; */ - 0, /* unsigned long clock_speed; */ - 0xff, /* unsigned char addr_filter; */ - HDLC_CRC_16_CCITT, /* unsigned short crc_type; */ - HDLC_PREAMBLE_LENGTH_8BITS, /* unsigned char preamble_length; */ - HDLC_PREAMBLE_PATTERN_NONE, /* unsigned char preamble; */ - 9600, /* unsigned long data_rate; */ - 8, /* unsigned char data_bits; */ - 1, /* unsigned char stop_bits; */ - ASYNC_PARITY_NONE /* unsigned char parity; */ -}; - -#define SHARED_MEM_ADDRESS_SIZE 0x40000 -#define BUFFERLISTSIZE 4096 -#define DMABUFFERSIZE 4096 -#define MAXRXFRAMES 7 - -typedef struct _DMABUFFERENTRY -{ - u32 phys_addr; /* 32-bit flat physical address of data buffer */ - volatile u16 count; /* buffer size/data count */ - volatile u16 status; /* Control/status field */ - volatile u16 rcc; /* character count field */ - u16 reserved; /* padding required by 16C32 */ - u32 link; /* 32-bit flat link to next buffer entry */ - char *virt_addr; /* virtual address of data buffer */ - u32 phys_entry; /* physical address of this buffer entry */ - dma_addr_t dma_addr; -} DMABUFFERENTRY, *DMAPBUFFERENTRY; - -/* The queue of BH actions to be performed */ - -#define BH_RECEIVE 1 -#define BH_TRANSMIT 2 -#define BH_STATUS 4 - -#define IO_PIN_SHUTDOWN_LIMIT 100 - -struct _input_signal_events { - int ri_up; - int ri_down; - int dsr_up; - int dsr_down; - int dcd_up; - int dcd_down; - int cts_up; - int cts_down; -}; - -/* transmit holding buffer definitions*/ -#define MAX_TX_HOLDING_BUFFERS 5 -struct tx_holding_buffer { - int buffer_size; - unsigned char * buffer; -}; - - -/* - * Device instance data structure - */ - -struct mgsl_struct { - int magic; - struct tty_port port; - int line; - int hw_version; - - struct mgsl_icount icount; - - int timeout; - int x_char; /* xon/xoff character */ - u16 read_status_mask; - u16 ignore_status_mask; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; - - wait_queue_head_t status_event_wait_q; - wait_queue_head_t event_wait_q; - struct timer_list tx_timer; /* HDLC transmit timeout timer */ - struct mgsl_struct *next_device; /* device list link */ - - spinlock_t irq_spinlock; /* spinlock for synchronizing with ISR */ - struct work_struct task; /* task structure for scheduling bh */ - - u32 EventMask; /* event trigger mask */ - u32 RecordedEvents; /* pending events */ - - u32 max_frame_size; /* as set by device config */ - - u32 pending_bh; - - bool bh_running; /* Protection from multiple */ - int isr_overflow; - bool bh_requested; - - int dcd_chkcount; /* check counts to prevent */ - int cts_chkcount; /* too many IRQs if a signal */ - int dsr_chkcount; /* is floating */ - int ri_chkcount; - - char *buffer_list; /* virtual address of Rx & Tx buffer lists */ - u32 buffer_list_phys; - dma_addr_t buffer_list_dma_addr; - - unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ - DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ - unsigned int current_rx_buffer; - - int num_tx_dma_buffers; /* number of tx dma frames required */ - int tx_dma_buffers_used; - unsigned int tx_buffer_count; /* count of total allocated Tx buffers */ - DMABUFFERENTRY *tx_buffer_list; /* list of transmit buffer entries */ - int start_tx_dma_buffer; /* tx dma buffer to start tx dma operation */ - int current_tx_buffer; /* next tx dma buffer to be loaded */ - - unsigned char *intermediate_rxbuffer; - - int num_tx_holding_buffers; /* number of tx holding buffer allocated */ - int get_tx_holding_index; /* next tx holding buffer for adapter to load */ - int put_tx_holding_index; /* next tx holding buffer to store user request */ - int tx_holding_count; /* number of tx holding buffers waiting */ - struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS]; - - bool rx_enabled; - bool rx_overflow; - bool rx_rcc_underrun; - - bool tx_enabled; - bool tx_active; - u32 idle_mode; - - u16 cmr_value; - u16 tcsr_value; - - char device_name[25]; /* device instance name */ - - unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */ - unsigned char bus; /* expansion bus number (zero based) */ - unsigned char function; /* PCI device number */ - - unsigned int io_base; /* base I/O address of adapter */ - unsigned int io_addr_size; /* size of the I/O address range */ - bool io_addr_requested; /* true if I/O address requested */ - - unsigned int irq_level; /* interrupt level */ - unsigned long irq_flags; - bool irq_requested; /* true if IRQ requested */ - - unsigned int dma_level; /* DMA channel */ - bool dma_requested; /* true if dma channel requested */ - - u16 mbre_bit; - u16 loopback_bits; - u16 usc_idle_mode; - - MGSL_PARAMS params; /* communications parameters */ - - unsigned char serial_signals; /* current serial signal states */ - - bool irq_occurred; /* for diagnostics use */ - unsigned int init_error; /* Initialization startup error (DIAGS) */ - int fDiagnosticsmode; /* Driver in Diagnostic mode? (DIAGS) */ - - u32 last_mem_alloc; - unsigned char* memory_base; /* shared memory address (PCI only) */ - u32 phys_memory_base; - bool shared_mem_requested; - - unsigned char* lcr_base; /* local config registers (PCI only) */ - u32 phys_lcr_base; - u32 lcr_offset; - bool lcr_mem_requested; - - u32 misc_ctrl_value; - char flag_buf[MAX_ASYNC_BUFFER_SIZE]; - char char_buf[MAX_ASYNC_BUFFER_SIZE]; - bool drop_rts_on_tx_done; - - bool loopmode_insert_requested; - bool loopmode_send_done_requested; - - struct _input_signal_events input_signal_events; - - /* generic HDLC device parts */ - int netcount; - spinlock_t netlock; - -#if SYNCLINK_GENERIC_HDLC - struct net_device *netdev; -#endif -}; - -#define MGSL_MAGIC 0x5401 - -/* - * The size of the serial xmit buffer is 1 page, or 4096 bytes - */ -#ifndef SERIAL_XMIT_SIZE -#define SERIAL_XMIT_SIZE 4096 -#endif - -/* - * These macros define the offsets used in calculating the - * I/O address of the specified USC registers. - */ - - -#define DCPIN 2 /* Bit 1 of I/O address */ -#define SDPIN 4 /* Bit 2 of I/O address */ - -#define DCAR 0 /* DMA command/address register */ -#define CCAR SDPIN /* channel command/address register */ -#define DATAREG DCPIN + SDPIN /* serial data register */ -#define MSBONLY 0x41 -#define LSBONLY 0x40 - -/* - * These macros define the register address (ordinal number) - * used for writing address/value pairs to the USC. - */ - -#define CMR 0x02 /* Channel mode Register */ -#define CCSR 0x04 /* Channel Command/status Register */ -#define CCR 0x06 /* Channel Control Register */ -#define PSR 0x08 /* Port status Register */ -#define PCR 0x0a /* Port Control Register */ -#define TMDR 0x0c /* Test mode Data Register */ -#define TMCR 0x0e /* Test mode Control Register */ -#define CMCR 0x10 /* Clock mode Control Register */ -#define HCR 0x12 /* Hardware Configuration Register */ -#define IVR 0x14 /* Interrupt Vector Register */ -#define IOCR 0x16 /* Input/Output Control Register */ -#define ICR 0x18 /* Interrupt Control Register */ -#define DCCR 0x1a /* Daisy Chain Control Register */ -#define MISR 0x1c /* Misc Interrupt status Register */ -#define SICR 0x1e /* status Interrupt Control Register */ -#define RDR 0x20 /* Receive Data Register */ -#define RMR 0x22 /* Receive mode Register */ -#define RCSR 0x24 /* Receive Command/status Register */ -#define RICR 0x26 /* Receive Interrupt Control Register */ -#define RSR 0x28 /* Receive Sync Register */ -#define RCLR 0x2a /* Receive count Limit Register */ -#define RCCR 0x2c /* Receive Character count Register */ -#define TC0R 0x2e /* Time Constant 0 Register */ -#define TDR 0x30 /* Transmit Data Register */ -#define TMR 0x32 /* Transmit mode Register */ -#define TCSR 0x34 /* Transmit Command/status Register */ -#define TICR 0x36 /* Transmit Interrupt Control Register */ -#define TSR 0x38 /* Transmit Sync Register */ -#define TCLR 0x3a /* Transmit count Limit Register */ -#define TCCR 0x3c /* Transmit Character count Register */ -#define TC1R 0x3e /* Time Constant 1 Register */ - - -/* - * MACRO DEFINITIONS FOR DMA REGISTERS - */ - -#define DCR 0x06 /* DMA Control Register (shared) */ -#define DACR 0x08 /* DMA Array count Register (shared) */ -#define BDCR 0x12 /* Burst/Dwell Control Register (shared) */ -#define DIVR 0x14 /* DMA Interrupt Vector Register (shared) */ -#define DICR 0x18 /* DMA Interrupt Control Register (shared) */ -#define CDIR 0x1a /* Clear DMA Interrupt Register (shared) */ -#define SDIR 0x1c /* Set DMA Interrupt Register (shared) */ - -#define TDMR 0x02 /* Transmit DMA mode Register */ -#define TDIAR 0x1e /* Transmit DMA Interrupt Arm Register */ -#define TBCR 0x2a /* Transmit Byte count Register */ -#define TARL 0x2c /* Transmit Address Register (low) */ -#define TARU 0x2e /* Transmit Address Register (high) */ -#define NTBCR 0x3a /* Next Transmit Byte count Register */ -#define NTARL 0x3c /* Next Transmit Address Register (low) */ -#define NTARU 0x3e /* Next Transmit Address Register (high) */ - -#define RDMR 0x82 /* Receive DMA mode Register (non-shared) */ -#define RDIAR 0x9e /* Receive DMA Interrupt Arm Register */ -#define RBCR 0xaa /* Receive Byte count Register */ -#define RARL 0xac /* Receive Address Register (low) */ -#define RARU 0xae /* Receive Address Register (high) */ -#define NRBCR 0xba /* Next Receive Byte count Register */ -#define NRARL 0xbc /* Next Receive Address Register (low) */ -#define NRARU 0xbe /* Next Receive Address Register (high) */ - - -/* - * MACRO DEFINITIONS FOR MODEM STATUS BITS - */ - -#define MODEMSTATUS_DTR 0x80 -#define MODEMSTATUS_DSR 0x40 -#define MODEMSTATUS_RTS 0x20 -#define MODEMSTATUS_CTS 0x10 -#define MODEMSTATUS_RI 0x04 -#define MODEMSTATUS_DCD 0x01 - - -/* - * Channel Command/Address Register (CCAR) Command Codes - */ - -#define RTCmd_Null 0x0000 -#define RTCmd_ResetHighestIus 0x1000 -#define RTCmd_TriggerChannelLoadDma 0x2000 -#define RTCmd_TriggerRxDma 0x2800 -#define RTCmd_TriggerTxDma 0x3000 -#define RTCmd_TriggerRxAndTxDma 0x3800 -#define RTCmd_PurgeRxFifo 0x4800 -#define RTCmd_PurgeTxFifo 0x5000 -#define RTCmd_PurgeRxAndTxFifo 0x5800 -#define RTCmd_LoadRcc 0x6800 -#define RTCmd_LoadTcc 0x7000 -#define RTCmd_LoadRccAndTcc 0x7800 -#define RTCmd_LoadTC0 0x8800 -#define RTCmd_LoadTC1 0x9000 -#define RTCmd_LoadTC0AndTC1 0x9800 -#define RTCmd_SerialDataLSBFirst 0xa000 -#define RTCmd_SerialDataMSBFirst 0xa800 -#define RTCmd_SelectBigEndian 0xb000 -#define RTCmd_SelectLittleEndian 0xb800 - - -/* - * DMA Command/Address Register (DCAR) Command Codes - */ - -#define DmaCmd_Null 0x0000 -#define DmaCmd_ResetTxChannel 0x1000 -#define DmaCmd_ResetRxChannel 0x1200 -#define DmaCmd_StartTxChannel 0x2000 -#define DmaCmd_StartRxChannel 0x2200 -#define DmaCmd_ContinueTxChannel 0x3000 -#define DmaCmd_ContinueRxChannel 0x3200 -#define DmaCmd_PauseTxChannel 0x4000 -#define DmaCmd_PauseRxChannel 0x4200 -#define DmaCmd_AbortTxChannel 0x5000 -#define DmaCmd_AbortRxChannel 0x5200 -#define DmaCmd_InitTxChannel 0x7000 -#define DmaCmd_InitRxChannel 0x7200 -#define DmaCmd_ResetHighestDmaIus 0x8000 -#define DmaCmd_ResetAllChannels 0x9000 -#define DmaCmd_StartAllChannels 0xa000 -#define DmaCmd_ContinueAllChannels 0xb000 -#define DmaCmd_PauseAllChannels 0xc000 -#define DmaCmd_AbortAllChannels 0xd000 -#define DmaCmd_InitAllChannels 0xf000 - -#define TCmd_Null 0x0000 -#define TCmd_ClearTxCRC 0x2000 -#define TCmd_SelectTicrTtsaData 0x4000 -#define TCmd_SelectTicrTxFifostatus 0x5000 -#define TCmd_SelectTicrIntLevel 0x6000 -#define TCmd_SelectTicrdma_level 0x7000 -#define TCmd_SendFrame 0x8000 -#define TCmd_SendAbort 0x9000 -#define TCmd_EnableDleInsertion 0xc000 -#define TCmd_DisableDleInsertion 0xd000 -#define TCmd_ClearEofEom 0xe000 -#define TCmd_SetEofEom 0xf000 - -#define RCmd_Null 0x0000 -#define RCmd_ClearRxCRC 0x2000 -#define RCmd_EnterHuntmode 0x3000 -#define RCmd_SelectRicrRtsaData 0x4000 -#define RCmd_SelectRicrRxFifostatus 0x5000 -#define RCmd_SelectRicrIntLevel 0x6000 -#define RCmd_SelectRicrdma_level 0x7000 - -/* - * Bits for enabling and disabling IRQs in Interrupt Control Register (ICR) - */ - -#define RECEIVE_STATUS BIT5 -#define RECEIVE_DATA BIT4 -#define TRANSMIT_STATUS BIT3 -#define TRANSMIT_DATA BIT2 -#define IO_PIN BIT1 -#define MISC BIT0 - - -/* - * Receive status Bits in Receive Command/status Register RCSR - */ - -#define RXSTATUS_SHORT_FRAME BIT8 -#define RXSTATUS_CODE_VIOLATION BIT8 -#define RXSTATUS_EXITED_HUNT BIT7 -#define RXSTATUS_IDLE_RECEIVED BIT6 -#define RXSTATUS_BREAK_RECEIVED BIT5 -#define RXSTATUS_ABORT_RECEIVED BIT5 -#define RXSTATUS_RXBOUND BIT4 -#define RXSTATUS_CRC_ERROR BIT3 -#define RXSTATUS_FRAMING_ERROR BIT3 -#define RXSTATUS_ABORT BIT2 -#define RXSTATUS_PARITY_ERROR BIT2 -#define RXSTATUS_OVERRUN BIT1 -#define RXSTATUS_DATA_AVAILABLE BIT0 -#define RXSTATUS_ALL 0x01f6 -#define usc_UnlatchRxstatusBits(a,b) usc_OutReg( (a), RCSR, (u16)((b) & RXSTATUS_ALL) ) - -/* - * Values for setting transmit idle mode in - * Transmit Control/status Register (TCSR) - */ -#define IDLEMODE_FLAGS 0x0000 -#define IDLEMODE_ALT_ONE_ZERO 0x0100 -#define IDLEMODE_ZERO 0x0200 -#define IDLEMODE_ONE 0x0300 -#define IDLEMODE_ALT_MARK_SPACE 0x0500 -#define IDLEMODE_SPACE 0x0600 -#define IDLEMODE_MARK 0x0700 -#define IDLEMODE_MASK 0x0700 - -/* - * IUSC revision identifiers - */ -#define IUSC_SL1660 0x4d44 -#define IUSC_PRE_SL1660 0x4553 - -/* - * Transmit status Bits in Transmit Command/status Register (TCSR) - */ - -#define TCSR_PRESERVE 0x0F00 - -#define TCSR_UNDERWAIT BIT11 -#define TXSTATUS_PREAMBLE_SENT BIT7 -#define TXSTATUS_IDLE_SENT BIT6 -#define TXSTATUS_ABORT_SENT BIT5 -#define TXSTATUS_EOF_SENT BIT4 -#define TXSTATUS_EOM_SENT BIT4 -#define TXSTATUS_CRC_SENT BIT3 -#define TXSTATUS_ALL_SENT BIT2 -#define TXSTATUS_UNDERRUN BIT1 -#define TXSTATUS_FIFO_EMPTY BIT0 -#define TXSTATUS_ALL 0x00fa -#define usc_UnlatchTxstatusBits(a,b) usc_OutReg( (a), TCSR, (u16)((a)->tcsr_value + ((b) & 0x00FF)) ) - - -#define MISCSTATUS_RXC_LATCHED BIT15 -#define MISCSTATUS_RXC BIT14 -#define MISCSTATUS_TXC_LATCHED BIT13 -#define MISCSTATUS_TXC BIT12 -#define MISCSTATUS_RI_LATCHED BIT11 -#define MISCSTATUS_RI BIT10 -#define MISCSTATUS_DSR_LATCHED BIT9 -#define MISCSTATUS_DSR BIT8 -#define MISCSTATUS_DCD_LATCHED BIT7 -#define MISCSTATUS_DCD BIT6 -#define MISCSTATUS_CTS_LATCHED BIT5 -#define MISCSTATUS_CTS BIT4 -#define MISCSTATUS_RCC_UNDERRUN BIT3 -#define MISCSTATUS_DPLL_NO_SYNC BIT2 -#define MISCSTATUS_BRG1_ZERO BIT1 -#define MISCSTATUS_BRG0_ZERO BIT0 - -#define usc_UnlatchIostatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0xaaa0)) -#define usc_UnlatchMiscstatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0x000f)) - -#define SICR_RXC_ACTIVE BIT15 -#define SICR_RXC_INACTIVE BIT14 -#define SICR_RXC (BIT15+BIT14) -#define SICR_TXC_ACTIVE BIT13 -#define SICR_TXC_INACTIVE BIT12 -#define SICR_TXC (BIT13+BIT12) -#define SICR_RI_ACTIVE BIT11 -#define SICR_RI_INACTIVE BIT10 -#define SICR_RI (BIT11+BIT10) -#define SICR_DSR_ACTIVE BIT9 -#define SICR_DSR_INACTIVE BIT8 -#define SICR_DSR (BIT9+BIT8) -#define SICR_DCD_ACTIVE BIT7 -#define SICR_DCD_INACTIVE BIT6 -#define SICR_DCD (BIT7+BIT6) -#define SICR_CTS_ACTIVE BIT5 -#define SICR_CTS_INACTIVE BIT4 -#define SICR_CTS (BIT5+BIT4) -#define SICR_RCC_UNDERFLOW BIT3 -#define SICR_DPLL_NO_SYNC BIT2 -#define SICR_BRG1_ZERO BIT1 -#define SICR_BRG0_ZERO BIT0 - -void usc_DisableMasterIrqBit( struct mgsl_struct *info ); -void usc_EnableMasterIrqBit( struct mgsl_struct *info ); -void usc_EnableInterrupts( struct mgsl_struct *info, u16 IrqMask ); -void usc_DisableInterrupts( struct mgsl_struct *info, u16 IrqMask ); -void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask ); - -#define usc_EnableInterrupts( a, b ) \ - usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0xc0 + (b)) ) - -#define usc_DisableInterrupts( a, b ) \ - usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0x80 + (b)) ) - -#define usc_EnableMasterIrqBit(a) \ - usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0x0f00) + 0xb000) ) - -#define usc_DisableMasterIrqBit(a) \ - usc_OutReg( (a), ICR, (u16)(usc_InReg((a),ICR) & 0x7f00) ) - -#define usc_ClearIrqPendingBits( a, b ) usc_OutReg( (a), DCCR, 0x40 + (b) ) - -/* - * Transmit status Bits in Transmit Control status Register (TCSR) - * and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) - */ - -#define TXSTATUS_PREAMBLE_SENT BIT7 -#define TXSTATUS_IDLE_SENT BIT6 -#define TXSTATUS_ABORT_SENT BIT5 -#define TXSTATUS_EOF BIT4 -#define TXSTATUS_CRC_SENT BIT3 -#define TXSTATUS_ALL_SENT BIT2 -#define TXSTATUS_UNDERRUN BIT1 -#define TXSTATUS_FIFO_EMPTY BIT0 - -#define DICR_MASTER BIT15 -#define DICR_TRANSMIT BIT0 -#define DICR_RECEIVE BIT1 - -#define usc_EnableDmaInterrupts(a,b) \ - usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) | (b)) ) - -#define usc_DisableDmaInterrupts(a,b) \ - usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) & ~(b)) ) - -#define usc_EnableStatusIrqs(a,b) \ - usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) | (b)) ) - -#define usc_DisablestatusIrqs(a,b) \ - usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) & ~(b)) ) - -/* Transmit status Bits in Transmit Control status Register (TCSR) */ -/* and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) */ - - -#define DISABLE_UNCONDITIONAL 0 -#define DISABLE_END_OF_FRAME 1 -#define ENABLE_UNCONDITIONAL 2 -#define ENABLE_AUTO_CTS 3 -#define ENABLE_AUTO_DCD 3 -#define usc_EnableTransmitter(a,b) \ - usc_OutReg( (a), TMR, (u16)((usc_InReg((a),TMR) & 0xfffc) | (b)) ) -#define usc_EnableReceiver(a,b) \ - usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) ) - -static u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port ); -static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value ); -static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ); - -static u16 usc_InReg( struct mgsl_struct *info, u16 Port ); -static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value ); -static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ); -void usc_RCmd( struct mgsl_struct *info, u16 Cmd ); -void usc_TCmd( struct mgsl_struct *info, u16 Cmd ); - -#define usc_TCmd(a,b) usc_OutReg((a), TCSR, (u16)((a)->tcsr_value + (b))) -#define usc_RCmd(a,b) usc_OutReg((a), RCSR, (b)) - -#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1)) - -static void usc_process_rxoverrun_sync( struct mgsl_struct *info ); -static void usc_start_receiver( struct mgsl_struct *info ); -static void usc_stop_receiver( struct mgsl_struct *info ); - -static void usc_start_transmitter( struct mgsl_struct *info ); -static void usc_stop_transmitter( struct mgsl_struct *info ); -static void usc_set_txidle( struct mgsl_struct *info ); -static void usc_load_txfifo( struct mgsl_struct *info ); - -static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate ); -static void usc_enable_loopback( struct mgsl_struct *info, int enable ); - -static void usc_get_serial_signals( struct mgsl_struct *info ); -static void usc_set_serial_signals( struct mgsl_struct *info ); - -static void usc_reset( struct mgsl_struct *info ); - -static void usc_set_sync_mode( struct mgsl_struct *info ); -static void usc_set_sdlc_mode( struct mgsl_struct *info ); -static void usc_set_async_mode( struct mgsl_struct *info ); -static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate ); - -static void usc_loopback_frame( struct mgsl_struct *info ); - -static void mgsl_tx_timeout(unsigned long context); - - -static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ); -static void usc_loopmode_insert_request( struct mgsl_struct * info ); -static int usc_loopmode_active( struct mgsl_struct * info); -static void usc_loopmode_send_done( struct mgsl_struct * info ); - -static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); - -#if SYNCLINK_GENERIC_HDLC -#define dev_to_port(D) (dev_to_hdlc(D)->priv) -static void hdlcdev_tx_done(struct mgsl_struct *info); -static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size); -static int hdlcdev_init(struct mgsl_struct *info); -static void hdlcdev_exit(struct mgsl_struct *info); -#endif - -/* - * Defines a BUS descriptor value for the PCI adapter - * local bus address ranges. - */ - -#define BUS_DESCRIPTOR( WrHold, WrDly, RdDly, Nwdd, Nwad, Nxda, Nrdd, Nrad ) \ -(0x00400020 + \ -((WrHold) << 30) + \ -((WrDly) << 28) + \ -((RdDly) << 26) + \ -((Nwdd) << 20) + \ -((Nwad) << 15) + \ -((Nxda) << 13) + \ -((Nrdd) << 11) + \ -((Nrad) << 6) ) - -static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit); - -/* - * Adapter diagnostic routines - */ -static bool mgsl_register_test( struct mgsl_struct *info ); -static bool mgsl_irq_test( struct mgsl_struct *info ); -static bool mgsl_dma_test( struct mgsl_struct *info ); -static bool mgsl_memory_test( struct mgsl_struct *info ); -static int mgsl_adapter_test( struct mgsl_struct *info ); - -/* - * device and resource management routines - */ -static int mgsl_claim_resources(struct mgsl_struct *info); -static void mgsl_release_resources(struct mgsl_struct *info); -static void mgsl_add_device(struct mgsl_struct *info); -static struct mgsl_struct* mgsl_allocate_device(void); - -/* - * DMA buffer manupulation functions. - */ -static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ); -static bool mgsl_get_rx_frame( struct mgsl_struct *info ); -static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info ); -static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ); -static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ); -static int num_free_tx_dma_buffers(struct mgsl_struct *info); -static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize); -static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count); - -/* - * DMA and Shared Memory buffer allocation and formatting - */ -static int mgsl_allocate_dma_buffers(struct mgsl_struct *info); -static void mgsl_free_dma_buffers(struct mgsl_struct *info); -static int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); -static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); -static int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info); -static void mgsl_free_buffer_list_memory(struct mgsl_struct *info); -static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info); -static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info); -static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info); -static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info); -static bool load_next_tx_holding_buffer(struct mgsl_struct *info); -static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize); - -/* - * Bottom half interrupt handlers - */ -static void mgsl_bh_handler(struct work_struct *work); -static void mgsl_bh_receive(struct mgsl_struct *info); -static void mgsl_bh_transmit(struct mgsl_struct *info); -static void mgsl_bh_status(struct mgsl_struct *info); - -/* - * Interrupt handler routines and dispatch table. - */ -static void mgsl_isr_null( struct mgsl_struct *info ); -static void mgsl_isr_transmit_data( struct mgsl_struct *info ); -static void mgsl_isr_receive_data( struct mgsl_struct *info ); -static void mgsl_isr_receive_status( struct mgsl_struct *info ); -static void mgsl_isr_transmit_status( struct mgsl_struct *info ); -static void mgsl_isr_io_pin( struct mgsl_struct *info ); -static void mgsl_isr_misc( struct mgsl_struct *info ); -static void mgsl_isr_receive_dma( struct mgsl_struct *info ); -static void mgsl_isr_transmit_dma( struct mgsl_struct *info ); - -typedef void (*isr_dispatch_func)(struct mgsl_struct *); - -static isr_dispatch_func UscIsrTable[7] = -{ - mgsl_isr_null, - mgsl_isr_misc, - mgsl_isr_io_pin, - mgsl_isr_transmit_data, - mgsl_isr_transmit_status, - mgsl_isr_receive_data, - mgsl_isr_receive_status -}; - -/* - * ioctl call handlers - */ -static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear); -static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount - __user *user_icount); -static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params); -static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params); -static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode); -static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode); -static int mgsl_txenable(struct mgsl_struct * info, int enable); -static int mgsl_txabort(struct mgsl_struct * info); -static int mgsl_rxenable(struct mgsl_struct * info, int enable); -static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask); -static int mgsl_loopmode_send_done( struct mgsl_struct * info ); - -/* set non-zero on successful registration with PCI subsystem */ -static bool pci_registered; - -/* - * Global linked list of SyncLink devices - */ -static struct mgsl_struct *mgsl_device_list; -static int mgsl_device_count; - -/* - * Set this param to non-zero to load eax with the - * .text section address and breakpoint on module load. - * This is useful for use with gdb and add-symbol-file command. - */ -static int break_on_load; - -/* - * Driver major number, defaults to zero to get auto - * assigned major number. May be forced as module parameter. - */ -static int ttymajor; - -/* - * Array of user specified options for ISA adapters. - */ -static int io[MAX_ISA_DEVICES]; -static int irq[MAX_ISA_DEVICES]; -static int dma[MAX_ISA_DEVICES]; -static int debug_level; -static int maxframe[MAX_TOTAL_DEVICES]; -static int txdmabufs[MAX_TOTAL_DEVICES]; -static int txholdbufs[MAX_TOTAL_DEVICES]; - -module_param(break_on_load, bool, 0); -module_param(ttymajor, int, 0); -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param_array(dma, int, NULL, 0); -module_param(debug_level, int, 0); -module_param_array(maxframe, int, NULL, 0); -module_param_array(txdmabufs, int, NULL, 0); -module_param_array(txholdbufs, int, NULL, 0); - -static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.38 $"; - -static int synclink_init_one (struct pci_dev *dev, - const struct pci_device_id *ent); -static void synclink_remove_one (struct pci_dev *dev); - -static struct pci_device_id synclink_pci_tbl[] = { - { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); - -MODULE_LICENSE("GPL"); - -static struct pci_driver synclink_pci_driver = { - .name = "synclink", - .id_table = synclink_pci_tbl, - .probe = synclink_init_one, - .remove = __devexit_p(synclink_remove_one), -}; - -static struct tty_driver *serial_driver; - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - - -static void mgsl_change_params(struct mgsl_struct *info); -static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout); - -/* - * 1st function defined in .text section. Calling this function in - * init_module() followed by a breakpoint allows a remote debugger - * (gdb) to get the .text address for the add-symbol-file command. - * This allows remote debugging of dynamically loadable modules. - */ -static void* mgsl_get_text_ptr(void) -{ - return mgsl_get_text_ptr; -} - -static inline int mgsl_paranoia_check(struct mgsl_struct *info, - char *name, const char *routine) -{ -#ifdef MGSL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for mgsl struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null mgsl_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != MGSL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#else - if (!info) - return 1; -#endif - return 0; -} - -/** - * line discipline callback wrappers - * - * The wrappers maintain line discipline references - * while calling into the line discipline. - * - * ldisc_receive_buf - pass receive data to line discipline - */ - -static void ldisc_receive_buf(struct tty_struct *tty, - const __u8 *data, char *flags, int count) -{ - struct tty_ldisc *ld; - if (!tty) - return; - ld = tty_ldisc_ref(tty); - if (ld) { - if (ld->ops->receive_buf) - ld->ops->receive_buf(tty, data, flags, count); - tty_ldisc_deref(ld); - } -} - -/* mgsl_stop() throttle (stop) transmitter - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static void mgsl_stop(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (mgsl_paranoia_check(info, tty->name, "mgsl_stop")) - return; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("mgsl_stop(%s)\n",info->device_name); - - spin_lock_irqsave(&info->irq_spinlock,flags); - if (info->tx_enabled) - usc_stop_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - -} /* end of mgsl_stop() */ - -/* mgsl_start() release (start) transmitter - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static void mgsl_start(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (mgsl_paranoia_check(info, tty->name, "mgsl_start")) - return; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("mgsl_start(%s)\n",info->device_name); - - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!info->tx_enabled) - usc_start_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - -} /* end of mgsl_start() */ - -/* - * Bottom half work queue access functions - */ - -/* mgsl_bh_action() Return next bottom half action to perform. - * Return Value: BH action code or 0 if nothing to do. - */ -static int mgsl_bh_action(struct mgsl_struct *info) -{ - unsigned long flags; - int rc = 0; - - spin_lock_irqsave(&info->irq_spinlock,flags); - - if (info->pending_bh & BH_RECEIVE) { - info->pending_bh &= ~BH_RECEIVE; - rc = BH_RECEIVE; - } else if (info->pending_bh & BH_TRANSMIT) { - info->pending_bh &= ~BH_TRANSMIT; - rc = BH_TRANSMIT; - } else if (info->pending_bh & BH_STATUS) { - info->pending_bh &= ~BH_STATUS; - rc = BH_STATUS; - } - - if (!rc) { - /* Mark BH routine as complete */ - info->bh_running = false; - info->bh_requested = false; - } - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - return rc; -} - -/* - * Perform bottom half processing of work items queued by ISR. - */ -static void mgsl_bh_handler(struct work_struct *work) -{ - struct mgsl_struct *info = - container_of(work, struct mgsl_struct, task); - int action; - - if (!info) - return; - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):mgsl_bh_handler(%s) entry\n", - __FILE__,__LINE__,info->device_name); - - info->bh_running = true; - - while((action = mgsl_bh_action(info)) != 0) { - - /* Process work item */ - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):mgsl_bh_handler() work item action=%d\n", - __FILE__,__LINE__,action); - - switch (action) { - - case BH_RECEIVE: - mgsl_bh_receive(info); - break; - case BH_TRANSMIT: - mgsl_bh_transmit(info); - break; - case BH_STATUS: - mgsl_bh_status(info); - break; - default: - /* unknown work item ID */ - printk("Unknown work item ID=%08X!\n", action); - break; - } - } - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):mgsl_bh_handler(%s) exit\n", - __FILE__,__LINE__,info->device_name); -} - -static void mgsl_bh_receive(struct mgsl_struct *info) -{ - bool (*get_rx_frame)(struct mgsl_struct *info) = - (info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame); - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):mgsl_bh_receive(%s)\n", - __FILE__,__LINE__,info->device_name); - - do - { - if (info->rx_rcc_underrun) { - unsigned long flags; - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_start_receiver(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - return; - } - } while(get_rx_frame(info)); -} - -static void mgsl_bh_transmit(struct mgsl_struct *info) -{ - struct tty_struct *tty = info->port.tty; - unsigned long flags; - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):mgsl_bh_transmit() entry on %s\n", - __FILE__,__LINE__,info->device_name); - - if (tty) - tty_wakeup(tty); - - /* if transmitter idle and loopmode_send_done_requested - * then start echoing RxD to TxD - */ - spin_lock_irqsave(&info->irq_spinlock,flags); - if ( !info->tx_active && info->loopmode_send_done_requested ) - usc_loopmode_send_done( info ); - spin_unlock_irqrestore(&info->irq_spinlock,flags); -} - -static void mgsl_bh_status(struct mgsl_struct *info) -{ - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):mgsl_bh_status() entry on %s\n", - __FILE__,__LINE__,info->device_name); - - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - info->dcd_chkcount = 0; - info->cts_chkcount = 0; -} - -/* mgsl_isr_receive_status() - * - * Service a receive status interrupt. The type of status - * interrupt is indicated by the state of the RCSR. - * This is only used for HDLC mode. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_receive_status( struct mgsl_struct *info ) -{ - u16 status = usc_InReg( info, RCSR ); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_receive_status status=%04X\n", - __FILE__,__LINE__,status); - - if ( (status & RXSTATUS_ABORT_RECEIVED) && - info->loopmode_insert_requested && - usc_loopmode_active(info) ) - { - ++info->icount.rxabort; - info->loopmode_insert_requested = false; - - /* clear CMR:13 to start echoing RxD to TxD */ - info->cmr_value &= ~BIT13; - usc_OutReg(info, CMR, info->cmr_value); - - /* disable received abort irq (no longer required) */ - usc_OutReg(info, RICR, - (usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED)); - } - - if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) { - if (status & RXSTATUS_EXITED_HUNT) - info->icount.exithunt++; - if (status & RXSTATUS_IDLE_RECEIVED) - info->icount.rxidle++; - wake_up_interruptible(&info->event_wait_q); - } - - if (status & RXSTATUS_OVERRUN){ - info->icount.rxover++; - usc_process_rxoverrun_sync( info ); - } - - usc_ClearIrqPendingBits( info, RECEIVE_STATUS ); - usc_UnlatchRxstatusBits( info, status ); - -} /* end of mgsl_isr_receive_status() */ - -/* mgsl_isr_transmit_status() - * - * Service a transmit status interrupt - * HDLC mode :end of transmit frame - * Async mode:all data is sent - * transmit status is indicated by bits in the TCSR. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_transmit_status( struct mgsl_struct *info ) -{ - u16 status = usc_InReg( info, TCSR ); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_transmit_status status=%04X\n", - __FILE__,__LINE__,status); - - usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); - usc_UnlatchTxstatusBits( info, status ); - - if ( status & (TXSTATUS_UNDERRUN | TXSTATUS_ABORT_SENT) ) - { - /* finished sending HDLC abort. This may leave */ - /* the TxFifo with data from the aborted frame */ - /* so purge the TxFifo. Also shutdown the DMA */ - /* channel in case there is data remaining in */ - /* the DMA buffer */ - usc_DmaCmd( info, DmaCmd_ResetTxChannel ); - usc_RTCmd( info, RTCmd_PurgeTxFifo ); - } - - if ( status & TXSTATUS_EOF_SENT ) - info->icount.txok++; - else if ( status & TXSTATUS_UNDERRUN ) - info->icount.txunder++; - else if ( status & TXSTATUS_ABORT_SENT ) - info->icount.txabort++; - else - info->icount.txunder++; - - info->tx_active = false; - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - del_timer(&info->tx_timer); - - if ( info->drop_rts_on_tx_done ) { - usc_get_serial_signals( info ); - if ( info->serial_signals & SerialSignal_RTS ) { - info->serial_signals &= ~SerialSignal_RTS; - usc_set_serial_signals( info ); - } - info->drop_rts_on_tx_done = false; - } - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - { - if (info->port.tty->stopped || info->port.tty->hw_stopped) { - usc_stop_transmitter(info); - return; - } - info->pending_bh |= BH_TRANSMIT; - } - -} /* end of mgsl_isr_transmit_status() */ - -/* mgsl_isr_io_pin() - * - * Service an Input/Output pin interrupt. The type of - * interrupt is indicated by bits in the MISR - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_io_pin( struct mgsl_struct *info ) -{ - struct mgsl_icount *icount; - u16 status = usc_InReg( info, MISR ); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_io_pin status=%04X\n", - __FILE__,__LINE__,status); - - usc_ClearIrqPendingBits( info, IO_PIN ); - usc_UnlatchIostatusBits( info, status ); - - if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED | - MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) { - icount = &info->icount; - /* update input line counters */ - if (status & MISCSTATUS_RI_LATCHED) { - if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) - usc_DisablestatusIrqs(info,SICR_RI); - icount->rng++; - if ( status & MISCSTATUS_RI ) - info->input_signal_events.ri_up++; - else - info->input_signal_events.ri_down++; - } - if (status & MISCSTATUS_DSR_LATCHED) { - if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) - usc_DisablestatusIrqs(info,SICR_DSR); - icount->dsr++; - if ( status & MISCSTATUS_DSR ) - info->input_signal_events.dsr_up++; - else - info->input_signal_events.dsr_down++; - } - if (status & MISCSTATUS_DCD_LATCHED) { - if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) - usc_DisablestatusIrqs(info,SICR_DCD); - icount->dcd++; - if (status & MISCSTATUS_DCD) { - info->input_signal_events.dcd_up++; - } else - info->input_signal_events.dcd_down++; -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) { - if (status & MISCSTATUS_DCD) - netif_carrier_on(info->netdev); - else - netif_carrier_off(info->netdev); - } -#endif - } - if (status & MISCSTATUS_CTS_LATCHED) - { - if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) - usc_DisablestatusIrqs(info,SICR_CTS); - icount->cts++; - if ( status & MISCSTATUS_CTS ) - info->input_signal_events.cts_up++; - else - info->input_signal_events.cts_down++; - } - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - - if ( (info->port.flags & ASYNC_CHECK_CD) && - (status & MISCSTATUS_DCD_LATCHED) ) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s CD now %s...", info->device_name, - (status & MISCSTATUS_DCD) ? "on" : "off"); - if (status & MISCSTATUS_DCD) - wake_up_interruptible(&info->port.open_wait); - else { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("doing serial hangup..."); - if (info->port.tty) - tty_hangup(info->port.tty); - } - } - - if ( (info->port.flags & ASYNC_CTS_FLOW) && - (status & MISCSTATUS_CTS_LATCHED) ) { - if (info->port.tty->hw_stopped) { - if (status & MISCSTATUS_CTS) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("CTS tx start..."); - if (info->port.tty) - info->port.tty->hw_stopped = 0; - usc_start_transmitter(info); - info->pending_bh |= BH_TRANSMIT; - return; - } - } else { - if (!(status & MISCSTATUS_CTS)) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("CTS tx stop..."); - if (info->port.tty) - info->port.tty->hw_stopped = 1; - usc_stop_transmitter(info); - } - } - } - } - - info->pending_bh |= BH_STATUS; - - /* for diagnostics set IRQ flag */ - if ( status & MISCSTATUS_TXC_LATCHED ){ - usc_OutReg( info, SICR, - (unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) ); - usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED ); - info->irq_occurred = true; - } - -} /* end of mgsl_isr_io_pin() */ - -/* mgsl_isr_transmit_data() - * - * Service a transmit data interrupt (async mode only). - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_transmit_data( struct mgsl_struct *info ) -{ - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n", - __FILE__,__LINE__,info->xmit_cnt); - - usc_ClearIrqPendingBits( info, TRANSMIT_DATA ); - - if (info->port.tty->stopped || info->port.tty->hw_stopped) { - usc_stop_transmitter(info); - return; - } - - if ( info->xmit_cnt ) - usc_load_txfifo( info ); - else - info->tx_active = false; - - if (info->xmit_cnt < WAKEUP_CHARS) - info->pending_bh |= BH_TRANSMIT; - -} /* end of mgsl_isr_transmit_data() */ - -/* mgsl_isr_receive_data() - * - * Service a receive data interrupt. This occurs - * when operating in asynchronous interrupt transfer mode. - * The receive data FIFO is flushed to the receive data buffers. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_receive_data( struct mgsl_struct *info ) -{ - int Fifocount; - u16 status; - int work = 0; - unsigned char DataByte; - struct tty_struct *tty = info->port.tty; - struct mgsl_icount *icount = &info->icount; - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_receive_data\n", - __FILE__,__LINE__); - - usc_ClearIrqPendingBits( info, RECEIVE_DATA ); - - /* select FIFO status for RICR readback */ - usc_RCmd( info, RCmd_SelectRicrRxFifostatus ); - - /* clear the Wordstatus bit so that status readback */ - /* only reflects the status of this byte */ - usc_OutReg( info, RICR+LSBONLY, (u16)(usc_InReg(info, RICR+LSBONLY) & ~BIT3 )); - - /* flush the receive FIFO */ - - while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) { - int flag; - - /* read one byte from RxFIFO */ - outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY), - info->io_base + CCAR ); - DataByte = inb( info->io_base + CCAR ); - - /* get the status of the received byte */ - status = usc_InReg(info, RCSR); - if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + - RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) - usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); - - icount->rx++; - - flag = 0; - if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + - RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) { - printk("rxerr=%04X\n",status); - /* update error statistics */ - if ( status & RXSTATUS_BREAK_RECEIVED ) { - status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR); - icount->brk++; - } else if (status & RXSTATUS_PARITY_ERROR) - icount->parity++; - else if (status & RXSTATUS_FRAMING_ERROR) - icount->frame++; - else if (status & RXSTATUS_OVERRUN) { - /* must issue purge fifo cmd before */ - /* 16C32 accepts more receive chars */ - usc_RTCmd(info,RTCmd_PurgeRxFifo); - icount->overrun++; - } - - /* discard char if tty control flags say so */ - if (status & info->ignore_status_mask) - continue; - - status &= info->read_status_mask; - - if (status & RXSTATUS_BREAK_RECEIVED) { - flag = TTY_BREAK; - if (info->port.flags & ASYNC_SAK) - do_SAK(tty); - } else if (status & RXSTATUS_PARITY_ERROR) - flag = TTY_PARITY; - else if (status & RXSTATUS_FRAMING_ERROR) - flag = TTY_FRAME; - } /* end of if (error) */ - tty_insert_flip_char(tty, DataByte, flag); - if (status & RXSTATUS_OVERRUN) { - /* Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - work += tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } - } - - if ( debug_level >= DEBUG_LEVEL_ISR ) { - printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n", - __FILE__,__LINE__,icount->rx,icount->brk, - icount->parity,icount->frame,icount->overrun); - } - - if(work) - tty_flip_buffer_push(tty); -} - -/* mgsl_isr_misc() - * - * Service a miscellaneous interrupt source. - * - * Arguments: info pointer to device extension (instance data) - * Return Value: None - */ -static void mgsl_isr_misc( struct mgsl_struct *info ) -{ - u16 status = usc_InReg( info, MISR ); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_misc status=%04X\n", - __FILE__,__LINE__,status); - - if ((status & MISCSTATUS_RCC_UNDERRUN) && - (info->params.mode == MGSL_MODE_HDLC)) { - - /* turn off receiver and rx DMA */ - usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); - usc_DmaCmd(info, DmaCmd_ResetRxChannel); - usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); - usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); - usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS); - - /* schedule BH handler to restart receiver */ - info->pending_bh |= BH_RECEIVE; - info->rx_rcc_underrun = true; - } - - usc_ClearIrqPendingBits( info, MISC ); - usc_UnlatchMiscstatusBits( info, status ); - -} /* end of mgsl_isr_misc() */ - -/* mgsl_isr_null() - * - * Services undefined interrupt vectors from the - * USC. (hence this function SHOULD never be called) - * - * Arguments: info pointer to device extension (instance data) - * Return Value: None - */ -static void mgsl_isr_null( struct mgsl_struct *info ) -{ - -} /* end of mgsl_isr_null() */ - -/* mgsl_isr_receive_dma() - * - * Service a receive DMA channel interrupt. - * For this driver there are two sources of receive DMA interrupts - * as identified in the Receive DMA mode Register (RDMR): - * - * BIT3 EOA/EOL End of List, all receive buffers in receive - * buffer list have been filled (no more free buffers - * available). The DMA controller has shut down. - * - * BIT2 EOB End of Buffer. This interrupt occurs when a receive - * DMA buffer is terminated in response to completion - * of a good frame or a frame with errors. The status - * of the frame is stored in the buffer entry in the - * list of receive buffer entries. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_receive_dma( struct mgsl_struct *info ) -{ - u16 status; - - /* clear interrupt pending and IUS bit for Rx DMA IRQ */ - usc_OutDmaReg( info, CDIR, BIT9+BIT1 ); - - /* Read the receive DMA status to identify interrupt type. */ - /* This also clears the status bits. */ - status = usc_InDmaReg( info, RDMR ); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_receive_dma(%s) status=%04X\n", - __FILE__,__LINE__,info->device_name,status); - - info->pending_bh |= BH_RECEIVE; - - if ( status & BIT3 ) { - info->rx_overflow = true; - info->icount.buf_overrun++; - } - -} /* end of mgsl_isr_receive_dma() */ - -/* mgsl_isr_transmit_dma() - * - * This function services a transmit DMA channel interrupt. - * - * For this driver there is one source of transmit DMA interrupts - * as identified in the Transmit DMA Mode Register (TDMR): - * - * BIT2 EOB End of Buffer. This interrupt occurs when a - * transmit DMA buffer has been emptied. - * - * The driver maintains enough transmit DMA buffers to hold at least - * one max frame size transmit frame. When operating in a buffered - * transmit mode, there may be enough transmit DMA buffers to hold at - * least two or more max frame size frames. On an EOB condition, - * determine if there are any queued transmit buffers and copy into - * transmit DMA buffers if we have room. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_isr_transmit_dma( struct mgsl_struct *info ) -{ - u16 status; - - /* clear interrupt pending and IUS bit for Tx DMA IRQ */ - usc_OutDmaReg(info, CDIR, BIT8+BIT0 ); - - /* Read the transmit DMA status to identify interrupt type. */ - /* This also clears the status bits. */ - - status = usc_InDmaReg( info, TDMR ); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n", - __FILE__,__LINE__,info->device_name,status); - - if ( status & BIT2 ) { - --info->tx_dma_buffers_used; - - /* if there are transmit frames queued, - * try to load the next one - */ - if ( load_next_tx_holding_buffer(info) ) { - /* if call returns non-zero value, we have - * at least one free tx holding buffer - */ - info->pending_bh |= BH_TRANSMIT; - } - } - -} /* end of mgsl_isr_transmit_dma() */ - -/* mgsl_interrupt() - * - * Interrupt service routine entry point. - * - * Arguments: - * - * irq interrupt number that caused interrupt - * dev_id device ID supplied during interrupt registration - * - * Return Value: None - */ -static irqreturn_t mgsl_interrupt(int dummy, void *dev_id) -{ - struct mgsl_struct *info = dev_id; - u16 UscVector; - u16 DmaVector; - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n", - __FILE__, __LINE__, info->irq_level); - - spin_lock(&info->irq_spinlock); - - for(;;) { - /* Read the interrupt vectors from hardware. */ - UscVector = usc_InReg(info, IVR) >> 9; - DmaVector = usc_InDmaReg(info, DIVR); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s UscVector=%08X DmaVector=%08X\n", - __FILE__,__LINE__,info->device_name,UscVector,DmaVector); - - if ( !UscVector && !DmaVector ) - break; - - /* Dispatch interrupt vector */ - if ( UscVector ) - (*UscIsrTable[UscVector])(info); - else if ( (DmaVector&(BIT10|BIT9)) == BIT10) - mgsl_isr_transmit_dma(info); - else - mgsl_isr_receive_dma(info); - - if ( info->isr_overflow ) { - printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n", - __FILE__, __LINE__, info->device_name, info->irq_level); - usc_DisableMasterIrqBit(info); - usc_DisableDmaInterrupts(info,DICR_MASTER); - break; - } - } - - /* Request bottom half processing if there's something - * for it to do and the bh is not already running - */ - - if ( info->pending_bh && !info->bh_running && !info->bh_requested ) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s queueing bh task.\n", - __FILE__,__LINE__,info->device_name); - schedule_work(&info->task); - info->bh_requested = true; - } - - spin_unlock(&info->irq_spinlock); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n", - __FILE__, __LINE__, info->irq_level); - - return IRQ_HANDLED; -} /* end of mgsl_interrupt() */ - -/* startup() - * - * Initialize and start device. - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise error code - */ -static int startup(struct mgsl_struct * info) -{ - int retval = 0; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name); - - if (info->port.flags & ASYNC_INITIALIZED) - return 0; - - if (!info->xmit_buf) { - /* allocate a page of memory for a transmit buffer */ - info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); - if (!info->xmit_buf) { - printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", - __FILE__,__LINE__,info->device_name); - return -ENOMEM; - } - } - - info->pending_bh = 0; - - memset(&info->icount, 0, sizeof(info->icount)); - - setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info); - - /* Allocate and claim adapter resources */ - retval = mgsl_claim_resources(info); - - /* perform existence check and diagnostics */ - if ( !retval ) - retval = mgsl_adapter_test(info); - - if ( retval ) { - if (capable(CAP_SYS_ADMIN) && info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - mgsl_release_resources(info); - return retval; - } - - /* program hardware for current parameters */ - mgsl_change_params(info); - - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags |= ASYNC_INITIALIZED; - - return 0; - -} /* end of startup() */ - -/* shutdown() - * - * Called by mgsl_close() and mgsl_hangup() to shutdown hardware - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void shutdown(struct mgsl_struct * info) -{ - unsigned long flags; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_shutdown(%s)\n", - __FILE__,__LINE__, info->device_name ); - - /* clear status wait queue because status changes */ - /* can't happen after shutting down the hardware */ - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - - del_timer_sync(&info->tx_timer); - - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = NULL; - } - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_DisableMasterIrqBit(info); - usc_stop_receiver(info); - usc_stop_transmitter(info); - usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS + - TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC ); - usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE); - - /* Disable DMAEN (Port 7, Bit 14) */ - /* This disconnects the DMA request signal from the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14)); - - /* Disable INTEN (Port 6, Bit12) */ - /* This disconnects the IRQ request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12)); - - if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { - info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - usc_set_serial_signals(info); - } - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - mgsl_release_resources(info); - - if (info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags &= ~ASYNC_INITIALIZED; - -} /* end of shutdown() */ - -static void mgsl_program_hw(struct mgsl_struct *info) -{ - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - - usc_stop_receiver(info); - usc_stop_transmitter(info); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - if (info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW || - info->netcount) - usc_set_sync_mode(info); - else - usc_set_async_mode(info); - - usc_set_serial_signals(info); - - info->dcd_chkcount = 0; - info->cts_chkcount = 0; - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - - usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI); - usc_EnableInterrupts(info, IO_PIN); - usc_get_serial_signals(info); - - if (info->netcount || info->port.tty->termios->c_cflag & CREAD) - usc_start_receiver(info); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); -} - -/* Reconfigure adapter based on new parameters - */ -static void mgsl_change_params(struct mgsl_struct *info) -{ - unsigned cflag; - int bits_per_char; - - if (!info->port.tty || !info->port.tty->termios) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_change_params(%s)\n", - __FILE__,__LINE__, info->device_name ); - - cflag = info->port.tty->termios->c_cflag; - - /* if B0 rate (hangup) specified then negate DTR and RTS */ - /* otherwise assert DTR and RTS */ - if (cflag & CBAUD) - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - - /* byte size and parity */ - - switch (cflag & CSIZE) { - case CS5: info->params.data_bits = 5; break; - case CS6: info->params.data_bits = 6; break; - case CS7: info->params.data_bits = 7; break; - case CS8: info->params.data_bits = 8; break; - /* Never happens, but GCC is too dumb to figure it out */ - default: info->params.data_bits = 7; break; - } - - if (cflag & CSTOPB) - info->params.stop_bits = 2; - else - info->params.stop_bits = 1; - - info->params.parity = ASYNC_PARITY_NONE; - if (cflag & PARENB) { - if (cflag & PARODD) - info->params.parity = ASYNC_PARITY_ODD; - else - info->params.parity = ASYNC_PARITY_EVEN; -#ifdef CMSPAR - if (cflag & CMSPAR) - info->params.parity = ASYNC_PARITY_SPACE; -#endif - } - - /* calculate number of jiffies to transmit a full - * FIFO (32 bytes) at specified data rate - */ - bits_per_char = info->params.data_bits + - info->params.stop_bits + 1; - - /* if port data rate is set to 460800 or less then - * allow tty settings to override, otherwise keep the - * current data rate. - */ - if (info->params.data_rate <= 460800) - info->params.data_rate = tty_get_baud_rate(info->port.tty); - - if ( info->params.data_rate ) { - info->timeout = (32*HZ*bits_per_char) / - info->params.data_rate; - } - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - if (cflag & CRTSCTS) - info->port.flags |= ASYNC_CTS_FLOW; - else - info->port.flags &= ~ASYNC_CTS_FLOW; - - if (cflag & CLOCAL) - info->port.flags &= ~ASYNC_CHECK_CD; - else - info->port.flags |= ASYNC_CHECK_CD; - - /* process tty input control flags */ - - info->read_status_mask = RXSTATUS_OVERRUN; - if (I_INPCK(info->port.tty)) - info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; - if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) - info->read_status_mask |= RXSTATUS_BREAK_RECEIVED; - - if (I_IGNPAR(info->port.tty)) - info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; - if (I_IGNBRK(info->port.tty)) { - info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED; - /* If ignoring parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->port.tty)) - info->ignore_status_mask |= RXSTATUS_OVERRUN; - } - - mgsl_program_hw(info); - -} /* end of mgsl_change_params() */ - -/* mgsl_put_char() - * - * Add a character to the transmit buffer. - * - * Arguments: tty pointer to tty information structure - * ch character to add to transmit buffer - * - * Return Value: None - */ -static int mgsl_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - int ret = 0; - - if (debug_level >= DEBUG_LEVEL_INFO) { - printk(KERN_DEBUG "%s(%d):mgsl_put_char(%d) on %s\n", - __FILE__, __LINE__, ch, info->device_name); - } - - if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) - return 0; - - if (!info->xmit_buf) - return 0; - - spin_lock_irqsave(&info->irq_spinlock, flags); - - if ((info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active) { - if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) { - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE-1; - info->xmit_cnt++; - ret = 1; - } - } - spin_unlock_irqrestore(&info->irq_spinlock, flags); - return ret; - -} /* end of mgsl_put_char() */ - -/* mgsl_flush_chars() - * - * Enable transmitter so remaining characters in the - * transmit buffer are sent. - * - * Arguments: tty pointer to tty information structure - * Return Value: None - */ -static void mgsl_flush_chars(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n", - __FILE__,__LINE__,info->device_name,info->xmit_cnt); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) - return; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n", - __FILE__,__LINE__,info->device_name ); - - spin_lock_irqsave(&info->irq_spinlock,flags); - - if (!info->tx_active) { - if ( (info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) { - /* operating in synchronous (frame oriented) mode */ - /* copy data from circular xmit_buf to */ - /* transmit DMA buffer. */ - mgsl_load_tx_dma_buffer(info, - info->xmit_buf,info->xmit_cnt); - } - usc_start_transmitter(info); - } - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - -} /* end of mgsl_flush_chars() */ - -/* mgsl_write() - * - * Send a block of data - * - * Arguments: - * - * tty pointer to tty information structure - * buf pointer to buffer containing send data - * count size of send data in bytes - * - * Return Value: number of characters written - */ -static int mgsl_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - int c, ret = 0; - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) count=%d\n", - __FILE__,__LINE__,info->device_name,count); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) - goto cleanup; - - if (!info->xmit_buf) - goto cleanup; - - if ( info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW ) { - /* operating in synchronous (frame oriented) mode */ - /* operating in synchronous (frame oriented) mode */ - if (info->tx_active) { - - if ( info->params.mode == MGSL_MODE_HDLC ) { - ret = 0; - goto cleanup; - } - /* transmitter is actively sending data - - * if we have multiple transmit dma and - * holding buffers, attempt to queue this - * frame for transmission at a later time. - */ - if (info->tx_holding_count >= info->num_tx_holding_buffers ) { - /* no tx holding buffers available */ - ret = 0; - goto cleanup; - } - - /* queue transmit frame request */ - ret = count; - save_tx_buffer_request(info,buf,count); - - /* if we have sufficient tx dma buffers, - * load the next buffered tx request - */ - spin_lock_irqsave(&info->irq_spinlock,flags); - load_next_tx_holding_buffer(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - goto cleanup; - } - - /* if operating in HDLC LoopMode and the adapter */ - /* has yet to be inserted into the loop, we can't */ - /* transmit */ - - if ( (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) && - !usc_loopmode_active(info) ) - { - ret = 0; - goto cleanup; - } - - if ( info->xmit_cnt ) { - /* Send accumulated from send_char() calls */ - /* as frame and wait before accepting more data. */ - ret = 0; - - /* copy data from circular xmit_buf to */ - /* transmit DMA buffer. */ - mgsl_load_tx_dma_buffer(info, - info->xmit_buf,info->xmit_cnt); - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) sync xmit_cnt flushing\n", - __FILE__,__LINE__,info->device_name); - } else { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) sync transmit accepted\n", - __FILE__,__LINE__,info->device_name); - ret = count; - info->xmit_cnt = count; - mgsl_load_tx_dma_buffer(info,buf,count); - } - } else { - while (1) { - spin_lock_irqsave(&info->irq_spinlock,flags); - c = min_t(int, count, - min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - spin_unlock_irqrestore(&info->irq_spinlock,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; - spin_unlock_irqrestore(&info->irq_spinlock,flags); - buf += c; - count -= c; - ret += c; - } - } - - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!info->tx_active) - usc_start_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } -cleanup: - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) returning=%d\n", - __FILE__,__LINE__,info->device_name,ret); - - return ret; - -} /* end of mgsl_write() */ - -/* mgsl_write_room() - * - * Return the count of free bytes in transmit buffer - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static int mgsl_write_room(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - int ret; - - if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_write_room(%s)=%d\n", - __FILE__,__LINE__, info->device_name,ret ); - - if ( info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW ) { - /* operating in synchronous (frame oriented) mode */ - if ( info->tx_active ) - return 0; - else - return HDLC_MAX_FRAME_SIZE; - } - - return ret; - -} /* end of mgsl_write_room() */ - -/* mgsl_chars_in_buffer() - * - * Return the count of bytes in transmit buffer - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static int mgsl_chars_in_buffer(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_chars_in_buffer(%s)\n", - __FILE__,__LINE__, info->device_name ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_chars_in_buffer")) - return 0; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_chars_in_buffer(%s)=%d\n", - __FILE__,__LINE__, info->device_name,info->xmit_cnt ); - - if ( info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW ) { - /* operating in synchronous (frame oriented) mode */ - if ( info->tx_active ) - return info->max_frame_size; - else - return 0; - } - - return info->xmit_cnt; -} /* end of mgsl_chars_in_buffer() */ - -/* mgsl_flush_buffer() - * - * Discard all data in the send buffer - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static void mgsl_flush_buffer(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_flush_buffer(%s) entry\n", - __FILE__,__LINE__, info->device_name ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_buffer")) - return; - - spin_lock_irqsave(&info->irq_spinlock,flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - del_timer(&info->tx_timer); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - tty_wakeup(tty); -} - -/* mgsl_send_xchar() - * - * Send a high-priority XON/XOFF character - * - * Arguments: tty pointer to tty info structure - * ch character to send - * Return Value: None - */ -static void mgsl_send_xchar(struct tty_struct *tty, char ch) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_send_xchar(%s,%d)\n", - __FILE__,__LINE__, info->device_name, ch ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_send_xchar")) - return; - - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!info->tx_enabled) - usc_start_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } -} /* end of mgsl_send_xchar() */ - -/* mgsl_throttle() - * - * Signal remote device to throttle send data (our receive data) - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static void mgsl_throttle(struct tty_struct * tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_throttle(%s) entry\n", - __FILE__,__LINE__, info->device_name ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_throttle")) - return; - - if (I_IXOFF(tty)) - mgsl_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->irq_spinlock,flags); - info->serial_signals &= ~SerialSignal_RTS; - usc_set_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } -} /* end of mgsl_throttle() */ - -/* mgsl_unthrottle() - * - * Signal remote device to stop throttling send data (our receive data) - * - * Arguments: tty pointer to tty info structure - * Return Value: None - */ -static void mgsl_unthrottle(struct tty_struct * tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_unthrottle(%s) entry\n", - __FILE__,__LINE__, info->device_name ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - mgsl_send_xchar(tty, START_CHAR(tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->irq_spinlock,flags); - info->serial_signals |= SerialSignal_RTS; - usc_set_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - -} /* end of mgsl_unthrottle() */ - -/* mgsl_get_stats() - * - * get the current serial parameters information - * - * Arguments: info pointer to device instance data - * user_icount pointer to buffer to hold returned stats - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount) -{ - int err; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_get_params(%s)\n", - __FILE__,__LINE__, info->device_name); - - if (!user_icount) { - memset(&info->icount, 0, sizeof(info->icount)); - } else { - mutex_lock(&info->port.mutex); - COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); - mutex_unlock(&info->port.mutex); - if (err) - return -EFAULT; - } - - return 0; - -} /* end of mgsl_get_stats() */ - -/* mgsl_get_params() - * - * get the current serial parameters information - * - * Arguments: info pointer to device instance data - * user_params pointer to buffer to hold returned params - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params) -{ - int err; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_get_params(%s)\n", - __FILE__,__LINE__, info->device_name); - - mutex_lock(&info->port.mutex); - COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); - mutex_unlock(&info->port.mutex); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; - } - - return 0; - -} /* end of mgsl_get_params() */ - -/* mgsl_set_params() - * - * set the serial parameters - * - * Arguments: - * - * info pointer to device instance data - * new_params user buffer containing new serial params - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params) -{ - unsigned long flags; - MGSL_PARAMS tmp_params; - int err; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_set_params %s\n", __FILE__,__LINE__, - info->device_name ); - COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_set_params(%s) user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; - } - - mutex_lock(&info->port.mutex); - spin_lock_irqsave(&info->irq_spinlock,flags); - memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - mgsl_change_params(info); - mutex_unlock(&info->port.mutex); - - return 0; - -} /* end of mgsl_set_params() */ - -/* mgsl_get_txidle() - * - * get the current transmit idle mode - * - * Arguments: info pointer to device instance data - * idle_mode pointer to buffer to hold returned idle mode - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode) -{ - int err; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_get_txidle(%s)=%d\n", - __FILE__,__LINE__, info->device_name, info->idle_mode); - - COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_get_txidle(%s) user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; - } - - return 0; - -} /* end of mgsl_get_txidle() */ - -/* mgsl_set_txidle() service ioctl to set transmit idle mode - * - * Arguments: info pointer to device instance data - * idle_mode new idle mode - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_set_txidle(%s,%d)\n", __FILE__,__LINE__, - info->device_name, idle_mode ); - - spin_lock_irqsave(&info->irq_spinlock,flags); - info->idle_mode = idle_mode; - usc_set_txidle( info ); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - return 0; - -} /* end of mgsl_set_txidle() */ - -/* mgsl_txenable() - * - * enable or disable the transmitter - * - * Arguments: - * - * info pointer to device instance data - * enable 1 = enable, 0 = disable - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_txenable(struct mgsl_struct * info, int enable) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_txenable(%s,%d)\n", __FILE__,__LINE__, - info->device_name, enable); - - spin_lock_irqsave(&info->irq_spinlock,flags); - if ( enable ) { - if ( !info->tx_enabled ) { - - usc_start_transmitter(info); - /*-------------------------------------------------- - * if HDLC/SDLC Loop mode, attempt to insert the - * station in the 'loop' by setting CMR:13. Upon - * receipt of the next GoAhead (RxAbort) sequence, - * the OnLoop indicator (CCSR:7) should go active - * to indicate that we are on the loop - *--------------------------------------------------*/ - if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) - usc_loopmode_insert_request( info ); - } - } else { - if ( info->tx_enabled ) - usc_stop_transmitter(info); - } - spin_unlock_irqrestore(&info->irq_spinlock,flags); - return 0; - -} /* end of mgsl_txenable() */ - -/* mgsl_txabort() abort send HDLC frame - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_txabort(struct mgsl_struct * info) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_txabort(%s)\n", __FILE__,__LINE__, - info->device_name); - - spin_lock_irqsave(&info->irq_spinlock,flags); - if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) - { - if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) - usc_loopmode_cancel_transmit( info ); - else - usc_TCmd(info,TCmd_SendAbort); - } - spin_unlock_irqrestore(&info->irq_spinlock,flags); - return 0; - -} /* end of mgsl_txabort() */ - -/* mgsl_rxenable() enable or disable the receiver - * - * Arguments: info pointer to device instance data - * enable 1 = enable, 0 = disable - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_rxenable(struct mgsl_struct * info, int enable) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_rxenable(%s,%d)\n", __FILE__,__LINE__, - info->device_name, enable); - - spin_lock_irqsave(&info->irq_spinlock,flags); - if ( enable ) { - if ( !info->rx_enabled ) - usc_start_receiver(info); - } else { - if ( info->rx_enabled ) - usc_stop_receiver(info); - } - spin_unlock_irqrestore(&info->irq_spinlock,flags); - return 0; - -} /* end of mgsl_rxenable() */ - -/* mgsl_wait_event() wait for specified event to occur - * - * Arguments: info pointer to device instance data - * mask pointer to bitmask of events to wait for - * Return Value: 0 if successful and bit mask updated with - * of events triggerred, - * otherwise error code - */ -static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr) -{ - unsigned long flags; - int s; - int rc=0; - struct mgsl_icount cprev, cnow; - int events; - int mask; - struct _input_signal_events oldsigs, newsigs; - DECLARE_WAITQUEUE(wait, current); - - COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int)); - if (rc) { - return -EFAULT; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_wait_event(%s,%d)\n", __FILE__,__LINE__, - info->device_name, mask); - - spin_lock_irqsave(&info->irq_spinlock,flags); - - /* return immediately if state matches requested events */ - usc_get_serial_signals(info); - s = info->serial_signals; - events = mask & - ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + - ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + - ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + - ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); - if (events) { - spin_unlock_irqrestore(&info->irq_spinlock,flags); - goto exit; - } - - /* save current irq counts */ - cprev = info->icount; - oldsigs = info->input_signal_events; - - /* enable hunt and idle irqs if needed */ - if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { - u16 oldreg = usc_InReg(info,RICR); - u16 newreg = oldreg + - (mask & MgslEvent_ExitHuntMode ? RXSTATUS_EXITED_HUNT:0) + - (mask & MgslEvent_IdleReceived ? RXSTATUS_IDLE_RECEIVED:0); - if (oldreg != newreg) - usc_OutReg(info, RICR, newreg); - } - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&info->event_wait_q, &wait); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get current irq counts */ - spin_lock_irqsave(&info->irq_spinlock,flags); - cnow = info->icount; - newsigs = info->input_signal_events; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - /* if no change, wait aborted for some reason */ - if (newsigs.dsr_up == oldsigs.dsr_up && - newsigs.dsr_down == oldsigs.dsr_down && - newsigs.dcd_up == oldsigs.dcd_up && - newsigs.dcd_down == oldsigs.dcd_down && - newsigs.cts_up == oldsigs.cts_up && - newsigs.cts_down == oldsigs.cts_down && - newsigs.ri_up == oldsigs.ri_up && - newsigs.ri_down == oldsigs.ri_down && - cnow.exithunt == cprev.exithunt && - cnow.rxidle == cprev.rxidle) { - rc = -EIO; - break; - } - - events = mask & - ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + - (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + - (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + - (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + - (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + - (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + - (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + - (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + - (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + - (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); - if (events) - break; - - cprev = cnow; - oldsigs = newsigs; - } - - remove_wait_queue(&info->event_wait_q, &wait); - set_current_state(TASK_RUNNING); - - if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!waitqueue_active(&info->event_wait_q)) { - /* disable enable exit hunt mode/idle rcvd IRQs */ - usc_OutReg(info, RICR, usc_InReg(info,RICR) & - ~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)); - } - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } -exit: - if ( rc == 0 ) - PUT_USER(rc, events, mask_ptr); - - return rc; - -} /* end of mgsl_wait_event() */ - -static int modem_input_wait(struct mgsl_struct *info,int arg) -{ - unsigned long flags; - int rc; - struct mgsl_icount cprev, cnow; - DECLARE_WAITQUEUE(wait, current); - - /* save current irq counts */ - spin_lock_irqsave(&info->irq_spinlock,flags); - cprev = info->icount; - add_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get new irq counts */ - spin_lock_irqsave(&info->irq_spinlock,flags); - cnow = info->icount; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - /* if no change, wait aborted for some reason */ - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - rc = -EIO; - break; - } - - /* check for change in caller specified modem input */ - if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || - (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || - (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || - (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { - rc = 0; - break; - } - - cprev = cnow; - } - remove_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_RUNNING); - return rc; -} - -/* return the state of the serial control and status signals - */ -static int tiocmget(struct tty_struct *tty) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned int result; - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_get_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) + - ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) + - ((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) + - ((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) + - ((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) + - ((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0); - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s tiocmget() value=%08X\n", - __FILE__,__LINE__, info->device_name, result ); - return result; -} - -/* set modem control signals (DTR/RTS) - */ -static int tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s tiocmset(%x,%x)\n", - __FILE__,__LINE__,info->device_name, set, clear); - - if (set & TIOCM_RTS) - info->serial_signals |= SerialSignal_RTS; - if (set & TIOCM_DTR) - info->serial_signals |= SerialSignal_DTR; - if (clear & TIOCM_RTS) - info->serial_signals &= ~SerialSignal_RTS; - if (clear & TIOCM_DTR) - info->serial_signals &= ~SerialSignal_DTR; - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_set_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - return 0; -} - -/* mgsl_break() Set or clear transmit break condition - * - * Arguments: tty pointer to tty instance data - * break_state -1=set break condition, 0=clear - * Return Value: error code - */ -static int mgsl_break(struct tty_struct *tty, int break_state) -{ - struct mgsl_struct * info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_break(%s,%d)\n", - __FILE__,__LINE__, info->device_name, break_state); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) - return -EINVAL; - - spin_lock_irqsave(&info->irq_spinlock,flags); - if (break_state == -1) - usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) | BIT7)); - else - usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - return 0; - -} /* end of mgsl_break() */ - -/* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ -static int msgl_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) - -{ - struct mgsl_struct * info = tty->driver_data; - struct mgsl_icount cnow; /* kernel counter temps */ - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - return 0; -} - -/* mgsl_ioctl() Service an IOCTL request - * - * Arguments: - * - * tty pointer to tty instance data - * cmd IOCTL command code - * arg command argument/context - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct mgsl_struct * info = tty->driver_data; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->device_name, cmd ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCMIWAIT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - return mgsl_ioctl_common(info, cmd, arg); -} - -static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - - switch (cmd) { - case MGSL_IOCGPARAMS: - return mgsl_get_params(info, argp); - case MGSL_IOCSPARAMS: - return mgsl_set_params(info, argp); - case MGSL_IOCGTXIDLE: - return mgsl_get_txidle(info, argp); - case MGSL_IOCSTXIDLE: - return mgsl_set_txidle(info,(int)arg); - case MGSL_IOCTXENABLE: - return mgsl_txenable(info,(int)arg); - case MGSL_IOCRXENABLE: - return mgsl_rxenable(info,(int)arg); - case MGSL_IOCTXABORT: - return mgsl_txabort(info); - case MGSL_IOCGSTATS: - return mgsl_get_stats(info, argp); - case MGSL_IOCWAITEVENT: - return mgsl_wait_event(info, argp); - case MGSL_IOCLOOPTXDONE: - return mgsl_loopmode_send_done(info); - /* Wait for modem input (DCD,RI,DSR,CTS) change - * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS) - */ - case TIOCMIWAIT: - return modem_input_wait(info,(int)arg); - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -/* mgsl_set_termios() - * - * Set new termios settings - * - * Arguments: - * - * tty pointer to tty structure - * termios pointer to buffer to hold returned old termios - * - * Return Value: None - */ -static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct mgsl_struct *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__, - tty->driver->name ); - - mgsl_change_params(info); - - /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios->c_cflag & CBAUD)) { - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_set_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios->c_cflag & CBAUD) { - info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->serial_signals |= SerialSignal_RTS; - } - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_set_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - - /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - mgsl_start(tty); - } - -} /* end of mgsl_set_termios() */ - -/* mgsl_close() - * - * Called when port is closed. Wait for remaining data to be - * sent. Disable port and free resources. - * - * Arguments: - * - * tty pointer to open tty structure - * filp pointer to open file object - * - * Return Value: None - */ -static void mgsl_close(struct tty_struct *tty, struct file * filp) -{ - struct mgsl_struct * info = tty->driver_data; - - if (mgsl_paranoia_check(info, tty->name, "mgsl_close")) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_close(%s) entry, count=%d\n", - __FILE__,__LINE__, info->device_name, info->port.count); - - if (tty_port_close_start(&info->port, tty, filp) == 0) - goto cleanup; - - mutex_lock(&info->port.mutex); - if (info->port.flags & ASYNC_INITIALIZED) - mgsl_wait_until_sent(tty, info->timeout); - mgsl_flush_buffer(tty); - tty_ldisc_flush(tty); - shutdown(info); - mutex_unlock(&info->port.mutex); - - tty_port_close_end(&info->port, tty); - info->port.tty = NULL; -cleanup: - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, - tty->driver->name, info->port.count); - -} /* end of mgsl_close() */ - -/* mgsl_wait_until_sent() - * - * Wait until the transmitter is empty. - * - * Arguments: - * - * tty pointer to tty info structure - * timeout time to wait for send completion - * - * Return Value: None - */ -static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct mgsl_struct * info = tty->driver_data; - unsigned long orig_jiffies, char_time; - - if (!info ) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_wait_until_sent(%s) entry\n", - __FILE__,__LINE__, info->device_name ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_wait_until_sent")) - return; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - goto exit; - - orig_jiffies = jiffies; - - /* Set check interval to 1/5 of estimated time to - * send a character, and make it at least 1. The check - * interval should also be less than the timeout. - * Note: use tight timings here to satisfy the NIST-PCTS. - */ - - if ( info->params.data_rate ) { - char_time = info->timeout/(32 * 5); - if (!char_time) - char_time++; - } else - char_time = 1; - - if (timeout) - char_time = min_t(unsigned long, char_time, timeout); - - if ( info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW ) { - while (info->tx_active) { - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - } else { - while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) && - info->tx_enabled) { - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - } - -exit: - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_wait_until_sent(%s) exit\n", - __FILE__,__LINE__, info->device_name ); - -} /* end of mgsl_wait_until_sent() */ - -/* mgsl_hangup() - * - * Called by tty_hangup() when a hangup is signaled. - * This is the same as to closing all open files for the port. - * - * Arguments: tty pointer to associated tty object - * Return Value: None - */ -static void mgsl_hangup(struct tty_struct *tty) -{ - struct mgsl_struct * info = tty->driver_data; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_hangup(%s)\n", - __FILE__,__LINE__, info->device_name ); - - if (mgsl_paranoia_check(info, tty->name, "mgsl_hangup")) - return; - - mgsl_flush_buffer(tty); - shutdown(info); - - info->port.count = 0; - info->port.flags &= ~ASYNC_NORMAL_ACTIVE; - info->port.tty = NULL; - - wake_up_interruptible(&info->port.open_wait); - -} /* end of mgsl_hangup() */ - -/* - * carrier_raised() - * - * Return true if carrier is raised - */ - -static int carrier_raised(struct tty_port *port) -{ - unsigned long flags; - struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); - - spin_lock_irqsave(&info->irq_spinlock, flags); - usc_get_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock, flags); - return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; -} - -static void dtr_rts(struct tty_port *port, int on) -{ - struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - if (on) - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - usc_set_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); -} - - -/* block_til_ready() - * - * Block the current process until the specified port - * is ready to be opened. - * - * Arguments: - * - * tty pointer to tty info structure - * filp pointer to open file object - * info pointer to device instance data - * - * Return Value: 0 if success, otherwise error code - */ -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct mgsl_struct *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - bool do_clocal = false; - bool extra_count = false; - unsigned long flags; - int dcd; - struct tty_port *port = &info->port; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):block_til_ready on %s\n", - __FILE__,__LINE__, tty->driver->name ); - - if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ - /* nonblock mode is set or port is not enabled */ - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = true; - - /* Wait for carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, port->count is dropped by one, so that - * mgsl_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - - retval = 0; - add_wait_queue(&port->open_wait, &wait); - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):block_til_ready before block on %s count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); - - spin_lock_irqsave(&info->irq_spinlock, flags); - if (!tty_hung_up_p(filp)) { - extra_count = true; - port->count--; - } - spin_unlock_irqrestore(&info->irq_spinlock, flags); - port->blocked_open++; - - while (1) { - if (tty->termios->c_cflag & CBAUD) - tty_port_raise_dtr_rts(port); - - set_current_state(TASK_INTERRUPTIBLE); - - if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ - retval = (port->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - break; - } - - dcd = tty_port_carrier_raised(&info->port); - - if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd)) - break; - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):block_til_ready blocking on %s count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); - - tty_unlock(); - schedule(); - tty_lock(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - - /* FIXME: Racy on hangup during close wait */ - if (extra_count) - port->count++; - port->blocked_open--; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):block_til_ready after blocking on %s count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); - - if (!retval) - port->flags |= ASYNC_NORMAL_ACTIVE; - - return retval; - -} /* end of block_til_ready() */ - -/* mgsl_open() - * - * Called when a port is opened. Init and enable port. - * Perform serial-specific initialization for the tty structure. - * - * Arguments: tty pointer to tty info structure - * filp associated file pointer - * - * Return Value: 0 if success, otherwise error code - */ -static int mgsl_open(struct tty_struct *tty, struct file * filp) -{ - struct mgsl_struct *info; - int retval, line; - unsigned long flags; - - /* verify range of specified line number */ - line = tty->index; - if ((line < 0) || (line >= mgsl_device_count)) { - printk("%s(%d):mgsl_open with invalid line #%d.\n", - __FILE__,__LINE__,line); - return -ENODEV; - } - - /* find the info structure for the specified line */ - info = mgsl_device_list; - while(info && info->line != line) - info = info->next_device; - if (mgsl_paranoia_check(info, tty->name, "mgsl_open")) - return -ENODEV; - - tty->driver_data = info; - info->port.tty = tty; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_open(%s), old ref count = %d\n", - __FILE__,__LINE__,tty->driver->name, info->port.count); - - /* If port is closing, signal caller to try again */ - if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ - if (info->port.flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->port.close_wait); - retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - goto cleanup; - } - - info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - spin_lock_irqsave(&info->netlock, flags); - if (info->netcount) { - retval = -EBUSY; - spin_unlock_irqrestore(&info->netlock, flags); - goto cleanup; - } - info->port.count++; - spin_unlock_irqrestore(&info->netlock, flags); - - if (info->port.count == 1) { - /* 1st open on this device, init hardware */ - retval = startup(info); - if (retval < 0) - goto cleanup; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):block_til_ready(%s) returned %d\n", - __FILE__,__LINE__, info->device_name, retval); - goto cleanup; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_open(%s) success\n", - __FILE__,__LINE__, info->device_name); - retval = 0; - -cleanup: - if (retval) { - if (tty->count == 1) - info->port.tty = NULL; /* tty layer will release tty struct */ - if(info->port.count) - info->port.count--; - } - - return retval; - -} /* end of mgsl_open() */ - -/* - * /proc fs routines.... - */ - -static inline void line_info(struct seq_file *m, struct mgsl_struct *info) -{ - char stat_buf[30]; - unsigned long flags; - - if (info->bus_type == MGSL_BUS_TYPE_PCI) { - seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", - info->device_name, info->io_base, info->irq_level, - info->phys_memory_base, info->phys_lcr_base); - } else { - seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", - info->device_name, info->io_base, - info->irq_level, info->dma_level); - } - - /* output current serial signal states */ - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_get_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if (info->serial_signals & SerialSignal_RTS) - strcat(stat_buf, "|RTS"); - if (info->serial_signals & SerialSignal_CTS) - strcat(stat_buf, "|CTS"); - if (info->serial_signals & SerialSignal_DTR) - strcat(stat_buf, "|DTR"); - if (info->serial_signals & SerialSignal_DSR) - strcat(stat_buf, "|DSR"); - if (info->serial_signals & SerialSignal_DCD) - strcat(stat_buf, "|CD"); - if (info->serial_signals & SerialSignal_RI) - strcat(stat_buf, "|RI"); - - if (info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW ) { - seq_printf(m, " HDLC txok:%d rxok:%d", - info->icount.txok, info->icount.rxok); - if (info->icount.txunder) - seq_printf(m, " txunder:%d", info->icount.txunder); - if (info->icount.txabort) - seq_printf(m, " txabort:%d", info->icount.txabort); - if (info->icount.rxshort) - seq_printf(m, " rxshort:%d", info->icount.rxshort); - if (info->icount.rxlong) - seq_printf(m, " rxlong:%d", info->icount.rxlong); - if (info->icount.rxover) - seq_printf(m, " rxover:%d", info->icount.rxover); - if (info->icount.rxcrc) - seq_printf(m, " rxcrc:%d", info->icount.rxcrc); - } else { - seq_printf(m, " ASYNC tx:%d rx:%d", - info->icount.tx, info->icount.rx); - if (info->icount.frame) - seq_printf(m, " fe:%d", info->icount.frame); - if (info->icount.parity) - seq_printf(m, " pe:%d", info->icount.parity); - if (info->icount.brk) - seq_printf(m, " brk:%d", info->icount.brk); - if (info->icount.overrun) - seq_printf(m, " oe:%d", info->icount.overrun); - } - - /* Append serial signal status to end */ - seq_printf(m, " %s\n", stat_buf+1); - - seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", - info->tx_active,info->bh_requested,info->bh_running, - info->pending_bh); - - spin_lock_irqsave(&info->irq_spinlock,flags); - { - u16 Tcsr = usc_InReg( info, TCSR ); - u16 Tdmr = usc_InDmaReg( info, TDMR ); - u16 Ticr = usc_InReg( info, TICR ); - u16 Rscr = usc_InReg( info, RCSR ); - u16 Rdmr = usc_InDmaReg( info, RDMR ); - u16 Ricr = usc_InReg( info, RICR ); - u16 Icr = usc_InReg( info, ICR ); - u16 Dccr = usc_InReg( info, DCCR ); - u16 Tmr = usc_InReg( info, TMR ); - u16 Tccr = usc_InReg( info, TCCR ); - u16 Ccar = inw( info->io_base + CCAR ); - seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" - "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", - Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); - } - spin_unlock_irqrestore(&info->irq_spinlock,flags); -} - -/* Called to print information about devices */ -static int mgsl_proc_show(struct seq_file *m, void *v) -{ - struct mgsl_struct *info; - - seq_printf(m, "synclink driver:%s\n", driver_version); - - info = mgsl_device_list; - while( info ) { - line_info(m, info); - info = info->next_device; - } - return 0; -} - -static int mgsl_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, mgsl_proc_show, NULL); -} - -static const struct file_operations mgsl_proc_fops = { - .owner = THIS_MODULE, - .open = mgsl_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* mgsl_allocate_dma_buffers() - * - * Allocate and format DMA buffers (ISA adapter) - * or format shared memory buffers (PCI adapter). - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise error - */ -static int mgsl_allocate_dma_buffers(struct mgsl_struct *info) -{ - unsigned short BuffersPerFrame; - - info->last_mem_alloc = 0; - - /* Calculate the number of DMA buffers necessary to hold the */ - /* largest allowable frame size. Note: If the max frame size is */ - /* not an even multiple of the DMA buffer size then we need to */ - /* round the buffer count per frame up one. */ - - BuffersPerFrame = (unsigned short)(info->max_frame_size/DMABUFFERSIZE); - if ( info->max_frame_size % DMABUFFERSIZE ) - BuffersPerFrame++; - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* - * The PCI adapter has 256KBytes of shared memory to use. - * This is 64 PAGE_SIZE buffers. - * - * The first page is used for padding at this time so the - * buffer list does not begin at offset 0 of the PCI - * adapter's shared memory. - * - * The 2nd page is used for the buffer list. A 4K buffer - * list can hold 128 DMA_BUFFER structures at 32 bytes - * each. - * - * This leaves 62 4K pages. - * - * The next N pages are used for transmit frame(s). We - * reserve enough 4K page blocks to hold the required - * number of transmit dma buffers (num_tx_dma_buffers), - * each of MaxFrameSize size. - * - * Of the remaining pages (62-N), determine how many can - * be used to receive full MaxFrameSize inbound frames - */ - info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; - info->rx_buffer_count = 62 - info->tx_buffer_count; - } else { - /* Calculate the number of PAGE_SIZE buffers needed for */ - /* receive and transmit DMA buffers. */ - - - /* Calculate the number of DMA buffers necessary to */ - /* hold 7 max size receive frames and one max size transmit frame. */ - /* The receive buffer count is bumped by one so we avoid an */ - /* End of List condition if all receive buffers are used when */ - /* using linked list DMA buffers. */ - - info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; - info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6; - - /* - * limit total TxBuffers & RxBuffers to 62 4K total - * (ala PCI Allocation) - */ - - if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 ) - info->rx_buffer_count = 62 - info->tx_buffer_count; - - } - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n", - __FILE__,__LINE__, info->tx_buffer_count,info->rx_buffer_count); - - if ( mgsl_alloc_buffer_list_memory( info ) < 0 || - mgsl_alloc_frame_memory(info, info->rx_buffer_list, info->rx_buffer_count) < 0 || - mgsl_alloc_frame_memory(info, info->tx_buffer_list, info->tx_buffer_count) < 0 || - mgsl_alloc_intermediate_rxbuffer_memory(info) < 0 || - mgsl_alloc_intermediate_txbuffer_memory(info) < 0 ) { - printk("%s(%d):Can't allocate DMA buffer memory\n",__FILE__,__LINE__); - return -ENOMEM; - } - - mgsl_reset_rx_dma_buffers( info ); - mgsl_reset_tx_dma_buffers( info ); - - return 0; - -} /* end of mgsl_allocate_dma_buffers() */ - -/* - * mgsl_alloc_buffer_list_memory() - * - * Allocate a common DMA buffer for use as the - * receive and transmit buffer lists. - * - * A buffer list is a set of buffer entries where each entry contains - * a pointer to an actual buffer and a pointer to the next buffer entry - * (plus some other info about the buffer). - * - * The buffer entries for a list are built to form a circular list so - * that when the entire list has been traversed you start back at the - * beginning. - * - * This function allocates memory for just the buffer entries. - * The links (pointer to next entry) are filled in with the physical - * address of the next entry so the adapter can navigate the list - * using bus master DMA. The pointers to the actual buffers are filled - * out later when the actual buffers are allocated. - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise error - */ -static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) -{ - unsigned int i; - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter uses shared memory. */ - info->buffer_list = info->memory_base + info->last_mem_alloc; - info->buffer_list_phys = info->last_mem_alloc; - info->last_mem_alloc += BUFFERLISTSIZE; - } else { - /* ISA adapter uses system memory. */ - /* The buffer lists are allocated as a common buffer that both */ - /* the processor and adapter can access. This allows the driver to */ - /* inspect portions of the buffer while other portions are being */ - /* updated by the adapter using Bus Master DMA. */ - - info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); - if (info->buffer_list == NULL) - return -ENOMEM; - info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); - } - - /* We got the memory for the buffer entry lists. */ - /* Initialize the memory block to all zeros. */ - memset( info->buffer_list, 0, BUFFERLISTSIZE ); - - /* Save virtual address pointers to the receive and */ - /* transmit buffer lists. (Receive 1st). These pointers will */ - /* be used by the processor to access the lists. */ - info->rx_buffer_list = (DMABUFFERENTRY *)info->buffer_list; - info->tx_buffer_list = (DMABUFFERENTRY *)info->buffer_list; - info->tx_buffer_list += info->rx_buffer_count; - - /* - * Build the links for the buffer entry lists such that - * two circular lists are built. (Transmit and Receive). - * - * Note: the links are physical addresses - * which are read by the adapter to determine the next - * buffer entry to use. - */ - - for ( i = 0; i < info->rx_buffer_count; i++ ) { - /* calculate and store physical address of this buffer entry */ - info->rx_buffer_list[i].phys_entry = - info->buffer_list_phys + (i * sizeof(DMABUFFERENTRY)); - - /* calculate and store physical address of */ - /* next entry in cirular list of entries */ - - info->rx_buffer_list[i].link = info->buffer_list_phys; - - if ( i < info->rx_buffer_count - 1 ) - info->rx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY); - } - - for ( i = 0; i < info->tx_buffer_count; i++ ) { - /* calculate and store physical address of this buffer entry */ - info->tx_buffer_list[i].phys_entry = info->buffer_list_phys + - ((info->rx_buffer_count + i) * sizeof(DMABUFFERENTRY)); - - /* calculate and store physical address of */ - /* next entry in cirular list of entries */ - - info->tx_buffer_list[i].link = info->buffer_list_phys + - info->rx_buffer_count * sizeof(DMABUFFERENTRY); - - if ( i < info->tx_buffer_count - 1 ) - info->tx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY); - } - - return 0; - -} /* end of mgsl_alloc_buffer_list_memory() */ - -/* Free DMA buffers allocated for use as the - * receive and transmit buffer lists. - * Warning: - * - * The data transfer buffers associated with the buffer list - * MUST be freed before freeing the buffer list itself because - * the buffer list contains the information necessary to free - * the individual buffers! - */ -static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) -{ - if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) - dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); - - info->buffer_list = NULL; - info->rx_buffer_list = NULL; - info->tx_buffer_list = NULL; - -} /* end of mgsl_free_buffer_list_memory() */ - -/* - * mgsl_alloc_frame_memory() - * - * Allocate the frame DMA buffers used by the specified buffer list. - * Each DMA buffer will be one memory page in size. This is necessary - * because memory can fragment enough that it may be impossible - * contiguous pages. - * - * Arguments: - * - * info pointer to device instance data - * BufferList pointer to list of buffer entries - * Buffercount count of buffer entries in buffer list - * - * Return Value: 0 if success, otherwise -ENOMEM - */ -static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) -{ - int i; - u32 phys_addr; - - /* Allocate page sized buffers for the receive buffer list */ - - for ( i = 0; i < Buffercount; i++ ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter uses shared memory buffers. */ - BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; - phys_addr = info->last_mem_alloc; - info->last_mem_alloc += DMABUFFERSIZE; - } else { - /* ISA adapter uses system memory. */ - BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); - if (BufferList[i].virt_addr == NULL) - return -ENOMEM; - phys_addr = (u32)(BufferList[i].dma_addr); - } - BufferList[i].phys_addr = phys_addr; - } - - return 0; - -} /* end of mgsl_alloc_frame_memory() */ - -/* - * mgsl_free_frame_memory() - * - * Free the buffers associated with - * each buffer entry of a buffer list. - * - * Arguments: - * - * info pointer to device instance data - * BufferList pointer to list of buffer entries - * Buffercount count of buffer entries in buffer list - * - * Return Value: None - */ -static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount) -{ - int i; - - if ( BufferList ) { - for ( i = 0 ; i < Buffercount ; i++ ) { - if ( BufferList[i].virt_addr ) { - if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); - BufferList[i].virt_addr = NULL; - } - } - } - -} /* end of mgsl_free_frame_memory() */ - -/* mgsl_free_dma_buffers() - * - * Free DMA buffers - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_free_dma_buffers( struct mgsl_struct *info ) -{ - mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count ); - mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count ); - mgsl_free_buffer_list_memory( info ); - -} /* end of mgsl_free_dma_buffers() */ - - -/* - * mgsl_alloc_intermediate_rxbuffer_memory() - * - * Allocate a buffer large enough to hold max_frame_size. This buffer - * is used to pass an assembled frame to the line discipline. - * - * Arguments: - * - * info pointer to device instance data - * - * Return Value: 0 if success, otherwise -ENOMEM - */ -static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) -{ - info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA); - if ( info->intermediate_rxbuffer == NULL ) - return -ENOMEM; - - return 0; - -} /* end of mgsl_alloc_intermediate_rxbuffer_memory() */ - -/* - * mgsl_free_intermediate_rxbuffer_memory() - * - * - * Arguments: - * - * info pointer to device instance data - * - * Return Value: None - */ -static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) -{ - kfree(info->intermediate_rxbuffer); - info->intermediate_rxbuffer = NULL; - -} /* end of mgsl_free_intermediate_rxbuffer_memory() */ - -/* - * mgsl_alloc_intermediate_txbuffer_memory() - * - * Allocate intermdiate transmit buffer(s) large enough to hold max_frame_size. - * This buffer is used to load transmit frames into the adapter's dma transfer - * buffers when there is sufficient space. - * - * Arguments: - * - * info pointer to device instance data - * - * Return Value: 0 if success, otherwise -ENOMEM - */ -static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) -{ - int i; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s %s(%d) allocating %d tx holding buffers\n", - info->device_name, __FILE__,__LINE__,info->num_tx_holding_buffers); - - memset(info->tx_holding_buffers,0,sizeof(info->tx_holding_buffers)); - - for ( i=0; inum_tx_holding_buffers; ++i) { - info->tx_holding_buffers[i].buffer = - kmalloc(info->max_frame_size, GFP_KERNEL); - if (info->tx_holding_buffers[i].buffer == NULL) { - for (--i; i >= 0; i--) { - kfree(info->tx_holding_buffers[i].buffer); - info->tx_holding_buffers[i].buffer = NULL; - } - return -ENOMEM; - } - } - - return 0; - -} /* end of mgsl_alloc_intermediate_txbuffer_memory() */ - -/* - * mgsl_free_intermediate_txbuffer_memory() - * - * - * Arguments: - * - * info pointer to device instance data - * - * Return Value: None - */ -static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) -{ - int i; - - for ( i=0; inum_tx_holding_buffers; ++i ) { - kfree(info->tx_holding_buffers[i].buffer); - info->tx_holding_buffers[i].buffer = NULL; - } - - info->get_tx_holding_index = 0; - info->put_tx_holding_index = 0; - info->tx_holding_count = 0; - -} /* end of mgsl_free_intermediate_txbuffer_memory() */ - - -/* - * load_next_tx_holding_buffer() - * - * attempts to load the next buffered tx request into the - * tx dma buffers - * - * Arguments: - * - * info pointer to device instance data - * - * Return Value: true if next buffered tx request loaded - * into adapter's tx dma buffer, - * false otherwise - */ -static bool load_next_tx_holding_buffer(struct mgsl_struct *info) -{ - bool ret = false; - - if ( info->tx_holding_count ) { - /* determine if we have enough tx dma buffers - * to accommodate the next tx frame - */ - struct tx_holding_buffer *ptx = - &info->tx_holding_buffers[info->get_tx_holding_index]; - int num_free = num_free_tx_dma_buffers(info); - int num_needed = ptx->buffer_size / DMABUFFERSIZE; - if ( ptx->buffer_size % DMABUFFERSIZE ) - ++num_needed; - - if (num_needed <= num_free) { - info->xmit_cnt = ptx->buffer_size; - mgsl_load_tx_dma_buffer(info,ptx->buffer,ptx->buffer_size); - - --info->tx_holding_count; - if ( ++info->get_tx_holding_index >= info->num_tx_holding_buffers) - info->get_tx_holding_index=0; - - /* restart transmit timer */ - mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); - - ret = true; - } - } - - return ret; -} - -/* - * save_tx_buffer_request() - * - * attempt to store transmit frame request for later transmission - * - * Arguments: - * - * info pointer to device instance data - * Buffer pointer to buffer containing frame to load - * BufferSize size in bytes of frame in Buffer - * - * Return Value: 1 if able to store, 0 otherwise - */ -static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize) -{ - struct tx_holding_buffer *ptx; - - if ( info->tx_holding_count >= info->num_tx_holding_buffers ) { - return 0; /* all buffers in use */ - } - - ptx = &info->tx_holding_buffers[info->put_tx_holding_index]; - ptx->buffer_size = BufferSize; - memcpy( ptx->buffer, Buffer, BufferSize); - - ++info->tx_holding_count; - if ( ++info->put_tx_holding_index >= info->num_tx_holding_buffers) - info->put_tx_holding_index=0; - - return 1; -} - -static int mgsl_claim_resources(struct mgsl_struct *info) -{ - if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) { - printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->io_base); - return -ENODEV; - } - info->io_addr_requested = true; - - if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags, - info->device_name, info ) < 0 ) { - printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n", - __FILE__,__LINE__,info->device_name, info->irq_level ); - goto errout; - } - info->irq_requested = true; - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { - printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base); - goto errout; - } - info->shared_mem_requested = true; - if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { - printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); - goto errout; - } - info->lcr_mem_requested = true; - - info->memory_base = ioremap_nocache(info->phys_memory_base, - 0x40000); - if (!info->memory_base) { - printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - if ( !mgsl_memory_test(info) ) { - printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - info->lcr_base = ioremap_nocache(info->phys_lcr_base, - PAGE_SIZE); - if (!info->lcr_base) { - printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); - goto errout; - } - info->lcr_base += info->lcr_offset; - - } else { - /* claim DMA channel */ - - if (request_dma(info->dma_level,info->device_name) < 0){ - printk( "%s(%d):Cant request DMA channel on device %s DMA=%d\n", - __FILE__,__LINE__,info->device_name, info->dma_level ); - mgsl_release_resources( info ); - return -ENODEV; - } - info->dma_requested = true; - - /* ISA adapter uses bus master DMA */ - set_dma_mode(info->dma_level,DMA_MODE_CASCADE); - enable_dma(info->dma_level); - } - - if ( mgsl_allocate_dma_buffers(info) < 0 ) { - printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n", - __FILE__,__LINE__,info->device_name, info->dma_level ); - goto errout; - } - - return 0; -errout: - mgsl_release_resources(info); - return -ENODEV; - -} /* end of mgsl_claim_resources() */ - -static void mgsl_release_resources(struct mgsl_struct *info) -{ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_release_resources(%s) entry\n", - __FILE__,__LINE__,info->device_name ); - - if ( info->irq_requested ) { - free_irq(info->irq_level, info); - info->irq_requested = false; - } - if ( info->dma_requested ) { - disable_dma(info->dma_level); - free_dma(info->dma_level); - info->dma_requested = false; - } - mgsl_free_dma_buffers(info); - mgsl_free_intermediate_rxbuffer_memory(info); - mgsl_free_intermediate_txbuffer_memory(info); - - if ( info->io_addr_requested ) { - release_region(info->io_base,info->io_addr_size); - info->io_addr_requested = false; - } - if ( info->shared_mem_requested ) { - release_mem_region(info->phys_memory_base,0x40000); - info->shared_mem_requested = false; - } - if ( info->lcr_mem_requested ) { - release_mem_region(info->phys_lcr_base + info->lcr_offset,128); - info->lcr_mem_requested = false; - } - if (info->memory_base){ - iounmap(info->memory_base); - info->memory_base = NULL; - } - if (info->lcr_base){ - iounmap(info->lcr_base - info->lcr_offset); - info->lcr_base = NULL; - } - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_release_resources(%s) exit\n", - __FILE__,__LINE__,info->device_name ); - -} /* end of mgsl_release_resources() */ - -/* mgsl_add_device() - * - * Add the specified device instance data structure to the - * global linked list of devices and increment the device count. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_add_device( struct mgsl_struct *info ) -{ - info->next_device = NULL; - info->line = mgsl_device_count; - sprintf(info->device_name,"ttySL%d",info->line); - - if (info->line < MAX_TOTAL_DEVICES) { - if (maxframe[info->line]) - info->max_frame_size = maxframe[info->line]; - - if (txdmabufs[info->line]) { - info->num_tx_dma_buffers = txdmabufs[info->line]; - if (info->num_tx_dma_buffers < 1) - info->num_tx_dma_buffers = 1; - } - - if (txholdbufs[info->line]) { - info->num_tx_holding_buffers = txholdbufs[info->line]; - if (info->num_tx_holding_buffers < 1) - info->num_tx_holding_buffers = 1; - else if (info->num_tx_holding_buffers > MAX_TX_HOLDING_BUFFERS) - info->num_tx_holding_buffers = MAX_TX_HOLDING_BUFFERS; - } - } - - mgsl_device_count++; - - if ( !mgsl_device_list ) - mgsl_device_list = info; - else { - struct mgsl_struct *current_dev = mgsl_device_list; - while( current_dev->next_device ) - current_dev = current_dev->next_device; - current_dev->next_device = info; - } - - if ( info->max_frame_size < 4096 ) - info->max_frame_size = 4096; - else if ( info->max_frame_size > 65535 ) - info->max_frame_size = 65535; - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", - info->hw_version + 1, info->device_name, info->io_base, info->irq_level, - info->phys_memory_base, info->phys_lcr_base, - info->max_frame_size ); - } else { - printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", - info->device_name, info->io_base, info->irq_level, info->dma_level, - info->max_frame_size ); - } - -#if SYNCLINK_GENERIC_HDLC - hdlcdev_init(info); -#endif - -} /* end of mgsl_add_device() */ - -static const struct tty_port_operations mgsl_port_ops = { - .carrier_raised = carrier_raised, - .dtr_rts = dtr_rts, -}; - - -/* mgsl_allocate_device() - * - * Allocate and initialize a device instance structure - * - * Arguments: none - * Return Value: pointer to mgsl_struct if success, otherwise NULL - */ -static struct mgsl_struct* mgsl_allocate_device(void) -{ - struct mgsl_struct *info; - - info = kzalloc(sizeof(struct mgsl_struct), - GFP_KERNEL); - - if (!info) { - printk("Error can't allocate device instance data\n"); - } else { - tty_port_init(&info->port); - info->port.ops = &mgsl_port_ops; - info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, mgsl_bh_handler); - info->max_frame_size = 4096; - info->port.close_delay = 5*HZ/10; - info->port.closing_wait = 30*HZ; - init_waitqueue_head(&info->status_event_wait_q); - init_waitqueue_head(&info->event_wait_q); - spin_lock_init(&info->irq_spinlock); - spin_lock_init(&info->netlock); - memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - info->idle_mode = HDLC_TXIDLE_FLAGS; - info->num_tx_dma_buffers = 1; - info->num_tx_holding_buffers = 0; - } - - return info; - -} /* end of mgsl_allocate_device()*/ - -static const struct tty_operations mgsl_ops = { - .open = mgsl_open, - .close = mgsl_close, - .write = mgsl_write, - .put_char = mgsl_put_char, - .flush_chars = mgsl_flush_chars, - .write_room = mgsl_write_room, - .chars_in_buffer = mgsl_chars_in_buffer, - .flush_buffer = mgsl_flush_buffer, - .ioctl = mgsl_ioctl, - .throttle = mgsl_throttle, - .unthrottle = mgsl_unthrottle, - .send_xchar = mgsl_send_xchar, - .break_ctl = mgsl_break, - .wait_until_sent = mgsl_wait_until_sent, - .set_termios = mgsl_set_termios, - .stop = mgsl_stop, - .start = mgsl_start, - .hangup = mgsl_hangup, - .tiocmget = tiocmget, - .tiocmset = tiocmset, - .get_icount = msgl_get_icount, - .proc_fops = &mgsl_proc_fops, -}; - -/* - * perform tty device initialization - */ -static int mgsl_init_tty(void) -{ - int rc; - - serial_driver = alloc_tty_driver(128); - if (!serial_driver) - return -ENOMEM; - - serial_driver->owner = THIS_MODULE; - serial_driver->driver_name = "synclink"; - serial_driver->name = "ttySL"; - serial_driver->major = ttymajor; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->init_termios.c_ispeed = 9600; - serial_driver->init_termios.c_ospeed = 9600; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &mgsl_ops); - if ((rc = tty_register_driver(serial_driver)) < 0) { - printk("%s(%d):Couldn't register serial driver\n", - __FILE__,__LINE__); - put_tty_driver(serial_driver); - serial_driver = NULL; - return rc; - } - - printk("%s %s, tty major#%d\n", - driver_name, driver_version, - serial_driver->major); - return 0; -} - -/* enumerate user specified ISA adapters - */ -static void mgsl_enum_isa_devices(void) -{ - struct mgsl_struct *info; - int i; - - /* Check for user specified ISA devices */ - - for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("ISA device specified io=%04X,irq=%d,dma=%d\n", - io[i], irq[i], dma[i] ); - - info = mgsl_allocate_device(); - if ( !info ) { - /* error allocating device instance data */ - if ( debug_level >= DEBUG_LEVEL_ERROR ) - printk( "can't allocate device instance data.\n"); - continue; - } - - /* Copy user configuration info to device instance data */ - info->io_base = (unsigned int)io[i]; - info->irq_level = (unsigned int)irq[i]; - info->irq_level = irq_canonicalize(info->irq_level); - info->dma_level = (unsigned int)dma[i]; - info->bus_type = MGSL_BUS_TYPE_ISA; - info->io_addr_size = 16; - info->irq_flags = 0; - - mgsl_add_device( info ); - } -} - -static void synclink_cleanup(void) -{ - int rc; - struct mgsl_struct *info; - struct mgsl_struct *tmp; - - printk("Unloading %s: %s\n", driver_name, driver_version); - - if (serial_driver) { - if ((rc = tty_unregister_driver(serial_driver))) - printk("%s(%d) failed to unregister tty driver err=%d\n", - __FILE__,__LINE__,rc); - put_tty_driver(serial_driver); - } - - info = mgsl_device_list; - while(info) { -#if SYNCLINK_GENERIC_HDLC - hdlcdev_exit(info); -#endif - mgsl_release_resources(info); - tmp = info; - info = info->next_device; - kfree(tmp); - } - - if (pci_registered) - pci_unregister_driver(&synclink_pci_driver); -} - -static int __init synclink_init(void) -{ - int rc; - - if (break_on_load) { - mgsl_get_text_ptr(); - BREAKPOINT(); - } - - printk("%s %s\n", driver_name, driver_version); - - mgsl_enum_isa_devices(); - if ((rc = pci_register_driver(&synclink_pci_driver)) < 0) - printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc); - else - pci_registered = true; - - if ((rc = mgsl_init_tty()) < 0) - goto error; - - return 0; - -error: - synclink_cleanup(); - return rc; -} - -static void __exit synclink_exit(void) -{ - synclink_cleanup(); -} - -module_init(synclink_init); -module_exit(synclink_exit); - -/* - * usc_RTCmd() - * - * Issue a USC Receive/Transmit command to the - * Channel Command/Address Register (CCAR). - * - * Notes: - * - * The command is encoded in the most significant 5 bits <15..11> - * of the CCAR value. Bits <10..7> of the CCAR must be preserved - * and Bits <6..0> must be written as zeros. - * - * Arguments: - * - * info pointer to device information structure - * Cmd command mask (use symbolic macros) - * - * Return Value: - * - * None - */ -static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) -{ - /* output command to CCAR in bits <15..11> */ - /* preserve bits <10..7>, bits <6..0> must be zero */ - - outw( Cmd + info->loopback_bits, info->io_base + CCAR ); - - /* Read to flush write to CCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base + CCAR ); - -} /* end of usc_RTCmd() */ - -/* - * usc_DmaCmd() - * - * Issue a DMA command to the DMA Command/Address Register (DCAR). - * - * Arguments: - * - * info pointer to device information structure - * Cmd DMA command mask (usc_DmaCmd_XX Macros) - * - * Return Value: - * - * None - */ -static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) -{ - /* write command mask to DCAR */ - outw( Cmd + info->mbre_bit, info->io_base ); - - /* Read to flush write to DCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base ); - -} /* end of usc_DmaCmd() */ - -/* - * usc_OutDmaReg() - * - * Write a 16-bit value to a USC DMA register - * - * Arguments: - * - * info pointer to device info structure - * RegAddr register address (number) for write - * RegValue 16-bit value to write to register - * - * Return Value: - * - * None - * - */ -static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) -{ - /* Note: The DCAR is located at the adapter base address */ - /* Note: must preserve state of BIT8 in DCAR */ - - outw( RegAddr + info->mbre_bit, info->io_base ); - outw( RegValue, info->io_base ); - - /* Read to flush write to DCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base ); - -} /* end of usc_OutDmaReg() */ - -/* - * usc_InDmaReg() - * - * Read a 16-bit value from a DMA register - * - * Arguments: - * - * info pointer to device info structure - * RegAddr register address (number) to read from - * - * Return Value: - * - * The 16-bit value read from register - * - */ -static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr ) -{ - /* Note: The DCAR is located at the adapter base address */ - /* Note: must preserve state of BIT8 in DCAR */ - - outw( RegAddr + info->mbre_bit, info->io_base ); - return inw( info->io_base ); - -} /* end of usc_InDmaReg() */ - -/* - * - * usc_OutReg() - * - * Write a 16-bit value to a USC serial channel register - * - * Arguments: - * - * info pointer to device info structure - * RegAddr register address (number) to write to - * RegValue 16-bit value to write to register - * - * Return Value: - * - * None - * - */ -static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) -{ - outw( RegAddr + info->loopback_bits, info->io_base + CCAR ); - outw( RegValue, info->io_base + CCAR ); - - /* Read to flush write to CCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base + CCAR ); - -} /* end of usc_OutReg() */ - -/* - * usc_InReg() - * - * Reads a 16-bit value from a USC serial channel register - * - * Arguments: - * - * info pointer to device extension - * RegAddr register address (number) to read from - * - * Return Value: - * - * 16-bit value read from register - */ -static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) -{ - outw( RegAddr + info->loopback_bits, info->io_base + CCAR ); - return inw( info->io_base + CCAR ); - -} /* end of usc_InReg() */ - -/* usc_set_sdlc_mode() - * - * Set up the adapter for SDLC DMA communications. - * - * Arguments: info pointer to device instance data - * Return Value: NONE - */ -static void usc_set_sdlc_mode( struct mgsl_struct *info ) -{ - u16 RegValue; - bool PreSL1660; - - /* - * determine if the IUSC on the adapter is pre-SL1660. If - * not, take advantage of the UnderWait feature of more - * modern chips. If an underrun occurs and this bit is set, - * the transmitter will idle the programmed idle pattern - * until the driver has time to service the underrun. Otherwise, - * the dma controller may get the cycles previously requested - * and begin transmitting queued tx data. - */ - usc_OutReg(info,TMCR,0x1f); - RegValue=usc_InReg(info,TMDR); - PreSL1660 = (RegValue == IUSC_PRE_SL1660); - - if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) - { - /* - ** Channel Mode Register (CMR) - ** - ** <15..14> 10 Tx Sub Modes, Send Flag on Underrun - ** <13> 0 0 = Transmit Disabled (initially) - ** <12> 0 1 = Consecutive Idles share common 0 - ** <11..8> 1110 Transmitter Mode = HDLC/SDLC Loop - ** <7..4> 0000 Rx Sub Modes, addr/ctrl field handling - ** <3..0> 0110 Receiver Mode = HDLC/SDLC - ** - ** 1000 1110 0000 0110 = 0x8e06 - */ - RegValue = 0x8e06; - - /*-------------------------------------------------- - * ignore user options for UnderRun Actions and - * preambles - *--------------------------------------------------*/ - } - else - { - /* Channel mode Register (CMR) - * - * <15..14> 00 Tx Sub modes, Underrun Action - * <13> 0 1 = Send Preamble before opening flag - * <12> 0 1 = Consecutive Idles share common 0 - * <11..8> 0110 Transmitter mode = HDLC/SDLC - * <7..4> 0000 Rx Sub modes, addr/ctrl field handling - * <3..0> 0110 Receiver mode = HDLC/SDLC - * - * 0000 0110 0000 0110 = 0x0606 - */ - if (info->params.mode == MGSL_MODE_RAW) { - RegValue = 0x0001; /* Set Receive mode = external sync */ - - usc_OutReg( info, IOCR, /* Set IOCR DCD is RxSync Detect Input */ - (unsigned short)((usc_InReg(info, IOCR) & ~(BIT13|BIT12)) | BIT12)); - - /* - * TxSubMode: - * CMR <15> 0 Don't send CRC on Tx Underrun - * CMR <14> x undefined - * CMR <13> 0 Send preamble before openning sync - * CMR <12> 0 Send 8-bit syncs, 1=send Syncs per TxLength - * - * TxMode: - * CMR <11-8) 0100 MonoSync - * - * 0x00 0100 xxxx xxxx 04xx - */ - RegValue |= 0x0400; - } - else { - - RegValue = 0x0606; - - if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 ) - RegValue |= BIT14; - else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG ) - RegValue |= BIT15; - else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC ) - RegValue |= BIT15 + BIT14; - } - - if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE ) - RegValue |= BIT13; - } - - if ( info->params.mode == MGSL_MODE_HDLC && - (info->params.flags & HDLC_FLAG_SHARE_ZERO) ) - RegValue |= BIT12; - - if ( info->params.addr_filter != 0xff ) - { - /* set up receive address filtering */ - usc_OutReg( info, RSR, info->params.addr_filter ); - RegValue |= BIT4; - } - - usc_OutReg( info, CMR, RegValue ); - info->cmr_value = RegValue; - - /* Receiver mode Register (RMR) - * - * <15..13> 000 encoding - * <12..11> 00 FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1) - * <10> 1 1 = Set CRC to all 1s (use for SDLC/HDLC) - * <9> 0 1 = Include Receive chars in CRC - * <8> 1 1 = Use Abort/PE bit as abort indicator - * <7..6> 00 Even parity - * <5> 0 parity disabled - * <4..2> 000 Receive Char Length = 8 bits - * <1..0> 00 Disable Receiver - * - * 0000 0101 0000 0000 = 0x0500 - */ - - RegValue = 0x0500; - - switch ( info->params.encoding ) { - case HDLC_ENCODING_NRZB: RegValue |= BIT13; break; - case HDLC_ENCODING_NRZI_MARK: RegValue |= BIT14; break; - case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 + BIT13; break; - case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT15; break; - case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 + BIT13; break; - case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break; - } - - if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT ) - RegValue |= BIT9; - else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT ) - RegValue |= ( BIT12 | BIT10 | BIT9 ); - - usc_OutReg( info, RMR, RegValue ); - - /* Set the Receive count Limit Register (RCLR) to 0xffff. */ - /* When an opening flag of an SDLC frame is recognized the */ - /* Receive Character count (RCC) is loaded with the value in */ - /* RCLR. The RCC is decremented for each received byte. The */ - /* value of RCC is stored after the closing flag of the frame */ - /* allowing the frame size to be computed. */ - - usc_OutReg( info, RCLR, RCLRVALUE ); - - usc_RCmd( info, RCmd_SelectRicrdma_level ); - - /* Receive Interrupt Control Register (RICR) - * - * <15..8> ? RxFIFO DMA Request Level - * <7> 0 Exited Hunt IA (Interrupt Arm) - * <6> 0 Idle Received IA - * <5> 0 Break/Abort IA - * <4> 0 Rx Bound IA - * <3> 1 Queued status reflects oldest 2 bytes in FIFO - * <2> 0 Abort/PE IA - * <1> 1 Rx Overrun IA - * <0> 0 Select TC0 value for readback - * - * 0000 0000 0000 1000 = 0x000a - */ - - /* Carry over the Exit Hunt and Idle Received bits */ - /* in case they have been armed by usc_ArmEvents. */ - - RegValue = usc_InReg( info, RICR ) & 0xc0; - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); - else - usc_OutReg( info, RICR, (u16)(0x140a | RegValue) ); - - /* Unlatch all Rx status bits and clear Rx status IRQ Pending */ - - usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_STATUS ); - - /* Transmit mode Register (TMR) - * - * <15..13> 000 encoding - * <12..11> 00 FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1) - * <10> 1 1 = Start CRC as all 1s (use for SDLC/HDLC) - * <9> 0 1 = Tx CRC Enabled - * <8> 0 1 = Append CRC to end of transmit frame - * <7..6> 00 Transmit parity Even - * <5> 0 Transmit parity Disabled - * <4..2> 000 Tx Char Length = 8 bits - * <1..0> 00 Disable Transmitter - * - * 0000 0100 0000 0000 = 0x0400 - */ - - RegValue = 0x0400; - - switch ( info->params.encoding ) { - case HDLC_ENCODING_NRZB: RegValue |= BIT13; break; - case HDLC_ENCODING_NRZI_MARK: RegValue |= BIT14; break; - case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 + BIT13; break; - case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT15; break; - case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 + BIT13; break; - case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break; - } - - if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT ) - RegValue |= BIT9 + BIT8; - else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT ) - RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8); - - usc_OutReg( info, TMR, RegValue ); - - usc_set_txidle( info ); - - - usc_TCmd( info, TCmd_SelectTicrdma_level ); - - /* Transmit Interrupt Control Register (TICR) - * - * <15..8> ? Transmit FIFO DMA Level - * <7> 0 Present IA (Interrupt Arm) - * <6> 0 Idle Sent IA - * <5> 1 Abort Sent IA - * <4> 1 EOF/EOM Sent IA - * <3> 0 CRC Sent IA - * <2> 1 1 = Wait for SW Trigger to Start Frame - * <1> 1 Tx Underrun IA - * <0> 0 TC0 constant on read back - * - * 0000 0000 0011 0110 = 0x0036 - */ - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, TICR, 0x0736 ); - else - usc_OutReg( info, TICR, 0x1436 ); - - usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); - - /* - ** Transmit Command/Status Register (TCSR) - ** - ** <15..12> 0000 TCmd - ** <11> 0/1 UnderWait - ** <10..08> 000 TxIdle - ** <7> x PreSent - ** <6> x IdleSent - ** <5> x AbortSent - ** <4> x EOF/EOM Sent - ** <3> x CRC Sent - ** <2> x All Sent - ** <1> x TxUnder - ** <0> x TxEmpty - ** - ** 0000 0000 0000 0000 = 0x0000 - */ - info->tcsr_value = 0; - - if ( !PreSL1660 ) - info->tcsr_value |= TCSR_UNDERWAIT; - - usc_OutReg( info, TCSR, info->tcsr_value ); - - /* Clock mode Control Register (CMCR) - * - * <15..14> 00 counter 1 Source = Disabled - * <13..12> 00 counter 0 Source = Disabled - * <11..10> 11 BRG1 Input is TxC Pin - * <9..8> 11 BRG0 Input is TxC Pin - * <7..6> 01 DPLL Input is BRG1 Output - * <5..3> XXX TxCLK comes from Port 0 - * <2..0> XXX RxCLK comes from Port 1 - * - * 0000 1111 0111 0111 = 0x0f77 - */ - - RegValue = 0x0f40; - - if ( info->params.flags & HDLC_FLAG_RXC_DPLL ) - RegValue |= 0x0003; /* RxCLK from DPLL */ - else if ( info->params.flags & HDLC_FLAG_RXC_BRG ) - RegValue |= 0x0004; /* RxCLK from BRG0 */ - else if ( info->params.flags & HDLC_FLAG_RXC_TXCPIN) - RegValue |= 0x0006; /* RxCLK from TXC Input */ - else - RegValue |= 0x0007; /* RxCLK from Port1 */ - - if ( info->params.flags & HDLC_FLAG_TXC_DPLL ) - RegValue |= 0x0018; /* TxCLK from DPLL */ - else if ( info->params.flags & HDLC_FLAG_TXC_BRG ) - RegValue |= 0x0020; /* TxCLK from BRG0 */ - else if ( info->params.flags & HDLC_FLAG_TXC_RXCPIN) - RegValue |= 0x0038; /* RxCLK from TXC Input */ - else - RegValue |= 0x0030; /* TxCLK from Port0 */ - - usc_OutReg( info, CMCR, RegValue ); - - - /* Hardware Configuration Register (HCR) - * - * <15..14> 00 CTR0 Divisor:00=32,01=16,10=8,11=4 - * <13> 0 CTR1DSel:0=CTR0Div determines CTR0Div - * <12> 0 CVOK:0=report code violation in biphase - * <11..10> 00 DPLL Divisor:00=32,01=16,10=8,11=4 - * <9..8> XX DPLL mode:00=disable,01=NRZ,10=Biphase,11=Biphase Level - * <7..6> 00 reserved - * <5> 0 BRG1 mode:0=continuous,1=single cycle - * <4> X BRG1 Enable - * <3..2> 00 reserved - * <1> 0 BRG0 mode:0=continuous,1=single cycle - * <0> 0 BRG0 Enable - */ - - RegValue = 0x0000; - - if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) { - u32 XtalSpeed; - u32 DpllDivisor; - u16 Tc; - - /* DPLL is enabled. Use BRG1 to provide continuous reference clock */ - /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */ - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - XtalSpeed = 11059200; - else - XtalSpeed = 14745600; - - if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { - DpllDivisor = 16; - RegValue |= BIT10; - } - else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) { - DpllDivisor = 8; - RegValue |= BIT11; - } - else - DpllDivisor = 32; - - /* Tc = (Xtal/Speed) - 1 */ - /* If twice the remainder of (Xtal/Speed) is greater than Speed */ - /* then rounding up gives a more precise time constant. Instead */ - /* of rounding up and then subtracting 1 we just don't subtract */ - /* the one in this case. */ - - /*-------------------------------------------------- - * ejz: for DPLL mode, application should use the - * same clock speed as the partner system, even - * though clocking is derived from the input RxData. - * In case the user uses a 0 for the clock speed, - * default to 0xffffffff and don't try to divide by - * zero - *--------------------------------------------------*/ - if ( info->params.clock_speed ) - { - Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed); - if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2) - / info->params.clock_speed) ) - Tc--; - } - else - Tc = -1; - - - /* Write 16-bit Time Constant for BRG1 */ - usc_OutReg( info, TC1R, Tc ); - - RegValue |= BIT4; /* enable BRG1 */ - - switch ( info->params.encoding ) { - case HDLC_ENCODING_NRZ: - case HDLC_ENCODING_NRZB: - case HDLC_ENCODING_NRZI_MARK: - case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT8; break; - case HDLC_ENCODING_BIPHASE_MARK: - case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break; - case HDLC_ENCODING_BIPHASE_LEVEL: - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break; - } - } - - usc_OutReg( info, HCR, RegValue ); - - - /* Channel Control/status Register (CCSR) - * - * <15> X RCC FIFO Overflow status (RO) - * <14> X RCC FIFO Not Empty status (RO) - * <13> 0 1 = Clear RCC FIFO (WO) - * <12> X DPLL Sync (RW) - * <11> X DPLL 2 Missed Clocks status (RO) - * <10> X DPLL 1 Missed Clock status (RO) - * <9..8> 00 DPLL Resync on rising and falling edges (RW) - * <7> X SDLC Loop On status (RO) - * <6> X SDLC Loop Send status (RO) - * <5> 1 Bypass counters for TxClk and RxClk (RW) - * <4..2> 000 Last Char of SDLC frame has 8 bits (RW) - * <1..0> 00 reserved - * - * 0000 0000 0010 0000 = 0x0020 - */ - - usc_OutReg( info, CCSR, 0x1020 ); - - - if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) { - usc_OutReg( info, SICR, - (u16)(usc_InReg(info,SICR) | SICR_CTS_INACTIVE) ); - } - - - /* enable Master Interrupt Enable bit (MIE) */ - usc_EnableMasterIrqBit( info ); - - usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA + - TRANSMIT_STATUS + TRANSMIT_DATA + MISC); - - /* arm RCC underflow interrupt */ - usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3)); - usc_EnableInterrupts(info, MISC); - - info->mbre_bit = 0; - outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ - usc_DmaCmd( info, DmaCmd_ResetAllChannels ); /* disable both DMA channels */ - info->mbre_bit = BIT8; - outw( BIT8, info->io_base ); /* set Master Bus Enable (DCAR) */ - - if (info->bus_type == MGSL_BUS_TYPE_ISA) { - /* Enable DMAEN (Port 7, Bit 14) */ - /* This connects the DMA request signal to the ISA bus */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14)); - } - - /* DMA Control Register (DCR) - * - * <15..14> 10 Priority mode = Alternating Tx/Rx - * 01 Rx has priority - * 00 Tx has priority - * - * <13> 1 Enable Priority Preempt per DCR<15..14> - * (WARNING DCR<11..10> must be 00 when this is 1) - * 0 Choose activate channel per DCR<11..10> - * - * <12> 0 Little Endian for Array/List - * <11..10> 00 Both Channels can use each bus grant - * <9..6> 0000 reserved - * <5> 0 7 CLK - Minimum Bus Re-request Interval - * <4> 0 1 = drive D/C and S/D pins - * <3> 1 1 = Add one wait state to all DMA cycles. - * <2> 0 1 = Strobe /UAS on every transfer. - * <1..0> 11 Addr incrementing only affects LS24 bits - * - * 0110 0000 0000 1011 = 0x600b - */ - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter does not need DMA wait state */ - usc_OutDmaReg( info, DCR, 0xa00b ); - } - else - usc_OutDmaReg( info, DCR, 0x800b ); - - - /* Receive DMA mode Register (RDMR) - * - * <15..14> 11 DMA mode = Linked List Buffer mode - * <13> 1 RSBinA/L = store Rx status Block in Arrary/List entry - * <12> 1 Clear count of List Entry after fetching - * <11..10> 00 Address mode = Increment - * <9> 1 Terminate Buffer on RxBound - * <8> 0 Bus Width = 16bits - * <7..0> ? status Bits (write as 0s) - * - * 1111 0010 0000 0000 = 0xf200 - */ - - usc_OutDmaReg( info, RDMR, 0xf200 ); - - - /* Transmit DMA mode Register (TDMR) - * - * <15..14> 11 DMA mode = Linked List Buffer mode - * <13> 1 TCBinA/L = fetch Tx Control Block from List entry - * <12> 1 Clear count of List Entry after fetching - * <11..10> 00 Address mode = Increment - * <9> 1 Terminate Buffer on end of frame - * <8> 0 Bus Width = 16bits - * <7..0> ? status Bits (Read Only so write as 0) - * - * 1111 0010 0000 0000 = 0xf200 - */ - - usc_OutDmaReg( info, TDMR, 0xf200 ); - - - /* DMA Interrupt Control Register (DICR) - * - * <15> 1 DMA Interrupt Enable - * <14> 0 1 = Disable IEO from USC - * <13> 0 1 = Don't provide vector during IntAck - * <12> 1 1 = Include status in Vector - * <10..2> 0 reserved, Must be 0s - * <1> 0 1 = Rx DMA Interrupt Enabled - * <0> 0 1 = Tx DMA Interrupt Enabled - * - * 1001 0000 0000 0000 = 0x9000 - */ - - usc_OutDmaReg( info, DICR, 0x9000 ); - - usc_InDmaReg( info, RDMR ); /* clear pending receive DMA IRQ bits */ - usc_InDmaReg( info, TDMR ); /* clear pending transmit DMA IRQ bits */ - usc_OutDmaReg( info, CDIR, 0x0303 ); /* clear IUS and Pending for Tx and Rx */ - - /* Channel Control Register (CCR) - * - * <15..14> 10 Use 32-bit Tx Control Blocks (TCBs) - * <13> 0 Trigger Tx on SW Command Disabled - * <12> 0 Flag Preamble Disabled - * <11..10> 00 Preamble Length - * <9..8> 00 Preamble Pattern - * <7..6> 10 Use 32-bit Rx status Blocks (RSBs) - * <5> 0 Trigger Rx on SW Command Disabled - * <4..0> 0 reserved - * - * 1000 0000 1000 0000 = 0x8080 - */ - - RegValue = 0x8080; - - switch ( info->params.preamble_length ) { - case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break; - case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break; - case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break; - } - - switch ( info->params.preamble ) { - case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break; - case HDLC_PREAMBLE_PATTERN_ONES: RegValue |= BIT8; break; - case HDLC_PREAMBLE_PATTERN_10: RegValue |= BIT9; break; - case HDLC_PREAMBLE_PATTERN_01: RegValue |= BIT9 + BIT8; break; - } - - usc_OutReg( info, CCR, RegValue ); - - - /* - * Burst/Dwell Control Register - * - * <15..8> 0x20 Maximum number of transfers per bus grant - * <7..0> 0x00 Maximum number of clock cycles per bus grant - */ - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* don't limit bus occupancy on PCI adapter */ - usc_OutDmaReg( info, BDCR, 0x0000 ); - } - else - usc_OutDmaReg( info, BDCR, 0x2000 ); - - usc_stop_transmitter(info); - usc_stop_receiver(info); - -} /* end of usc_set_sdlc_mode() */ - -/* usc_enable_loopback() - * - * Set the 16C32 for internal loopback mode. - * The TxCLK and RxCLK signals are generated from the BRG0 and - * the TxD is looped back to the RxD internally. - * - * Arguments: info pointer to device instance data - * enable 1 = enable loopback, 0 = disable - * Return Value: None - */ -static void usc_enable_loopback(struct mgsl_struct *info, int enable) -{ - if (enable) { - /* blank external TXD output */ - usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6)); - - /* Clock mode Control Register (CMCR) - * - * <15..14> 00 counter 1 Disabled - * <13..12> 00 counter 0 Disabled - * <11..10> 11 BRG1 Input is TxC Pin - * <9..8> 11 BRG0 Input is TxC Pin - * <7..6> 01 DPLL Input is BRG1 Output - * <5..3> 100 TxCLK comes from BRG0 - * <2..0> 100 RxCLK comes from BRG0 - * - * 0000 1111 0110 0100 = 0x0f64 - */ - - usc_OutReg( info, CMCR, 0x0f64 ); - - /* Write 16-bit Time Constant for BRG0 */ - /* use clock speed if available, otherwise use 8 for diagnostics */ - if (info->params.clock_speed) { - if (info->bus_type == MGSL_BUS_TYPE_PCI) - usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); - else - usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1)); - } else - usc_OutReg(info, TC0R, (u16)8); - - /* Hardware Configuration Register (HCR) Clear Bit 1, BRG0 - mode = Continuous Set Bit 0 to enable BRG0. */ - usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) ); - - /* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */ - usc_OutReg(info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004)); - - /* set Internal Data loopback mode */ - info->loopback_bits = 0x300; - outw( 0x0300, info->io_base + CCAR ); - } else { - /* enable external TXD output */ - usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6)); - - /* clear Internal Data loopback mode */ - info->loopback_bits = 0; - outw( 0,info->io_base + CCAR ); - } - -} /* end of usc_enable_loopback() */ - -/* usc_enable_aux_clock() - * - * Enabled the AUX clock output at the specified frequency. - * - * Arguments: - * - * info pointer to device extension - * data_rate data rate of clock in bits per second - * A data rate of 0 disables the AUX clock. - * - * Return Value: None - */ -static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) -{ - u32 XtalSpeed; - u16 Tc; - - if ( data_rate ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - XtalSpeed = 11059200; - else - XtalSpeed = 14745600; - - - /* Tc = (Xtal/Speed) - 1 */ - /* If twice the remainder of (Xtal/Speed) is greater than Speed */ - /* then rounding up gives a more precise time constant. Instead */ - /* of rounding up and then subtracting 1 we just don't subtract */ - /* the one in this case. */ - - - Tc = (u16)(XtalSpeed/data_rate); - if ( !(((XtalSpeed % data_rate) * 2) / data_rate) ) - Tc--; - - /* Write 16-bit Time Constant for BRG0 */ - usc_OutReg( info, TC0R, Tc ); - - /* - * Hardware Configuration Register (HCR) - * Clear Bit 1, BRG0 mode = Continuous - * Set Bit 0 to enable BRG0. - */ - - usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) ); - - /* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */ - usc_OutReg( info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) ); - } else { - /* data rate == 0 so turn off BRG0 */ - usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) ); - } - -} /* end of usc_enable_aux_clock() */ - -/* - * - * usc_process_rxoverrun_sync() - * - * This function processes a receive overrun by resetting the - * receive DMA buffers and issuing a Purge Rx FIFO command - * to allow the receiver to continue receiving. - * - * Arguments: - * - * info pointer to device extension - * - * Return Value: None - */ -static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) -{ - int start_index; - int end_index; - int frame_start_index; - bool start_of_frame_found = false; - bool end_of_frame_found = false; - bool reprogram_dma = false; - - DMABUFFERENTRY *buffer_list = info->rx_buffer_list; - u32 phys_addr; - - usc_DmaCmd( info, DmaCmd_PauseRxChannel ); - usc_RCmd( info, RCmd_EnterHuntmode ); - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - - /* CurrentRxBuffer points to the 1st buffer of the next */ - /* possibly available receive frame. */ - - frame_start_index = start_index = end_index = info->current_rx_buffer; - - /* Search for an unfinished string of buffers. This means */ - /* that a receive frame started (at least one buffer with */ - /* count set to zero) but there is no terminiting buffer */ - /* (status set to non-zero). */ - - while( !buffer_list[end_index].count ) - { - /* Count field has been reset to zero by 16C32. */ - /* This buffer is currently in use. */ - - if ( !start_of_frame_found ) - { - start_of_frame_found = true; - frame_start_index = end_index; - end_of_frame_found = false; - } - - if ( buffer_list[end_index].status ) - { - /* Status field has been set by 16C32. */ - /* This is the last buffer of a received frame. */ - - /* We want to leave the buffers for this frame intact. */ - /* Move on to next possible frame. */ - - start_of_frame_found = false; - end_of_frame_found = true; - } - - /* advance to next buffer entry in linked list */ - end_index++; - if ( end_index == info->rx_buffer_count ) - end_index = 0; - - if ( start_index == end_index ) - { - /* The entire list has been searched with all Counts == 0 and */ - /* all Status == 0. The receive buffers are */ - /* completely screwed, reset all receive buffers! */ - mgsl_reset_rx_dma_buffers( info ); - frame_start_index = 0; - start_of_frame_found = false; - reprogram_dma = true; - break; - } - } - - if ( start_of_frame_found && !end_of_frame_found ) - { - /* There is an unfinished string of receive DMA buffers */ - /* as a result of the receiver overrun. */ - - /* Reset the buffers for the unfinished frame */ - /* and reprogram the receive DMA controller to start */ - /* at the 1st buffer of unfinished frame. */ - - start_index = frame_start_index; - - do - { - *((unsigned long *)&(info->rx_buffer_list[start_index++].count)) = DMABUFFERSIZE; - - /* Adjust index for wrap around. */ - if ( start_index == info->rx_buffer_count ) - start_index = 0; - - } while( start_index != end_index ); - - reprogram_dma = true; - } - - if ( reprogram_dma ) - { - usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); - usc_ClearIrqPendingBits(info, RECEIVE_DATA|RECEIVE_STATUS); - usc_UnlatchRxstatusBits(info, RECEIVE_DATA|RECEIVE_STATUS); - - usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); - - /* This empties the receive FIFO and loads the RCC with RCLR */ - usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); - - /* program 16C32 with physical address of 1st DMA buffer entry */ - phys_addr = info->rx_buffer_list[frame_start_index].phys_entry; - usc_OutDmaReg( info, NRARL, (u16)phys_addr ); - usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) ); - - usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); - usc_EnableInterrupts( info, RECEIVE_STATUS ); - - /* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */ - /* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */ - - usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 ); - usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) ); - usc_DmaCmd( info, DmaCmd_InitRxChannel ); - if ( info->params.flags & HDLC_FLAG_AUTO_DCD ) - usc_EnableReceiver(info,ENABLE_AUTO_DCD); - else - usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); - } - else - { - /* This empties the receive FIFO and loads the RCC with RCLR */ - usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - } - -} /* end of usc_process_rxoverrun_sync() */ - -/* usc_stop_receiver() - * - * Disable USC receiver - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_stop_receiver( struct mgsl_struct *info ) -{ - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):usc_stop_receiver(%s)\n", - __FILE__,__LINE__, info->device_name ); - - /* Disable receive DMA channel. */ - /* This also disables receive DMA channel interrupts */ - usc_DmaCmd( info, DmaCmd_ResetRxChannel ); - - usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); - usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS ); - - usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); - - /* This empties the receive FIFO and loads the RCC with RCLR */ - usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - - info->rx_enabled = false; - info->rx_overflow = false; - info->rx_rcc_underrun = false; - -} /* end of stop_receiver() */ - -/* usc_start_receiver() - * - * Enable the USC receiver - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_start_receiver( struct mgsl_struct *info ) -{ - u32 phys_addr; - - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):usc_start_receiver(%s)\n", - __FILE__,__LINE__, info->device_name ); - - mgsl_reset_rx_dma_buffers( info ); - usc_stop_receiver( info ); - - usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - - if ( info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW ) { - /* DMA mode Transfers */ - /* Program the DMA controller. */ - /* Enable the DMA controller end of buffer interrupt. */ - - /* program 16C32 with physical address of 1st DMA buffer entry */ - phys_addr = info->rx_buffer_list[0].phys_entry; - usc_OutDmaReg( info, NRARL, (u16)phys_addr ); - usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) ); - - usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); - usc_EnableInterrupts( info, RECEIVE_STATUS ); - - /* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */ - /* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */ - - usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 ); - usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) ); - usc_DmaCmd( info, DmaCmd_InitRxChannel ); - if ( info->params.flags & HDLC_FLAG_AUTO_DCD ) - usc_EnableReceiver(info,ENABLE_AUTO_DCD); - else - usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); - } else { - usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); - usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); - usc_EnableInterrupts(info, RECEIVE_DATA); - - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - usc_RCmd( info, RCmd_EnterHuntmode ); - - usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); - } - - usc_OutReg( info, CCSR, 0x1020 ); - - info->rx_enabled = true; - -} /* end of usc_start_receiver() */ - -/* usc_start_transmitter() - * - * Enable the USC transmitter and send a transmit frame if - * one is loaded in the DMA buffers. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_start_transmitter( struct mgsl_struct *info ) -{ - u32 phys_addr; - unsigned int FrameSize; - - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):usc_start_transmitter(%s)\n", - __FILE__,__LINE__, info->device_name ); - - if ( info->xmit_cnt ) { - - /* If auto RTS enabled and RTS is inactive, then assert */ - /* RTS and set a flag indicating that the driver should */ - /* negate RTS when the transmission completes. */ - - info->drop_rts_on_tx_done = false; - - if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) { - usc_get_serial_signals( info ); - if ( !(info->serial_signals & SerialSignal_RTS) ) { - info->serial_signals |= SerialSignal_RTS; - usc_set_serial_signals( info ); - info->drop_rts_on_tx_done = true; - } - } - - - if ( info->params.mode == MGSL_MODE_ASYNC ) { - if ( !info->tx_active ) { - usc_UnlatchTxstatusBits(info, TXSTATUS_ALL); - usc_ClearIrqPendingBits(info, TRANSMIT_STATUS + TRANSMIT_DATA); - usc_EnableInterrupts(info, TRANSMIT_DATA); - usc_load_txfifo(info); - } - } else { - /* Disable transmit DMA controller while programming. */ - usc_DmaCmd( info, DmaCmd_ResetTxChannel ); - - /* Transmit DMA buffer is loaded, so program USC */ - /* to send the frame contained in the buffers. */ - - FrameSize = info->tx_buffer_list[info->start_tx_dma_buffer].rcc; - - /* if operating in Raw sync mode, reset the rcc component - * of the tx dma buffer entry, otherwise, the serial controller - * will send a closing sync char after this count. - */ - if ( info->params.mode == MGSL_MODE_RAW ) - info->tx_buffer_list[info->start_tx_dma_buffer].rcc = 0; - - /* Program the Transmit Character Length Register (TCLR) */ - /* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */ - usc_OutReg( info, TCLR, (u16)FrameSize ); - - usc_RTCmd( info, RTCmd_PurgeTxFifo ); - - /* Program the address of the 1st DMA Buffer Entry in linked list */ - phys_addr = info->tx_buffer_list[info->start_tx_dma_buffer].phys_entry; - usc_OutDmaReg( info, NTARL, (u16)phys_addr ); - usc_OutDmaReg( info, NTARU, (u16)(phys_addr >> 16) ); - - usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); - usc_EnableInterrupts( info, TRANSMIT_STATUS ); - - if ( info->params.mode == MGSL_MODE_RAW && - info->num_tx_dma_buffers > 1 ) { - /* When running external sync mode, attempt to 'stream' transmit */ - /* by filling tx dma buffers as they become available. To do this */ - /* we need to enable Tx DMA EOB Status interrupts : */ - /* */ - /* 1. Arm End of Buffer (EOB) Transmit DMA Interrupt (BIT2 of TDIAR) */ - /* 2. Enable Transmit DMA Interrupts (BIT0 of DICR) */ - - usc_OutDmaReg( info, TDIAR, BIT2|BIT3 ); - usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT0) ); - } - - /* Initialize Transmit DMA Channel */ - usc_DmaCmd( info, DmaCmd_InitTxChannel ); - - usc_TCmd( info, TCmd_SendFrame ); - - mod_timer(&info->tx_timer, jiffies + - msecs_to_jiffies(5000)); - } - info->tx_active = true; - } - - if ( !info->tx_enabled ) { - info->tx_enabled = true; - if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) - usc_EnableTransmitter(info,ENABLE_AUTO_CTS); - else - usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL); - } - -} /* end of usc_start_transmitter() */ - -/* usc_stop_transmitter() - * - * Stops the transmitter and DMA - * - * Arguments: info pointer to device isntance data - * Return Value: None - */ -static void usc_stop_transmitter( struct mgsl_struct *info ) -{ - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):usc_stop_transmitter(%s)\n", - __FILE__,__LINE__, info->device_name ); - - del_timer(&info->tx_timer); - - usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA ); - usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA ); - - usc_EnableTransmitter(info,DISABLE_UNCONDITIONAL); - usc_DmaCmd( info, DmaCmd_ResetTxChannel ); - usc_RTCmd( info, RTCmd_PurgeTxFifo ); - - info->tx_enabled = false; - info->tx_active = false; - -} /* end of usc_stop_transmitter() */ - -/* usc_load_txfifo() - * - * Fill the transmit FIFO until the FIFO is full or - * there is no more data to load. - * - * Arguments: info pointer to device extension (instance data) - * Return Value: None - */ -static void usc_load_txfifo( struct mgsl_struct *info ) -{ - int Fifocount; - u8 TwoBytes[2]; - - if ( !info->xmit_cnt && !info->x_char ) - return; - - /* Select transmit FIFO status readback in TICR */ - usc_TCmd( info, TCmd_SelectTicrTxFifostatus ); - - /* load the Transmit FIFO until FIFOs full or all data sent */ - - while( (Fifocount = usc_InReg(info, TICR) >> 8) && info->xmit_cnt ) { - /* there is more space in the transmit FIFO and */ - /* there is more data in transmit buffer */ - - if ( (info->xmit_cnt > 1) && (Fifocount > 1) && !info->x_char ) { - /* write a 16-bit word from transmit buffer to 16C32 */ - - TwoBytes[0] = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - TwoBytes[1] = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - - outw( *((u16 *)TwoBytes), info->io_base + DATAREG); - - info->xmit_cnt -= 2; - info->icount.tx += 2; - } else { - /* only 1 byte left to transmit or 1 FIFO slot left */ - - outw( (inw( info->io_base + CCAR) & 0x0780) | (TDR+LSBONLY), - info->io_base + CCAR ); - - if (info->x_char) { - /* transmit pending high priority char */ - outw( info->x_char,info->io_base + CCAR ); - info->x_char = 0; - } else { - outw( info->xmit_buf[info->xmit_tail++],info->io_base + CCAR ); - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - info->icount.tx++; - } - } - -} /* end of usc_load_txfifo() */ - -/* usc_reset() - * - * Reset the adapter to a known state and prepare it for further use. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_reset( struct mgsl_struct *info ) -{ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - int i; - u32 readval; - - /* Set BIT30 of Misc Control Register */ - /* (Local Control Register 0x50) to force reset of USC. */ - - volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); - u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28); - - info->misc_ctrl_value |= BIT30; - *MiscCtrl = info->misc_ctrl_value; - - /* - * Force at least 170ns delay before clearing - * reset bit. Each read from LCR takes at least - * 30ns so 10 times for 300ns to be safe. - */ - for(i=0;i<10;i++) - readval = *MiscCtrl; - - info->misc_ctrl_value &= ~BIT30; - *MiscCtrl = info->misc_ctrl_value; - - *LCR0BRDR = BUS_DESCRIPTOR( - 1, // Write Strobe Hold (0-3) - 2, // Write Strobe Delay (0-3) - 2, // Read Strobe Delay (0-3) - 0, // NWDD (Write data-data) (0-3) - 4, // NWAD (Write Addr-data) (0-31) - 0, // NXDA (Read/Write Data-Addr) (0-3) - 0, // NRDD (Read Data-Data) (0-3) - 5 // NRAD (Read Addr-Data) (0-31) - ); - } else { - /* do HW reset */ - outb( 0,info->io_base + 8 ); - } - - info->mbre_bit = 0; - info->loopback_bits = 0; - info->usc_idle_mode = 0; - - /* - * Program the Bus Configuration Register (BCR) - * - * <15> 0 Don't use separate address - * <14..6> 0 reserved - * <5..4> 00 IAckmode = Default, don't care - * <3> 1 Bus Request Totem Pole output - * <2> 1 Use 16 Bit data bus - * <1> 0 IRQ Totem Pole output - * <0> 0 Don't Shift Right Addr - * - * 0000 0000 0000 1100 = 0x000c - * - * By writing to io_base + SDPIN the Wait/Ack pin is - * programmed to work as a Wait pin. - */ - - outw( 0x000c,info->io_base + SDPIN ); - - - outw( 0,info->io_base ); - outw( 0,info->io_base + CCAR ); - - /* select little endian byte ordering */ - usc_RTCmd( info, RTCmd_SelectLittleEndian ); - - - /* Port Control Register (PCR) - * - * <15..14> 11 Port 7 is Output (~DMAEN, Bit 14 : 0 = Enabled) - * <13..12> 11 Port 6 is Output (~INTEN, Bit 12 : 0 = Enabled) - * <11..10> 00 Port 5 is Input (No Connect, Don't Care) - * <9..8> 00 Port 4 is Input (No Connect, Don't Care) - * <7..6> 11 Port 3 is Output (~RTS, Bit 6 : 0 = Enabled ) - * <5..4> 11 Port 2 is Output (~DTR, Bit 4 : 0 = Enabled ) - * <3..2> 01 Port 1 is Input (Dedicated RxC) - * <1..0> 01 Port 0 is Input (Dedicated TxC) - * - * 1111 0000 1111 0101 = 0xf0f5 - */ - - usc_OutReg( info, PCR, 0xf0f5 ); - - - /* - * Input/Output Control Register - * - * <15..14> 00 CTS is active low input - * <13..12> 00 DCD is active low input - * <11..10> 00 TxREQ pin is input (DSR) - * <9..8> 00 RxREQ pin is input (RI) - * <7..6> 00 TxD is output (Transmit Data) - * <5..3> 000 TxC Pin in Input (14.7456MHz Clock) - * <2..0> 100 RxC is Output (drive with BRG0) - * - * 0000 0000 0000 0100 = 0x0004 - */ - - usc_OutReg( info, IOCR, 0x0004 ); - -} /* end of usc_reset() */ - -/* usc_set_async_mode() - * - * Program adapter for asynchronous communications. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_set_async_mode( struct mgsl_struct *info ) -{ - u16 RegValue; - - /* disable interrupts while programming USC */ - usc_DisableMasterIrqBit( info ); - - outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ - usc_DmaCmd( info, DmaCmd_ResetAllChannels ); /* disable both DMA channels */ - - usc_loopback_frame( info ); - - /* Channel mode Register (CMR) - * - * <15..14> 00 Tx Sub modes, 00 = 1 Stop Bit - * <13..12> 00 00 = 16X Clock - * <11..8> 0000 Transmitter mode = Asynchronous - * <7..6> 00 reserved? - * <5..4> 00 Rx Sub modes, 00 = 16X Clock - * <3..0> 0000 Receiver mode = Asynchronous - * - * 0000 0000 0000 0000 = 0x0 - */ - - RegValue = 0; - if ( info->params.stop_bits != 1 ) - RegValue |= BIT14; - usc_OutReg( info, CMR, RegValue ); - - - /* Receiver mode Register (RMR) - * - * <15..13> 000 encoding = None - * <12..08> 00000 reserved (Sync Only) - * <7..6> 00 Even parity - * <5> 0 parity disabled - * <4..2> 000 Receive Char Length = 8 bits - * <1..0> 00 Disable Receiver - * - * 0000 0000 0000 0000 = 0x0 - */ - - RegValue = 0; - - if ( info->params.data_bits != 8 ) - RegValue |= BIT4+BIT3+BIT2; - - if ( info->params.parity != ASYNC_PARITY_NONE ) { - RegValue |= BIT5; - if ( info->params.parity != ASYNC_PARITY_ODD ) - RegValue |= BIT6; - } - - usc_OutReg( info, RMR, RegValue ); - - - /* Set IRQ trigger level */ - - usc_RCmd( info, RCmd_SelectRicrIntLevel ); - - - /* Receive Interrupt Control Register (RICR) - * - * <15..8> ? RxFIFO IRQ Request Level - * - * Note: For async mode the receive FIFO level must be set - * to 0 to avoid the situation where the FIFO contains fewer bytes - * than the trigger level and no more data is expected. - * - * <7> 0 Exited Hunt IA (Interrupt Arm) - * <6> 0 Idle Received IA - * <5> 0 Break/Abort IA - * <4> 0 Rx Bound IA - * <3> 0 Queued status reflects oldest byte in FIFO - * <2> 0 Abort/PE IA - * <1> 0 Rx Overrun IA - * <0> 0 Select TC0 value for readback - * - * 0000 0000 0100 0000 = 0x0000 + (FIFOLEVEL in MSB) - */ - - usc_OutReg( info, RICR, 0x0000 ); - - usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_STATUS ); - - - /* Transmit mode Register (TMR) - * - * <15..13> 000 encoding = None - * <12..08> 00000 reserved (Sync Only) - * <7..6> 00 Transmit parity Even - * <5> 0 Transmit parity Disabled - * <4..2> 000 Tx Char Length = 8 bits - * <1..0> 00 Disable Transmitter - * - * 0000 0000 0000 0000 = 0x0 - */ - - RegValue = 0; - - if ( info->params.data_bits != 8 ) - RegValue |= BIT4+BIT3+BIT2; - - if ( info->params.parity != ASYNC_PARITY_NONE ) { - RegValue |= BIT5; - if ( info->params.parity != ASYNC_PARITY_ODD ) - RegValue |= BIT6; - } - - usc_OutReg( info, TMR, RegValue ); - - usc_set_txidle( info ); - - - /* Set IRQ trigger level */ - - usc_TCmd( info, TCmd_SelectTicrIntLevel ); - - - /* Transmit Interrupt Control Register (TICR) - * - * <15..8> ? Transmit FIFO IRQ Level - * <7> 0 Present IA (Interrupt Arm) - * <6> 1 Idle Sent IA - * <5> 0 Abort Sent IA - * <4> 0 EOF/EOM Sent IA - * <3> 0 CRC Sent IA - * <2> 0 1 = Wait for SW Trigger to Start Frame - * <1> 0 Tx Underrun IA - * <0> 0 TC0 constant on read back - * - * 0000 0000 0100 0000 = 0x0040 - */ - - usc_OutReg( info, TICR, 0x1f40 ); - - usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); - - usc_enable_async_clock( info, info->params.data_rate ); - - - /* Channel Control/status Register (CCSR) - * - * <15> X RCC FIFO Overflow status (RO) - * <14> X RCC FIFO Not Empty status (RO) - * <13> 0 1 = Clear RCC FIFO (WO) - * <12> X DPLL in Sync status (RO) - * <11> X DPLL 2 Missed Clocks status (RO) - * <10> X DPLL 1 Missed Clock status (RO) - * <9..8> 00 DPLL Resync on rising and falling edges (RW) - * <7> X SDLC Loop On status (RO) - * <6> X SDLC Loop Send status (RO) - * <5> 1 Bypass counters for TxClk and RxClk (RW) - * <4..2> 000 Last Char of SDLC frame has 8 bits (RW) - * <1..0> 00 reserved - * - * 0000 0000 0010 0000 = 0x0020 - */ - - usc_OutReg( info, CCSR, 0x0020 ); - - usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA + - RECEIVE_DATA + RECEIVE_STATUS ); - - usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA + - RECEIVE_DATA + RECEIVE_STATUS ); - - usc_EnableMasterIrqBit( info ); - - if (info->bus_type == MGSL_BUS_TYPE_ISA) { - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); - } - - if (info->params.loopback) { - info->loopback_bits = 0x300; - outw(0x0300, info->io_base + CCAR); - } - -} /* end of usc_set_async_mode() */ - -/* usc_loopback_frame() - * - * Loop back a small (2 byte) dummy SDLC frame. - * Interrupts and DMA are NOT used. The purpose of this is to - * clear any 'stale' status info left over from running in async mode. - * - * The 16C32 shows the strange behaviour of marking the 1st - * received SDLC frame with a CRC error even when there is no - * CRC error. To get around this a small dummy from of 2 bytes - * is looped back when switching from async to sync mode. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_loopback_frame( struct mgsl_struct *info ) -{ - int i; - unsigned long oldmode = info->params.mode; - - info->params.mode = MGSL_MODE_HDLC; - - usc_DisableMasterIrqBit( info ); - - usc_set_sdlc_mode( info ); - usc_enable_loopback( info, 1 ); - - /* Write 16-bit Time Constant for BRG0 */ - usc_OutReg( info, TC0R, 0 ); - - /* Channel Control Register (CCR) - * - * <15..14> 00 Don't use 32-bit Tx Control Blocks (TCBs) - * <13> 0 Trigger Tx on SW Command Disabled - * <12> 0 Flag Preamble Disabled - * <11..10> 00 Preamble Length = 8-Bits - * <9..8> 01 Preamble Pattern = flags - * <7..6> 10 Don't use 32-bit Rx status Blocks (RSBs) - * <5> 0 Trigger Rx on SW Command Disabled - * <4..0> 0 reserved - * - * 0000 0001 0000 0000 = 0x0100 - */ - - usc_OutReg( info, CCR, 0x0100 ); - - /* SETUP RECEIVER */ - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); - - /* SETUP TRANSMITTER */ - /* Program the Transmit Character Length Register (TCLR) */ - /* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */ - usc_OutReg( info, TCLR, 2 ); - usc_RTCmd( info, RTCmd_PurgeTxFifo ); - - /* unlatch Tx status bits, and start transmit channel. */ - usc_UnlatchTxstatusBits(info,TXSTATUS_ALL); - outw(0,info->io_base + DATAREG); - - /* ENABLE TRANSMITTER */ - usc_TCmd( info, TCmd_SendFrame ); - usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL); - - /* WAIT FOR RECEIVE COMPLETE */ - for (i=0 ; i<1000 ; i++) - if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1)) - break; - - /* clear Internal Data loopback mode */ - usc_enable_loopback(info, 0); - - usc_EnableMasterIrqBit(info); - - info->params.mode = oldmode; - -} /* end of usc_loopback_frame() */ - -/* usc_set_sync_mode() Programs the USC for SDLC communications. - * - * Arguments: info pointer to adapter info structure - * Return Value: None - */ -static void usc_set_sync_mode( struct mgsl_struct *info ) -{ - usc_loopback_frame( info ); - usc_set_sdlc_mode( info ); - - if (info->bus_type == MGSL_BUS_TYPE_ISA) { - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); - } - - usc_enable_aux_clock(info, info->params.clock_speed); - - if (info->params.loopback) - usc_enable_loopback(info,1); - -} /* end of mgsl_set_sync_mode() */ - -/* usc_set_txidle() Set the HDLC idle mode for the transmitter. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_set_txidle( struct mgsl_struct *info ) -{ - u16 usc_idle_mode = IDLEMODE_FLAGS; - - /* Map API idle mode to USC register bits */ - - switch( info->idle_mode ){ - case HDLC_TXIDLE_FLAGS: usc_idle_mode = IDLEMODE_FLAGS; break; - case HDLC_TXIDLE_ALT_ZEROS_ONES: usc_idle_mode = IDLEMODE_ALT_ONE_ZERO; break; - case HDLC_TXIDLE_ZEROS: usc_idle_mode = IDLEMODE_ZERO; break; - case HDLC_TXIDLE_ONES: usc_idle_mode = IDLEMODE_ONE; break; - case HDLC_TXIDLE_ALT_MARK_SPACE: usc_idle_mode = IDLEMODE_ALT_MARK_SPACE; break; - case HDLC_TXIDLE_SPACE: usc_idle_mode = IDLEMODE_SPACE; break; - case HDLC_TXIDLE_MARK: usc_idle_mode = IDLEMODE_MARK; break; - } - - info->usc_idle_mode = usc_idle_mode; - //usc_OutReg(info, TCSR, usc_idle_mode); - info->tcsr_value &= ~IDLEMODE_MASK; /* clear idle mode bits */ - info->tcsr_value += usc_idle_mode; - usc_OutReg(info, TCSR, info->tcsr_value); - - /* - * if SyncLink WAN adapter is running in external sync mode, the - * transmitter has been set to Monosync in order to try to mimic - * a true raw outbound bit stream. Monosync still sends an open/close - * sync char at the start/end of a frame. Try to match those sync - * patterns to the idle mode set here - */ - if ( info->params.mode == MGSL_MODE_RAW ) { - unsigned char syncpat = 0; - switch( info->idle_mode ) { - case HDLC_TXIDLE_FLAGS: - syncpat = 0x7e; - break; - case HDLC_TXIDLE_ALT_ZEROS_ONES: - syncpat = 0x55; - break; - case HDLC_TXIDLE_ZEROS: - case HDLC_TXIDLE_SPACE: - syncpat = 0x00; - break; - case HDLC_TXIDLE_ONES: - case HDLC_TXIDLE_MARK: - syncpat = 0xff; - break; - case HDLC_TXIDLE_ALT_MARK_SPACE: - syncpat = 0xaa; - break; - } - - usc_SetTransmitSyncChars(info,syncpat,syncpat); - } - -} /* end of usc_set_txidle() */ - -/* usc_get_serial_signals() - * - * Query the adapter for the state of the V24 status (input) signals. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_get_serial_signals( struct mgsl_struct *info ) -{ - u16 status; - - /* clear all serial signals except DTR and RTS */ - info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS; - - /* Read the Misc Interrupt status Register (MISR) to get */ - /* the V24 status signals. */ - - status = usc_InReg( info, MISR ); - - /* set serial signal bits to reflect MISR */ - - if ( status & MISCSTATUS_CTS ) - info->serial_signals |= SerialSignal_CTS; - - if ( status & MISCSTATUS_DCD ) - info->serial_signals |= SerialSignal_DCD; - - if ( status & MISCSTATUS_RI ) - info->serial_signals |= SerialSignal_RI; - - if ( status & MISCSTATUS_DSR ) - info->serial_signals |= SerialSignal_DSR; - -} /* end of usc_get_serial_signals() */ - -/* usc_set_serial_signals() - * - * Set the state of DTR and RTS based on contents of - * serial_signals member of device extension. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void usc_set_serial_signals( struct mgsl_struct *info ) -{ - u16 Control; - unsigned char V24Out = info->serial_signals; - - /* get the current value of the Port Control Register (PCR) */ - - Control = usc_InReg( info, PCR ); - - if ( V24Out & SerialSignal_RTS ) - Control &= ~(BIT6); - else - Control |= BIT6; - - if ( V24Out & SerialSignal_DTR ) - Control &= ~(BIT4); - else - Control |= BIT4; - - usc_OutReg( info, PCR, Control ); - -} /* end of usc_set_serial_signals() */ - -/* usc_enable_async_clock() - * - * Enable the async clock at the specified frequency. - * - * Arguments: info pointer to device instance data - * data_rate data rate of clock in bps - * 0 disables the AUX clock. - * Return Value: None - */ -static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) -{ - if ( data_rate ) { - /* - * Clock mode Control Register (CMCR) - * - * <15..14> 00 counter 1 Disabled - * <13..12> 00 counter 0 Disabled - * <11..10> 11 BRG1 Input is TxC Pin - * <9..8> 11 BRG0 Input is TxC Pin - * <7..6> 01 DPLL Input is BRG1 Output - * <5..3> 100 TxCLK comes from BRG0 - * <2..0> 100 RxCLK comes from BRG0 - * - * 0000 1111 0110 0100 = 0x0f64 - */ - - usc_OutReg( info, CMCR, 0x0f64 ); - - - /* - * Write 16-bit Time Constant for BRG0 - * Time Constant = (ClkSpeed / data_rate) - 1 - * ClkSpeed = 921600 (ISA), 691200 (PCI) - */ - - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); - else - usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) ); - - - /* - * Hardware Configuration Register (HCR) - * Clear Bit 1, BRG0 mode = Continuous - * Set Bit 0 to enable BRG0. - */ - - usc_OutReg( info, HCR, - (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) ); - - - /* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */ - - usc_OutReg( info, IOCR, - (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) ); - } else { - /* data rate == 0 so turn off BRG0 */ - usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) ); - } - -} /* end of usc_enable_async_clock() */ - -/* - * Buffer Structures: - * - * Normal memory access uses virtual addresses that can make discontiguous - * physical memory pages appear to be contiguous in the virtual address - * space (the processors memory mapping handles the conversions). - * - * DMA transfers require physically contiguous memory. This is because - * the DMA system controller and DMA bus masters deal with memory using - * only physical addresses. - * - * This causes a problem under Windows NT when large DMA buffers are - * needed. Fragmentation of the nonpaged pool prevents allocations of - * physically contiguous buffers larger than the PAGE_SIZE. - * - * However the 16C32 supports Bus Master Scatter/Gather DMA which - * allows DMA transfers to physically discontiguous buffers. Information - * about each data transfer buffer is contained in a memory structure - * called a 'buffer entry'. A list of buffer entries is maintained - * to track and control the use of the data transfer buffers. - * - * To support this strategy we will allocate sufficient PAGE_SIZE - * contiguous memory buffers to allow for the total required buffer - * space. - * - * The 16C32 accesses the list of buffer entries using Bus Master - * DMA. Control information is read from the buffer entries by the - * 16C32 to control data transfers. status information is written to - * the buffer entries by the 16C32 to indicate the status of completed - * transfers. - * - * The CPU writes control information to the buffer entries to control - * the 16C32 and reads status information from the buffer entries to - * determine information about received and transmitted frames. - * - * Because the CPU and 16C32 (adapter) both need simultaneous access - * to the buffer entries, the buffer entry memory is allocated with - * HalAllocateCommonBuffer(). This restricts the size of the buffer - * entry list to PAGE_SIZE. - * - * The actual data buffers on the other hand will only be accessed - * by the CPU or the adapter but not by both simultaneously. This allows - * Scatter/Gather packet based DMA procedures for using physically - * discontiguous pages. - */ - -/* - * mgsl_reset_tx_dma_buffers() - * - * Set the count for all transmit buffers to 0 to indicate the - * buffer is available for use and set the current buffer to the - * first buffer. This effectively makes all buffers free and - * discards any data in buffers. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ) -{ - unsigned int i; - - for ( i = 0; i < info->tx_buffer_count; i++ ) { - *((unsigned long *)&(info->tx_buffer_list[i].count)) = 0; - } - - info->current_tx_buffer = 0; - info->start_tx_dma_buffer = 0; - info->tx_dma_buffers_used = 0; - - info->get_tx_holding_index = 0; - info->put_tx_holding_index = 0; - info->tx_holding_count = 0; - -} /* end of mgsl_reset_tx_dma_buffers() */ - -/* - * num_free_tx_dma_buffers() - * - * returns the number of free tx dma buffers available - * - * Arguments: info pointer to device instance data - * Return Value: number of free tx dma buffers - */ -static int num_free_tx_dma_buffers(struct mgsl_struct *info) -{ - return info->tx_buffer_count - info->tx_dma_buffers_used; -} - -/* - * mgsl_reset_rx_dma_buffers() - * - * Set the count for all receive buffers to DMABUFFERSIZE - * and set the current buffer to the first buffer. This effectively - * makes all buffers free and discards any data in buffers. - * - * Arguments: info pointer to device instance data - * Return Value: None - */ -static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) -{ - unsigned int i; - - for ( i = 0; i < info->rx_buffer_count; i++ ) { - *((unsigned long *)&(info->rx_buffer_list[i].count)) = DMABUFFERSIZE; -// info->rx_buffer_list[i].count = DMABUFFERSIZE; -// info->rx_buffer_list[i].status = 0; - } - - info->current_rx_buffer = 0; - -} /* end of mgsl_reset_rx_dma_buffers() */ - -/* - * mgsl_free_rx_frame_buffers() - * - * Free the receive buffers used by a received SDLC - * frame such that the buffers can be reused. - * - * Arguments: - * - * info pointer to device instance data - * StartIndex index of 1st receive buffer of frame - * EndIndex index of last receive buffer of frame - * - * Return Value: None - */ -static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ) -{ - bool Done = false; - DMABUFFERENTRY *pBufEntry; - unsigned int Index; - - /* Starting with 1st buffer entry of the frame clear the status */ - /* field and set the count field to DMA Buffer Size. */ - - Index = StartIndex; - - while( !Done ) { - pBufEntry = &(info->rx_buffer_list[Index]); - - if ( Index == EndIndex ) { - /* This is the last buffer of the frame! */ - Done = true; - } - - /* reset current buffer for reuse */ -// pBufEntry->status = 0; -// pBufEntry->count = DMABUFFERSIZE; - *((unsigned long *)&(pBufEntry->count)) = DMABUFFERSIZE; - - /* advance to next buffer entry in linked list */ - Index++; - if ( Index == info->rx_buffer_count ) - Index = 0; - } - - /* set current buffer to next buffer after last buffer of frame */ - info->current_rx_buffer = Index; - -} /* end of free_rx_frame_buffers() */ - -/* mgsl_get_rx_frame() - * - * This function attempts to return a received SDLC frame from the - * receive DMA buffers. Only frames received without errors are returned. - * - * Arguments: info pointer to device extension - * Return Value: true if frame returned, otherwise false - */ -static bool mgsl_get_rx_frame(struct mgsl_struct *info) -{ - unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ - unsigned short status; - DMABUFFERENTRY *pBufEntry; - unsigned int framesize = 0; - bool ReturnCode = false; - unsigned long flags; - struct tty_struct *tty = info->port.tty; - bool return_frame = false; - - /* - * current_rx_buffer points to the 1st buffer of the next available - * receive frame. To find the last buffer of the frame look for - * a non-zero status field in the buffer entries. (The status - * field is set by the 16C32 after completing a receive frame. - */ - - StartIndex = EndIndex = info->current_rx_buffer; - - while( !info->rx_buffer_list[EndIndex].status ) { - /* - * If the count field of the buffer entry is non-zero then - * this buffer has not been used. (The 16C32 clears the count - * field when it starts using the buffer.) If an unused buffer - * is encountered then there are no frames available. - */ - - if ( info->rx_buffer_list[EndIndex].count ) - goto Cleanup; - - /* advance to next buffer entry in linked list */ - EndIndex++; - if ( EndIndex == info->rx_buffer_count ) - EndIndex = 0; - - /* if entire list searched then no frame available */ - if ( EndIndex == StartIndex ) { - /* If this occurs then something bad happened, - * all buffers have been 'used' but none mark - * the end of a frame. Reset buffers and receiver. - */ - - if ( info->rx_enabled ){ - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_start_receiver(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - goto Cleanup; - } - } - - - /* check status of receive frame */ - - status = info->rx_buffer_list[EndIndex].status; - - if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN + - RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) { - if ( status & RXSTATUS_SHORT_FRAME ) - info->icount.rxshort++; - else if ( status & RXSTATUS_ABORT ) - info->icount.rxabort++; - else if ( status & RXSTATUS_OVERRUN ) - info->icount.rxover++; - else { - info->icount.rxcrc++; - if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) - return_frame = true; - } - framesize = 0; -#if SYNCLINK_GENERIC_HDLC - { - info->netdev->stats.rx_errors++; - info->netdev->stats.rx_frame_errors++; - } -#endif - } else - return_frame = true; - - if ( return_frame ) { - /* receive frame has no errors, get frame size. - * The frame size is the starting value of the RCC (which was - * set to 0xffff) minus the ending value of the RCC (decremented - * once for each receive character) minus 2 for the 16-bit CRC. - */ - - framesize = RCLRVALUE - info->rx_buffer_list[EndIndex].rcc; - - /* adjust frame size for CRC if any */ - if ( info->params.crc_type == HDLC_CRC_16_CCITT ) - framesize -= 2; - else if ( info->params.crc_type == HDLC_CRC_32_CCITT ) - framesize -= 4; - } - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk("%s(%d):mgsl_get_rx_frame(%s) status=%04X size=%d\n", - __FILE__,__LINE__,info->device_name,status,framesize); - - if ( debug_level >= DEBUG_LEVEL_DATA ) - mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr, - min_t(int, framesize, DMABUFFERSIZE),0); - - if (framesize) { - if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) && - ((framesize+1) > info->max_frame_size) ) || - (framesize > info->max_frame_size) ) - info->icount.rxlong++; - else { - /* copy dma buffer(s) to contiguous intermediate buffer */ - int copy_count = framesize; - int index = StartIndex; - unsigned char *ptmp = info->intermediate_rxbuffer; - - if ( !(status & RXSTATUS_CRC_ERROR)) - info->icount.rxok++; - - while(copy_count) { - int partial_count; - if ( copy_count > DMABUFFERSIZE ) - partial_count = DMABUFFERSIZE; - else - partial_count = copy_count; - - pBufEntry = &(info->rx_buffer_list[index]); - memcpy( ptmp, pBufEntry->virt_addr, partial_count ); - ptmp += partial_count; - copy_count -= partial_count; - - if ( ++index == info->rx_buffer_count ) - index = 0; - } - - if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) { - ++framesize; - *ptmp = (status & RXSTATUS_CRC_ERROR ? - RX_CRC_ERROR : - RX_OK); - - if ( debug_level >= DEBUG_LEVEL_DATA ) - printk("%s(%d):mgsl_get_rx_frame(%s) rx frame status=%d\n", - __FILE__,__LINE__,info->device_name, - *ptmp); - } - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_rx(info,info->intermediate_rxbuffer,framesize); - else -#endif - ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); - } - } - /* Free the buffers used by this frame. */ - mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex ); - - ReturnCode = true; - -Cleanup: - - if ( info->rx_enabled && info->rx_overflow ) { - /* The receiver needs to restarted because of - * a receive overflow (buffer or FIFO). If the - * receive buffers are now empty, then restart receiver. - */ - - if ( !info->rx_buffer_list[EndIndex].status && - info->rx_buffer_list[EndIndex].count ) { - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_start_receiver(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - } - - return ReturnCode; - -} /* end of mgsl_get_rx_frame() */ - -/* mgsl_get_raw_rx_frame() - * - * This function attempts to return a received frame from the - * receive DMA buffers when running in external loop mode. In this mode, - * we will return at most one DMABUFFERSIZE frame to the application. - * The USC receiver is triggering off of DCD going active to start a new - * frame, and DCD going inactive to terminate the frame (similar to - * processing a closing flag character). - * - * In this routine, we will return DMABUFFERSIZE "chunks" at a time. - * If DCD goes inactive, the last Rx DMA Buffer will have a non-zero - * status field and the RCC field will indicate the length of the - * entire received frame. We take this RCC field and get the modulus - * of RCC and DMABUFFERSIZE to determine if number of bytes in the - * last Rx DMA buffer and return that last portion of the frame. - * - * Arguments: info pointer to device extension - * Return Value: true if frame returned, otherwise false - */ -static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info) -{ - unsigned int CurrentIndex, NextIndex; - unsigned short status; - DMABUFFERENTRY *pBufEntry; - unsigned int framesize = 0; - bool ReturnCode = false; - unsigned long flags; - struct tty_struct *tty = info->port.tty; - - /* - * current_rx_buffer points to the 1st buffer of the next available - * receive frame. The status field is set by the 16C32 after - * completing a receive frame. If the status field of this buffer - * is zero, either the USC is still filling this buffer or this - * is one of a series of buffers making up a received frame. - * - * If the count field of this buffer is zero, the USC is either - * using this buffer or has used this buffer. Look at the count - * field of the next buffer. If that next buffer's count is - * non-zero, the USC is still actively using the current buffer. - * Otherwise, if the next buffer's count field is zero, the - * current buffer is complete and the USC is using the next - * buffer. - */ - CurrentIndex = NextIndex = info->current_rx_buffer; - ++NextIndex; - if ( NextIndex == info->rx_buffer_count ) - NextIndex = 0; - - if ( info->rx_buffer_list[CurrentIndex].status != 0 || - (info->rx_buffer_list[CurrentIndex].count == 0 && - info->rx_buffer_list[NextIndex].count == 0)) { - /* - * Either the status field of this dma buffer is non-zero - * (indicating the last buffer of a receive frame) or the next - * buffer is marked as in use -- implying this buffer is complete - * and an intermediate buffer for this received frame. - */ - - status = info->rx_buffer_list[CurrentIndex].status; - - if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN + - RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) { - if ( status & RXSTATUS_SHORT_FRAME ) - info->icount.rxshort++; - else if ( status & RXSTATUS_ABORT ) - info->icount.rxabort++; - else if ( status & RXSTATUS_OVERRUN ) - info->icount.rxover++; - else - info->icount.rxcrc++; - framesize = 0; - } else { - /* - * A receive frame is available, get frame size and status. - * - * The frame size is the starting value of the RCC (which was - * set to 0xffff) minus the ending value of the RCC (decremented - * once for each receive character) minus 2 or 4 for the 16-bit - * or 32-bit CRC. - * - * If the status field is zero, this is an intermediate buffer. - * It's size is 4K. - * - * If the DMA Buffer Entry's Status field is non-zero, the - * receive operation completed normally (ie: DCD dropped). The - * RCC field is valid and holds the received frame size. - * It is possible that the RCC field will be zero on a DMA buffer - * entry with a non-zero status. This can occur if the total - * frame size (number of bytes between the time DCD goes active - * to the time DCD goes inactive) exceeds 65535 bytes. In this - * case the 16C32 has underrun on the RCC count and appears to - * stop updating this counter to let us know the actual received - * frame size. If this happens (non-zero status and zero RCC), - * simply return the entire RxDMA Buffer - */ - if ( status ) { - /* - * In the event that the final RxDMA Buffer is - * terminated with a non-zero status and the RCC - * field is zero, we interpret this as the RCC - * having underflowed (received frame > 65535 bytes). - * - * Signal the event to the user by passing back - * a status of RxStatus_CrcError returning the full - * buffer and let the app figure out what data is - * actually valid - */ - if ( info->rx_buffer_list[CurrentIndex].rcc ) - framesize = RCLRVALUE - info->rx_buffer_list[CurrentIndex].rcc; - else - framesize = DMABUFFERSIZE; - } - else - framesize = DMABUFFERSIZE; - } - - if ( framesize > DMABUFFERSIZE ) { - /* - * if running in raw sync mode, ISR handler for - * End Of Buffer events terminates all buffers at 4K. - * If this frame size is said to be >4K, get the - * actual number of bytes of the frame in this buffer. - */ - framesize = framesize % DMABUFFERSIZE; - } - - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk("%s(%d):mgsl_get_raw_rx_frame(%s) status=%04X size=%d\n", - __FILE__,__LINE__,info->device_name,status,framesize); - - if ( debug_level >= DEBUG_LEVEL_DATA ) - mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr, - min_t(int, framesize, DMABUFFERSIZE),0); - - if (framesize) { - /* copy dma buffer(s) to contiguous intermediate buffer */ - /* NOTE: we never copy more than DMABUFFERSIZE bytes */ - - pBufEntry = &(info->rx_buffer_list[CurrentIndex]); - memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize); - info->icount.rxok++; - - ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); - } - - /* Free the buffers used by this frame. */ - mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex ); - - ReturnCode = true; - } - - - if ( info->rx_enabled && info->rx_overflow ) { - /* The receiver needs to restarted because of - * a receive overflow (buffer or FIFO). If the - * receive buffers are now empty, then restart receiver. - */ - - if ( !info->rx_buffer_list[CurrentIndex].status && - info->rx_buffer_list[CurrentIndex].count ) { - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_start_receiver(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - } - - return ReturnCode; - -} /* end of mgsl_get_raw_rx_frame() */ - -/* mgsl_load_tx_dma_buffer() - * - * Load the transmit DMA buffer with the specified data. - * - * Arguments: - * - * info pointer to device extension - * Buffer pointer to buffer containing frame to load - * BufferSize size in bytes of frame in Buffer - * - * Return Value: None - */ -static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, - const char *Buffer, unsigned int BufferSize) -{ - unsigned short Copycount; - unsigned int i = 0; - DMABUFFERENTRY *pBufEntry; - - if ( debug_level >= DEBUG_LEVEL_DATA ) - mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1); - - if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) { - /* set CMR:13 to start transmit when - * next GoAhead (abort) is received - */ - info->cmr_value |= BIT13; - } - - /* begin loading the frame in the next available tx dma - * buffer, remember it's starting location for setting - * up tx dma operation - */ - i = info->current_tx_buffer; - info->start_tx_dma_buffer = i; - - /* Setup the status and RCC (Frame Size) fields of the 1st */ - /* buffer entry in the transmit DMA buffer list. */ - - info->tx_buffer_list[i].status = info->cmr_value & 0xf000; - info->tx_buffer_list[i].rcc = BufferSize; - info->tx_buffer_list[i].count = BufferSize; - - /* Copy frame data from 1st source buffer to the DMA buffers. */ - /* The frame data may span multiple DMA buffers. */ - - while( BufferSize ){ - /* Get a pointer to next DMA buffer entry. */ - pBufEntry = &info->tx_buffer_list[i++]; - - if ( i == info->tx_buffer_count ) - i=0; - - /* Calculate the number of bytes that can be copied from */ - /* the source buffer to this DMA buffer. */ - if ( BufferSize > DMABUFFERSIZE ) - Copycount = DMABUFFERSIZE; - else - Copycount = BufferSize; - - /* Actually copy data from source buffer to DMA buffer. */ - /* Also set the data count for this individual DMA buffer. */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); - else - memcpy(pBufEntry->virt_addr, Buffer, Copycount); - - pBufEntry->count = Copycount; - - /* Advance source pointer and reduce remaining data count. */ - Buffer += Copycount; - BufferSize -= Copycount; - - ++info->tx_dma_buffers_used; - } - - /* remember next available tx dma buffer */ - info->current_tx_buffer = i; - -} /* end of mgsl_load_tx_dma_buffer() */ - -/* - * mgsl_register_test() - * - * Performs a register test of the 16C32. - * - * Arguments: info pointer to device instance data - * Return Value: true if test passed, otherwise false - */ -static bool mgsl_register_test( struct mgsl_struct *info ) -{ - static unsigned short BitPatterns[] = - { 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f }; - static unsigned int Patterncount = ARRAY_SIZE(BitPatterns); - unsigned int i; - bool rc = true; - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_reset(info); - - /* Verify the reset state of some registers. */ - - if ( (usc_InReg( info, SICR ) != 0) || - (usc_InReg( info, IVR ) != 0) || - (usc_InDmaReg( info, DIVR ) != 0) ){ - rc = false; - } - - if ( rc ){ - /* Write bit patterns to various registers but do it out of */ - /* sync, then read back and verify values. */ - - for ( i = 0 ; i < Patterncount ; i++ ) { - usc_OutReg( info, TC0R, BitPatterns[i] ); - usc_OutReg( info, TC1R, BitPatterns[(i+1)%Patterncount] ); - usc_OutReg( info, TCLR, BitPatterns[(i+2)%Patterncount] ); - usc_OutReg( info, RCLR, BitPatterns[(i+3)%Patterncount] ); - usc_OutReg( info, RSR, BitPatterns[(i+4)%Patterncount] ); - usc_OutDmaReg( info, TBCR, BitPatterns[(i+5)%Patterncount] ); - - if ( (usc_InReg( info, TC0R ) != BitPatterns[i]) || - (usc_InReg( info, TC1R ) != BitPatterns[(i+1)%Patterncount]) || - (usc_InReg( info, TCLR ) != BitPatterns[(i+2)%Patterncount]) || - (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) || - (usc_InReg( info, RSR ) != BitPatterns[(i+4)%Patterncount]) || - (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){ - rc = false; - break; - } - } - } - - usc_reset(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - return rc; - -} /* end of mgsl_register_test() */ - -/* mgsl_irq_test() Perform interrupt test of the 16C32. - * - * Arguments: info pointer to device instance data - * Return Value: true if test passed, otherwise false - */ -static bool mgsl_irq_test( struct mgsl_struct *info ) -{ - unsigned long EndTime; - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_reset(info); - - /* - * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition. - * The ISR sets irq_occurred to true. - */ - - info->irq_occurred = false; - - /* Enable INTEN gate for ISA adapter (Port 6, Bit12) */ - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg( info, PCR, (unsigned short)((usc_InReg(info, PCR) | BIT13) & ~BIT12) ); - - usc_EnableMasterIrqBit(info); - usc_EnableInterrupts(info, IO_PIN); - usc_ClearIrqPendingBits(info, IO_PIN); - - usc_UnlatchIostatusBits(info, MISCSTATUS_TXC_LATCHED); - usc_EnableStatusIrqs(info, SICR_TXC_ACTIVE + SICR_TXC_INACTIVE); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - EndTime=100; - while( EndTime-- && !info->irq_occurred ) { - msleep_interruptible(10); - } - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_reset(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - return info->irq_occurred; - -} /* end of mgsl_irq_test() */ - -/* mgsl_dma_test() - * - * Perform a DMA test of the 16C32. A small frame is - * transmitted via DMA from a transmit buffer to a receive buffer - * using single buffer DMA mode. - * - * Arguments: info pointer to device instance data - * Return Value: true if test passed, otherwise false - */ -static bool mgsl_dma_test( struct mgsl_struct *info ) -{ - unsigned short FifoLevel; - unsigned long phys_addr; - unsigned int FrameSize; - unsigned int i; - char *TmpPtr; - bool rc = true; - unsigned short status=0; - unsigned long EndTime; - unsigned long flags; - MGSL_PARAMS tmp_params; - - /* save current port options */ - memcpy(&tmp_params,&info->params,sizeof(MGSL_PARAMS)); - /* load default port options */ - memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - -#define TESTFRAMESIZE 40 - - spin_lock_irqsave(&info->irq_spinlock,flags); - - /* setup 16C32 for SDLC DMA transfer mode */ - - usc_reset(info); - usc_set_sdlc_mode(info); - usc_enable_loopback(info,1); - - /* Reprogram the RDMR so that the 16C32 does NOT clear the count - * field of the buffer entry after fetching buffer address. This - * way we can detect a DMA failure for a DMA read (which should be - * non-destructive to system memory) before we try and write to - * memory (where a failure could corrupt system memory). - */ - - /* Receive DMA mode Register (RDMR) - * - * <15..14> 11 DMA mode = Linked List Buffer mode - * <13> 1 RSBinA/L = store Rx status Block in List entry - * <12> 0 1 = Clear count of List Entry after fetching - * <11..10> 00 Address mode = Increment - * <9> 1 Terminate Buffer on RxBound - * <8> 0 Bus Width = 16bits - * <7..0> ? status Bits (write as 0s) - * - * 1110 0010 0000 0000 = 0xe200 - */ - - usc_OutDmaReg( info, RDMR, 0xe200 ); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - - /* SETUP TRANSMIT AND RECEIVE DMA BUFFERS */ - - FrameSize = TESTFRAMESIZE; - - /* setup 1st transmit buffer entry: */ - /* with frame size and transmit control word */ - - info->tx_buffer_list[0].count = FrameSize; - info->tx_buffer_list[0].rcc = FrameSize; - info->tx_buffer_list[0].status = 0x4000; - - /* build a transmit frame in 1st transmit DMA buffer */ - - TmpPtr = info->tx_buffer_list[0].virt_addr; - for (i = 0; i < FrameSize; i++ ) - *TmpPtr++ = i; - - /* setup 1st receive buffer entry: */ - /* clear status, set max receive buffer size */ - - info->rx_buffer_list[0].status = 0; - info->rx_buffer_list[0].count = FrameSize + 4; - - /* zero out the 1st receive buffer */ - - memset( info->rx_buffer_list[0].virt_addr, 0, FrameSize + 4 ); - - /* Set count field of next buffer entries to prevent */ - /* 16C32 from using buffers after the 1st one. */ - - info->tx_buffer_list[1].count = 0; - info->rx_buffer_list[1].count = 0; - - - /***************************/ - /* Program 16C32 receiver. */ - /***************************/ - - spin_lock_irqsave(&info->irq_spinlock,flags); - - /* setup DMA transfers */ - usc_RTCmd( info, RTCmd_PurgeRxFifo ); - - /* program 16C32 receiver with physical address of 1st DMA buffer entry */ - phys_addr = info->rx_buffer_list[0].phys_entry; - usc_OutDmaReg( info, NRARL, (unsigned short)phys_addr ); - usc_OutDmaReg( info, NRARU, (unsigned short)(phys_addr >> 16) ); - - /* Clear the Rx DMA status bits (read RDMR) and start channel */ - usc_InDmaReg( info, RDMR ); - usc_DmaCmd( info, DmaCmd_InitRxChannel ); - - /* Enable Receiver (RMR <1..0> = 10) */ - usc_OutReg( info, RMR, (unsigned short)((usc_InReg(info, RMR) & 0xfffc) | 0x0002) ); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - - /*************************************************************/ - /* WAIT FOR RECEIVER TO DMA ALL PARAMETERS FROM BUFFER ENTRY */ - /*************************************************************/ - - /* Wait 100ms for interrupt. */ - EndTime = jiffies + msecs_to_jiffies(100); - - for(;;) { - if (time_after(jiffies, EndTime)) { - rc = false; - break; - } - - spin_lock_irqsave(&info->irq_spinlock,flags); - status = usc_InDmaReg( info, RDMR ); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - if ( !(status & BIT4) && (status & BIT5) ) { - /* INITG (BIT 4) is inactive (no entry read in progress) AND */ - /* BUSY (BIT 5) is active (channel still active). */ - /* This means the buffer entry read has completed. */ - break; - } - } - - - /******************************/ - /* Program 16C32 transmitter. */ - /******************************/ - - spin_lock_irqsave(&info->irq_spinlock,flags); - - /* Program the Transmit Character Length Register (TCLR) */ - /* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */ - - usc_OutReg( info, TCLR, (unsigned short)info->tx_buffer_list[0].count ); - usc_RTCmd( info, RTCmd_PurgeTxFifo ); - - /* Program the address of the 1st DMA Buffer Entry in linked list */ - - phys_addr = info->tx_buffer_list[0].phys_entry; - usc_OutDmaReg( info, NTARL, (unsigned short)phys_addr ); - usc_OutDmaReg( info, NTARU, (unsigned short)(phys_addr >> 16) ); - - /* unlatch Tx status bits, and start transmit channel. */ - - usc_OutReg( info, TCSR, (unsigned short)(( usc_InReg(info, TCSR) & 0x0f00) | 0xfa) ); - usc_DmaCmd( info, DmaCmd_InitTxChannel ); - - /* wait for DMA controller to fill transmit FIFO */ - - usc_TCmd( info, TCmd_SelectTicrTxFifostatus ); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - - /**********************************/ - /* WAIT FOR TRANSMIT FIFO TO FILL */ - /**********************************/ - - /* Wait 100ms */ - EndTime = jiffies + msecs_to_jiffies(100); - - for(;;) { - if (time_after(jiffies, EndTime)) { - rc = false; - break; - } - - spin_lock_irqsave(&info->irq_spinlock,flags); - FifoLevel = usc_InReg(info, TICR) >> 8; - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - if ( FifoLevel < 16 ) - break; - else - if ( FrameSize < 32 ) { - /* This frame is smaller than the entire transmit FIFO */ - /* so wait for the entire frame to be loaded. */ - if ( FifoLevel <= (32 - FrameSize) ) - break; - } - } - - - if ( rc ) - { - /* Enable 16C32 transmitter. */ - - spin_lock_irqsave(&info->irq_spinlock,flags); - - /* Transmit mode Register (TMR), <1..0> = 10, Enable Transmitter */ - usc_TCmd( info, TCmd_SendFrame ); - usc_OutReg( info, TMR, (unsigned short)((usc_InReg(info, TMR) & 0xfffc) | 0x0002) ); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - - /******************************/ - /* WAIT FOR TRANSMIT COMPLETE */ - /******************************/ - - /* Wait 100ms */ - EndTime = jiffies + msecs_to_jiffies(100); - - /* While timer not expired wait for transmit complete */ - - spin_lock_irqsave(&info->irq_spinlock,flags); - status = usc_InReg( info, TCSR ); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) { - if (time_after(jiffies, EndTime)) { - rc = false; - break; - } - - spin_lock_irqsave(&info->irq_spinlock,flags); - status = usc_InReg( info, TCSR ); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - } - } - - - if ( rc ){ - /* CHECK FOR TRANSMIT ERRORS */ - if ( status & (BIT5 + BIT1) ) - rc = false; - } - - if ( rc ) { - /* WAIT FOR RECEIVE COMPLETE */ - - /* Wait 100ms */ - EndTime = jiffies + msecs_to_jiffies(100); - - /* Wait for 16C32 to write receive status to buffer entry. */ - status=info->rx_buffer_list[0].status; - while ( status == 0 ) { - if (time_after(jiffies, EndTime)) { - rc = false; - break; - } - status=info->rx_buffer_list[0].status; - } - } - - - if ( rc ) { - /* CHECK FOR RECEIVE ERRORS */ - status = info->rx_buffer_list[0].status; - - if ( status & (BIT8 + BIT3 + BIT1) ) { - /* receive error has occurred */ - rc = false; - } else { - if ( memcmp( info->tx_buffer_list[0].virt_addr , - info->rx_buffer_list[0].virt_addr, FrameSize ) ){ - rc = false; - } - } - } - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_reset( info ); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - /* restore current port options */ - memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); - - return rc; - -} /* end of mgsl_dma_test() */ - -/* mgsl_adapter_test() - * - * Perform the register, IRQ, and DMA tests for the 16C32. - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise -ENODEV - */ -static int mgsl_adapter_test( struct mgsl_struct *info ) -{ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):Testing device %s\n", - __FILE__,__LINE__,info->device_name ); - - if ( !mgsl_register_test( info ) ) { - info->init_error = DiagStatus_AddressFailure; - printk( "%s(%d):Register test failure for device %s Addr=%04X\n", - __FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) ); - return -ENODEV; - } - - if ( !mgsl_irq_test( info ) ) { - info->init_error = DiagStatus_IrqFailure; - printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n", - __FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) ); - return -ENODEV; - } - - if ( !mgsl_dma_test( info ) ) { - info->init_error = DiagStatus_DmaFailure; - printk( "%s(%d):DMA test failure for device %s DMA=%d\n", - __FILE__,__LINE__,info->device_name, (unsigned short)(info->dma_level) ); - return -ENODEV; - } - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):device %s passed diagnostics\n", - __FILE__,__LINE__,info->device_name ); - - return 0; - -} /* end of mgsl_adapter_test() */ - -/* mgsl_memory_test() - * - * Test the shared memory on a PCI adapter. - * - * Arguments: info pointer to device instance data - * Return Value: true if test passed, otherwise false - */ -static bool mgsl_memory_test( struct mgsl_struct *info ) -{ - static unsigned long BitPatterns[] = - { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; - unsigned long Patterncount = ARRAY_SIZE(BitPatterns); - unsigned long i; - unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long); - unsigned long * TestAddr; - - if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - return true; - - TestAddr = (unsigned long *)info->memory_base; - - /* Test data lines with test pattern at one location. */ - - for ( i = 0 ; i < Patterncount ; i++ ) { - *TestAddr = BitPatterns[i]; - if ( *TestAddr != BitPatterns[i] ) - return false; - } - - /* Test address lines with incrementing pattern over */ - /* entire address range. */ - - for ( i = 0 ; i < TestLimit ; i++ ) { - *TestAddr = i * 4; - TestAddr++; - } - - TestAddr = (unsigned long *)info->memory_base; - - for ( i = 0 ; i < TestLimit ; i++ ) { - if ( *TestAddr != i * 4 ) - return false; - TestAddr++; - } - - memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE ); - - return true; - -} /* End Of mgsl_memory_test() */ - - -/* mgsl_load_pci_memory() - * - * Load a large block of data into the PCI shared memory. - * Use this instead of memcpy() or memmove() to move data - * into the PCI shared memory. - * - * Notes: - * - * This function prevents the PCI9050 interface chip from hogging - * the adapter local bus, which can starve the 16C32 by preventing - * 16C32 bus master cycles. - * - * The PCI9050 documentation says that the 9050 will always release - * control of the local bus after completing the current read - * or write operation. - * - * It appears that as long as the PCI9050 write FIFO is full, the - * PCI9050 treats all of the writes as a single burst transaction - * and will not release the bus. This causes DMA latency problems - * at high speeds when copying large data blocks to the shared - * memory. - * - * This function in effect, breaks the a large shared memory write - * into multiple transations by interleaving a shared memory read - * which will flush the write FIFO and 'complete' the write - * transation. This allows any pending DMA request to gain control - * of the local bus in a timely fasion. - * - * Arguments: - * - * TargetPtr pointer to target address in PCI shared memory - * SourcePtr pointer to source buffer for data - * count count in bytes of data to copy - * - * Return Value: None - */ -static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr, - unsigned short count ) -{ - /* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */ -#define PCI_LOAD_INTERVAL 64 - - unsigned short Intervalcount = count / PCI_LOAD_INTERVAL; - unsigned short Index; - unsigned long Dummy; - - for ( Index = 0 ; Index < Intervalcount ; Index++ ) - { - memcpy(TargetPtr, SourcePtr, PCI_LOAD_INTERVAL); - Dummy = *((volatile unsigned long *)TargetPtr); - TargetPtr += PCI_LOAD_INTERVAL; - SourcePtr += PCI_LOAD_INTERVAL; - } - - memcpy( TargetPtr, SourcePtr, count % PCI_LOAD_INTERVAL ); - -} /* End Of mgsl_load_pci_memory() */ - -static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit) -{ - int i; - int linecount; - if (xmit) - printk("%s tx data:\n",info->device_name); - else - printk("%s rx data:\n",info->device_name); - - while(count) { - if (count > 16) - linecount = 16; - else - linecount = count; - - for(i=0;i=040 && data[i]<=0176) - printk("%c",data[i]); - else - printk("."); - } - printk("\n"); - - data += linecount; - count -= linecount; - } -} /* end of mgsl_trace_block() */ - -/* mgsl_tx_timeout() - * - * called when HDLC frame times out - * update stats and do tx completion processing - * - * Arguments: context pointer to device instance data - * Return Value: None - */ -static void mgsl_tx_timeout(unsigned long context) -{ - struct mgsl_struct *info = (struct mgsl_struct*)context; - unsigned long flags; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_tx_timeout(%s)\n", - __FILE__,__LINE__,info->device_name); - if(info->tx_active && - (info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW) ) { - info->icount.txtimeout++; - } - spin_lock_irqsave(&info->irq_spinlock,flags); - info->tx_active = false; - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) - usc_loopmode_cancel_transmit( info ); - - spin_unlock_irqrestore(&info->irq_spinlock,flags); - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - mgsl_bh_transmit(info); - -} /* end of mgsl_tx_timeout() */ - -/* signal that there are no more frames to send, so that - * line is 'released' by echoing RxD to TxD when current - * transmission is complete (or immediately if no tx in progress). - */ -static int mgsl_loopmode_send_done( struct mgsl_struct * info ) -{ - unsigned long flags; - - spin_lock_irqsave(&info->irq_spinlock,flags); - if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) { - if (info->tx_active) - info->loopmode_send_done_requested = true; - else - usc_loopmode_send_done(info); - } - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - return 0; -} - -/* release the line by echoing RxD to TxD - * upon completion of a transmit frame - */ -static void usc_loopmode_send_done( struct mgsl_struct * info ) -{ - info->loopmode_send_done_requested = false; - /* clear CMR:13 to 0 to start echoing RxData to TxData */ - info->cmr_value &= ~BIT13; - usc_OutReg(info, CMR, info->cmr_value); -} - -/* abort a transmit in progress while in HDLC LoopMode - */ -static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) -{ - /* reset tx dma channel and purge TxFifo */ - usc_RTCmd( info, RTCmd_PurgeTxFifo ); - usc_DmaCmd( info, DmaCmd_ResetTxChannel ); - usc_loopmode_send_done( info ); -} - -/* for HDLC/SDLC LoopMode, setting CMR:13 after the transmitter is enabled - * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort) - * we must clear CMR:13 to begin repeating TxData to RxData - */ -static void usc_loopmode_insert_request( struct mgsl_struct * info ) -{ - info->loopmode_insert_requested = true; - - /* enable RxAbort irq. On next RxAbort, clear CMR:13 to - * begin repeating TxData on RxData (complete insertion) - */ - usc_OutReg( info, RICR, - (usc_InReg( info, RICR ) | RXSTATUS_ABORT_RECEIVED ) ); - - /* set CMR:13 to insert into loop on next GoAhead (RxAbort) */ - info->cmr_value |= BIT13; - usc_OutReg(info, CMR, info->cmr_value); -} - -/* return 1 if station is inserted into the loop, otherwise 0 - */ -static int usc_loopmode_active( struct mgsl_struct * info) -{ - return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ; -} - -#if SYNCLINK_GENERIC_HDLC - -/** - * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) - * set encoding and frame check sequence (FCS) options - * - * dev pointer to network device structure - * encoding serial encoding setting - * parity FCS setting - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -{ - struct mgsl_struct *info = dev_to_port(dev); - unsigned char new_encoding; - unsigned short new_crctype; - - /* return error if TTY interface open */ - if (info->port.count) - return -EBUSY; - - switch (encoding) - { - case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; - case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; - case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; - case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; - case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; - default: return -EINVAL; - } - - switch (parity) - { - case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; - case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; - case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; - default: return -EINVAL; - } - - info->params.encoding = new_encoding; - info->params.crc_type = new_crctype; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - mgsl_program_hw(info); - - return 0; -} - -/** - * called by generic HDLC layer to send frame - * - * skb socket buffer containing HDLC frame - * dev pointer to network device structure - */ -static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct mgsl_struct *info = dev_to_port(dev); - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); - - /* stop sending until this frame completes */ - netif_stop_queue(dev); - - /* copy data to device buffers */ - info->xmit_cnt = skb->len; - mgsl_load_tx_dma_buffer(info, skb->data, skb->len); - - /* update network statistics */ - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - - /* done with socket buffer, so free it */ - dev_kfree_skb(skb); - - /* save start time for transmit timeout detection */ - dev->trans_start = jiffies; - - /* start hardware transmitter if necessary */ - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!info->tx_active) - usc_start_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - return NETDEV_TX_OK; -} - -/** - * called by network layer when interface enabled - * claim resources and initialize hardware - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_open(struct net_device *dev) -{ - struct mgsl_struct *info = dev_to_port(dev); - int rc; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); - - /* generic HDLC layer open processing */ - if ((rc = hdlc_open(dev))) - return rc; - - /* arbitrate between network and tty opens */ - spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); - spin_unlock_irqrestore(&info->netlock, flags); - return -EBUSY; - } - info->netcount=1; - spin_unlock_irqrestore(&info->netlock, flags); - - /* claim resources and init adapter */ - if ((rc = startup(info)) != 0) { - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return rc; - } - - /* assert DTR and RTS, apply hardware settings */ - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - mgsl_program_hw(info); - - /* enable network layer transmit */ - dev->trans_start = jiffies; - netif_start_queue(dev); - - /* inform generic HDLC layer of current DCD status */ - spin_lock_irqsave(&info->irq_spinlock, flags); - usc_get_serial_signals(info); - spin_unlock_irqrestore(&info->irq_spinlock, flags); - if (info->serial_signals & SerialSignal_DCD) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - return 0; -} - -/** - * called by network layer when interface is disabled - * shutdown hardware and release resources - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_close(struct net_device *dev) -{ - struct mgsl_struct *info = dev_to_port(dev); - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - - netif_stop_queue(dev); - - /* shutdown adapter and release resources */ - shutdown(info); - - hdlc_close(dev); - - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - - return 0; -} - -/** - * called by network layer to process IOCTL call to network device - * - * dev pointer to network device structure - * ifr pointer to network interface request structure - * cmd IOCTL command code - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line; - sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; - struct mgsl_struct *info = dev_to_port(dev); - unsigned int flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - - /* return error if TTY interface open */ - if (info->port.count) - return -EBUSY; - - if (cmd != SIOCWANDEV) - return hdlc_ioctl(dev, ifr, cmd); - - switch(ifr->ifr_settings.type) { - case IF_GET_IFACE: /* return current sync_serial_settings */ - - ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - - flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - - switch (flags){ - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; - case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; - default: new_line.clock_type = CLOCK_DEFAULT; - } - - new_line.clock_rate = info->params.clock_speed; - new_line.loopback = info->params.loopback ? 1:0; - - if (copy_to_user(line, &new_line, size)) - return -EFAULT; - return 0; - - case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&new_line, line, size)) - return -EFAULT; - - switch (new_line.clock_type) - { - case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; - case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; - case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; - case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; - case CLOCK_DEFAULT: flags = info->params.flags & - (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; - default: return -EINVAL; - } - - if (new_line.loopback != 0 && new_line.loopback != 1) - return -EINVAL; - - info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - info->params.flags |= flags; - - info->params.loopback = new_line.loopback; - - if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) - info->params.clock_speed = new_line.clock_rate; - else - info->params.clock_speed = 0; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - mgsl_program_hw(info); - return 0; - - default: - return hdlc_ioctl(dev, ifr, cmd); - } -} - -/** - * called by network layer when transmit timeout is detected - * - * dev pointer to network device structure - */ -static void hdlcdev_tx_timeout(struct net_device *dev) -{ - struct mgsl_struct *info = dev_to_port(dev); - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("hdlcdev_tx_timeout(%s)\n",dev->name); - - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; - - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_stop_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); - - netif_wake_queue(dev); -} - -/** - * called by device driver when transmit completes - * reenable network layer transmit if stopped - * - * info pointer to device instance information - */ -static void hdlcdev_tx_done(struct mgsl_struct *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); -} - -/** - * called by device driver when frame received - * pass frame to network layer - * - * info pointer to device instance information - * buf pointer to buffer contianing frame data - * size count of data bytes in buf - */ -static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) -{ - struct sk_buff *skb = dev_alloc_skb(size); - struct net_device *dev = info->netdev; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("hdlcdev_rx(%s)\n", dev->name); - - if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - dev->name); - dev->stats.rx_dropped++; - return; - } - - memcpy(skb_put(skb, size), buf, size); - - skb->protocol = hdlc_type_trans(skb, dev); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += size; - - netif_rx(skb); -} - -static const struct net_device_ops hdlcdev_ops = { - .ndo_open = hdlcdev_open, - .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, - .ndo_start_xmit = hdlc_start_xmit, - .ndo_do_ioctl = hdlcdev_ioctl, - .ndo_tx_timeout = hdlcdev_tx_timeout, -}; - -/** - * called by device driver when adding device instance - * do generic HDLC initialization - * - * info pointer to device instance information - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_init(struct mgsl_struct *info) -{ - int rc; - struct net_device *dev; - hdlc_device *hdlc; - - /* allocate and initialize network and HDLC layer objects */ - - if (!(dev = alloc_hdlcdev(info))) { - printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); - return -ENOMEM; - } - - /* for network layer reporting purposes only */ - dev->base_addr = info->io_base; - dev->irq = info->irq_level; - dev->dma = info->dma_level; - - /* network layer callbacks and settings */ - dev->netdev_ops = &hdlcdev_ops; - dev->watchdog_timeo = 10 * HZ; - dev->tx_queue_len = 50; - - /* generic HDLC layer callbacks and settings */ - hdlc = dev_to_hdlc(dev); - hdlc->attach = hdlcdev_attach; - hdlc->xmit = hdlcdev_xmit; - - /* register objects with HDLC layer */ - if ((rc = register_hdlc_device(dev))) { - printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); - free_netdev(dev); - return rc; - } - - info->netdev = dev; - return 0; -} - -/** - * called by device driver when removing device instance - * do generic HDLC cleanup - * - * info pointer to device instance information - */ -static void hdlcdev_exit(struct mgsl_struct *info) -{ - unregister_hdlc_device(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; -} - -#endif /* CONFIG_HDLC */ - - -static int __devinit synclink_init_one (struct pci_dev *dev, - const struct pci_device_id *ent) -{ - struct mgsl_struct *info; - - if (pci_enable_device(dev)) { - printk("error enabling pci device %p\n", dev); - return -EIO; - } - - if (!(info = mgsl_allocate_device())) { - printk("can't allocate device instance data.\n"); - return -EIO; - } - - /* Copy user configuration info to device instance data */ - - info->io_base = pci_resource_start(dev, 2); - info->irq_level = dev->irq; - info->phys_memory_base = pci_resource_start(dev, 3); - - /* Because veremap only works on page boundaries we must map - * a larger area than is actually implemented for the LCR - * memory range. We map a full page starting at the page boundary. - */ - info->phys_lcr_base = pci_resource_start(dev, 0); - info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); - info->phys_lcr_base &= ~(PAGE_SIZE-1); - - info->bus_type = MGSL_BUS_TYPE_PCI; - info->io_addr_size = 8; - info->irq_flags = IRQF_SHARED; - - if (dev->device == 0x0210) { - /* Version 1 PCI9030 based universal PCI adapter */ - info->misc_ctrl_value = 0x007c4080; - info->hw_version = 1; - } else { - /* Version 0 PCI9050 based 5V PCI adapter - * A PCI9050 bug prevents reading LCR registers if - * LCR base address bit 7 is set. Maintain shadow - * value so we can write to LCR misc control reg. - */ - info->misc_ctrl_value = 0x087e4546; - info->hw_version = 0; - } - - mgsl_add_device(info); - - return 0; -} - -static void __devexit synclink_remove_one (struct pci_dev *dev) -{ -} - diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c deleted file mode 100644 index a35dd549a008..000000000000 --- a/drivers/char/synclink_gt.c +++ /dev/null @@ -1,5161 +0,0 @@ -/* - * Device driver for Microgate SyncLink GT serial adapters. - * - * written by Paul Fulghum for Microgate Corporation - * paulkf@microgate.com - * - * Microgate and SyncLink are trademarks of Microgate Corporation - * - * This code is released under the GNU General Public License (GPL) - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * DEBUG OUTPUT DEFINITIONS - * - * uncomment lines below to enable specific types of debug output - * - * DBGINFO information - most verbose output - * DBGERR serious errors - * DBGBH bottom half service routine debugging - * DBGISR interrupt service routine debugging - * DBGDATA output receive and transmit data - * DBGTBUF output transmit DMA buffers and registers - * DBGRBUF output receive DMA buffers and registers - */ - -#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt -#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt -#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt -#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt -#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) -/*#define DBGTBUF(info) dump_tbufs(info)*/ -/*#define DBGRBUF(info) dump_rbufs(info)*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) -#define SYNCLINK_GENERIC_HDLC 1 -#else -#define SYNCLINK_GENERIC_HDLC 0 -#endif - -/* - * module identification - */ -static char *driver_name = "SyncLink GT"; -static char *tty_driver_name = "synclink_gt"; -static char *tty_dev_prefix = "ttySLG"; -MODULE_LICENSE("GPL"); -#define MGSL_MAGIC 0x5401 -#define MAX_DEVICES 32 - -static struct pci_device_id pci_table[] = { - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {0,}, /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, pci_table); - -static int init_one(struct pci_dev *dev,const struct pci_device_id *ent); -static void remove_one(struct pci_dev *dev); -static struct pci_driver pci_driver = { - .name = "synclink_gt", - .id_table = pci_table, - .probe = init_one, - .remove = __devexit_p(remove_one), -}; - -static bool pci_registered; - -/* - * module configuration and status - */ -static struct slgt_info *slgt_device_list; -static int slgt_device_count; - -static int ttymajor; -static int debug_level; -static int maxframe[MAX_DEVICES]; - -module_param(ttymajor, int, 0); -module_param(debug_level, int, 0); -module_param_array(maxframe, int, NULL, 0); - -MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); -MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); -MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); - -/* - * tty support and callbacks - */ -static struct tty_driver *serial_driver; - -static int open(struct tty_struct *tty, struct file * filp); -static void close(struct tty_struct *tty, struct file * filp); -static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); - -static int write(struct tty_struct *tty, const unsigned char *buf, int count); -static int put_char(struct tty_struct *tty, unsigned char ch); -static void send_xchar(struct tty_struct *tty, char ch); -static void wait_until_sent(struct tty_struct *tty, int timeout); -static int write_room(struct tty_struct *tty); -static void flush_chars(struct tty_struct *tty); -static void flush_buffer(struct tty_struct *tty); -static void tx_hold(struct tty_struct *tty); -static void tx_release(struct tty_struct *tty); - -static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int chars_in_buffer(struct tty_struct *tty); -static void throttle(struct tty_struct * tty); -static void unthrottle(struct tty_struct * tty); -static int set_break(struct tty_struct *tty, int break_state); - -/* - * generic HDLC support and callbacks - */ -#if SYNCLINK_GENERIC_HDLC -#define dev_to_port(D) (dev_to_hdlc(D)->priv) -static void hdlcdev_tx_done(struct slgt_info *info); -static void hdlcdev_rx(struct slgt_info *info, char *buf, int size); -static int hdlcdev_init(struct slgt_info *info); -static void hdlcdev_exit(struct slgt_info *info); -#endif - - -/* - * device specific structures, macros and functions - */ - -#define SLGT_MAX_PORTS 4 -#define SLGT_REG_SIZE 256 - -/* - * conditional wait facility - */ -struct cond_wait { - struct cond_wait *next; - wait_queue_head_t q; - wait_queue_t wait; - unsigned int data; -}; -static void init_cond_wait(struct cond_wait *w, unsigned int data); -static void add_cond_wait(struct cond_wait **head, struct cond_wait *w); -static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w); -static void flush_cond_wait(struct cond_wait **head); - -/* - * DMA buffer descriptor and access macros - */ -struct slgt_desc -{ - __le16 count; - __le16 status; - __le32 pbuf; /* physical address of data buffer */ - __le32 next; /* physical address of next descriptor */ - - /* driver book keeping */ - char *buf; /* virtual address of data buffer */ - unsigned int pdesc; /* physical address of this descriptor */ - dma_addr_t buf_dma_addr; - unsigned short buf_count; -}; - -#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) -#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) -#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) -#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) -#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b)) -#define desc_count(a) (le16_to_cpu((a).count)) -#define desc_status(a) (le16_to_cpu((a).status)) -#define desc_complete(a) (le16_to_cpu((a).status) & BIT15) -#define desc_eof(a) (le16_to_cpu((a).status) & BIT2) -#define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1) -#define desc_abort(a) (le16_to_cpu((a).status) & BIT0) -#define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3) - -struct _input_signal_events { - int ri_up; - int ri_down; - int dsr_up; - int dsr_down; - int dcd_up; - int dcd_down; - int cts_up; - int cts_down; -}; - -/* - * device instance data structure - */ -struct slgt_info { - void *if_ptr; /* General purpose pointer (used by SPPP) */ - struct tty_port port; - - struct slgt_info *next_device; /* device list link */ - - int magic; - - char device_name[25]; - struct pci_dev *pdev; - - int port_count; /* count of ports on adapter */ - int adapter_num; /* adapter instance number */ - int port_num; /* port instance number */ - - /* array of pointers to port contexts on this adapter */ - struct slgt_info *port_array[SLGT_MAX_PORTS]; - - int line; /* tty line instance number */ - - struct mgsl_icount icount; - - int timeout; - int x_char; /* xon/xoff character */ - unsigned int read_status_mask; - unsigned int ignore_status_mask; - - wait_queue_head_t status_event_wait_q; - wait_queue_head_t event_wait_q; - struct timer_list tx_timer; - struct timer_list rx_timer; - - unsigned int gpio_present; - struct cond_wait *gpio_wait_q; - - spinlock_t lock; /* spinlock for synchronizing with ISR */ - - struct work_struct task; - u32 pending_bh; - bool bh_requested; - bool bh_running; - - int isr_overflow; - bool irq_requested; /* true if IRQ requested */ - bool irq_occurred; /* for diagnostics use */ - - /* device configuration */ - - unsigned int bus_type; - unsigned int irq_level; - unsigned long irq_flags; - - unsigned char __iomem * reg_addr; /* memory mapped registers address */ - u32 phys_reg_addr; - bool reg_addr_requested; - - MGSL_PARAMS params; /* communications parameters */ - u32 idle_mode; - u32 max_frame_size; /* as set by device config */ - - unsigned int rbuf_fill_level; - unsigned int rx_pio; - unsigned int if_mode; - unsigned int base_clock; - unsigned int xsync; - unsigned int xctrl; - - /* device status */ - - bool rx_enabled; - bool rx_restart; - - bool tx_enabled; - bool tx_active; - - unsigned char signals; /* serial signal states */ - int init_error; /* initialization error */ - - unsigned char *tx_buf; - int tx_count; - - char flag_buf[MAX_ASYNC_BUFFER_SIZE]; - char char_buf[MAX_ASYNC_BUFFER_SIZE]; - bool drop_rts_on_tx_done; - struct _input_signal_events input_signal_events; - - int dcd_chkcount; /* check counts to prevent */ - int cts_chkcount; /* too many IRQs if a signal */ - int dsr_chkcount; /* is floating */ - int ri_chkcount; - - char *bufs; /* virtual address of DMA buffer lists */ - dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */ - - unsigned int rbuf_count; - struct slgt_desc *rbufs; - unsigned int rbuf_current; - unsigned int rbuf_index; - unsigned int rbuf_fill_index; - unsigned short rbuf_fill_count; - - unsigned int tbuf_count; - struct slgt_desc *tbufs; - unsigned int tbuf_current; - unsigned int tbuf_start; - - unsigned char *tmp_rbuf; - unsigned int tmp_rbuf_count; - - /* SPPP/Cisco HDLC device parts */ - - int netcount; - spinlock_t netlock; -#if SYNCLINK_GENERIC_HDLC - struct net_device *netdev; -#endif - -}; - -static MGSL_PARAMS default_params = { - .mode = MGSL_MODE_HDLC, - .loopback = 0, - .flags = HDLC_FLAG_UNDERRUN_ABORT15, - .encoding = HDLC_ENCODING_NRZI_SPACE, - .clock_speed = 0, - .addr_filter = 0xff, - .crc_type = HDLC_CRC_16_CCITT, - .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS, - .preamble = HDLC_PREAMBLE_PATTERN_NONE, - .data_rate = 9600, - .data_bits = 8, - .stop_bits = 1, - .parity = ASYNC_PARITY_NONE -}; - - -#define BH_RECEIVE 1 -#define BH_TRANSMIT 2 -#define BH_STATUS 4 -#define IO_PIN_SHUTDOWN_LIMIT 100 - -#define DMABUFSIZE 256 -#define DESC_LIST_SIZE 4096 - -#define MASK_PARITY BIT1 -#define MASK_FRAMING BIT0 -#define MASK_BREAK BIT14 -#define MASK_OVERRUN BIT4 - -#define GSR 0x00 /* global status */ -#define JCR 0x04 /* JTAG control */ -#define IODR 0x08 /* GPIO direction */ -#define IOER 0x0c /* GPIO interrupt enable */ -#define IOVR 0x10 /* GPIO value */ -#define IOSR 0x14 /* GPIO interrupt status */ -#define TDR 0x80 /* tx data */ -#define RDR 0x80 /* rx data */ -#define TCR 0x82 /* tx control */ -#define TIR 0x84 /* tx idle */ -#define TPR 0x85 /* tx preamble */ -#define RCR 0x86 /* rx control */ -#define VCR 0x88 /* V.24 control */ -#define CCR 0x89 /* clock control */ -#define BDR 0x8a /* baud divisor */ -#define SCR 0x8c /* serial control */ -#define SSR 0x8e /* serial status */ -#define RDCSR 0x90 /* rx DMA control/status */ -#define TDCSR 0x94 /* tx DMA control/status */ -#define RDDAR 0x98 /* rx DMA descriptor address */ -#define TDDAR 0x9c /* tx DMA descriptor address */ -#define XSR 0x40 /* extended sync pattern */ -#define XCR 0x44 /* extended control */ - -#define RXIDLE BIT14 -#define RXBREAK BIT14 -#define IRQ_TXDATA BIT13 -#define IRQ_TXIDLE BIT12 -#define IRQ_TXUNDER BIT11 /* HDLC */ -#define IRQ_RXDATA BIT10 -#define IRQ_RXIDLE BIT9 /* HDLC */ -#define IRQ_RXBREAK BIT9 /* async */ -#define IRQ_RXOVER BIT8 -#define IRQ_DSR BIT7 -#define IRQ_CTS BIT6 -#define IRQ_DCD BIT5 -#define IRQ_RI BIT4 -#define IRQ_ALL 0x3ff0 -#define IRQ_MASTER BIT0 - -#define slgt_irq_on(info, mask) \ - wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask))) -#define slgt_irq_off(info, mask) \ - wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask))) - -static __u8 rd_reg8(struct slgt_info *info, unsigned int addr); -static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value); -static __u16 rd_reg16(struct slgt_info *info, unsigned int addr); -static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value); -static __u32 rd_reg32(struct slgt_info *info, unsigned int addr); -static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value); - -static void msc_set_vcr(struct slgt_info *info); - -static int startup(struct slgt_info *info); -static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info); -static void shutdown(struct slgt_info *info); -static void program_hw(struct slgt_info *info); -static void change_params(struct slgt_info *info); - -static int register_test(struct slgt_info *info); -static int irq_test(struct slgt_info *info); -static int loopback_test(struct slgt_info *info); -static int adapter_test(struct slgt_info *info); - -static void reset_adapter(struct slgt_info *info); -static void reset_port(struct slgt_info *info); -static void async_mode(struct slgt_info *info); -static void sync_mode(struct slgt_info *info); - -static void rx_stop(struct slgt_info *info); -static void rx_start(struct slgt_info *info); -static void reset_rbufs(struct slgt_info *info); -static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last); -static void rdma_reset(struct slgt_info *info); -static bool rx_get_frame(struct slgt_info *info); -static bool rx_get_buf(struct slgt_info *info); - -static void tx_start(struct slgt_info *info); -static void tx_stop(struct slgt_info *info); -static void tx_set_idle(struct slgt_info *info); -static unsigned int free_tbuf_count(struct slgt_info *info); -static unsigned int tbuf_bytes(struct slgt_info *info); -static void reset_tbufs(struct slgt_info *info); -static void tdma_reset(struct slgt_info *info); -static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count); - -static void get_signals(struct slgt_info *info); -static void set_signals(struct slgt_info *info); -static void enable_loopback(struct slgt_info *info); -static void set_rate(struct slgt_info *info, u32 data_rate); - -static int bh_action(struct slgt_info *info); -static void bh_handler(struct work_struct *work); -static void bh_transmit(struct slgt_info *info); -static void isr_serial(struct slgt_info *info); -static void isr_rdma(struct slgt_info *info); -static void isr_txeom(struct slgt_info *info, unsigned short status); -static void isr_tdma(struct slgt_info *info); - -static int alloc_dma_bufs(struct slgt_info *info); -static void free_dma_bufs(struct slgt_info *info); -static int alloc_desc(struct slgt_info *info); -static void free_desc(struct slgt_info *info); -static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); -static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); - -static int alloc_tmp_rbuf(struct slgt_info *info); -static void free_tmp_rbuf(struct slgt_info *info); - -static void tx_timeout(unsigned long context); -static void rx_timeout(unsigned long context); - -/* - * ioctl handlers - */ -static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount); -static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params); -static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params); -static int get_txidle(struct slgt_info *info, int __user *idle_mode); -static int set_txidle(struct slgt_info *info, int idle_mode); -static int tx_enable(struct slgt_info *info, int enable); -static int tx_abort(struct slgt_info *info); -static int rx_enable(struct slgt_info *info, int enable); -static int modem_input_wait(struct slgt_info *info,int arg); -static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); -static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear); -static int set_break(struct tty_struct *tty, int break_state); -static int get_interface(struct slgt_info *info, int __user *if_mode); -static int set_interface(struct slgt_info *info, int if_mode); -static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); -static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); -static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); -static int get_xsync(struct slgt_info *info, int __user *if_mode); -static int set_xsync(struct slgt_info *info, int if_mode); -static int get_xctrl(struct slgt_info *info, int __user *if_mode); -static int set_xctrl(struct slgt_info *info, int if_mode); - -/* - * driver functions - */ -static void add_device(struct slgt_info *info); -static void device_init(int adapter_num, struct pci_dev *pdev); -static int claim_resources(struct slgt_info *info); -static void release_resources(struct slgt_info *info); - -/* - * DEBUG OUTPUT CODE - */ -#ifndef DBGINFO -#define DBGINFO(fmt) -#endif -#ifndef DBGERR -#define DBGERR(fmt) -#endif -#ifndef DBGBH -#define DBGBH(fmt) -#endif -#ifndef DBGISR -#define DBGISR(fmt) -#endif - -#ifdef DBGDATA -static void trace_block(struct slgt_info *info, const char *data, int count, const char *label) -{ - int i; - int linecount; - printk("%s %s data:\n",info->device_name, label); - while(count) { - linecount = (count > 16) ? 16 : count; - for(i=0; i < linecount; i++) - printk("%02X ",(unsigned char)data[i]); - for(;i<17;i++) - printk(" "); - for(i=0;i=040 && data[i]<=0176) - printk("%c",data[i]); - else - printk("."); - } - printk("\n"); - data += linecount; - count -= linecount; - } -} -#else -#define DBGDATA(info, buf, size, label) -#endif - -#ifdef DBGTBUF -static void dump_tbufs(struct slgt_info *info) -{ - int i; - printk("tbuf_current=%d\n", info->tbuf_current); - for (i=0 ; i < info->tbuf_count ; i++) { - printk("%d: count=%04X status=%04X\n", - i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status)); - } -} -#else -#define DBGTBUF(info) -#endif - -#ifdef DBGRBUF -static void dump_rbufs(struct slgt_info *info) -{ - int i; - printk("rbuf_current=%d\n", info->rbuf_current); - for (i=0 ; i < info->rbuf_count ; i++) { - printk("%d: count=%04X status=%04X\n", - i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status)); - } -} -#else -#define DBGRBUF(info) -#endif - -static inline int sanity_check(struct slgt_info *info, char *devname, const char *name) -{ -#ifdef SANITY_CHECK - if (!info) { - printk("null struct slgt_info for (%s) in %s\n", devname, name); - return 1; - } - if (info->magic != MGSL_MAGIC) { - printk("bad magic number struct slgt_info (%s) in %s\n", devname, name); - return 1; - } -#else - if (!info) - return 1; -#endif - return 0; -} - -/** - * line discipline callback wrappers - * - * The wrappers maintain line discipline references - * while calling into the line discipline. - * - * ldisc_receive_buf - pass receive data to line discipline - */ -static void ldisc_receive_buf(struct tty_struct *tty, - const __u8 *data, char *flags, int count) -{ - struct tty_ldisc *ld; - if (!tty) - return; - ld = tty_ldisc_ref(tty); - if (ld) { - if (ld->ops->receive_buf) - ld->ops->receive_buf(tty, data, flags, count); - tty_ldisc_deref(ld); - } -} - -/* tty callbacks */ - -static int open(struct tty_struct *tty, struct file *filp) -{ - struct slgt_info *info; - int retval, line; - unsigned long flags; - - line = tty->index; - if ((line < 0) || (line >= slgt_device_count)) { - DBGERR(("%s: open with invalid line #%d.\n", driver_name, line)); - return -ENODEV; - } - - info = slgt_device_list; - while(info && info->line != line) - info = info->next_device; - if (sanity_check(info, tty->name, "open")) - return -ENODEV; - if (info->init_error) { - DBGERR(("%s init error=%d\n", info->device_name, info->init_error)); - return -ENODEV; - } - - tty->driver_data = info; - info->port.tty = tty; - - DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count)); - - /* If port is closing, signal caller to try again */ - if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ - if (info->port.flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->port.close_wait); - retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - goto cleanup; - } - - mutex_lock(&info->port.mutex); - info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - spin_lock_irqsave(&info->netlock, flags); - if (info->netcount) { - retval = -EBUSY; - spin_unlock_irqrestore(&info->netlock, flags); - mutex_unlock(&info->port.mutex); - goto cleanup; - } - info->port.count++; - spin_unlock_irqrestore(&info->netlock, flags); - - if (info->port.count == 1) { - /* 1st open on this device, init hardware */ - retval = startup(info); - if (retval < 0) { - mutex_unlock(&info->port.mutex); - goto cleanup; - } - } - mutex_unlock(&info->port.mutex); - retval = block_til_ready(tty, filp, info); - if (retval) { - DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); - goto cleanup; - } - - retval = 0; - -cleanup: - if (retval) { - if (tty->count == 1) - info->port.tty = NULL; /* tty layer will release tty struct */ - if(info->port.count) - info->port.count--; - } - - DBGINFO(("%s open rc=%d\n", info->device_name, retval)); - return retval; -} - -static void close(struct tty_struct *tty, struct file *filp) -{ - struct slgt_info *info = tty->driver_data; - - if (sanity_check(info, tty->name, "close")) - return; - DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); - - if (tty_port_close_start(&info->port, tty, filp) == 0) - goto cleanup; - - mutex_lock(&info->port.mutex); - if (info->port.flags & ASYNC_INITIALIZED) - wait_until_sent(tty, info->timeout); - flush_buffer(tty); - tty_ldisc_flush(tty); - - shutdown(info); - mutex_unlock(&info->port.mutex); - - tty_port_close_end(&info->port, tty); - info->port.tty = NULL; -cleanup: - DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); -} - -static void hangup(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "hangup")) - return; - DBGINFO(("%s hangup\n", info->device_name)); - - flush_buffer(tty); - - mutex_lock(&info->port.mutex); - shutdown(info); - - spin_lock_irqsave(&info->port.lock, flags); - info->port.count = 0; - info->port.flags &= ~ASYNC_NORMAL_ACTIVE; - info->port.tty = NULL; - spin_unlock_irqrestore(&info->port.lock, flags); - mutex_unlock(&info->port.mutex); - - wake_up_interruptible(&info->port.open_wait); -} - -static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - DBGINFO(("%s set_termios\n", tty->driver->name)); - - change_params(info); - - /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios->c_cflag & CBAUD)) { - info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios->c_cflag & CBAUD) { - info->signals |= SerialSignal_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->signals |= SerialSignal_RTS; - } - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - tx_release(tty); - } -} - -static void update_tx_timer(struct slgt_info *info) -{ - /* - * use worst case speed of 1200bps to calculate transmit timeout - * based on data in buffers (tbuf_bytes) and FIFO (128 bytes) - */ - if (info->params.mode == MGSL_MODE_HDLC) { - int timeout = (tbuf_bytes(info) * 7) + 1000; - mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout)); - } -} - -static int write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int ret = 0; - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "write")) - return -EIO; - - DBGINFO(("%s write count=%d\n", info->device_name, count)); - - if (!info->tx_buf || (count > info->max_frame_size)) - return -EIO; - - if (!count || tty->stopped || tty->hw_stopped) - return 0; - - spin_lock_irqsave(&info->lock, flags); - - if (info->tx_count) { - /* send accumulated data from send_char() */ - if (!tx_load(info, info->tx_buf, info->tx_count)) - goto cleanup; - info->tx_count = 0; - } - - if (tx_load(info, buf, count)) - ret = count; - -cleanup: - spin_unlock_irqrestore(&info->lock, flags); - DBGINFO(("%s write rc=%d\n", info->device_name, ret)); - return ret; -} - -static int put_char(struct tty_struct *tty, unsigned char ch) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - int ret = 0; - - if (sanity_check(info, tty->name, "put_char")) - return 0; - DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); - if (!info->tx_buf) - return 0; - spin_lock_irqsave(&info->lock,flags); - if (info->tx_count < info->max_frame_size) { - info->tx_buf[info->tx_count++] = ch; - ret = 1; - } - spin_unlock_irqrestore(&info->lock,flags); - return ret; -} - -static void send_xchar(struct tty_struct *tty, char ch) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "send_xchar")) - return; - DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch)); - info->x_char = ch; - if (ch) { - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_enabled) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -static void wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct slgt_info *info = tty->driver_data; - unsigned long orig_jiffies, char_time; - - if (!info ) - return; - if (sanity_check(info, tty->name, "wait_until_sent")) - return; - DBGINFO(("%s wait_until_sent entry\n", info->device_name)); - if (!(info->port.flags & ASYNC_INITIALIZED)) - goto exit; - - orig_jiffies = jiffies; - - /* Set check interval to 1/5 of estimated time to - * send a character, and make it at least 1. The check - * interval should also be less than the timeout. - * Note: use tight timings here to satisfy the NIST-PCTS. - */ - - if (info->params.data_rate) { - char_time = info->timeout/(32 * 5); - if (!char_time) - char_time++; - } else - char_time = 1; - - if (timeout) - char_time = min_t(unsigned long, char_time, timeout); - - while (info->tx_active) { - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } -exit: - DBGINFO(("%s wait_until_sent exit\n", info->device_name)); -} - -static int write_room(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - int ret; - - if (sanity_check(info, tty->name, "write_room")) - return 0; - ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; - DBGINFO(("%s write_room=%d\n", info->device_name, ret)); - return ret; -} - -static void flush_chars(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "flush_chars")) - return; - DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count)); - - if (info->tx_count <= 0 || tty->stopped || - tty->hw_stopped || !info->tx_buf) - return; - - DBGINFO(("%s flush_chars start transmit\n", info->device_name)); - - spin_lock_irqsave(&info->lock,flags); - if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) - info->tx_count = 0; - spin_unlock_irqrestore(&info->lock,flags); -} - -static void flush_buffer(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "flush_buffer")) - return; - DBGINFO(("%s flush_buffer\n", info->device_name)); - - spin_lock_irqsave(&info->lock, flags); - info->tx_count = 0; - spin_unlock_irqrestore(&info->lock, flags); - - tty_wakeup(tty); -} - -/* - * throttle (stop) transmitter - */ -static void tx_hold(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "tx_hold")) - return; - DBGINFO(("%s tx_hold\n", info->device_name)); - spin_lock_irqsave(&info->lock,flags); - if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC) - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); -} - -/* - * release (start) transmitter - */ -static void tx_release(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "tx_release")) - return; - DBGINFO(("%s tx_release\n", info->device_name)); - spin_lock_irqsave(&info->lock, flags); - if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) - info->tx_count = 0; - spin_unlock_irqrestore(&info->lock, flags); -} - -/* - * Service an IOCTL request - * - * Arguments - * - * tty pointer to tty instance data - * cmd IOCTL command code - * arg command argument/context - * - * Return 0 if success, otherwise error code - */ -static int ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct slgt_info *info = tty->driver_data; - void __user *argp = (void __user *)arg; - int ret; - - if (sanity_check(info, tty->name, "ioctl")) - return -ENODEV; - DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCMIWAIT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case MGSL_IOCWAITEVENT: - return wait_mgsl_event(info, argp); - case TIOCMIWAIT: - return modem_input_wait(info,(int)arg); - case MGSL_IOCSGPIO: - return set_gpio(info, argp); - case MGSL_IOCGGPIO: - return get_gpio(info, argp); - case MGSL_IOCWAITGPIO: - return wait_gpio(info, argp); - case MGSL_IOCGXSYNC: - return get_xsync(info, argp); - case MGSL_IOCSXSYNC: - return set_xsync(info, (int)arg); - case MGSL_IOCGXCTRL: - return get_xctrl(info, argp); - case MGSL_IOCSXCTRL: - return set_xctrl(info, (int)arg); - } - mutex_lock(&info->port.mutex); - switch (cmd) { - case MGSL_IOCGPARAMS: - ret = get_params(info, argp); - break; - case MGSL_IOCSPARAMS: - ret = set_params(info, argp); - break; - case MGSL_IOCGTXIDLE: - ret = get_txidle(info, argp); - break; - case MGSL_IOCSTXIDLE: - ret = set_txidle(info, (int)arg); - break; - case MGSL_IOCTXENABLE: - ret = tx_enable(info, (int)arg); - break; - case MGSL_IOCRXENABLE: - ret = rx_enable(info, (int)arg); - break; - case MGSL_IOCTXABORT: - ret = tx_abort(info); - break; - case MGSL_IOCGSTATS: - ret = get_stats(info, argp); - break; - case MGSL_IOCGIF: - ret = get_interface(info, argp); - break; - case MGSL_IOCSIF: - ret = set_interface(info,(int)arg); - break; - default: - ret = -ENOIOCTLCMD; - } - mutex_unlock(&info->port.mutex); - return ret; -} - -static int get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) - -{ - struct slgt_info *info = tty->driver_data; - struct mgsl_icount cnow; /* kernel counter temps */ - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->lock,flags); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - -/* - * support for 32 bit ioctl calls on 64 bit systems - */ -#ifdef CONFIG_COMPAT -static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params) -{ - struct MGSL_PARAMS32 tmp_params; - - DBGINFO(("%s get_params32\n", info->device_name)); - memset(&tmp_params, 0, sizeof(tmp_params)); - tmp_params.mode = (compat_ulong_t)info->params.mode; - tmp_params.loopback = info->params.loopback; - tmp_params.flags = info->params.flags; - tmp_params.encoding = info->params.encoding; - tmp_params.clock_speed = (compat_ulong_t)info->params.clock_speed; - tmp_params.addr_filter = info->params.addr_filter; - tmp_params.crc_type = info->params.crc_type; - tmp_params.preamble_length = info->params.preamble_length; - tmp_params.preamble = info->params.preamble; - tmp_params.data_rate = (compat_ulong_t)info->params.data_rate; - tmp_params.data_bits = info->params.data_bits; - tmp_params.stop_bits = info->params.stop_bits; - tmp_params.parity = info->params.parity; - if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32))) - return -EFAULT; - return 0; -} - -static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params) -{ - struct MGSL_PARAMS32 tmp_params; - - DBGINFO(("%s set_params32\n", info->device_name)); - if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32))) - return -EFAULT; - - spin_lock(&info->lock); - if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) { - info->base_clock = tmp_params.clock_speed; - } else { - info->params.mode = tmp_params.mode; - info->params.loopback = tmp_params.loopback; - info->params.flags = tmp_params.flags; - info->params.encoding = tmp_params.encoding; - info->params.clock_speed = tmp_params.clock_speed; - info->params.addr_filter = tmp_params.addr_filter; - info->params.crc_type = tmp_params.crc_type; - info->params.preamble_length = tmp_params.preamble_length; - info->params.preamble = tmp_params.preamble; - info->params.data_rate = tmp_params.data_rate; - info->params.data_bits = tmp_params.data_bits; - info->params.stop_bits = tmp_params.stop_bits; - info->params.parity = tmp_params.parity; - } - spin_unlock(&info->lock); - - program_hw(info); - - return 0; -} - -static long slgt_compat_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct slgt_info *info = tty->driver_data; - int rc = -ENOIOCTLCMD; - - if (sanity_check(info, tty->name, "compat_ioctl")) - return -ENODEV; - DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd)); - - switch (cmd) { - - case MGSL_IOCSPARAMS32: - rc = set_params32(info, compat_ptr(arg)); - break; - - case MGSL_IOCGPARAMS32: - rc = get_params32(info, compat_ptr(arg)); - break; - - case MGSL_IOCGPARAMS: - case MGSL_IOCSPARAMS: - case MGSL_IOCGTXIDLE: - case MGSL_IOCGSTATS: - case MGSL_IOCWAITEVENT: - case MGSL_IOCGIF: - case MGSL_IOCSGPIO: - case MGSL_IOCGGPIO: - case MGSL_IOCWAITGPIO: - case MGSL_IOCGXSYNC: - case MGSL_IOCGXCTRL: - case MGSL_IOCSTXIDLE: - case MGSL_IOCTXENABLE: - case MGSL_IOCRXENABLE: - case MGSL_IOCTXABORT: - case TIOCMIWAIT: - case MGSL_IOCSIF: - case MGSL_IOCSXSYNC: - case MGSL_IOCSXCTRL: - rc = ioctl(tty, cmd, arg); - break; - } - - DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc)); - return rc; -} -#else -#define slgt_compat_ioctl NULL -#endif /* ifdef CONFIG_COMPAT */ - -/* - * proc fs support - */ -static inline void line_info(struct seq_file *m, struct slgt_info *info) -{ - char stat_buf[30]; - unsigned long flags; - - seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", - info->device_name, info->phys_reg_addr, - info->irq_level, info->max_frame_size); - - /* output current serial signal states */ - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if (info->signals & SerialSignal_RTS) - strcat(stat_buf, "|RTS"); - if (info->signals & SerialSignal_CTS) - strcat(stat_buf, "|CTS"); - if (info->signals & SerialSignal_DTR) - strcat(stat_buf, "|DTR"); - if (info->signals & SerialSignal_DSR) - strcat(stat_buf, "|DSR"); - if (info->signals & SerialSignal_DCD) - strcat(stat_buf, "|CD"); - if (info->signals & SerialSignal_RI) - strcat(stat_buf, "|RI"); - - if (info->params.mode != MGSL_MODE_ASYNC) { - seq_printf(m, "\tHDLC txok:%d rxok:%d", - info->icount.txok, info->icount.rxok); - if (info->icount.txunder) - seq_printf(m, " txunder:%d", info->icount.txunder); - if (info->icount.txabort) - seq_printf(m, " txabort:%d", info->icount.txabort); - if (info->icount.rxshort) - seq_printf(m, " rxshort:%d", info->icount.rxshort); - if (info->icount.rxlong) - seq_printf(m, " rxlong:%d", info->icount.rxlong); - if (info->icount.rxover) - seq_printf(m, " rxover:%d", info->icount.rxover); - if (info->icount.rxcrc) - seq_printf(m, " rxcrc:%d", info->icount.rxcrc); - } else { - seq_printf(m, "\tASYNC tx:%d rx:%d", - info->icount.tx, info->icount.rx); - if (info->icount.frame) - seq_printf(m, " fe:%d", info->icount.frame); - if (info->icount.parity) - seq_printf(m, " pe:%d", info->icount.parity); - if (info->icount.brk) - seq_printf(m, " brk:%d", info->icount.brk); - if (info->icount.overrun) - seq_printf(m, " oe:%d", info->icount.overrun); - } - - /* Append serial signal status to end */ - seq_printf(m, " %s\n", stat_buf+1); - - seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", - info->tx_active,info->bh_requested,info->bh_running, - info->pending_bh); -} - -/* Called to print information about devices - */ -static int synclink_gt_proc_show(struct seq_file *m, void *v) -{ - struct slgt_info *info; - - seq_puts(m, "synclink_gt driver\n"); - - info = slgt_device_list; - while( info ) { - line_info(m, info); - info = info->next_device; - } - return 0; -} - -static int synclink_gt_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, synclink_gt_proc_show, NULL); -} - -static const struct file_operations synclink_gt_proc_fops = { - .owner = THIS_MODULE, - .open = synclink_gt_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * return count of bytes in transmit buffer - */ -static int chars_in_buffer(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - int count; - if (sanity_check(info, tty->name, "chars_in_buffer")) - return 0; - count = tbuf_bytes(info); - DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); - return count; -} - -/* - * signal remote device to throttle send data (our receive data) - */ -static void throttle(struct tty_struct * tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "throttle")) - return; - DBGINFO(("%s throttle\n", info->device_name)); - if (I_IXOFF(tty)) - send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); - info->signals &= ~SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* - * signal remote device to stop throttling send data (our receive data) - */ -static void unthrottle(struct tty_struct * tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "unthrottle")) - return; - DBGINFO(("%s unthrottle\n", info->device_name)); - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - send_xchar(tty, START_CHAR(tty)); - } - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); - info->signals |= SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* - * set or clear transmit break condition - * break_state -1=set break condition, 0=clear - */ -static int set_break(struct tty_struct *tty, int break_state) -{ - struct slgt_info *info = tty->driver_data; - unsigned short value; - unsigned long flags; - - if (sanity_check(info, tty->name, "set_break")) - return -EINVAL; - DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); - - spin_lock_irqsave(&info->lock,flags); - value = rd_reg16(info, TCR); - if (break_state == -1) - value |= BIT6; - else - value &= ~BIT6; - wr_reg16(info, TCR, value); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -#if SYNCLINK_GENERIC_HDLC - -/** - * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) - * set encoding and frame check sequence (FCS) options - * - * dev pointer to network device structure - * encoding serial encoding setting - * parity FCS setting - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -{ - struct slgt_info *info = dev_to_port(dev); - unsigned char new_encoding; - unsigned short new_crctype; - - /* return error if TTY interface open */ - if (info->port.count) - return -EBUSY; - - DBGINFO(("%s hdlcdev_attach\n", info->device_name)); - - switch (encoding) - { - case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; - case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; - case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; - case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; - case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; - default: return -EINVAL; - } - - switch (parity) - { - case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; - case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; - case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; - default: return -EINVAL; - } - - info->params.encoding = new_encoding; - info->params.crc_type = new_crctype; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - program_hw(info); - - return 0; -} - -/** - * called by generic HDLC layer to send frame - * - * skb socket buffer containing HDLC frame - * dev pointer to network device structure - */ -static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - unsigned long flags; - - DBGINFO(("%s hdlc_xmit\n", dev->name)); - - if (!skb->len) - return NETDEV_TX_OK; - - /* stop sending until this frame completes */ - netif_stop_queue(dev); - - /* update network statistics */ - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - - /* save start time for transmit timeout detection */ - dev->trans_start = jiffies; - - spin_lock_irqsave(&info->lock, flags); - tx_load(info, skb->data, skb->len); - spin_unlock_irqrestore(&info->lock, flags); - - /* done with socket buffer, so free it */ - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - -/** - * called by network layer when interface enabled - * claim resources and initialize hardware - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_open(struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - int rc; - unsigned long flags; - - if (!try_module_get(THIS_MODULE)) - return -EBUSY; - - DBGINFO(("%s hdlcdev_open\n", dev->name)); - - /* generic HDLC layer open processing */ - if ((rc = hdlc_open(dev))) - return rc; - - /* arbitrate between network and tty opens */ - spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { - DBGINFO(("%s hdlc_open busy\n", dev->name)); - spin_unlock_irqrestore(&info->netlock, flags); - return -EBUSY; - } - info->netcount=1; - spin_unlock_irqrestore(&info->netlock, flags); - - /* claim resources and init adapter */ - if ((rc = startup(info)) != 0) { - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return rc; - } - - /* assert DTR and RTS, apply hardware settings */ - info->signals |= SerialSignal_RTS + SerialSignal_DTR; - program_hw(info); - - /* enable network layer transmit */ - dev->trans_start = jiffies; - netif_start_queue(dev); - - /* inform generic HDLC layer of current DCD status */ - spin_lock_irqsave(&info->lock, flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock, flags); - if (info->signals & SerialSignal_DCD) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - return 0; -} - -/** - * called by network layer when interface is disabled - * shutdown hardware and release resources - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_close(struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - unsigned long flags; - - DBGINFO(("%s hdlcdev_close\n", dev->name)); - - netif_stop_queue(dev); - - /* shutdown adapter and release resources */ - shutdown(info); - - hdlc_close(dev); - - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - - module_put(THIS_MODULE); - return 0; -} - -/** - * called by network layer to process IOCTL call to network device - * - * dev pointer to network device structure - * ifr pointer to network interface request structure - * cmd IOCTL command code - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line; - sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; - struct slgt_info *info = dev_to_port(dev); - unsigned int flags; - - DBGINFO(("%s hdlcdev_ioctl\n", dev->name)); - - /* return error if TTY interface open */ - if (info->port.count) - return -EBUSY; - - if (cmd != SIOCWANDEV) - return hdlc_ioctl(dev, ifr, cmd); - - memset(&new_line, 0, sizeof(new_line)); - - switch(ifr->ifr_settings.type) { - case IF_GET_IFACE: /* return current sync_serial_settings */ - - ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - - flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - - switch (flags){ - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; - case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; - default: new_line.clock_type = CLOCK_DEFAULT; - } - - new_line.clock_rate = info->params.clock_speed; - new_line.loopback = info->params.loopback ? 1:0; - - if (copy_to_user(line, &new_line, size)) - return -EFAULT; - return 0; - - case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&new_line, line, size)) - return -EFAULT; - - switch (new_line.clock_type) - { - case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; - case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; - case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; - case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; - case CLOCK_DEFAULT: flags = info->params.flags & - (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; - default: return -EINVAL; - } - - if (new_line.loopback != 0 && new_line.loopback != 1) - return -EINVAL; - - info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - info->params.flags |= flags; - - info->params.loopback = new_line.loopback; - - if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) - info->params.clock_speed = new_line.clock_rate; - else - info->params.clock_speed = 0; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - program_hw(info); - return 0; - - default: - return hdlc_ioctl(dev, ifr, cmd); - } -} - -/** - * called by network layer when transmit timeout is detected - * - * dev pointer to network device structure - */ -static void hdlcdev_tx_timeout(struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - unsigned long flags; - - DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name)); - - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; - - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); - - netif_wake_queue(dev); -} - -/** - * called by device driver when transmit completes - * reenable network layer transmit if stopped - * - * info pointer to device instance information - */ -static void hdlcdev_tx_done(struct slgt_info *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); -} - -/** - * called by device driver when frame received - * pass frame to network layer - * - * info pointer to device instance information - * buf pointer to buffer contianing frame data - * size count of data bytes in buf - */ -static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) -{ - struct sk_buff *skb = dev_alloc_skb(size); - struct net_device *dev = info->netdev; - - DBGINFO(("%s hdlcdev_rx\n", dev->name)); - - if (skb == NULL) { - DBGERR(("%s: can't alloc skb, drop packet\n", dev->name)); - dev->stats.rx_dropped++; - return; - } - - memcpy(skb_put(skb, size), buf, size); - - skb->protocol = hdlc_type_trans(skb, dev); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += size; - - netif_rx(skb); -} - -static const struct net_device_ops hdlcdev_ops = { - .ndo_open = hdlcdev_open, - .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, - .ndo_start_xmit = hdlc_start_xmit, - .ndo_do_ioctl = hdlcdev_ioctl, - .ndo_tx_timeout = hdlcdev_tx_timeout, -}; - -/** - * called by device driver when adding device instance - * do generic HDLC initialization - * - * info pointer to device instance information - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_init(struct slgt_info *info) -{ - int rc; - struct net_device *dev; - hdlc_device *hdlc; - - /* allocate and initialize network and HDLC layer objects */ - - if (!(dev = alloc_hdlcdev(info))) { - printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name); - return -ENOMEM; - } - - /* for network layer reporting purposes only */ - dev->mem_start = info->phys_reg_addr; - dev->mem_end = info->phys_reg_addr + SLGT_REG_SIZE - 1; - dev->irq = info->irq_level; - - /* network layer callbacks and settings */ - dev->netdev_ops = &hdlcdev_ops; - dev->watchdog_timeo = 10 * HZ; - dev->tx_queue_len = 50; - - /* generic HDLC layer callbacks and settings */ - hdlc = dev_to_hdlc(dev); - hdlc->attach = hdlcdev_attach; - hdlc->xmit = hdlcdev_xmit; - - /* register objects with HDLC layer */ - if ((rc = register_hdlc_device(dev))) { - printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); - free_netdev(dev); - return rc; - } - - info->netdev = dev; - return 0; -} - -/** - * called by device driver when removing device instance - * do generic HDLC cleanup - * - * info pointer to device instance information - */ -static void hdlcdev_exit(struct slgt_info *info) -{ - unregister_hdlc_device(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; -} - -#endif /* ifdef CONFIG_HDLC */ - -/* - * get async data from rx DMA buffers - */ -static void rx_async(struct slgt_info *info) -{ - struct tty_struct *tty = info->port.tty; - struct mgsl_icount *icount = &info->icount; - unsigned int start, end; - unsigned char *p; - unsigned char status; - struct slgt_desc *bufs = info->rbufs; - int i, count; - int chars = 0; - int stat; - unsigned char ch; - - start = end = info->rbuf_current; - - while(desc_complete(bufs[end])) { - count = desc_count(bufs[end]) - info->rbuf_index; - p = bufs[end].buf + info->rbuf_index; - - DBGISR(("%s rx_async count=%d\n", info->device_name, count)); - DBGDATA(info, p, count, "rx"); - - for(i=0 ; i < count; i+=2, p+=2) { - ch = *p; - icount->rx++; - - stat = 0; - - if ((status = *(p+1) & (BIT1 + BIT0))) { - if (status & BIT1) - icount->parity++; - else if (status & BIT0) - icount->frame++; - /* discard char if tty control flags say so */ - if (status & info->ignore_status_mask) - continue; - if (status & BIT1) - stat = TTY_PARITY; - else if (status & BIT0) - stat = TTY_FRAME; - } - if (tty) { - tty_insert_flip_char(tty, ch, stat); - chars++; - } - } - - if (i < count) { - /* receive buffer not completed */ - info->rbuf_index += i; - mod_timer(&info->rx_timer, jiffies + 1); - break; - } - - info->rbuf_index = 0; - free_rbufs(info, end, end); - - if (++end == info->rbuf_count) - end = 0; - - /* if entire list searched then no frame available */ - if (end == start) - break; - } - - if (tty && chars) - tty_flip_buffer_push(tty); -} - -/* - * return next bottom half action to perform - */ -static int bh_action(struct slgt_info *info) -{ - unsigned long flags; - int rc; - - spin_lock_irqsave(&info->lock,flags); - - if (info->pending_bh & BH_RECEIVE) { - info->pending_bh &= ~BH_RECEIVE; - rc = BH_RECEIVE; - } else if (info->pending_bh & BH_TRANSMIT) { - info->pending_bh &= ~BH_TRANSMIT; - rc = BH_TRANSMIT; - } else if (info->pending_bh & BH_STATUS) { - info->pending_bh &= ~BH_STATUS; - rc = BH_STATUS; - } else { - /* Mark BH routine as complete */ - info->bh_running = false; - info->bh_requested = false; - rc = 0; - } - - spin_unlock_irqrestore(&info->lock,flags); - - return rc; -} - -/* - * perform bottom half processing - */ -static void bh_handler(struct work_struct *work) -{ - struct slgt_info *info = container_of(work, struct slgt_info, task); - int action; - - if (!info) - return; - info->bh_running = true; - - while((action = bh_action(info))) { - switch (action) { - case BH_RECEIVE: - DBGBH(("%s bh receive\n", info->device_name)); - switch(info->params.mode) { - case MGSL_MODE_ASYNC: - rx_async(info); - break; - case MGSL_MODE_HDLC: - while(rx_get_frame(info)); - break; - case MGSL_MODE_RAW: - case MGSL_MODE_MONOSYNC: - case MGSL_MODE_BISYNC: - case MGSL_MODE_XSYNC: - while(rx_get_buf(info)); - break; - } - /* restart receiver if rx DMA buffers exhausted */ - if (info->rx_restart) - rx_start(info); - break; - case BH_TRANSMIT: - bh_transmit(info); - break; - case BH_STATUS: - DBGBH(("%s bh status\n", info->device_name)); - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - info->dcd_chkcount = 0; - info->cts_chkcount = 0; - break; - default: - DBGBH(("%s unknown action\n", info->device_name)); - break; - } - } - DBGBH(("%s bh_handler exit\n", info->device_name)); -} - -static void bh_transmit(struct slgt_info *info) -{ - struct tty_struct *tty = info->port.tty; - - DBGBH(("%s bh_transmit\n", info->device_name)); - if (tty) - tty_wakeup(tty); -} - -static void dsr_change(struct slgt_info *info, unsigned short status) -{ - if (status & BIT3) { - info->signals |= SerialSignal_DSR; - info->input_signal_events.dsr_up++; - } else { - info->signals &= ~SerialSignal_DSR; - info->input_signal_events.dsr_down++; - } - DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_DSR); - return; - } - info->icount.dsr++; - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; -} - -static void cts_change(struct slgt_info *info, unsigned short status) -{ - if (status & BIT2) { - info->signals |= SerialSignal_CTS; - info->input_signal_events.cts_up++; - } else { - info->signals &= ~SerialSignal_CTS; - info->input_signal_events.cts_down++; - } - DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_CTS); - return; - } - info->icount.cts++; - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; - - if (info->port.flags & ASYNC_CTS_FLOW) { - if (info->port.tty) { - if (info->port.tty->hw_stopped) { - if (info->signals & SerialSignal_CTS) { - info->port.tty->hw_stopped = 0; - info->pending_bh |= BH_TRANSMIT; - return; - } - } else { - if (!(info->signals & SerialSignal_CTS)) - info->port.tty->hw_stopped = 1; - } - } - } -} - -static void dcd_change(struct slgt_info *info, unsigned short status) -{ - if (status & BIT1) { - info->signals |= SerialSignal_DCD; - info->input_signal_events.dcd_up++; - } else { - info->signals &= ~SerialSignal_DCD; - info->input_signal_events.dcd_down++; - } - DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_DCD); - return; - } - info->icount.dcd++; -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) { - if (info->signals & SerialSignal_DCD) - netif_carrier_on(info->netdev); - else - netif_carrier_off(info->netdev); - } -#endif - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; - - if (info->port.flags & ASYNC_CHECK_CD) { - if (info->signals & SerialSignal_DCD) - wake_up_interruptible(&info->port.open_wait); - else { - if (info->port.tty) - tty_hangup(info->port.tty); - } - } -} - -static void ri_change(struct slgt_info *info, unsigned short status) -{ - if (status & BIT0) { - info->signals |= SerialSignal_RI; - info->input_signal_events.ri_up++; - } else { - info->signals &= ~SerialSignal_RI; - info->input_signal_events.ri_down++; - } - DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_RI); - return; - } - info->icount.rng++; - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; -} - -static void isr_rxdata(struct slgt_info *info) -{ - unsigned int count = info->rbuf_fill_count; - unsigned int i = info->rbuf_fill_index; - unsigned short reg; - - while (rd_reg16(info, SSR) & IRQ_RXDATA) { - reg = rd_reg16(info, RDR); - DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg)); - if (desc_complete(info->rbufs[i])) { - /* all buffers full */ - rx_stop(info); - info->rx_restart = 1; - continue; - } - info->rbufs[i].buf[count++] = (unsigned char)reg; - /* async mode saves status byte to buffer for each data byte */ - if (info->params.mode == MGSL_MODE_ASYNC) - info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8); - if (count == info->rbuf_fill_level || (reg & BIT10)) { - /* buffer full or end of frame */ - set_desc_count(info->rbufs[i], count); - set_desc_status(info->rbufs[i], BIT15 | (reg >> 8)); - info->rbuf_fill_count = count = 0; - if (++i == info->rbuf_count) - i = 0; - info->pending_bh |= BH_RECEIVE; - } - } - - info->rbuf_fill_index = i; - info->rbuf_fill_count = count; -} - -static void isr_serial(struct slgt_info *info) -{ - unsigned short status = rd_reg16(info, SSR); - - DBGISR(("%s isr_serial status=%04X\n", info->device_name, status)); - - wr_reg16(info, SSR, status); /* clear pending */ - - info->irq_occurred = true; - - if (info->params.mode == MGSL_MODE_ASYNC) { - if (status & IRQ_TXIDLE) { - if (info->tx_active) - isr_txeom(info, status); - } - if (info->rx_pio && (status & IRQ_RXDATA)) - isr_rxdata(info); - if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { - info->icount.brk++; - /* process break detection if tty control allows */ - if (info->port.tty) { - if (!(status & info->ignore_status_mask)) { - if (info->read_status_mask & MASK_BREAK) { - tty_insert_flip_char(info->port.tty, 0, TTY_BREAK); - if (info->port.flags & ASYNC_SAK) - do_SAK(info->port.tty); - } - } - } - } - } else { - if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) - isr_txeom(info, status); - if (info->rx_pio && (status & IRQ_RXDATA)) - isr_rxdata(info); - if (status & IRQ_RXIDLE) { - if (status & RXIDLE) - info->icount.rxidle++; - else - info->icount.exithunt++; - wake_up_interruptible(&info->event_wait_q); - } - - if (status & IRQ_RXOVER) - rx_start(info); - } - - if (status & IRQ_DSR) - dsr_change(info, status); - if (status & IRQ_CTS) - cts_change(info, status); - if (status & IRQ_DCD) - dcd_change(info, status); - if (status & IRQ_RI) - ri_change(info, status); -} - -static void isr_rdma(struct slgt_info *info) -{ - unsigned int status = rd_reg32(info, RDCSR); - - DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status)); - - /* RDCSR (rx DMA control/status) - * - * 31..07 reserved - * 06 save status byte to DMA buffer - * 05 error - * 04 eol (end of list) - * 03 eob (end of buffer) - * 02 IRQ enable - * 01 reset - * 00 enable - */ - wr_reg32(info, RDCSR, status); /* clear pending */ - - if (status & (BIT5 + BIT4)) { - DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name)); - info->rx_restart = true; - } - info->pending_bh |= BH_RECEIVE; -} - -static void isr_tdma(struct slgt_info *info) -{ - unsigned int status = rd_reg32(info, TDCSR); - - DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status)); - - /* TDCSR (tx DMA control/status) - * - * 31..06 reserved - * 05 error - * 04 eol (end of list) - * 03 eob (end of buffer) - * 02 IRQ enable - * 01 reset - * 00 enable - */ - wr_reg32(info, TDCSR, status); /* clear pending */ - - if (status & (BIT5 + BIT4 + BIT3)) { - // another transmit buffer has completed - // run bottom half to get more send data from user - info->pending_bh |= BH_TRANSMIT; - } -} - -/* - * return true if there are unsent tx DMA buffers, otherwise false - * - * if there are unsent buffers then info->tbuf_start - * is set to index of first unsent buffer - */ -static bool unsent_tbufs(struct slgt_info *info) -{ - unsigned int i = info->tbuf_current; - bool rc = false; - - /* - * search backwards from last loaded buffer (precedes tbuf_current) - * for first unsent buffer (desc_count > 0) - */ - - do { - if (i) - i--; - else - i = info->tbuf_count - 1; - if (!desc_count(info->tbufs[i])) - break; - info->tbuf_start = i; - rc = true; - } while (i != info->tbuf_current); - - return rc; -} - -static void isr_txeom(struct slgt_info *info, unsigned short status) -{ - DBGISR(("%s txeom status=%04x\n", info->device_name, status)); - - slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); - tdma_reset(info); - if (status & IRQ_TXUNDER) { - unsigned short val = rd_reg16(info, TCR); - wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, TCR, val); /* clear reset bit */ - } - - if (info->tx_active) { - if (info->params.mode != MGSL_MODE_ASYNC) { - if (status & IRQ_TXUNDER) - info->icount.txunder++; - else if (status & IRQ_TXIDLE) - info->icount.txok++; - } - - if (unsent_tbufs(info)) { - tx_start(info); - update_tx_timer(info); - return; - } - info->tx_active = false; - - del_timer(&info->tx_timer); - - if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) { - info->signals &= ~SerialSignal_RTS; - info->drop_rts_on_tx_done = false; - set_signals(info); - } - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - { - if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { - tx_stop(info); - return; - } - info->pending_bh |= BH_TRANSMIT; - } - } -} - -static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state) -{ - struct cond_wait *w, *prev; - - /* wake processes waiting for specific transitions */ - for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) { - if (w->data & changed) { - w->data = state; - wake_up_interruptible(&w->q); - if (prev != NULL) - prev->next = w->next; - else - info->gpio_wait_q = w->next; - } else - prev = w; - } -} - -/* interrupt service routine - * - * irq interrupt number - * dev_id device ID supplied during interrupt registration - */ -static irqreturn_t slgt_interrupt(int dummy, void *dev_id) -{ - struct slgt_info *info = dev_id; - unsigned int gsr; - unsigned int i; - - DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); - - while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { - DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); - info->irq_occurred = true; - for(i=0; i < info->port_count ; i++) { - if (info->port_array[i] == NULL) - continue; - spin_lock(&info->port_array[i]->lock); - if (gsr & (BIT8 << i)) - isr_serial(info->port_array[i]); - if (gsr & (BIT16 << (i*2))) - isr_rdma(info->port_array[i]); - if (gsr & (BIT17 << (i*2))) - isr_tdma(info->port_array[i]); - spin_unlock(&info->port_array[i]->lock); - } - } - - if (info->gpio_present) { - unsigned int state; - unsigned int changed; - spin_lock(&info->lock); - while ((changed = rd_reg32(info, IOSR)) != 0) { - DBGISR(("%s iosr=%08x\n", info->device_name, changed)); - /* read latched state of GPIO signals */ - state = rd_reg32(info, IOVR); - /* clear pending GPIO interrupt bits */ - wr_reg32(info, IOSR, changed); - for (i=0 ; i < info->port_count ; i++) { - if (info->port_array[i] != NULL) - isr_gpio(info->port_array[i], changed, state); - } - } - spin_unlock(&info->lock); - } - - for(i=0; i < info->port_count ; i++) { - struct slgt_info *port = info->port_array[i]; - if (port == NULL) - continue; - spin_lock(&port->lock); - if ((port->port.count || port->netcount) && - port->pending_bh && !port->bh_running && - !port->bh_requested) { - DBGISR(("%s bh queued\n", port->device_name)); - schedule_work(&port->task); - port->bh_requested = true; - } - spin_unlock(&port->lock); - } - - DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); - return IRQ_HANDLED; -} - -static int startup(struct slgt_info *info) -{ - DBGINFO(("%s startup\n", info->device_name)); - - if (info->port.flags & ASYNC_INITIALIZED) - return 0; - - if (!info->tx_buf) { - info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); - if (!info->tx_buf) { - DBGERR(("%s can't allocate tx buffer\n", info->device_name)); - return -ENOMEM; - } - } - - info->pending_bh = 0; - - memset(&info->icount, 0, sizeof(info->icount)); - - /* program hardware for current parameters */ - change_params(info); - - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags |= ASYNC_INITIALIZED; - - return 0; -} - -/* - * called by close() and hangup() to shutdown hardware - */ -static void shutdown(struct slgt_info *info) -{ - unsigned long flags; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - - DBGINFO(("%s shutdown\n", info->device_name)); - - /* clear status wait queue because status changes */ - /* can't happen after shutting down the hardware */ - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - - del_timer_sync(&info->tx_timer); - del_timer_sync(&info->rx_timer); - - kfree(info->tx_buf); - info->tx_buf = NULL; - - spin_lock_irqsave(&info->lock,flags); - - tx_stop(info); - rx_stop(info); - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - - if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { - info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - set_signals(info); - } - - flush_cond_wait(&info->gpio_wait_q); - - spin_unlock_irqrestore(&info->lock,flags); - - if (info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags &= ~ASYNC_INITIALIZED; -} - -static void program_hw(struct slgt_info *info) -{ - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - - rx_stop(info); - tx_stop(info); - - if (info->params.mode != MGSL_MODE_ASYNC || - info->netcount) - sync_mode(info); - else - async_mode(info); - - set_signals(info); - - info->dcd_chkcount = 0; - info->cts_chkcount = 0; - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - - slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI); - get_signals(info); - - if (info->netcount || - (info->port.tty && info->port.tty->termios->c_cflag & CREAD)) - rx_start(info); - - spin_unlock_irqrestore(&info->lock,flags); -} - -/* - * reconfigure adapter based on new parameters - */ -static void change_params(struct slgt_info *info) -{ - unsigned cflag; - int bits_per_char; - - if (!info->port.tty || !info->port.tty->termios) - return; - DBGINFO(("%s change_params\n", info->device_name)); - - cflag = info->port.tty->termios->c_cflag; - - /* if B0 rate (hangup) specified then negate DTR and RTS */ - /* otherwise assert DTR and RTS */ - if (cflag & CBAUD) - info->signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - - /* byte size and parity */ - - switch (cflag & CSIZE) { - case CS5: info->params.data_bits = 5; break; - case CS6: info->params.data_bits = 6; break; - case CS7: info->params.data_bits = 7; break; - case CS8: info->params.data_bits = 8; break; - default: info->params.data_bits = 7; break; - } - - info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1; - - if (cflag & PARENB) - info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN; - else - info->params.parity = ASYNC_PARITY_NONE; - - /* calculate number of jiffies to transmit a full - * FIFO (32 bytes) at specified data rate - */ - bits_per_char = info->params.data_bits + - info->params.stop_bits + 1; - - info->params.data_rate = tty_get_baud_rate(info->port.tty); - - if (info->params.data_rate) { - info->timeout = (32*HZ*bits_per_char) / - info->params.data_rate; - } - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - if (cflag & CRTSCTS) - info->port.flags |= ASYNC_CTS_FLOW; - else - info->port.flags &= ~ASYNC_CTS_FLOW; - - if (cflag & CLOCAL) - info->port.flags &= ~ASYNC_CHECK_CD; - else - info->port.flags |= ASYNC_CHECK_CD; - - /* process tty input control flags */ - - info->read_status_mask = IRQ_RXOVER; - if (I_INPCK(info->port.tty)) - info->read_status_mask |= MASK_PARITY | MASK_FRAMING; - if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) - info->read_status_mask |= MASK_BREAK; - if (I_IGNPAR(info->port.tty)) - info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING; - if (I_IGNBRK(info->port.tty)) { - info->ignore_status_mask |= MASK_BREAK; - /* If ignoring parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->port.tty)) - info->ignore_status_mask |= MASK_OVERRUN; - } - - program_hw(info); -} - -static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount) -{ - DBGINFO(("%s get_stats\n", info->device_name)); - if (!user_icount) { - memset(&info->icount, 0, sizeof(info->icount)); - } else { - if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount))) - return -EFAULT; - } - return 0; -} - -static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params) -{ - DBGINFO(("%s get_params\n", info->device_name)); - if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS))) - return -EFAULT; - return 0; -} - -static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params) -{ - unsigned long flags; - MGSL_PARAMS tmp_params; - - DBGINFO(("%s set_params\n", info->device_name)); - if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS))) - return -EFAULT; - - spin_lock_irqsave(&info->lock, flags); - if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) - info->base_clock = tmp_params.clock_speed; - else - memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS)); - spin_unlock_irqrestore(&info->lock, flags); - - program_hw(info); - - return 0; -} - -static int get_txidle(struct slgt_info *info, int __user *idle_mode) -{ - DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode)); - if (put_user(info->idle_mode, idle_mode)) - return -EFAULT; - return 0; -} - -static int set_txidle(struct slgt_info *info, int idle_mode) -{ - unsigned long flags; - DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); - spin_lock_irqsave(&info->lock,flags); - info->idle_mode = idle_mode; - if (info->params.mode != MGSL_MODE_ASYNC) - tx_set_idle(info); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int tx_enable(struct slgt_info *info, int enable) -{ - unsigned long flags; - DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable)); - spin_lock_irqsave(&info->lock,flags); - if (enable) { - if (!info->tx_enabled) - tx_start(info); - } else { - if (info->tx_enabled) - tx_stop(info); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* - * abort transmit HDLC frame - */ -static int tx_abort(struct slgt_info *info) -{ - unsigned long flags; - DBGINFO(("%s tx_abort\n", info->device_name)); - spin_lock_irqsave(&info->lock,flags); - tdma_reset(info); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int rx_enable(struct slgt_info *info, int enable) -{ - unsigned long flags; - unsigned int rbuf_fill_level; - DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable)); - spin_lock_irqsave(&info->lock,flags); - /* - * enable[31..16] = receive DMA buffer fill level - * 0 = noop (leave fill level unchanged) - * fill level must be multiple of 4 and <= buffer size - */ - rbuf_fill_level = ((unsigned int)enable) >> 16; - if (rbuf_fill_level) { - if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) { - spin_unlock_irqrestore(&info->lock, flags); - return -EINVAL; - } - info->rbuf_fill_level = rbuf_fill_level; - if (rbuf_fill_level < 128) - info->rx_pio = 1; /* PIO mode */ - else - info->rx_pio = 0; /* DMA mode */ - rx_stop(info); /* restart receiver to use new fill level */ - } - - /* - * enable[1..0] = receiver enable command - * 0 = disable - * 1 = enable - * 2 = enable or force hunt mode if already enabled - */ - enable &= 3; - if (enable) { - if (!info->rx_enabled) - rx_start(info); - else if (enable == 2) { - /* force hunt mode (write 1 to RCR[3]) */ - wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3); - } - } else { - if (info->rx_enabled) - rx_stop(info); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* - * wait for specified event to occur - */ -static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr) -{ - unsigned long flags; - int s; - int rc=0; - struct mgsl_icount cprev, cnow; - int events; - int mask; - struct _input_signal_events oldsigs, newsigs; - DECLARE_WAITQUEUE(wait, current); - - if (get_user(mask, mask_ptr)) - return -EFAULT; - - DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask)); - - spin_lock_irqsave(&info->lock,flags); - - /* return immediately if state matches requested events */ - get_signals(info); - s = info->signals; - - events = mask & - ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + - ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + - ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + - ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); - if (events) { - spin_unlock_irqrestore(&info->lock,flags); - goto exit; - } - - /* save current irq counts */ - cprev = info->icount; - oldsigs = info->input_signal_events; - - /* enable hunt and idle irqs if needed */ - if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) { - unsigned short val = rd_reg16(info, SCR); - if (!(val & IRQ_RXIDLE)) - wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE)); - } - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&info->event_wait_q, &wait); - - spin_unlock_irqrestore(&info->lock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get current irq counts */ - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - newsigs = info->input_signal_events; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - /* if no change, wait aborted for some reason */ - if (newsigs.dsr_up == oldsigs.dsr_up && - newsigs.dsr_down == oldsigs.dsr_down && - newsigs.dcd_up == oldsigs.dcd_up && - newsigs.dcd_down == oldsigs.dcd_down && - newsigs.cts_up == oldsigs.cts_up && - newsigs.cts_down == oldsigs.cts_down && - newsigs.ri_up == oldsigs.ri_up && - newsigs.ri_down == oldsigs.ri_down && - cnow.exithunt == cprev.exithunt && - cnow.rxidle == cprev.rxidle) { - rc = -EIO; - break; - } - - events = mask & - ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + - (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + - (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + - (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + - (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + - (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + - (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + - (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + - (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + - (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); - if (events) - break; - - cprev = cnow; - oldsigs = newsigs; - } - - remove_wait_queue(&info->event_wait_q, &wait); - set_current_state(TASK_RUNNING); - - - if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { - spin_lock_irqsave(&info->lock,flags); - if (!waitqueue_active(&info->event_wait_q)) { - /* disable enable exit hunt mode/idle rcvd IRQs */ - wr_reg16(info, SCR, - (unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE)); - } - spin_unlock_irqrestore(&info->lock,flags); - } -exit: - if (rc == 0) - rc = put_user(events, mask_ptr); - return rc; -} - -static int get_interface(struct slgt_info *info, int __user *if_mode) -{ - DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode)); - if (put_user(info->if_mode, if_mode)) - return -EFAULT; - return 0; -} - -static int set_interface(struct slgt_info *info, int if_mode) -{ - unsigned long flags; - unsigned short val; - - DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode)); - spin_lock_irqsave(&info->lock,flags); - info->if_mode = if_mode; - - msc_set_vcr(info); - - /* TCR (tx control) 07 1=RTS driver control */ - val = rd_reg16(info, TCR); - if (info->if_mode & MGSL_INTERFACE_RTS_EN) - val |= BIT7; - else - val &= ~BIT7; - wr_reg16(info, TCR, val); - - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int get_xsync(struct slgt_info *info, int __user *xsync) -{ - DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync)); - if (put_user(info->xsync, xsync)) - return -EFAULT; - return 0; -} - -/* - * set extended sync pattern (1 to 4 bytes) for extended sync mode - * - * sync pattern is contained in least significant bytes of value - * most significant byte of sync pattern is oldest (1st sent/detected) - */ -static int set_xsync(struct slgt_info *info, int xsync) -{ - unsigned long flags; - - DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync)); - spin_lock_irqsave(&info->lock, flags); - info->xsync = xsync; - wr_reg32(info, XSR, xsync); - spin_unlock_irqrestore(&info->lock, flags); - return 0; -} - -static int get_xctrl(struct slgt_info *info, int __user *xctrl) -{ - DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl)); - if (put_user(info->xctrl, xctrl)) - return -EFAULT; - return 0; -} - -/* - * set extended control options - * - * xctrl[31:19] reserved, must be zero - * xctrl[18:17] extended sync pattern length in bytes - * 00 = 1 byte in xsr[7:0] - * 01 = 2 bytes in xsr[15:0] - * 10 = 3 bytes in xsr[23:0] - * 11 = 4 bytes in xsr[31:0] - * xctrl[16] 1 = enable terminal count, 0=disabled - * xctrl[15:0] receive terminal count for fixed length packets - * value is count minus one (0 = 1 byte packet) - * when terminal count is reached, receiver - * automatically returns to hunt mode and receive - * FIFO contents are flushed to DMA buffers with - * end of frame (EOF) status - */ -static int set_xctrl(struct slgt_info *info, int xctrl) -{ - unsigned long flags; - - DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl)); - spin_lock_irqsave(&info->lock, flags); - info->xctrl = xctrl; - wr_reg32(info, XCR, xctrl); - spin_unlock_irqrestore(&info->lock, flags); - return 0; -} - -/* - * set general purpose IO pin state and direction - * - * user_gpio fields: - * state each bit indicates a pin state - * smask set bit indicates pin state to set - * dir each bit indicates a pin direction (0=input, 1=output) - * dmask set bit indicates pin direction to set - */ -static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) -{ - unsigned long flags; - struct gpio_desc gpio; - __u32 data; - - if (!info->gpio_present) - return -EINVAL; - if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) - return -EFAULT; - DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n", - info->device_name, gpio.state, gpio.smask, - gpio.dir, gpio.dmask)); - - spin_lock_irqsave(&info->port_array[0]->lock, flags); - if (gpio.dmask) { - data = rd_reg32(info, IODR); - data |= gpio.dmask & gpio.dir; - data &= ~(gpio.dmask & ~gpio.dir); - wr_reg32(info, IODR, data); - } - if (gpio.smask) { - data = rd_reg32(info, IOVR); - data |= gpio.smask & gpio.state; - data &= ~(gpio.smask & ~gpio.state); - wr_reg32(info, IOVR, data); - } - spin_unlock_irqrestore(&info->port_array[0]->lock, flags); - - return 0; -} - -/* - * get general purpose IO pin state and direction - */ -static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) -{ - struct gpio_desc gpio; - if (!info->gpio_present) - return -EINVAL; - gpio.state = rd_reg32(info, IOVR); - gpio.smask = 0xffffffff; - gpio.dir = rd_reg32(info, IODR); - gpio.dmask = 0xffffffff; - if (copy_to_user(user_gpio, &gpio, sizeof(gpio))) - return -EFAULT; - DBGINFO(("%s get_gpio state=%08x dir=%08x\n", - info->device_name, gpio.state, gpio.dir)); - return 0; -} - -/* - * conditional wait facility - */ -static void init_cond_wait(struct cond_wait *w, unsigned int data) -{ - init_waitqueue_head(&w->q); - init_waitqueue_entry(&w->wait, current); - w->data = data; -} - -static void add_cond_wait(struct cond_wait **head, struct cond_wait *w) -{ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&w->q, &w->wait); - w->next = *head; - *head = w; -} - -static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw) -{ - struct cond_wait *w, *prev; - remove_wait_queue(&cw->q, &cw->wait); - set_current_state(TASK_RUNNING); - for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) { - if (w == cw) { - if (prev != NULL) - prev->next = w->next; - else - *head = w->next; - break; - } - } -} - -static void flush_cond_wait(struct cond_wait **head) -{ - while (*head != NULL) { - wake_up_interruptible(&(*head)->q); - *head = (*head)->next; - } -} - -/* - * wait for general purpose I/O pin(s) to enter specified state - * - * user_gpio fields: - * state - bit indicates target pin state - * smask - set bit indicates watched pin - * - * The wait ends when at least one watched pin enters the specified - * state. When 0 (no error) is returned, user_gpio->state is set to the - * state of all GPIO pins when the wait ends. - * - * Note: Each pin may be a dedicated input, dedicated output, or - * configurable input/output. The number and configuration of pins - * varies with the specific adapter model. Only input pins (dedicated - * or configured) can be monitored with this function. - */ -static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) -{ - unsigned long flags; - int rc = 0; - struct gpio_desc gpio; - struct cond_wait wait; - u32 state; - - if (!info->gpio_present) - return -EINVAL; - if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) - return -EFAULT; - DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n", - info->device_name, gpio.state, gpio.smask)); - /* ignore output pins identified by set IODR bit */ - if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0) - return -EINVAL; - init_cond_wait(&wait, gpio.smask); - - spin_lock_irqsave(&info->port_array[0]->lock, flags); - /* enable interrupts for watched pins */ - wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); - /* get current pin states */ - state = rd_reg32(info, IOVR); - - if (gpio.smask & ~(state ^ gpio.state)) { - /* already in target state */ - gpio.state = state; - } else { - /* wait for target state */ - add_cond_wait(&info->gpio_wait_q, &wait); - spin_unlock_irqrestore(&info->port_array[0]->lock, flags); - schedule(); - if (signal_pending(current)) - rc = -ERESTARTSYS; - else - gpio.state = wait.data; - spin_lock_irqsave(&info->port_array[0]->lock, flags); - remove_cond_wait(&info->gpio_wait_q, &wait); - } - - /* disable all GPIO interrupts if no waiting processes */ - if (info->gpio_wait_q == NULL) - wr_reg32(info, IOER, 0); - spin_unlock_irqrestore(&info->port_array[0]->lock, flags); - - if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) - rc = -EFAULT; - return rc; -} - -static int modem_input_wait(struct slgt_info *info,int arg) -{ - unsigned long flags; - int rc; - struct mgsl_icount cprev, cnow; - DECLARE_WAITQUEUE(wait, current); - - /* save current irq counts */ - spin_lock_irqsave(&info->lock,flags); - cprev = info->icount; - add_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get new irq counts */ - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - /* if no change, wait aborted for some reason */ - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - rc = -EIO; - break; - } - - /* check for change in caller specified modem input */ - if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || - (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || - (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || - (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { - rc = 0; - break; - } - - cprev = cnow; - } - remove_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_RUNNING); - return rc; -} - -/* - * return state of serial control and status signals - */ -static int tiocmget(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned int result; - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) + - ((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) + - ((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) + - ((info->signals & SerialSignal_RI) ? TIOCM_RNG:0) + - ((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) + - ((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0); - - DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result)); - return result; -} - -/* - * set modem control signals (DTR/RTS) - * - * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit - * TIOCMSET = set/clear signal values - * value bit mask for command - */ -static int tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear)); - - if (set & TIOCM_RTS) - info->signals |= SerialSignal_RTS; - if (set & TIOCM_DTR) - info->signals |= SerialSignal_DTR; - if (clear & TIOCM_RTS) - info->signals &= ~SerialSignal_RTS; - if (clear & TIOCM_DTR) - info->signals &= ~SerialSignal_DTR; - - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int carrier_raised(struct tty_port *port) -{ - unsigned long flags; - struct slgt_info *info = container_of(port, struct slgt_info, port); - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - return (info->signals & SerialSignal_DCD) ? 1 : 0; -} - -static void dtr_rts(struct tty_port *port, int on) -{ - unsigned long flags; - struct slgt_info *info = container_of(port, struct slgt_info, port); - - spin_lock_irqsave(&info->lock,flags); - if (on) - info->signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); -} - - -/* - * block current process until the device is ready to open - */ -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct slgt_info *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - bool do_clocal = false; - bool extra_count = false; - unsigned long flags; - int cd; - struct tty_port *port = &info->port; - - DBGINFO(("%s block_til_ready\n", tty->driver->name)); - - if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ - /* nonblock mode is set or port is not enabled */ - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = true; - - /* Wait for carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, port->count is dropped by one, so that - * close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - - retval = 0; - add_wait_queue(&port->open_wait, &wait); - - spin_lock_irqsave(&info->lock, flags); - if (!tty_hung_up_p(filp)) { - extra_count = true; - port->count--; - } - spin_unlock_irqrestore(&info->lock, flags); - port->blocked_open++; - - while (1) { - if ((tty->termios->c_cflag & CBAUD)) - tty_port_raise_dtr_rts(port); - - set_current_state(TASK_INTERRUPTIBLE); - - if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ - retval = (port->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - break; - } - - cd = tty_port_carrier_raised(port); - - if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd )) - break; - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); - tty_unlock(); - schedule(); - tty_lock(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - - if (extra_count) - port->count++; - port->blocked_open--; - - if (!retval) - port->flags |= ASYNC_NORMAL_ACTIVE; - - DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); - return retval; -} - -static int alloc_tmp_rbuf(struct slgt_info *info) -{ - info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL); - if (info->tmp_rbuf == NULL) - return -ENOMEM; - return 0; -} - -static void free_tmp_rbuf(struct slgt_info *info) -{ - kfree(info->tmp_rbuf); - info->tmp_rbuf = NULL; -} - -/* - * allocate DMA descriptor lists. - */ -static int alloc_desc(struct slgt_info *info) -{ - unsigned int i; - unsigned int pbufs; - - /* allocate memory to hold descriptor lists */ - info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr); - if (info->bufs == NULL) - return -ENOMEM; - - memset(info->bufs, 0, DESC_LIST_SIZE); - - info->rbufs = (struct slgt_desc*)info->bufs; - info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count; - - pbufs = (unsigned int)info->bufs_dma_addr; - - /* - * Build circular lists of descriptors - */ - - for (i=0; i < info->rbuf_count; i++) { - /* physical address of this descriptor */ - info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc)); - - /* physical address of next descriptor */ - if (i == info->rbuf_count - 1) - info->rbufs[i].next = cpu_to_le32(pbufs); - else - info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc))); - set_desc_count(info->rbufs[i], DMABUFSIZE); - } - - for (i=0; i < info->tbuf_count; i++) { - /* physical address of this descriptor */ - info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc)); - - /* physical address of next descriptor */ - if (i == info->tbuf_count - 1) - info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc)); - else - info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc))); - } - - return 0; -} - -static void free_desc(struct slgt_info *info) -{ - if (info->bufs != NULL) { - pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr); - info->bufs = NULL; - info->rbufs = NULL; - info->tbufs = NULL; - } -} - -static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) -{ - int i; - for (i=0; i < count; i++) { - if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL) - return -ENOMEM; - bufs[i].pbuf = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr); - } - return 0; -} - -static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) -{ - int i; - for (i=0; i < count; i++) { - if (bufs[i].buf == NULL) - continue; - pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr); - bufs[i].buf = NULL; - } -} - -static int alloc_dma_bufs(struct slgt_info *info) -{ - info->rbuf_count = 32; - info->tbuf_count = 32; - - if (alloc_desc(info) < 0 || - alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 || - alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 || - alloc_tmp_rbuf(info) < 0) { - DBGERR(("%s DMA buffer alloc fail\n", info->device_name)); - return -ENOMEM; - } - reset_rbufs(info); - return 0; -} - -static void free_dma_bufs(struct slgt_info *info) -{ - if (info->bufs) { - free_bufs(info, info->rbufs, info->rbuf_count); - free_bufs(info, info->tbufs, info->tbuf_count); - free_desc(info); - } - free_tmp_rbuf(info); -} - -static int claim_resources(struct slgt_info *info) -{ - if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) { - DBGERR(("%s reg addr conflict, addr=%08X\n", - info->device_name, info->phys_reg_addr)); - info->init_error = DiagStatus_AddressConflict; - goto errout; - } - else - info->reg_addr_requested = true; - - info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE); - if (!info->reg_addr) { - DBGERR(("%s cant map device registers, addr=%08X\n", - info->device_name, info->phys_reg_addr)); - info->init_error = DiagStatus_CantAssignPciResources; - goto errout; - } - return 0; - -errout: - release_resources(info); - return -ENODEV; -} - -static void release_resources(struct slgt_info *info) -{ - if (info->irq_requested) { - free_irq(info->irq_level, info); - info->irq_requested = false; - } - - if (info->reg_addr_requested) { - release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE); - info->reg_addr_requested = false; - } - - if (info->reg_addr) { - iounmap(info->reg_addr); - info->reg_addr = NULL; - } -} - -/* Add the specified device instance data structure to the - * global linked list of devices and increment the device count. - */ -static void add_device(struct slgt_info *info) -{ - char *devstr; - - info->next_device = NULL; - info->line = slgt_device_count; - sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line); - - if (info->line < MAX_DEVICES) { - if (maxframe[info->line]) - info->max_frame_size = maxframe[info->line]; - } - - slgt_device_count++; - - if (!slgt_device_list) - slgt_device_list = info; - else { - struct slgt_info *current_dev = slgt_device_list; - while(current_dev->next_device) - current_dev = current_dev->next_device; - current_dev->next_device = info; - } - - if (info->max_frame_size < 4096) - info->max_frame_size = 4096; - else if (info->max_frame_size > 65535) - info->max_frame_size = 65535; - - switch(info->pdev->device) { - case SYNCLINK_GT_DEVICE_ID: - devstr = "GT"; - break; - case SYNCLINK_GT2_DEVICE_ID: - devstr = "GT2"; - break; - case SYNCLINK_GT4_DEVICE_ID: - devstr = "GT4"; - break; - case SYNCLINK_AC_DEVICE_ID: - devstr = "AC"; - info->params.mode = MGSL_MODE_ASYNC; - break; - default: - devstr = "(unknown model)"; - } - printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n", - devstr, info->device_name, info->phys_reg_addr, - info->irq_level, info->max_frame_size); - -#if SYNCLINK_GENERIC_HDLC - hdlcdev_init(info); -#endif -} - -static const struct tty_port_operations slgt_port_ops = { - .carrier_raised = carrier_raised, - .dtr_rts = dtr_rts, -}; - -/* - * allocate device instance structure, return NULL on failure - */ -static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) -{ - struct slgt_info *info; - - info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL); - - if (!info) { - DBGERR(("%s device alloc failed adapter=%d port=%d\n", - driver_name, adapter_num, port_num)); - } else { - tty_port_init(&info->port); - info->port.ops = &slgt_port_ops; - info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler); - info->max_frame_size = 4096; - info->base_clock = 14745600; - info->rbuf_fill_level = DMABUFSIZE; - info->port.close_delay = 5*HZ/10; - info->port.closing_wait = 30*HZ; - init_waitqueue_head(&info->status_event_wait_q); - init_waitqueue_head(&info->event_wait_q); - spin_lock_init(&info->netlock); - memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - info->idle_mode = HDLC_TXIDLE_FLAGS; - info->adapter_num = adapter_num; - info->port_num = port_num; - - 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; - info->irq_level = pdev->irq; - info->phys_reg_addr = pci_resource_start(pdev,0); - - info->bus_type = MGSL_BUS_TYPE_PCI; - info->irq_flags = IRQF_SHARED; - - info->init_error = -1; /* assume error, set to 0 on successful init */ - } - - return info; -} - -static void device_init(int adapter_num, struct pci_dev *pdev) -{ - struct slgt_info *port_array[SLGT_MAX_PORTS]; - int i; - int port_count = 1; - - if (pdev->device == SYNCLINK_GT2_DEVICE_ID) - port_count = 2; - else if (pdev->device == SYNCLINK_GT4_DEVICE_ID) - port_count = 4; - - /* allocate device instances for all ports */ - for (i=0; i < port_count; ++i) { - port_array[i] = alloc_dev(adapter_num, i, pdev); - if (port_array[i] == NULL) { - for (--i; i >= 0; --i) - kfree(port_array[i]); - return; - } - } - - /* give copy of port_array to all ports and add to device list */ - for (i=0; i < port_count; ++i) { - memcpy(port_array[i]->port_array, port_array, sizeof(port_array)); - add_device(port_array[i]); - port_array[i]->port_count = port_count; - spin_lock_init(&port_array[i]->lock); - } - - /* Allocate and claim adapter resources */ - if (!claim_resources(port_array[0])) { - - alloc_dma_bufs(port_array[0]); - - /* copy resource information from first port to others */ - for (i = 1; i < port_count; ++i) { - port_array[i]->irq_level = port_array[0]->irq_level; - port_array[i]->reg_addr = port_array[0]->reg_addr; - alloc_dma_bufs(port_array[i]); - } - - if (request_irq(port_array[0]->irq_level, - slgt_interrupt, - port_array[0]->irq_flags, - port_array[0]->device_name, - port_array[0]) < 0) { - DBGERR(("%s request_irq failed IRQ=%d\n", - port_array[0]->device_name, - port_array[0]->irq_level)); - } else { - port_array[0]->irq_requested = true; - adapter_test(port_array[0]); - for (i=1 ; i < port_count ; i++) { - port_array[i]->init_error = port_array[0]->init_error; - port_array[i]->gpio_present = port_array[0]->gpio_present; - } - } - } - - for (i=0; i < port_count; ++i) - tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev)); -} - -static int __devinit init_one(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - if (pci_enable_device(dev)) { - printk("error enabling pci device %p\n", dev); - return -EIO; - } - pci_set_master(dev); - device_init(slgt_device_count, dev); - return 0; -} - -static void __devexit remove_one(struct pci_dev *dev) -{ -} - -static const struct tty_operations ops = { - .open = open, - .close = close, - .write = write, - .put_char = put_char, - .flush_chars = flush_chars, - .write_room = write_room, - .chars_in_buffer = chars_in_buffer, - .flush_buffer = flush_buffer, - .ioctl = ioctl, - .compat_ioctl = slgt_compat_ioctl, - .throttle = throttle, - .unthrottle = unthrottle, - .send_xchar = send_xchar, - .break_ctl = set_break, - .wait_until_sent = wait_until_sent, - .set_termios = set_termios, - .stop = tx_hold, - .start = tx_release, - .hangup = hangup, - .tiocmget = tiocmget, - .tiocmset = tiocmset, - .get_icount = get_icount, - .proc_fops = &synclink_gt_proc_fops, -}; - -static void slgt_cleanup(void) -{ - int rc; - struct slgt_info *info; - struct slgt_info *tmp; - - printk(KERN_INFO "unload %s\n", driver_name); - - if (serial_driver) { - for (info=slgt_device_list ; info != NULL ; info=info->next_device) - tty_unregister_device(serial_driver, info->line); - if ((rc = tty_unregister_driver(serial_driver))) - DBGERR(("tty_unregister_driver error=%d\n", rc)); - put_tty_driver(serial_driver); - } - - /* reset devices */ - info = slgt_device_list; - while(info) { - reset_port(info); - info = info->next_device; - } - - /* release devices */ - info = slgt_device_list; - while(info) { -#if SYNCLINK_GENERIC_HDLC - hdlcdev_exit(info); -#endif - free_dma_bufs(info); - free_tmp_rbuf(info); - if (info->port_num == 0) - release_resources(info); - tmp = info; - info = info->next_device; - kfree(tmp); - } - - if (pci_registered) - pci_unregister_driver(&pci_driver); -} - -/* - * Driver initialization entry point. - */ -static int __init slgt_init(void) -{ - int rc; - - printk(KERN_INFO "%s\n", driver_name); - - serial_driver = alloc_tty_driver(MAX_DEVICES); - if (!serial_driver) { - printk("%s can't allocate tty driver\n", driver_name); - return -ENOMEM; - } - - /* Initialize the tty_driver structure */ - - serial_driver->owner = THIS_MODULE; - serial_driver->driver_name = tty_driver_name; - serial_driver->name = tty_dev_prefix; - serial_driver->major = ttymajor; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->init_termios.c_ispeed = 9600; - serial_driver->init_termios.c_ospeed = 9600; - serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - tty_set_operations(serial_driver, &ops); - if ((rc = tty_register_driver(serial_driver)) < 0) { - DBGERR(("%s can't register serial driver\n", driver_name)); - put_tty_driver(serial_driver); - serial_driver = NULL; - goto error; - } - - printk(KERN_INFO "%s, tty major#%d\n", - driver_name, serial_driver->major); - - slgt_device_count = 0; - if ((rc = pci_register_driver(&pci_driver)) < 0) { - printk("%s pci_register_driver error=%d\n", driver_name, rc); - goto error; - } - pci_registered = true; - - if (!slgt_device_list) - printk("%s no devices found\n",driver_name); - - return 0; - -error: - slgt_cleanup(); - return rc; -} - -static void __exit slgt_exit(void) -{ - slgt_cleanup(); -} - -module_init(slgt_init); -module_exit(slgt_exit); - -/* - * register access routines - */ - -#define CALC_REGADDR() \ - unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ - if (addr >= 0x80) \ - reg_addr += (info->port_num) * 32; \ - else if (addr >= 0x40) \ - reg_addr += (info->port_num) * 16; - -static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) -{ - CALC_REGADDR(); - return readb((void __iomem *)reg_addr); -} - -static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value) -{ - CALC_REGADDR(); - writeb(value, (void __iomem *)reg_addr); -} - -static __u16 rd_reg16(struct slgt_info *info, unsigned int addr) -{ - CALC_REGADDR(); - return readw((void __iomem *)reg_addr); -} - -static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value) -{ - CALC_REGADDR(); - writew(value, (void __iomem *)reg_addr); -} - -static __u32 rd_reg32(struct slgt_info *info, unsigned int addr) -{ - CALC_REGADDR(); - return readl((void __iomem *)reg_addr); -} - -static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value) -{ - CALC_REGADDR(); - writel(value, (void __iomem *)reg_addr); -} - -static void rdma_reset(struct slgt_info *info) -{ - unsigned int i; - - /* set reset bit */ - wr_reg32(info, RDCSR, BIT1); - - /* wait for enable bit cleared */ - for(i=0 ; i < 1000 ; i++) - if (!(rd_reg32(info, RDCSR) & BIT0)) - break; -} - -static void tdma_reset(struct slgt_info *info) -{ - unsigned int i; - - /* set reset bit */ - wr_reg32(info, TDCSR, BIT1); - - /* wait for enable bit cleared */ - for(i=0 ; i < 1000 ; i++) - if (!(rd_reg32(info, TDCSR) & BIT0)) - break; -} - -/* - * enable internal loopback - * TxCLK and RxCLK are generated from BRG - * and TxD is looped back to RxD internally. - */ -static void enable_loopback(struct slgt_info *info) -{ - /* SCR (serial control) BIT2=looopback enable */ - wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2)); - - if (info->params.mode != MGSL_MODE_ASYNC) { - /* CCR (clock control) - * 07..05 tx clock source (010 = BRG) - * 04..02 rx clock source (010 = BRG) - * 01 auxclk enable (0 = disable) - * 00 BRG enable (1 = enable) - * - * 0100 1001 - */ - wr_reg8(info, CCR, 0x49); - - /* set speed if available, otherwise use default */ - if (info->params.clock_speed) - set_rate(info, info->params.clock_speed); - else - set_rate(info, 3686400); - } -} - -/* - * set baud rate generator to specified rate - */ -static void set_rate(struct slgt_info *info, u32 rate) -{ - unsigned int div; - unsigned int osc = info->base_clock; - - /* div = osc/rate - 1 - * - * Round div up if osc/rate is not integer to - * force to next slowest rate. - */ - - if (rate) { - div = osc/rate; - if (!(osc % rate) && div) - div--; - wr_reg16(info, BDR, (unsigned short)div); - } -} - -static void rx_stop(struct slgt_info *info) -{ - unsigned short val; - - /* disable and reset receiver */ - val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ - wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, RCR, val); /* clear reset bit */ - - slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE); - - /* clear pending rx interrupts */ - wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER); - - rdma_reset(info); - - info->rx_enabled = false; - info->rx_restart = false; -} - -static void rx_start(struct slgt_info *info) -{ - unsigned short val; - - slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA); - - /* clear pending rx overrun IRQ */ - wr_reg16(info, SSR, IRQ_RXOVER); - - /* reset and disable receiver */ - val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ - wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, RCR, val); /* clear reset bit */ - - rdma_reset(info); - reset_rbufs(info); - - if (info->rx_pio) { - /* rx request when rx FIFO not empty */ - wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14)); - slgt_irq_on(info, IRQ_RXDATA); - if (info->params.mode == MGSL_MODE_ASYNC) { - /* enable saving of rx status */ - wr_reg32(info, RDCSR, BIT6); - } - } else { - /* rx request when rx FIFO half full */ - wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14)); - /* set 1st descriptor address */ - wr_reg32(info, RDDAR, info->rbufs[0].pdesc); - - if (info->params.mode != MGSL_MODE_ASYNC) { - /* enable rx DMA and DMA interrupt */ - wr_reg32(info, RDCSR, (BIT2 + BIT0)); - } else { - /* enable saving of rx status, rx DMA and DMA interrupt */ - wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); - } - } - - slgt_irq_on(info, IRQ_RXOVER); - - /* enable receiver */ - wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1)); - - info->rx_restart = false; - info->rx_enabled = true; -} - -static void tx_start(struct slgt_info *info) -{ - if (!info->tx_enabled) { - wr_reg16(info, TCR, - (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2)); - info->tx_enabled = true; - } - - if (desc_count(info->tbufs[info->tbuf_start])) { - info->drop_rts_on_tx_done = false; - - if (info->params.mode != MGSL_MODE_ASYNC) { - if (info->params.flags & HDLC_FLAG_AUTO_RTS) { - get_signals(info); - if (!(info->signals & SerialSignal_RTS)) { - info->signals |= SerialSignal_RTS; - set_signals(info); - info->drop_rts_on_tx_done = true; - } - } - - slgt_irq_off(info, IRQ_TXDATA); - slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); - /* clear tx idle and underrun status bits */ - wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); - } else { - slgt_irq_off(info, IRQ_TXDATA); - slgt_irq_on(info, IRQ_TXIDLE); - /* clear tx idle status bit */ - wr_reg16(info, SSR, IRQ_TXIDLE); - } - /* set 1st descriptor address and start DMA */ - wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - wr_reg32(info, TDCSR, BIT2 + BIT0); - info->tx_active = true; - } -} - -static void tx_stop(struct slgt_info *info) -{ - unsigned short val; - - del_timer(&info->tx_timer); - - tdma_reset(info); - - /* reset and disable transmitter */ - val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */ - wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ - - slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); - - /* clear tx idle and underrun status bit */ - wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); - - reset_tbufs(info); - - info->tx_enabled = false; - info->tx_active = false; -} - -static void reset_port(struct slgt_info *info) -{ - if (!info->reg_addr) - return; - - tx_stop(info); - rx_stop(info); - - info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - set_signals(info); - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); -} - -static void reset_adapter(struct slgt_info *info) -{ - int i; - for (i=0; i < info->port_count; ++i) { - if (info->port_array[i]) - reset_port(info->port_array[i]); - } -} - -static void async_mode(struct slgt_info *info) -{ - unsigned short val; - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - tx_stop(info); - rx_stop(info); - - /* TCR (tx control) - * - * 15..13 mode, 010=async - * 12..10 encoding, 000=NRZ - * 09 parity enable - * 08 1=odd parity, 0=even parity - * 07 1=RTS driver control - * 06 1=break enable - * 05..04 character length - * 00=5 bits - * 01=6 bits - * 10=7 bits - * 11=8 bits - * 03 0=1 stop bit, 1=2 stop bits - * 02 reset - * 01 enable - * 00 auto-CTS enable - */ - val = 0x4000; - - if (info->if_mode & MGSL_INTERFACE_RTS_EN) - val |= BIT7; - - if (info->params.parity != ASYNC_PARITY_NONE) { - val |= BIT9; - if (info->params.parity == ASYNC_PARITY_ODD) - val |= BIT8; - } - - switch (info->params.data_bits) - { - case 6: val |= BIT4; break; - case 7: val |= BIT5; break; - case 8: val |= BIT5 + BIT4; break; - } - - if (info->params.stop_bits != 1) - val |= BIT3; - - if (info->params.flags & HDLC_FLAG_AUTO_CTS) - val |= BIT0; - - wr_reg16(info, TCR, val); - - /* RCR (rx control) - * - * 15..13 mode, 010=async - * 12..10 encoding, 000=NRZ - * 09 parity enable - * 08 1=odd parity, 0=even parity - * 07..06 reserved, must be 0 - * 05..04 character length - * 00=5 bits - * 01=6 bits - * 10=7 bits - * 11=8 bits - * 03 reserved, must be zero - * 02 reset - * 01 enable - * 00 auto-DCD enable - */ - val = 0x4000; - - if (info->params.parity != ASYNC_PARITY_NONE) { - val |= BIT9; - if (info->params.parity == ASYNC_PARITY_ODD) - val |= BIT8; - } - - switch (info->params.data_bits) - { - case 6: val |= BIT4; break; - case 7: val |= BIT5; break; - case 8: val |= BIT5 + BIT4; break; - } - - if (info->params.flags & HDLC_FLAG_AUTO_DCD) - val |= BIT0; - - wr_reg16(info, RCR, val); - - /* CCR (clock control) - * - * 07..05 011 = tx clock source is BRG/16 - * 04..02 010 = rx clock source is BRG - * 01 0 = auxclk disabled - * 00 1 = BRG enabled - * - * 0110 1001 - */ - wr_reg8(info, CCR, 0x69); - - msc_set_vcr(info); - - /* SCR (serial control) - * - * 15 1=tx req on FIFO half empty - * 14 1=rx req on FIFO half full - * 13 tx data IRQ enable - * 12 tx idle IRQ enable - * 11 rx break on IRQ enable - * 10 rx data IRQ enable - * 09 rx break off IRQ enable - * 08 overrun IRQ enable - * 07 DSR IRQ enable - * 06 CTS IRQ enable - * 05 DCD IRQ enable - * 04 RI IRQ enable - * 03 0=16x sampling, 1=8x sampling - * 02 1=txd->rxd internal loopback enable - * 01 reserved, must be zero - * 00 1=master IRQ enable - */ - val = BIT15 + BIT14 + BIT0; - /* JCR[8] : 1 = x8 async mode feature available */ - if ((rd_reg32(info, JCR) & BIT8) && info->params.data_rate && - ((info->base_clock < (info->params.data_rate * 16)) || - (info->base_clock % (info->params.data_rate * 16)))) { - /* use 8x sampling */ - val |= BIT3; - set_rate(info, info->params.data_rate * 8); - } else { - /* use 16x sampling */ - set_rate(info, info->params.data_rate * 16); - } - wr_reg16(info, SCR, val); - - slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER); - - if (info->params.loopback) - enable_loopback(info); -} - -static void sync_mode(struct slgt_info *info) -{ - unsigned short val; - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - tx_stop(info); - rx_stop(info); - - /* TCR (tx control) - * - * 15..13 mode - * 000=HDLC/SDLC - * 001=raw bit synchronous - * 010=asynchronous/isochronous - * 011=monosync byte synchronous - * 100=bisync byte synchronous - * 101=xsync byte synchronous - * 12..10 encoding - * 09 CRC enable - * 08 CRC32 - * 07 1=RTS driver control - * 06 preamble enable - * 05..04 preamble length - * 03 share open/close flag - * 02 reset - * 01 enable - * 00 auto-CTS enable - */ - val = BIT2; - - switch(info->params.mode) { - case MGSL_MODE_XSYNC: - val |= BIT15 + BIT13; - break; - case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; - case MGSL_MODE_BISYNC: val |= BIT15; break; - case MGSL_MODE_RAW: val |= BIT13; break; - } - if (info->if_mode & MGSL_INTERFACE_RTS_EN) - val |= BIT7; - - switch(info->params.encoding) - { - case HDLC_ENCODING_NRZB: val |= BIT10; break; - case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; - case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; - case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; - case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; - case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; - } - - switch (info->params.crc_type & HDLC_CRC_MASK) - { - case HDLC_CRC_16_CCITT: val |= BIT9; break; - case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; - } - - if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) - val |= BIT6; - - switch (info->params.preamble_length) - { - case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break; - case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break; - case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break; - } - - if (info->params.flags & HDLC_FLAG_AUTO_CTS) - val |= BIT0; - - wr_reg16(info, TCR, val); - - /* TPR (transmit preamble) */ - - switch (info->params.preamble) - { - case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break; - case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break; - case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break; - case HDLC_PREAMBLE_PATTERN_10: val = 0x55; break; - case HDLC_PREAMBLE_PATTERN_01: val = 0xaa; break; - default: val = 0x7e; break; - } - wr_reg8(info, TPR, (unsigned char)val); - - /* RCR (rx control) - * - * 15..13 mode - * 000=HDLC/SDLC - * 001=raw bit synchronous - * 010=asynchronous/isochronous - * 011=monosync byte synchronous - * 100=bisync byte synchronous - * 101=xsync byte synchronous - * 12..10 encoding - * 09 CRC enable - * 08 CRC32 - * 07..03 reserved, must be 0 - * 02 reset - * 01 enable - * 00 auto-DCD enable - */ - val = 0; - - switch(info->params.mode) { - case MGSL_MODE_XSYNC: - val |= BIT15 + BIT13; - break; - case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; - case MGSL_MODE_BISYNC: val |= BIT15; break; - case MGSL_MODE_RAW: val |= BIT13; break; - } - - switch(info->params.encoding) - { - case HDLC_ENCODING_NRZB: val |= BIT10; break; - case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; - case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; - case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; - case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; - case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; - } - - switch (info->params.crc_type & HDLC_CRC_MASK) - { - case HDLC_CRC_16_CCITT: val |= BIT9; break; - case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; - } - - if (info->params.flags & HDLC_FLAG_AUTO_DCD) - val |= BIT0; - - wr_reg16(info, RCR, val); - - /* CCR (clock control) - * - * 07..05 tx clock source - * 04..02 rx clock source - * 01 auxclk enable - * 00 BRG enable - */ - val = 0; - - if (info->params.flags & HDLC_FLAG_TXC_BRG) - { - // when RxC source is DPLL, BRG generates 16X DPLL - // reference clock, so take TxC from BRG/16 to get - // transmit clock at actual data rate - if (info->params.flags & HDLC_FLAG_RXC_DPLL) - val |= BIT6 + BIT5; /* 011, txclk = BRG/16 */ - else - val |= BIT6; /* 010, txclk = BRG */ - } - else if (info->params.flags & HDLC_FLAG_TXC_DPLL) - val |= BIT7; /* 100, txclk = DPLL Input */ - else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN) - val |= BIT5; /* 001, txclk = RXC Input */ - - if (info->params.flags & HDLC_FLAG_RXC_BRG) - val |= BIT3; /* 010, rxclk = BRG */ - else if (info->params.flags & HDLC_FLAG_RXC_DPLL) - val |= BIT4; /* 100, rxclk = DPLL */ - else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN) - val |= BIT2; /* 001, rxclk = TXC Input */ - - if (info->params.clock_speed) - val |= BIT1 + BIT0; - - wr_reg8(info, CCR, (unsigned char)val); - - if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL)) - { - // program DPLL mode - switch(info->params.encoding) - { - case HDLC_ENCODING_BIPHASE_MARK: - case HDLC_ENCODING_BIPHASE_SPACE: - val = BIT7; break; - case HDLC_ENCODING_BIPHASE_LEVEL: - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: - val = BIT7 + BIT6; break; - default: val = BIT6; // NRZ encodings - } - wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val)); - - // DPLL requires a 16X reference clock from BRG - set_rate(info, info->params.clock_speed * 16); - } - else - set_rate(info, info->params.clock_speed); - - tx_set_idle(info); - - msc_set_vcr(info); - - /* SCR (serial control) - * - * 15 1=tx req on FIFO half empty - * 14 1=rx req on FIFO half full - * 13 tx data IRQ enable - * 12 tx idle IRQ enable - * 11 underrun IRQ enable - * 10 rx data IRQ enable - * 09 rx idle IRQ enable - * 08 overrun IRQ enable - * 07 DSR IRQ enable - * 06 CTS IRQ enable - * 05 DCD IRQ enable - * 04 RI IRQ enable - * 03 reserved, must be zero - * 02 1=txd->rxd internal loopback enable - * 01 reserved, must be zero - * 00 1=master IRQ enable - */ - wr_reg16(info, SCR, BIT15 + BIT14 + BIT0); - - if (info->params.loopback) - enable_loopback(info); -} - -/* - * set transmit idle mode - */ -static void tx_set_idle(struct slgt_info *info) -{ - unsigned char val; - unsigned short tcr; - - /* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits - * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits - */ - tcr = rd_reg16(info, TCR); - if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) { - /* disable preamble, set idle size to 16 bits */ - tcr = (tcr & ~(BIT6 + BIT5)) | BIT4; - /* MSB of 16 bit idle specified in tx preamble register (TPR) */ - wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff)); - } else if (!(tcr & BIT6)) { - /* preamble is disabled, set idle size to 8 bits */ - tcr &= ~(BIT5 + BIT4); - } - wr_reg16(info, TCR, tcr); - - if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) { - /* LSB of custom tx idle specified in tx idle register */ - val = (unsigned char)(info->idle_mode & 0xff); - } else { - /* standard 8 bit idle patterns */ - switch(info->idle_mode) - { - case HDLC_TXIDLE_FLAGS: val = 0x7e; break; - case HDLC_TXIDLE_ALT_ZEROS_ONES: - case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; - case HDLC_TXIDLE_ZEROS: - case HDLC_TXIDLE_SPACE: val = 0x00; break; - default: val = 0xff; - } - } - - wr_reg8(info, TIR, val); -} - -/* - * get state of V24 status (input) signals - */ -static void get_signals(struct slgt_info *info) -{ - unsigned short status = rd_reg16(info, SSR); - - /* clear all serial signals except DTR and RTS */ - info->signals &= SerialSignal_DTR + SerialSignal_RTS; - - if (status & BIT3) - info->signals |= SerialSignal_DSR; - if (status & BIT2) - info->signals |= SerialSignal_CTS; - if (status & BIT1) - info->signals |= SerialSignal_DCD; - if (status & BIT0) - info->signals |= SerialSignal_RI; -} - -/* - * set V.24 Control Register based on current configuration - */ -static void msc_set_vcr(struct slgt_info *info) -{ - unsigned char val = 0; - - /* VCR (V.24 control) - * - * 07..04 serial IF select - * 03 DTR - * 02 RTS - * 01 LL - * 00 RL - */ - - switch(info->if_mode & MGSL_INTERFACE_MASK) - { - case MGSL_INTERFACE_RS232: - val |= BIT5; /* 0010 */ - break; - case MGSL_INTERFACE_V35: - val |= BIT7 + BIT6 + BIT5; /* 1110 */ - break; - case MGSL_INTERFACE_RS422: - val |= BIT6; /* 0100 */ - break; - } - - if (info->if_mode & MGSL_INTERFACE_MSB_FIRST) - val |= BIT4; - if (info->signals & SerialSignal_DTR) - val |= BIT3; - if (info->signals & SerialSignal_RTS) - val |= BIT2; - if (info->if_mode & MGSL_INTERFACE_LL) - val |= BIT1; - if (info->if_mode & MGSL_INTERFACE_RL) - val |= BIT0; - wr_reg8(info, VCR, val); -} - -/* - * set state of V24 control (output) signals - */ -static void set_signals(struct slgt_info *info) -{ - unsigned char val = rd_reg8(info, VCR); - if (info->signals & SerialSignal_DTR) - val |= BIT3; - else - val &= ~BIT3; - if (info->signals & SerialSignal_RTS) - val |= BIT2; - else - val &= ~BIT2; - wr_reg8(info, VCR, val); -} - -/* - * free range of receive DMA buffers (i to last) - */ -static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last) -{ - int done = 0; - - while(!done) { - /* reset current buffer for reuse */ - info->rbufs[i].status = 0; - set_desc_count(info->rbufs[i], info->rbuf_fill_level); - if (i == last) - done = 1; - if (++i == info->rbuf_count) - i = 0; - } - info->rbuf_current = i; -} - -/* - * mark all receive DMA buffers as free - */ -static void reset_rbufs(struct slgt_info *info) -{ - free_rbufs(info, 0, info->rbuf_count - 1); - info->rbuf_fill_index = 0; - info->rbuf_fill_count = 0; -} - -/* - * pass receive HDLC frame to upper layer - * - * return true if frame available, otherwise false - */ -static bool rx_get_frame(struct slgt_info *info) -{ - unsigned int start, end; - unsigned short status; - unsigned int framesize = 0; - unsigned long flags; - struct tty_struct *tty = info->port.tty; - unsigned char addr_field = 0xff; - unsigned int crc_size = 0; - - switch (info->params.crc_type & HDLC_CRC_MASK) { - case HDLC_CRC_16_CCITT: crc_size = 2; break; - case HDLC_CRC_32_CCITT: crc_size = 4; break; - } - -check_again: - - framesize = 0; - addr_field = 0xff; - start = end = info->rbuf_current; - - for (;;) { - if (!desc_complete(info->rbufs[end])) - goto cleanup; - - if (framesize == 0 && info->params.addr_filter != 0xff) - addr_field = info->rbufs[end].buf[0]; - - framesize += desc_count(info->rbufs[end]); - - if (desc_eof(info->rbufs[end])) - break; - - if (++end == info->rbuf_count) - end = 0; - - if (end == info->rbuf_current) { - if (info->rx_enabled){ - spin_lock_irqsave(&info->lock,flags); - rx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } - goto cleanup; - } - } - - /* status - * - * 15 buffer complete - * 14..06 reserved - * 05..04 residue - * 02 eof (end of frame) - * 01 CRC error - * 00 abort - */ - status = desc_status(info->rbufs[end]); - - /* ignore CRC bit if not using CRC (bit is undefined) */ - if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE) - status &= ~BIT1; - - if (framesize == 0 || - (addr_field != 0xff && addr_field != info->params.addr_filter)) { - free_rbufs(info, start, end); - goto check_again; - } - - if (framesize < (2 + crc_size) || status & BIT0) { - info->icount.rxshort++; - framesize = 0; - } else if (status & BIT1) { - info->icount.rxcrc++; - if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) - framesize = 0; - } - -#if SYNCLINK_GENERIC_HDLC - if (framesize == 0) { - info->netdev->stats.rx_errors++; - info->netdev->stats.rx_frame_errors++; - } -#endif - - DBGBH(("%s rx frame status=%04X size=%d\n", - info->device_name, status, framesize)); - DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx"); - - if (framesize) { - if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { - framesize -= crc_size; - crc_size = 0; - } - - if (framesize > info->max_frame_size + crc_size) - info->icount.rxlong++; - else { - /* copy dma buffer(s) to contiguous temp buffer */ - int copy_count = framesize; - int i = start; - unsigned char *p = info->tmp_rbuf; - info->tmp_rbuf_count = framesize; - - info->icount.rxok++; - - while(copy_count) { - int partial_count = min_t(int, copy_count, info->rbuf_fill_level); - memcpy(p, info->rbufs[i].buf, partial_count); - p += partial_count; - copy_count -= partial_count; - if (++i == info->rbuf_count) - i = 0; - } - - if (info->params.crc_type & HDLC_CRC_RETURN_EX) { - *p = (status & BIT1) ? RX_CRC_ERROR : RX_OK; - framesize++; - } - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_rx(info,info->tmp_rbuf, framesize); - else -#endif - ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize); - } - } - free_rbufs(info, start, end); - return true; - -cleanup: - return false; -} - -/* - * pass receive buffer (RAW synchronous mode) to tty layer - * return true if buffer available, otherwise false - */ -static bool rx_get_buf(struct slgt_info *info) -{ - unsigned int i = info->rbuf_current; - unsigned int count; - - if (!desc_complete(info->rbufs[i])) - return false; - count = desc_count(info->rbufs[i]); - switch(info->params.mode) { - case MGSL_MODE_MONOSYNC: - case MGSL_MODE_BISYNC: - case MGSL_MODE_XSYNC: - /* ignore residue in byte synchronous modes */ - if (desc_residue(info->rbufs[i])) - count--; - break; - } - DBGDATA(info, info->rbufs[i].buf, count, "rx"); - DBGINFO(("rx_get_buf size=%d\n", count)); - if (count) - ldisc_receive_buf(info->port.tty, info->rbufs[i].buf, - info->flag_buf, count); - free_rbufs(info, i, i); - return true; -} - -static void reset_tbufs(struct slgt_info *info) -{ - unsigned int i; - info->tbuf_current = 0; - for (i=0 ; i < info->tbuf_count ; i++) { - info->tbufs[i].status = 0; - info->tbufs[i].count = 0; - } -} - -/* - * return number of free transmit DMA buffers - */ -static unsigned int free_tbuf_count(struct slgt_info *info) -{ - unsigned int count = 0; - unsigned int i = info->tbuf_current; - - do - { - if (desc_count(info->tbufs[i])) - break; /* buffer in use */ - ++count; - if (++i == info->tbuf_count) - i=0; - } while (i != info->tbuf_current); - - /* if tx DMA active, last zero count buffer is in use */ - if (count && (rd_reg32(info, TDCSR) & BIT0)) - --count; - - return count; -} - -/* - * return number of bytes in unsent transmit DMA buffers - * and the serial controller tx FIFO - */ -static unsigned int tbuf_bytes(struct slgt_info *info) -{ - unsigned int total_count = 0; - unsigned int i = info->tbuf_current; - unsigned int reg_value; - unsigned int count; - unsigned int active_buf_count = 0; - - /* - * Add descriptor counts for all tx DMA buffers. - * If count is zero (cleared by DMA controller after read), - * the buffer is complete or is actively being read from. - * - * Record buf_count of last buffer with zero count starting - * from current ring position. buf_count is mirror - * copy of count and is not cleared by serial controller. - * If DMA controller is active, that buffer is actively - * being read so add to total. - */ - do { - count = desc_count(info->tbufs[i]); - if (count) - total_count += count; - else if (!total_count) - active_buf_count = info->tbufs[i].buf_count; - if (++i == info->tbuf_count) - i = 0; - } while (i != info->tbuf_current); - - /* read tx DMA status register */ - reg_value = rd_reg32(info, TDCSR); - - /* if tx DMA active, last zero count buffer is in use */ - if (reg_value & BIT0) - total_count += active_buf_count; - - /* add tx FIFO count = reg_value[15..8] */ - total_count += (reg_value >> 8) & 0xff; - - /* if transmitter active add one byte for shift register */ - if (info->tx_active) - total_count++; - - return total_count; -} - -/* - * load data into transmit DMA buffer ring and start transmitter if needed - * return true if data accepted, otherwise false (buffers full) - */ -static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size) -{ - unsigned short count; - unsigned int i; - struct slgt_desc *d; - - /* check required buffer space */ - if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info)) - return false; - - DBGDATA(info, buf, size, "tx"); - - /* - * copy data to one or more DMA buffers in circular ring - * tbuf_start = first buffer for this data - * tbuf_current = next free buffer - * - * Copy all data before making data visible to DMA controller by - * setting descriptor count of the first buffer. - * This prevents an active DMA controller from reading the first DMA - * buffers of a frame and stopping before the final buffers are filled. - */ - - info->tbuf_start = i = info->tbuf_current; - - while (size) { - d = &info->tbufs[i]; - - count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); - memcpy(d->buf, buf, count); - - size -= count; - buf += count; - - /* - * set EOF bit for last buffer of HDLC frame or - * for every buffer in raw mode - */ - if ((!size && info->params.mode == MGSL_MODE_HDLC) || - info->params.mode == MGSL_MODE_RAW) - set_desc_eof(*d, 1); - else - set_desc_eof(*d, 0); - - /* set descriptor count for all but first buffer */ - if (i != info->tbuf_start) - set_desc_count(*d, count); - d->buf_count = count; - - if (++i == info->tbuf_count) - i = 0; - } - - info->tbuf_current = i; - - /* set first buffer count to make new data visible to DMA controller */ - d = &info->tbufs[info->tbuf_start]; - set_desc_count(*d, d->buf_count); - - /* start transmitter if needed and update transmit timeout */ - if (!info->tx_active) - tx_start(info); - update_tx_timer(info); - - return true; -} - -static int register_test(struct slgt_info *info) -{ - static unsigned short patterns[] = - {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696}; - static unsigned int count = ARRAY_SIZE(patterns); - unsigned int i; - int rc = 0; - - for (i=0 ; i < count ; i++) { - wr_reg16(info, TIR, patterns[i]); - wr_reg16(info, BDR, patterns[(i+1)%count]); - if ((rd_reg16(info, TIR) != patterns[i]) || - (rd_reg16(info, BDR) != patterns[(i+1)%count])) { - rc = -ENODEV; - break; - } - } - info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0; - info->init_error = rc ? 0 : DiagStatus_AddressFailure; - return rc; -} - -static int irq_test(struct slgt_info *info) -{ - unsigned long timeout; - unsigned long flags; - struct tty_struct *oldtty = info->port.tty; - u32 speed = info->params.data_rate; - - info->params.data_rate = 921600; - info->port.tty = NULL; - - spin_lock_irqsave(&info->lock, flags); - async_mode(info); - slgt_irq_on(info, IRQ_TXIDLE); - - /* enable transmitter */ - wr_reg16(info, TCR, - (unsigned short)(rd_reg16(info, TCR) | BIT1)); - - /* write one byte and wait for tx idle */ - wr_reg16(info, TDR, 0); - - /* assume failure */ - info->init_error = DiagStatus_IrqFailure; - info->irq_occurred = false; - - spin_unlock_irqrestore(&info->lock, flags); - - timeout=100; - while(timeout-- && !info->irq_occurred) - msleep_interruptible(10); - - spin_lock_irqsave(&info->lock,flags); - reset_port(info); - spin_unlock_irqrestore(&info->lock,flags); - - info->params.data_rate = speed; - info->port.tty = oldtty; - - info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure; - return info->irq_occurred ? 0 : -ENODEV; -} - -static int loopback_test_rx(struct slgt_info *info) -{ - unsigned char *src, *dest; - int count; - - if (desc_complete(info->rbufs[0])) { - count = desc_count(info->rbufs[0]); - src = info->rbufs[0].buf; - dest = info->tmp_rbuf; - - for( ; count ; count-=2, src+=2) { - /* src=data byte (src+1)=status byte */ - if (!(*(src+1) & (BIT9 + BIT8))) { - *dest = *src; - dest++; - info->tmp_rbuf_count++; - } - } - DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx"); - return 1; - } - return 0; -} - -static int loopback_test(struct slgt_info *info) -{ -#define TESTFRAMESIZE 20 - - unsigned long timeout; - u16 count = TESTFRAMESIZE; - unsigned char buf[TESTFRAMESIZE]; - int rc = -ENODEV; - unsigned long flags; - - struct tty_struct *oldtty = info->port.tty; - MGSL_PARAMS params; - - memcpy(¶ms, &info->params, sizeof(params)); - - info->params.mode = MGSL_MODE_ASYNC; - info->params.data_rate = 921600; - info->params.loopback = 1; - info->port.tty = NULL; - - /* build and send transmit frame */ - for (count = 0; count < TESTFRAMESIZE; ++count) - buf[count] = (unsigned char)count; - - info->tmp_rbuf_count = 0; - memset(info->tmp_rbuf, 0, TESTFRAMESIZE); - - /* program hardware for HDLC and enabled receiver */ - spin_lock_irqsave(&info->lock,flags); - async_mode(info); - rx_start(info); - tx_load(info, buf, count); - spin_unlock_irqrestore(&info->lock, flags); - - /* wait for receive complete */ - for (timeout = 100; timeout; --timeout) { - msleep_interruptible(10); - if (loopback_test_rx(info)) { - rc = 0; - break; - } - } - - /* verify received frame length and contents */ - if (!rc && (info->tmp_rbuf_count != count || - memcmp(buf, info->tmp_rbuf, count))) { - rc = -ENODEV; - } - - spin_lock_irqsave(&info->lock,flags); - reset_adapter(info); - spin_unlock_irqrestore(&info->lock,flags); - - memcpy(&info->params, ¶ms, sizeof(info->params)); - info->port.tty = oldtty; - - info->init_error = rc ? DiagStatus_DmaFailure : 0; - return rc; -} - -static int adapter_test(struct slgt_info *info) -{ - DBGINFO(("testing %s\n", info->device_name)); - if (register_test(info) < 0) { - printk("register test failure %s addr=%08X\n", - info->device_name, info->phys_reg_addr); - } else if (irq_test(info) < 0) { - printk("IRQ test failure %s IRQ=%d\n", - info->device_name, info->irq_level); - } else if (loopback_test(info) < 0) { - printk("loopback test failure %s\n", info->device_name); - } - return info->init_error; -} - -/* - * transmit timeout handler - */ -static void tx_timeout(unsigned long context) -{ - struct slgt_info *info = (struct slgt_info*)context; - unsigned long flags; - - DBGINFO(("%s tx_timeout\n", info->device_name)); - if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) { - info->icount.txtimeout++; - } - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - bh_transmit(info); -} - -/* - * receive buffer polling timer - */ -static void rx_timeout(unsigned long context) -{ - struct slgt_info *info = (struct slgt_info*)context; - unsigned long flags; - - DBGINFO(("%s rx_timeout\n", info->device_name)); - spin_lock_irqsave(&info->lock, flags); - info->pending_bh |= BH_RECEIVE; - spin_unlock_irqrestore(&info->lock, flags); - bh_handler(&info->task); -} - diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c deleted file mode 100644 index 327343694473..000000000000 --- a/drivers/char/synclinkmp.c +++ /dev/null @@ -1,5600 +0,0 @@ -/* - * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $ - * - * Device driver for Microgate SyncLink Multiport - * high speed multiprotocol serial adapter. - * - * written by Paul Fulghum for Microgate Corporation - * paulkf@microgate.com - * - * Microgate and SyncLink are trademarks of Microgate Corporation - * - * Derived from serial.c written by Theodore Ts'o and Linus Torvalds - * This code is released under the GNU General Public License (GPL) - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) -#if defined(__i386__) -# define BREAKPOINT() asm(" int $3"); -#else -# define BREAKPOINT() { } -#endif - -#define MAX_DEVICES 12 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) -#define SYNCLINK_GENERIC_HDLC 1 -#else -#define SYNCLINK_GENERIC_HDLC 0 -#endif - -#define GET_USER(error,value,addr) error = get_user(value,addr) -#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 -#define PUT_USER(error,value,addr) error = put_user(value,addr) -#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 - -#include - -static MGSL_PARAMS default_params = { - MGSL_MODE_HDLC, /* unsigned long mode */ - 0, /* unsigned char loopback; */ - HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */ - HDLC_ENCODING_NRZI_SPACE, /* unsigned char encoding; */ - 0, /* unsigned long clock_speed; */ - 0xff, /* unsigned char addr_filter; */ - HDLC_CRC_16_CCITT, /* unsigned short crc_type; */ - HDLC_PREAMBLE_LENGTH_8BITS, /* unsigned char preamble_length; */ - HDLC_PREAMBLE_PATTERN_NONE, /* unsigned char preamble; */ - 9600, /* unsigned long data_rate; */ - 8, /* unsigned char data_bits; */ - 1, /* unsigned char stop_bits; */ - ASYNC_PARITY_NONE /* unsigned char parity; */ -}; - -/* size in bytes of DMA data buffers */ -#define SCABUFSIZE 1024 -#define SCA_MEM_SIZE 0x40000 -#define SCA_BASE_SIZE 512 -#define SCA_REG_SIZE 16 -#define SCA_MAX_PORTS 4 -#define SCAMAXDESC 128 - -#define BUFFERLISTSIZE 4096 - -/* SCA-I style DMA buffer descriptor */ -typedef struct _SCADESC -{ - u16 next; /* lower l6 bits of next descriptor addr */ - u16 buf_ptr; /* lower 16 bits of buffer addr */ - u8 buf_base; /* upper 8 bits of buffer addr */ - u8 pad1; - u16 length; /* length of buffer */ - u8 status; /* status of buffer */ - u8 pad2; -} SCADESC, *PSCADESC; - -typedef struct _SCADESC_EX -{ - /* device driver bookkeeping section */ - char *virt_addr; /* virtual address of data buffer */ - u16 phys_entry; /* lower 16-bits of physical address of this descriptor */ -} SCADESC_EX, *PSCADESC_EX; - -/* The queue of BH actions to be performed */ - -#define BH_RECEIVE 1 -#define BH_TRANSMIT 2 -#define BH_STATUS 4 - -#define IO_PIN_SHUTDOWN_LIMIT 100 - -struct _input_signal_events { - int ri_up; - int ri_down; - int dsr_up; - int dsr_down; - int dcd_up; - int dcd_down; - int cts_up; - int cts_down; -}; - -/* - * Device instance data structure - */ -typedef struct _synclinkmp_info { - void *if_ptr; /* General purpose pointer (used by SPPP) */ - int magic; - struct tty_port port; - int line; - unsigned short close_delay; - unsigned short closing_wait; /* time to wait before closing */ - - struct mgsl_icount icount; - - int timeout; - int x_char; /* xon/xoff character */ - u16 read_status_mask1; /* break detection (SR1 indications) */ - u16 read_status_mask2; /* parity/framing/overun (SR2 indications) */ - unsigned char ignore_status_mask1; /* break detection (SR1 indications) */ - unsigned char ignore_status_mask2; /* parity/framing/overun (SR2 indications) */ - unsigned char *tx_buf; - int tx_put; - int tx_get; - int tx_count; - - wait_queue_head_t status_event_wait_q; - wait_queue_head_t event_wait_q; - struct timer_list tx_timer; /* HDLC transmit timeout timer */ - struct _synclinkmp_info *next_device; /* device list link */ - struct timer_list status_timer; /* input signal status check timer */ - - spinlock_t lock; /* spinlock for synchronizing with ISR */ - struct work_struct task; /* task structure for scheduling bh */ - - u32 max_frame_size; /* as set by device config */ - - u32 pending_bh; - - bool bh_running; /* Protection from multiple */ - int isr_overflow; - bool bh_requested; - - int dcd_chkcount; /* check counts to prevent */ - int cts_chkcount; /* too many IRQs if a signal */ - int dsr_chkcount; /* is floating */ - int ri_chkcount; - - char *buffer_list; /* virtual address of Rx & Tx buffer lists */ - unsigned long buffer_list_phys; - - unsigned int rx_buf_count; /* count of total allocated Rx buffers */ - SCADESC *rx_buf_list; /* list of receive buffer entries */ - SCADESC_EX rx_buf_list_ex[SCAMAXDESC]; /* list of receive buffer entries */ - unsigned int current_rx_buf; - - unsigned int tx_buf_count; /* count of total allocated Tx buffers */ - SCADESC *tx_buf_list; /* list of transmit buffer entries */ - SCADESC_EX tx_buf_list_ex[SCAMAXDESC]; /* list of transmit buffer entries */ - unsigned int last_tx_buf; - - unsigned char *tmp_rx_buf; - unsigned int tmp_rx_buf_count; - - bool rx_enabled; - bool rx_overflow; - - bool tx_enabled; - bool tx_active; - u32 idle_mode; - - unsigned char ie0_value; - unsigned char ie1_value; - unsigned char ie2_value; - unsigned char ctrlreg_value; - unsigned char old_signals; - - char device_name[25]; /* device instance name */ - - int port_count; - int adapter_num; - int port_num; - - struct _synclinkmp_info *port_array[SCA_MAX_PORTS]; - - unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */ - - unsigned int irq_level; /* interrupt level */ - unsigned long irq_flags; - bool irq_requested; /* true if IRQ requested */ - - MGSL_PARAMS params; /* communications parameters */ - - unsigned char serial_signals; /* current serial signal states */ - - bool irq_occurred; /* for diagnostics use */ - unsigned int init_error; /* Initialization startup error */ - - u32 last_mem_alloc; - unsigned char* memory_base; /* shared memory address (PCI only) */ - u32 phys_memory_base; - int shared_mem_requested; - - unsigned char* sca_base; /* HD64570 SCA Memory address */ - u32 phys_sca_base; - u32 sca_offset; - bool sca_base_requested; - - unsigned char* lcr_base; /* local config registers (PCI only) */ - u32 phys_lcr_base; - u32 lcr_offset; - int lcr_mem_requested; - - unsigned char* statctrl_base; /* status/control register memory */ - u32 phys_statctrl_base; - u32 statctrl_offset; - bool sca_statctrl_requested; - - u32 misc_ctrl_value; - char flag_buf[MAX_ASYNC_BUFFER_SIZE]; - char char_buf[MAX_ASYNC_BUFFER_SIZE]; - bool drop_rts_on_tx_done; - - struct _input_signal_events input_signal_events; - - /* SPPP/Cisco HDLC device parts */ - int netcount; - spinlock_t netlock; - -#if SYNCLINK_GENERIC_HDLC - struct net_device *netdev; -#endif - -} SLMP_INFO; - -#define MGSL_MAGIC 0x5401 - -/* - * define serial signal status change macros - */ -#define MISCSTATUS_DCD_LATCHED (SerialSignal_DCD<<8) /* indicates change in DCD */ -#define MISCSTATUS_RI_LATCHED (SerialSignal_RI<<8) /* indicates change in RI */ -#define MISCSTATUS_CTS_LATCHED (SerialSignal_CTS<<8) /* indicates change in CTS */ -#define MISCSTATUS_DSR_LATCHED (SerialSignal_DSR<<8) /* change in DSR */ - -/* Common Register macros */ -#define LPR 0x00 -#define PABR0 0x02 -#define PABR1 0x03 -#define WCRL 0x04 -#define WCRM 0x05 -#define WCRH 0x06 -#define DPCR 0x08 -#define DMER 0x09 -#define ISR0 0x10 -#define ISR1 0x11 -#define ISR2 0x12 -#define IER0 0x14 -#define IER1 0x15 -#define IER2 0x16 -#define ITCR 0x18 -#define INTVR 0x1a -#define IMVR 0x1c - -/* MSCI Register macros */ -#define TRB 0x20 -#define TRBL 0x20 -#define TRBH 0x21 -#define SR0 0x22 -#define SR1 0x23 -#define SR2 0x24 -#define SR3 0x25 -#define FST 0x26 -#define IE0 0x28 -#define IE1 0x29 -#define IE2 0x2a -#define FIE 0x2b -#define CMD 0x2c -#define MD0 0x2e -#define MD1 0x2f -#define MD2 0x30 -#define CTL 0x31 -#define SA0 0x32 -#define SA1 0x33 -#define IDL 0x34 -#define TMC 0x35 -#define RXS 0x36 -#define TXS 0x37 -#define TRC0 0x38 -#define TRC1 0x39 -#define RRC 0x3a -#define CST0 0x3c -#define CST1 0x3d - -/* Timer Register Macros */ -#define TCNT 0x60 -#define TCNTL 0x60 -#define TCNTH 0x61 -#define TCONR 0x62 -#define TCONRL 0x62 -#define TCONRH 0x63 -#define TMCS 0x64 -#define TEPR 0x65 - -/* DMA Controller Register macros */ -#define DARL 0x80 -#define DARH 0x81 -#define DARB 0x82 -#define BAR 0x80 -#define BARL 0x80 -#define BARH 0x81 -#define BARB 0x82 -#define SAR 0x84 -#define SARL 0x84 -#define SARH 0x85 -#define SARB 0x86 -#define CPB 0x86 -#define CDA 0x88 -#define CDAL 0x88 -#define CDAH 0x89 -#define EDA 0x8a -#define EDAL 0x8a -#define EDAH 0x8b -#define BFL 0x8c -#define BFLL 0x8c -#define BFLH 0x8d -#define BCR 0x8e -#define BCRL 0x8e -#define BCRH 0x8f -#define DSR 0x90 -#define DMR 0x91 -#define FCT 0x93 -#define DIR 0x94 -#define DCMD 0x95 - -/* combine with timer or DMA register address */ -#define TIMER0 0x00 -#define TIMER1 0x08 -#define TIMER2 0x10 -#define TIMER3 0x18 -#define RXDMA 0x00 -#define TXDMA 0x20 - -/* SCA Command Codes */ -#define NOOP 0x00 -#define TXRESET 0x01 -#define TXENABLE 0x02 -#define TXDISABLE 0x03 -#define TXCRCINIT 0x04 -#define TXCRCEXCL 0x05 -#define TXEOM 0x06 -#define TXABORT 0x07 -#define MPON 0x08 -#define TXBUFCLR 0x09 -#define RXRESET 0x11 -#define RXENABLE 0x12 -#define RXDISABLE 0x13 -#define RXCRCINIT 0x14 -#define RXREJECT 0x15 -#define SEARCHMP 0x16 -#define RXCRCEXCL 0x17 -#define RXCRCCALC 0x18 -#define CHRESET 0x21 -#define HUNT 0x31 - -/* DMA command codes */ -#define SWABORT 0x01 -#define FEICLEAR 0x02 - -/* IE0 */ -#define TXINTE BIT7 -#define RXINTE BIT6 -#define TXRDYE BIT1 -#define RXRDYE BIT0 - -/* IE1 & SR1 */ -#define UDRN BIT7 -#define IDLE BIT6 -#define SYNCD BIT4 -#define FLGD BIT4 -#define CCTS BIT3 -#define CDCD BIT2 -#define BRKD BIT1 -#define ABTD BIT1 -#define GAPD BIT1 -#define BRKE BIT0 -#define IDLD BIT0 - -/* IE2 & SR2 */ -#define EOM BIT7 -#define PMP BIT6 -#define SHRT BIT6 -#define PE BIT5 -#define ABT BIT5 -#define FRME BIT4 -#define RBIT BIT4 -#define OVRN BIT3 -#define CRCE BIT2 - - -/* - * Global linked list of SyncLink devices - */ -static SLMP_INFO *synclinkmp_device_list = NULL; -static int synclinkmp_adapter_count = -1; -static int synclinkmp_device_count = 0; - -/* - * Set this param to non-zero to load eax with the - * .text section address and breakpoint on module load. - * This is useful for use with gdb and add-symbol-file command. - */ -static int break_on_load = 0; - -/* - * Driver major number, defaults to zero to get auto - * assigned major number. May be forced as module parameter. - */ -static int ttymajor = 0; - -/* - * Array of user specified options for ISA adapters. - */ -static int debug_level = 0; -static int maxframe[MAX_DEVICES] = {0,}; - -module_param(break_on_load, bool, 0); -module_param(ttymajor, int, 0); -module_param(debug_level, int, 0); -module_param_array(maxframe, int, NULL, 0); - -static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.38 $"; - -static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); -static void synclinkmp_remove_one(struct pci_dev *dev); - -static struct pci_device_id synclinkmp_pci_tbl[] = { - { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_SCA, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl); - -MODULE_LICENSE("GPL"); - -static struct pci_driver synclinkmp_pci_driver = { - .name = "synclinkmp", - .id_table = synclinkmp_pci_tbl, - .probe = synclinkmp_init_one, - .remove = __devexit_p(synclinkmp_remove_one), -}; - - -static struct tty_driver *serial_driver; - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - - -/* tty callbacks */ - -static int open(struct tty_struct *tty, struct file * filp); -static void close(struct tty_struct *tty, struct file * filp); -static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); - -static int write(struct tty_struct *tty, const unsigned char *buf, int count); -static int put_char(struct tty_struct *tty, unsigned char ch); -static void send_xchar(struct tty_struct *tty, char ch); -static void wait_until_sent(struct tty_struct *tty, int timeout); -static int write_room(struct tty_struct *tty); -static void flush_chars(struct tty_struct *tty); -static void flush_buffer(struct tty_struct *tty); -static void tx_hold(struct tty_struct *tty); -static void tx_release(struct tty_struct *tty); - -static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int chars_in_buffer(struct tty_struct *tty); -static void throttle(struct tty_struct * tty); -static void unthrottle(struct tty_struct * tty); -static int set_break(struct tty_struct *tty, int break_state); - -#if SYNCLINK_GENERIC_HDLC -#define dev_to_port(D) (dev_to_hdlc(D)->priv) -static void hdlcdev_tx_done(SLMP_INFO *info); -static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size); -static int hdlcdev_init(SLMP_INFO *info); -static void hdlcdev_exit(SLMP_INFO *info); -#endif - -/* ioctl handlers */ - -static int get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount); -static int get_params(SLMP_INFO *info, MGSL_PARAMS __user *params); -static int set_params(SLMP_INFO *info, MGSL_PARAMS __user *params); -static int get_txidle(SLMP_INFO *info, int __user *idle_mode); -static int set_txidle(SLMP_INFO *info, int idle_mode); -static int tx_enable(SLMP_INFO *info, int enable); -static int tx_abort(SLMP_INFO *info); -static int rx_enable(SLMP_INFO *info, int enable); -static int modem_input_wait(SLMP_INFO *info,int arg); -static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); -static int tiocmget(struct tty_struct *tty); -static int tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear); -static int set_break(struct tty_struct *tty, int break_state); - -static void add_device(SLMP_INFO *info); -static void device_init(int adapter_num, struct pci_dev *pdev); -static int claim_resources(SLMP_INFO *info); -static void release_resources(SLMP_INFO *info); - -static int startup(SLMP_INFO *info); -static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); -static int carrier_raised(struct tty_port *port); -static void shutdown(SLMP_INFO *info); -static void program_hw(SLMP_INFO *info); -static void change_params(SLMP_INFO *info); - -static bool init_adapter(SLMP_INFO *info); -static bool register_test(SLMP_INFO *info); -static bool irq_test(SLMP_INFO *info); -static bool loopback_test(SLMP_INFO *info); -static int adapter_test(SLMP_INFO *info); -static bool memory_test(SLMP_INFO *info); - -static void reset_adapter(SLMP_INFO *info); -static void reset_port(SLMP_INFO *info); -static void async_mode(SLMP_INFO *info); -static void hdlc_mode(SLMP_INFO *info); - -static void rx_stop(SLMP_INFO *info); -static void rx_start(SLMP_INFO *info); -static void rx_reset_buffers(SLMP_INFO *info); -static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last); -static bool rx_get_frame(SLMP_INFO *info); - -static void tx_start(SLMP_INFO *info); -static void tx_stop(SLMP_INFO *info); -static void tx_load_fifo(SLMP_INFO *info); -static void tx_set_idle(SLMP_INFO *info); -static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count); - -static void get_signals(SLMP_INFO *info); -static void set_signals(SLMP_INFO *info); -static void enable_loopback(SLMP_INFO *info, int enable); -static void set_rate(SLMP_INFO *info, u32 data_rate); - -static int bh_action(SLMP_INFO *info); -static void bh_handler(struct work_struct *work); -static void bh_receive(SLMP_INFO *info); -static void bh_transmit(SLMP_INFO *info); -static void bh_status(SLMP_INFO *info); -static void isr_timer(SLMP_INFO *info); -static void isr_rxint(SLMP_INFO *info); -static void isr_rxrdy(SLMP_INFO *info); -static void isr_txint(SLMP_INFO *info); -static void isr_txrdy(SLMP_INFO *info); -static void isr_rxdmaok(SLMP_INFO *info); -static void isr_rxdmaerror(SLMP_INFO *info); -static void isr_txdmaok(SLMP_INFO *info); -static void isr_txdmaerror(SLMP_INFO *info); -static void isr_io_pin(SLMP_INFO *info, u16 status); - -static int alloc_dma_bufs(SLMP_INFO *info); -static void free_dma_bufs(SLMP_INFO *info); -static int alloc_buf_list(SLMP_INFO *info); -static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *list, SCADESC_EX *list_ex,int count); -static int alloc_tmp_rx_buf(SLMP_INFO *info); -static void free_tmp_rx_buf(SLMP_INFO *info); - -static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count); -static void trace_block(SLMP_INFO *info, const char* data, int count, int xmit); -static void tx_timeout(unsigned long context); -static void status_timeout(unsigned long context); - -static unsigned char read_reg(SLMP_INFO *info, unsigned char addr); -static void write_reg(SLMP_INFO *info, unsigned char addr, unsigned char val); -static u16 read_reg16(SLMP_INFO *info, unsigned char addr); -static void write_reg16(SLMP_INFO *info, unsigned char addr, u16 val); -static unsigned char read_status_reg(SLMP_INFO * info); -static void write_control_reg(SLMP_INFO * info); - - -static unsigned char rx_active_fifo_level = 16; // rx request FIFO activation level in bytes -static unsigned char tx_active_fifo_level = 16; // tx request FIFO activation level in bytes -static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes - -static u32 misc_ctrl_value = 0x007e4040; -static u32 lcr1_brdr_value = 0x00800028; - -static u32 read_ahead_count = 8; - -/* DPCR, DMA Priority Control - * - * 07..05 Not used, must be 0 - * 04 BRC, bus release condition: 0=all transfers complete - * 1=release after 1 xfer on all channels - * 03 CCC, channel change condition: 0=every cycle - * 1=after each channel completes all xfers - * 02..00 PR<2..0>, priority 100=round robin - * - * 00000100 = 0x00 - */ -static unsigned char dma_priority = 0x04; - -// Number of bytes that can be written to shared RAM -// in a single write operation -static u32 sca_pci_load_interval = 64; - -/* - * 1st function defined in .text section. Calling this function in - * init_module() followed by a breakpoint allows a remote debugger - * (gdb) to get the .text address for the add-symbol-file command. - * This allows remote debugging of dynamically loadable modules. - */ -static void* synclinkmp_get_text_ptr(void); -static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;} - -static inline int sanity_check(SLMP_INFO *info, - char *name, const char *routine) -{ -#ifdef SANITY_CHECK - static const char *badmagic = - "Warning: bad magic number for synclinkmp_struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null synclinkmp_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != MGSL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#else - if (!info) - return 1; -#endif - return 0; -} - -/** - * line discipline callback wrappers - * - * The wrappers maintain line discipline references - * while calling into the line discipline. - * - * ldisc_receive_buf - pass receive data to line discipline - */ - -static void ldisc_receive_buf(struct tty_struct *tty, - const __u8 *data, char *flags, int count) -{ - struct tty_ldisc *ld; - if (!tty) - return; - ld = tty_ldisc_ref(tty); - if (ld) { - if (ld->ops->receive_buf) - ld->ops->receive_buf(tty, data, flags, count); - tty_ldisc_deref(ld); - } -} - -/* tty callbacks */ - -/* Called when a port is opened. Init and enable port. - */ -static int open(struct tty_struct *tty, struct file *filp) -{ - SLMP_INFO *info; - int retval, line; - unsigned long flags; - - line = tty->index; - if ((line < 0) || (line >= synclinkmp_device_count)) { - printk("%s(%d): open with invalid line #%d.\n", - __FILE__,__LINE__,line); - return -ENODEV; - } - - info = synclinkmp_device_list; - while(info && info->line != line) - info = info->next_device; - if (sanity_check(info, tty->name, "open")) - return -ENODEV; - if ( info->init_error ) { - printk("%s(%d):%s device is not allocated, init error=%d\n", - __FILE__,__LINE__,info->device_name,info->init_error); - return -ENODEV; - } - - tty->driver_data = info; - info->port.tty = tty; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s open(), old ref count = %d\n", - __FILE__,__LINE__,tty->driver->name, info->port.count); - - /* If port is closing, signal caller to try again */ - if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ - if (info->port.flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->port.close_wait); - retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - goto cleanup; - } - - info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - spin_lock_irqsave(&info->netlock, flags); - if (info->netcount) { - retval = -EBUSY; - spin_unlock_irqrestore(&info->netlock, flags); - goto cleanup; - } - info->port.count++; - spin_unlock_irqrestore(&info->netlock, flags); - - if (info->port.count == 1) { - /* 1st open on this device, init hardware */ - retval = startup(info); - if (retval < 0) - goto cleanup; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s block_til_ready() returned %d\n", - __FILE__,__LINE__, info->device_name, retval); - goto cleanup; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s open() success\n", - __FILE__,__LINE__, info->device_name); - retval = 0; - -cleanup: - if (retval) { - if (tty->count == 1) - info->port.tty = NULL; /* tty layer will release tty struct */ - if(info->port.count) - info->port.count--; - } - - return retval; -} - -/* Called when port is closed. Wait for remaining data to be - * sent. Disable port and free resources. - */ -static void close(struct tty_struct *tty, struct file *filp) -{ - SLMP_INFO * info = tty->driver_data; - - if (sanity_check(info, tty->name, "close")) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s close() entry, count=%d\n", - __FILE__,__LINE__, info->device_name, info->port.count); - - if (tty_port_close_start(&info->port, tty, filp) == 0) - goto cleanup; - - mutex_lock(&info->port.mutex); - if (info->port.flags & ASYNC_INITIALIZED) - wait_until_sent(tty, info->timeout); - - flush_buffer(tty); - tty_ldisc_flush(tty); - shutdown(info); - mutex_unlock(&info->port.mutex); - - tty_port_close_end(&info->port, tty); - info->port.tty = NULL; -cleanup: - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, - tty->driver->name, info->port.count); -} - -/* Called by tty_hangup() when a hangup is signaled. - * This is the same as closing all open descriptors for the port. - */ -static void hangup(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s hangup()\n", - __FILE__,__LINE__, info->device_name ); - - if (sanity_check(info, tty->name, "hangup")) - return; - - mutex_lock(&info->port.mutex); - flush_buffer(tty); - shutdown(info); - - spin_lock_irqsave(&info->port.lock, flags); - info->port.count = 0; - info->port.flags &= ~ASYNC_NORMAL_ACTIVE; - info->port.tty = NULL; - spin_unlock_irqrestore(&info->port.lock, flags); - mutex_unlock(&info->port.mutex); - - wake_up_interruptible(&info->port.open_wait); -} - -/* Set new termios settings - */ -static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__, - tty->driver->name ); - - change_params(info); - - /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios->c_cflag & CBAUD)) { - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios->c_cflag & CBAUD) { - info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->serial_signals |= SerialSignal_RTS; - } - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - tx_release(tty); - } -} - -/* Send a block of data - * - * Arguments: - * - * tty pointer to tty information structure - * buf pointer to buffer containing send data - * count size of send data in bytes - * - * Return Value: number of characters written - */ -static int write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int c, ret = 0; - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s write() count=%d\n", - __FILE__,__LINE__,info->device_name,count); - - if (sanity_check(info, tty->name, "write")) - goto cleanup; - - if (!info->tx_buf) - goto cleanup; - - if (info->params.mode == MGSL_MODE_HDLC) { - if (count > info->max_frame_size) { - ret = -EIO; - goto cleanup; - } - if (info->tx_active) - goto cleanup; - if (info->tx_count) { - /* send accumulated data from send_char() calls */ - /* as frame and wait before accepting more data. */ - tx_load_dma_buffer(info, info->tx_buf, info->tx_count); - goto start; - } - ret = info->tx_count = count; - tx_load_dma_buffer(info, buf, count); - goto start; - } - - for (;;) { - c = min_t(int, count, - min(info->max_frame_size - info->tx_count - 1, - info->max_frame_size - info->tx_put)); - if (c <= 0) - break; - - memcpy(info->tx_buf + info->tx_put, buf, c); - - spin_lock_irqsave(&info->lock,flags); - info->tx_put += c; - if (info->tx_put >= info->max_frame_size) - info->tx_put -= info->max_frame_size; - info->tx_count += c; - spin_unlock_irqrestore(&info->lock,flags); - - buf += c; - count -= c; - ret += c; - } - - if (info->params.mode == MGSL_MODE_HDLC) { - if (count) { - ret = info->tx_count = 0; - goto cleanup; - } - tx_load_dma_buffer(info, info->tx_buf, info->tx_count); - } -start: - if (info->tx_count && !tty->stopped && !tty->hw_stopped) { - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } - -cleanup: - if (debug_level >= DEBUG_LEVEL_INFO) - printk( "%s(%d):%s write() returning=%d\n", - __FILE__,__LINE__,info->device_name,ret); - return ret; -} - -/* Add a character to the transmit buffer. - */ -static int put_char(struct tty_struct *tty, unsigned char ch) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - int ret = 0; - - if ( debug_level >= DEBUG_LEVEL_INFO ) { - printk( "%s(%d):%s put_char(%d)\n", - __FILE__,__LINE__,info->device_name,ch); - } - - if (sanity_check(info, tty->name, "put_char")) - return 0; - - if (!info->tx_buf) - return 0; - - spin_lock_irqsave(&info->lock,flags); - - if ( (info->params.mode != MGSL_MODE_HDLC) || - !info->tx_active ) { - - if (info->tx_count < info->max_frame_size - 1) { - info->tx_buf[info->tx_put++] = ch; - if (info->tx_put >= info->max_frame_size) - info->tx_put -= info->max_frame_size; - info->tx_count++; - ret = 1; - } - } - - spin_unlock_irqrestore(&info->lock,flags); - return ret; -} - -/* Send a high-priority XON/XOFF character - */ -static void send_xchar(struct tty_struct *tty, char ch) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s send_xchar(%d)\n", - __FILE__,__LINE__, info->device_name, ch ); - - if (sanity_check(info, tty->name, "send_xchar")) - return; - - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_enabled) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* Wait until the transmitter is empty. - */ -static void wait_until_sent(struct tty_struct *tty, int timeout) -{ - SLMP_INFO * info = tty->driver_data; - unsigned long orig_jiffies, char_time; - - if (!info ) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s wait_until_sent() entry\n", - __FILE__,__LINE__, info->device_name ); - - if (sanity_check(info, tty->name, "wait_until_sent")) - return; - - if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags)) - goto exit; - - orig_jiffies = jiffies; - - /* Set check interval to 1/5 of estimated time to - * send a character, and make it at least 1. The check - * interval should also be less than the timeout. - * Note: use tight timings here to satisfy the NIST-PCTS. - */ - - if ( info->params.data_rate ) { - char_time = info->timeout/(32 * 5); - if (!char_time) - char_time++; - } else - char_time = 1; - - if (timeout) - char_time = min_t(unsigned long, char_time, timeout); - - if ( info->params.mode == MGSL_MODE_HDLC ) { - while (info->tx_active) { - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - } else { - /* - * TODO: determine if there is something similar to USC16C32 - * TXSTATUS_ALL_SENT status - */ - while ( info->tx_active && info->tx_enabled) { - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - } - -exit: - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s wait_until_sent() exit\n", - __FILE__,__LINE__, info->device_name ); -} - -/* Return the count of free bytes in transmit buffer - */ -static int write_room(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - int ret; - - if (sanity_check(info, tty->name, "write_room")) - return 0; - - if (info->params.mode == MGSL_MODE_HDLC) { - ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; - } else { - ret = info->max_frame_size - info->tx_count - 1; - if (ret < 0) - ret = 0; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s write_room()=%d\n", - __FILE__, __LINE__, info->device_name, ret); - - return ret; -} - -/* enable transmitter and send remaining buffered characters - */ -static void flush_chars(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s flush_chars() entry tx_count=%d\n", - __FILE__,__LINE__,info->device_name,info->tx_count); - - if (sanity_check(info, tty->name, "flush_chars")) - return; - - if (info->tx_count <= 0 || tty->stopped || tty->hw_stopped || - !info->tx_buf) - return; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s flush_chars() entry, starting transmitter\n", - __FILE__,__LINE__,info->device_name ); - - spin_lock_irqsave(&info->lock,flags); - - if (!info->tx_active) { - if ( (info->params.mode == MGSL_MODE_HDLC) && - info->tx_count ) { - /* operating in synchronous (frame oriented) mode */ - /* copy data from circular tx_buf to */ - /* transmit DMA buffer. */ - tx_load_dma_buffer(info, - info->tx_buf,info->tx_count); - } - tx_start(info); - } - - spin_unlock_irqrestore(&info->lock,flags); -} - -/* Discard all data in the send buffer - */ -static void flush_buffer(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s flush_buffer() entry\n", - __FILE__,__LINE__, info->device_name ); - - if (sanity_check(info, tty->name, "flush_buffer")) - return; - - spin_lock_irqsave(&info->lock,flags); - info->tx_count = info->tx_put = info->tx_get = 0; - del_timer(&info->tx_timer); - spin_unlock_irqrestore(&info->lock,flags); - - tty_wakeup(tty); -} - -/* throttle (stop) transmitter - */ -static void tx_hold(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "tx_hold")) - return; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s(%d):%s tx_hold()\n", - __FILE__,__LINE__,info->device_name); - - spin_lock_irqsave(&info->lock,flags); - if (info->tx_enabled) - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); -} - -/* release (start) transmitter - */ -static void tx_release(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "tx_release")) - return; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s(%d):%s tx_release()\n", - __FILE__,__LINE__,info->device_name); - - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_enabled) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); -} - -/* Service an IOCTL request - * - * Arguments: - * - * tty pointer to tty instance data - * cmd IOCTL command code - * arg command argument/context - * - * Return Value: 0 if success, otherwise error code - */ -static int ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - SLMP_INFO *info = tty->driver_data; - void __user *argp = (void __user *)arg; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__, - info->device_name, cmd ); - - if (sanity_check(info, tty->name, "ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCMIWAIT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case MGSL_IOCGPARAMS: - return get_params(info, argp); - case MGSL_IOCSPARAMS: - return set_params(info, argp); - case MGSL_IOCGTXIDLE: - return get_txidle(info, argp); - case MGSL_IOCSTXIDLE: - return set_txidle(info, (int)arg); - case MGSL_IOCTXENABLE: - return tx_enable(info, (int)arg); - case MGSL_IOCRXENABLE: - return rx_enable(info, (int)arg); - case MGSL_IOCTXABORT: - return tx_abort(info); - case MGSL_IOCGSTATS: - return get_stats(info, argp); - case MGSL_IOCWAITEVENT: - return wait_mgsl_event(info, argp); - case MGSL_IOCLOOPTXDONE: - return 0; // TODO: Not supported, need to document - /* Wait for modem input (DCD,RI,DSR,CTS) change - * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS) - */ - case TIOCMIWAIT: - return modem_input_wait(info,(int)arg); - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - SLMP_INFO *info = tty->driver_data; - struct mgsl_icount cnow; /* kernel counter temps */ - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->lock,flags); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - -/* - * /proc fs routines.... - */ - -static inline void line_info(struct seq_file *m, SLMP_INFO *info) -{ - char stat_buf[30]; - unsigned long flags; - - seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" - "\tIRQ=%d MaxFrameSize=%u\n", - info->device_name, - info->phys_sca_base, - info->phys_memory_base, - info->phys_statctrl_base, - info->phys_lcr_base, - info->irq_level, - info->max_frame_size ); - - /* output current serial signal states */ - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if (info->serial_signals & SerialSignal_RTS) - strcat(stat_buf, "|RTS"); - if (info->serial_signals & SerialSignal_CTS) - strcat(stat_buf, "|CTS"); - if (info->serial_signals & SerialSignal_DTR) - strcat(stat_buf, "|DTR"); - if (info->serial_signals & SerialSignal_DSR) - strcat(stat_buf, "|DSR"); - if (info->serial_signals & SerialSignal_DCD) - strcat(stat_buf, "|CD"); - if (info->serial_signals & SerialSignal_RI) - strcat(stat_buf, "|RI"); - - if (info->params.mode == MGSL_MODE_HDLC) { - seq_printf(m, "\tHDLC txok:%d rxok:%d", - info->icount.txok, info->icount.rxok); - if (info->icount.txunder) - seq_printf(m, " txunder:%d", info->icount.txunder); - if (info->icount.txabort) - seq_printf(m, " txabort:%d", info->icount.txabort); - if (info->icount.rxshort) - seq_printf(m, " rxshort:%d", info->icount.rxshort); - if (info->icount.rxlong) - seq_printf(m, " rxlong:%d", info->icount.rxlong); - if (info->icount.rxover) - seq_printf(m, " rxover:%d", info->icount.rxover); - if (info->icount.rxcrc) - seq_printf(m, " rxlong:%d", info->icount.rxcrc); - } else { - seq_printf(m, "\tASYNC tx:%d rx:%d", - info->icount.tx, info->icount.rx); - if (info->icount.frame) - seq_printf(m, " fe:%d", info->icount.frame); - if (info->icount.parity) - seq_printf(m, " pe:%d", info->icount.parity); - if (info->icount.brk) - seq_printf(m, " brk:%d", info->icount.brk); - if (info->icount.overrun) - seq_printf(m, " oe:%d", info->icount.overrun); - } - - /* Append serial signal status to end */ - seq_printf(m, " %s\n", stat_buf+1); - - seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", - info->tx_active,info->bh_requested,info->bh_running, - info->pending_bh); -} - -/* Called to print information about devices - */ -static int synclinkmp_proc_show(struct seq_file *m, void *v) -{ - SLMP_INFO *info; - - seq_printf(m, "synclinkmp driver:%s\n", driver_version); - - info = synclinkmp_device_list; - while( info ) { - line_info(m, info); - info = info->next_device; - } - return 0; -} - -static int synclinkmp_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, synclinkmp_proc_show, NULL); -} - -static const struct file_operations synclinkmp_proc_fops = { - .owner = THIS_MODULE, - .open = synclinkmp_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* Return the count of bytes in transmit buffer - */ -static int chars_in_buffer(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - - if (sanity_check(info, tty->name, "chars_in_buffer")) - return 0; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s chars_in_buffer()=%d\n", - __FILE__, __LINE__, info->device_name, info->tx_count); - - return info->tx_count; -} - -/* Signal remote device to throttle send data (our receive data) - */ -static void throttle(struct tty_struct * tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s throttle() entry\n", - __FILE__,__LINE__, info->device_name ); - - if (sanity_check(info, tty->name, "throttle")) - return; - - if (I_IXOFF(tty)) - send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); - info->serial_signals &= ~SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* Signal remote device to stop throttling send data (our receive data) - */ -static void unthrottle(struct tty_struct * tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s unthrottle() entry\n", - __FILE__,__LINE__, info->device_name ); - - if (sanity_check(info, tty->name, "unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - send_xchar(tty, START_CHAR(tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); - info->serial_signals |= SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* set or clear transmit break condition - * break_state -1=set break condition, 0=clear - */ -static int set_break(struct tty_struct *tty, int break_state) -{ - unsigned char RegValue; - SLMP_INFO * info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s set_break(%d)\n", - __FILE__,__LINE__, info->device_name, break_state); - - if (sanity_check(info, tty->name, "set_break")) - return -EINVAL; - - spin_lock_irqsave(&info->lock,flags); - RegValue = read_reg(info, CTL); - if (break_state == -1) - RegValue |= BIT3; - else - RegValue &= ~BIT3; - write_reg(info, CTL, RegValue); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -#if SYNCLINK_GENERIC_HDLC - -/** - * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) - * set encoding and frame check sequence (FCS) options - * - * dev pointer to network device structure - * encoding serial encoding setting - * parity FCS setting - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -{ - SLMP_INFO *info = dev_to_port(dev); - unsigned char new_encoding; - unsigned short new_crctype; - - /* return error if TTY interface open */ - if (info->port.count) - return -EBUSY; - - switch (encoding) - { - case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; - case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; - case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; - case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; - case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; - default: return -EINVAL; - } - - switch (parity) - { - case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; - case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; - case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; - default: return -EINVAL; - } - - info->params.encoding = new_encoding; - info->params.crc_type = new_crctype; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - program_hw(info); - - return 0; -} - -/** - * called by generic HDLC layer to send frame - * - * skb socket buffer containing HDLC frame - * dev pointer to network device structure - */ -static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - SLMP_INFO *info = dev_to_port(dev); - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); - - /* stop sending until this frame completes */ - netif_stop_queue(dev); - - /* copy data to device buffers */ - info->tx_count = skb->len; - tx_load_dma_buffer(info, skb->data, skb->len); - - /* update network statistics */ - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - - /* done with socket buffer, so free it */ - dev_kfree_skb(skb); - - /* save start time for transmit timeout detection */ - dev->trans_start = jiffies; - - /* start hardware transmitter if necessary */ - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - - return NETDEV_TX_OK; -} - -/** - * called by network layer when interface enabled - * claim resources and initialize hardware - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_open(struct net_device *dev) -{ - SLMP_INFO *info = dev_to_port(dev); - int rc; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); - - /* generic HDLC layer open processing */ - if ((rc = hdlc_open(dev))) - return rc; - - /* arbitrate between network and tty opens */ - spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); - spin_unlock_irqrestore(&info->netlock, flags); - return -EBUSY; - } - info->netcount=1; - spin_unlock_irqrestore(&info->netlock, flags); - - /* claim resources and init adapter */ - if ((rc = startup(info)) != 0) { - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return rc; - } - - /* assert DTR and RTS, apply hardware settings */ - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - program_hw(info); - - /* enable network layer transmit */ - dev->trans_start = jiffies; - netif_start_queue(dev); - - /* inform generic HDLC layer of current DCD status */ - spin_lock_irqsave(&info->lock, flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock, flags); - if (info->serial_signals & SerialSignal_DCD) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - return 0; -} - -/** - * called by network layer when interface is disabled - * shutdown hardware and release resources - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_close(struct net_device *dev) -{ - SLMP_INFO *info = dev_to_port(dev); - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - - netif_stop_queue(dev); - - /* shutdown adapter and release resources */ - shutdown(info); - - hdlc_close(dev); - - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - - return 0; -} - -/** - * called by network layer to process IOCTL call to network device - * - * dev pointer to network device structure - * ifr pointer to network interface request structure - * cmd IOCTL command code - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line; - sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; - SLMP_INFO *info = dev_to_port(dev); - unsigned int flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - - /* return error if TTY interface open */ - if (info->port.count) - return -EBUSY; - - if (cmd != SIOCWANDEV) - return hdlc_ioctl(dev, ifr, cmd); - - switch(ifr->ifr_settings.type) { - case IF_GET_IFACE: /* return current sync_serial_settings */ - - ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - - flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - - switch (flags){ - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; - case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; - default: new_line.clock_type = CLOCK_DEFAULT; - } - - new_line.clock_rate = info->params.clock_speed; - new_line.loopback = info->params.loopback ? 1:0; - - if (copy_to_user(line, &new_line, size)) - return -EFAULT; - return 0; - - case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&new_line, line, size)) - return -EFAULT; - - switch (new_line.clock_type) - { - case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; - case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; - case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; - case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; - case CLOCK_DEFAULT: flags = info->params.flags & - (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; - default: return -EINVAL; - } - - if (new_line.loopback != 0 && new_line.loopback != 1) - return -EINVAL; - - info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - info->params.flags |= flags; - - info->params.loopback = new_line.loopback; - - if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) - info->params.clock_speed = new_line.clock_rate; - else - info->params.clock_speed = 0; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - program_hw(info); - return 0; - - default: - return hdlc_ioctl(dev, ifr, cmd); - } -} - -/** - * called by network layer when transmit timeout is detected - * - * dev pointer to network device structure - */ -static void hdlcdev_tx_timeout(struct net_device *dev) -{ - SLMP_INFO *info = dev_to_port(dev); - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("hdlcdev_tx_timeout(%s)\n",dev->name); - - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; - - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); - - netif_wake_queue(dev); -} - -/** - * called by device driver when transmit completes - * reenable network layer transmit if stopped - * - * info pointer to device instance information - */ -static void hdlcdev_tx_done(SLMP_INFO *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); -} - -/** - * called by device driver when frame received - * pass frame to network layer - * - * info pointer to device instance information - * buf pointer to buffer contianing frame data - * size count of data bytes in buf - */ -static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) -{ - struct sk_buff *skb = dev_alloc_skb(size); - struct net_device *dev = info->netdev; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("hdlcdev_rx(%s)\n",dev->name); - - if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - dev->name); - dev->stats.rx_dropped++; - return; - } - - memcpy(skb_put(skb, size), buf, size); - - skb->protocol = hdlc_type_trans(skb, dev); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += size; - - netif_rx(skb); -} - -static const struct net_device_ops hdlcdev_ops = { - .ndo_open = hdlcdev_open, - .ndo_stop = hdlcdev_close, - .ndo_change_mtu = hdlc_change_mtu, - .ndo_start_xmit = hdlc_start_xmit, - .ndo_do_ioctl = hdlcdev_ioctl, - .ndo_tx_timeout = hdlcdev_tx_timeout, -}; - -/** - * called by device driver when adding device instance - * do generic HDLC initialization - * - * info pointer to device instance information - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_init(SLMP_INFO *info) -{ - int rc; - struct net_device *dev; - hdlc_device *hdlc; - - /* allocate and initialize network and HDLC layer objects */ - - if (!(dev = alloc_hdlcdev(info))) { - printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); - return -ENOMEM; - } - - /* for network layer reporting purposes only */ - dev->mem_start = info->phys_sca_base; - dev->mem_end = info->phys_sca_base + SCA_BASE_SIZE - 1; - dev->irq = info->irq_level; - - /* network layer callbacks and settings */ - dev->netdev_ops = &hdlcdev_ops; - dev->watchdog_timeo = 10 * HZ; - dev->tx_queue_len = 50; - - /* generic HDLC layer callbacks and settings */ - hdlc = dev_to_hdlc(dev); - hdlc->attach = hdlcdev_attach; - hdlc->xmit = hdlcdev_xmit; - - /* register objects with HDLC layer */ - if ((rc = register_hdlc_device(dev))) { - printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); - free_netdev(dev); - return rc; - } - - info->netdev = dev; - return 0; -} - -/** - * called by device driver when removing device instance - * do generic HDLC cleanup - * - * info pointer to device instance information - */ -static void hdlcdev_exit(SLMP_INFO *info) -{ - unregister_hdlc_device(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; -} - -#endif /* CONFIG_HDLC */ - - -/* Return next bottom half action to perform. - * Return Value: BH action code or 0 if nothing to do. - */ -static int bh_action(SLMP_INFO *info) -{ - unsigned long flags; - int rc = 0; - - spin_lock_irqsave(&info->lock,flags); - - if (info->pending_bh & BH_RECEIVE) { - info->pending_bh &= ~BH_RECEIVE; - rc = BH_RECEIVE; - } else if (info->pending_bh & BH_TRANSMIT) { - info->pending_bh &= ~BH_TRANSMIT; - rc = BH_TRANSMIT; - } else if (info->pending_bh & BH_STATUS) { - info->pending_bh &= ~BH_STATUS; - rc = BH_STATUS; - } - - if (!rc) { - /* Mark BH routine as complete */ - info->bh_running = false; - info->bh_requested = false; - } - - spin_unlock_irqrestore(&info->lock,flags); - - return rc; -} - -/* Perform bottom half processing of work items queued by ISR. - */ -static void bh_handler(struct work_struct *work) -{ - SLMP_INFO *info = container_of(work, SLMP_INFO, task); - int action; - - if (!info) - return; - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s bh_handler() entry\n", - __FILE__,__LINE__,info->device_name); - - info->bh_running = true; - - while((action = bh_action(info)) != 0) { - - /* Process work item */ - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s bh_handler() work item action=%d\n", - __FILE__,__LINE__,info->device_name, action); - - switch (action) { - - case BH_RECEIVE: - bh_receive(info); - break; - case BH_TRANSMIT: - bh_transmit(info); - break; - case BH_STATUS: - bh_status(info); - break; - default: - /* unknown work item ID */ - printk("%s(%d):%s Unknown work item ID=%08X!\n", - __FILE__,__LINE__,info->device_name,action); - break; - } - } - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s bh_handler() exit\n", - __FILE__,__LINE__,info->device_name); -} - -static void bh_receive(SLMP_INFO *info) -{ - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s bh_receive()\n", - __FILE__,__LINE__,info->device_name); - - while( rx_get_frame(info) ); -} - -static void bh_transmit(SLMP_INFO *info) -{ - struct tty_struct *tty = info->port.tty; - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s bh_transmit() entry\n", - __FILE__,__LINE__,info->device_name); - - if (tty) - tty_wakeup(tty); -} - -static void bh_status(SLMP_INFO *info) -{ - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s bh_status() entry\n", - __FILE__,__LINE__,info->device_name); - - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - info->dcd_chkcount = 0; - info->cts_chkcount = 0; -} - -static void isr_timer(SLMP_INFO * info) -{ - unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0; - - /* IER2<7..4> = timer<3..0> interrupt enables (0=disabled) */ - write_reg(info, IER2, 0); - - /* TMCS, Timer Control/Status Register - * - * 07 CMF, Compare match flag (read only) 1=match - * 06 ECMI, CMF Interrupt Enable: 0=disabled - * 05 Reserved, must be 0 - * 04 TME, Timer Enable - * 03..00 Reserved, must be 0 - * - * 0000 0000 - */ - write_reg(info, (unsigned char)(timer + TMCS), 0); - - info->irq_occurred = true; - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_timer()\n", - __FILE__,__LINE__,info->device_name); -} - -static void isr_rxint(SLMP_INFO * info) -{ - struct tty_struct *tty = info->port.tty; - struct mgsl_icount *icount = &info->icount; - unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD); - unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN; - - /* clear status bits */ - if (status) - write_reg(info, SR1, status); - - if (status2) - write_reg(info, SR2, status2); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_rxint status=%02X %02x\n", - __FILE__,__LINE__,info->device_name,status,status2); - - if (info->params.mode == MGSL_MODE_ASYNC) { - if (status & BRKD) { - icount->brk++; - - /* process break detection if tty control - * is not set to ignore it - */ - if ( tty ) { - if (!(status & info->ignore_status_mask1)) { - if (info->read_status_mask1 & BRKD) { - tty_insert_flip_char(tty, 0, TTY_BREAK); - if (info->port.flags & ASYNC_SAK) - do_SAK(tty); - } - } - } - } - } - else { - if (status & (FLGD|IDLD)) { - if (status & FLGD) - info->icount.exithunt++; - else if (status & IDLD) - info->icount.rxidle++; - wake_up_interruptible(&info->event_wait_q); - } - } - - if (status & CDCD) { - /* simulate a common modem status change interrupt - * for our handler - */ - get_signals( info ); - isr_io_pin(info, - MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD)); - } -} - -/* - * handle async rx data interrupts - */ -static void isr_rxrdy(SLMP_INFO * info) -{ - u16 status; - unsigned char DataByte; - struct tty_struct *tty = info->port.tty; - struct mgsl_icount *icount = &info->icount; - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_rxrdy\n", - __FILE__,__LINE__,info->device_name); - - while((status = read_reg(info,CST0)) & BIT0) - { - int flag = 0; - bool over = false; - DataByte = read_reg(info,TRB); - - icount->rx++; - - if ( status & (PE + FRME + OVRN) ) { - printk("%s(%d):%s rxerr=%04X\n", - __FILE__,__LINE__,info->device_name,status); - - /* update error statistics */ - if (status & PE) - icount->parity++; - else if (status & FRME) - icount->frame++; - else if (status & OVRN) - icount->overrun++; - - /* discard char if tty control flags say so */ - if (status & info->ignore_status_mask2) - continue; - - status &= info->read_status_mask2; - - if ( tty ) { - if (status & PE) - flag = TTY_PARITY; - else if (status & FRME) - flag = TTY_FRAME; - if (status & OVRN) { - /* Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - over = true; - } - } - } /* end of if (error) */ - - if ( tty ) { - tty_insert_flip_char(tty, DataByte, flag); - if (over) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } - } - - if ( debug_level >= DEBUG_LEVEL_ISR ) { - printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n", - __FILE__,__LINE__,info->device_name, - icount->rx,icount->brk,icount->parity, - icount->frame,icount->overrun); - } - - if ( tty ) - tty_flip_buffer_push(tty); -} - -static void isr_txeom(SLMP_INFO * info, unsigned char status) -{ - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_txeom status=%02x\n", - __FILE__,__LINE__,info->device_name,status); - - write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ - write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */ - write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ - - if (status & UDRN) { - write_reg(info, CMD, TXRESET); - write_reg(info, CMD, TXENABLE); - } else - write_reg(info, CMD, TXBUFCLR); - - /* disable and clear tx interrupts */ - info->ie0_value &= ~TXRDYE; - info->ie1_value &= ~(IDLE + UDRN); - write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); - write_reg(info, SR1, (unsigned char)(UDRN + IDLE)); - - if ( info->tx_active ) { - if (info->params.mode != MGSL_MODE_ASYNC) { - if (status & UDRN) - info->icount.txunder++; - else if (status & IDLE) - info->icount.txok++; - } - - info->tx_active = false; - info->tx_count = info->tx_put = info->tx_get = 0; - - del_timer(&info->tx_timer); - - if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) { - info->serial_signals &= ~SerialSignal_RTS; - info->drop_rts_on_tx_done = false; - set_signals(info); - } - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - { - if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { - tx_stop(info); - return; - } - info->pending_bh |= BH_TRANSMIT; - } - } -} - - -/* - * handle tx status interrupts - */ -static void isr_txint(SLMP_INFO * info) -{ - unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS); - - /* clear status bits */ - write_reg(info, SR1, status); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_txint status=%02x\n", - __FILE__,__LINE__,info->device_name,status); - - if (status & (UDRN + IDLE)) - isr_txeom(info, status); - - if (status & CCTS) { - /* simulate a common modem status change interrupt - * for our handler - */ - get_signals( info ); - isr_io_pin(info, - MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS)); - - } -} - -/* - * handle async tx data interrupts - */ -static void isr_txrdy(SLMP_INFO * info) -{ - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_txrdy() tx_count=%d\n", - __FILE__,__LINE__,info->device_name,info->tx_count); - - if (info->params.mode != MGSL_MODE_ASYNC) { - /* disable TXRDY IRQ, enable IDLE IRQ */ - info->ie0_value &= ~TXRDYE; - info->ie1_value |= IDLE; - write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); - return; - } - - if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { - tx_stop(info); - return; - } - - if ( info->tx_count ) - tx_load_fifo( info ); - else { - info->tx_active = false; - info->ie0_value &= ~TXRDYE; - write_reg(info, IE0, info->ie0_value); - } - - if (info->tx_count < WAKEUP_CHARS) - info->pending_bh |= BH_TRANSMIT; -} - -static void isr_rxdmaok(SLMP_INFO * info) -{ - /* BIT7 = EOT (end of transfer) - * BIT6 = EOM (end of message/frame) - */ - unsigned char status = read_reg(info,RXDMA + DSR) & 0xc0; - - /* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */ - write_reg(info, RXDMA + DSR, (unsigned char)(status | 1)); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_rxdmaok(), status=%02x\n", - __FILE__,__LINE__,info->device_name,status); - - info->pending_bh |= BH_RECEIVE; -} - -static void isr_rxdmaerror(SLMP_INFO * info) -{ - /* BIT5 = BOF (buffer overflow) - * BIT4 = COF (counter overflow) - */ - unsigned char status = read_reg(info,RXDMA + DSR) & 0x30; - - /* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */ - write_reg(info, RXDMA + DSR, (unsigned char)(status | 1)); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n", - __FILE__,__LINE__,info->device_name,status); - - info->rx_overflow = true; - info->pending_bh |= BH_RECEIVE; -} - -static void isr_txdmaok(SLMP_INFO * info) -{ - unsigned char status_reg1 = read_reg(info, SR1); - - write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ - write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */ - write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_txdmaok(), status=%02x\n", - __FILE__,__LINE__,info->device_name,status_reg1); - - /* program TXRDY as FIFO empty flag, enable TXRDY IRQ */ - write_reg16(info, TRC0, 0); - info->ie0_value |= TXRDYE; - write_reg(info, IE0, info->ie0_value); -} - -static void isr_txdmaerror(SLMP_INFO * info) -{ - /* BIT5 = BOF (buffer overflow) - * BIT4 = COF (counter overflow) - */ - unsigned char status = read_reg(info,TXDMA + DSR) & 0x30; - - /* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */ - write_reg(info, TXDMA + DSR, (unsigned char)(status | 1)); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s isr_txdmaerror(), status=%02x\n", - __FILE__,__LINE__,info->device_name,status); -} - -/* handle input serial signal changes - */ -static void isr_io_pin( SLMP_INFO *info, u16 status ) -{ - struct mgsl_icount *icount; - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):isr_io_pin status=%04X\n", - __FILE__,__LINE__,status); - - if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED | - MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) { - icount = &info->icount; - /* update input line counters */ - if (status & MISCSTATUS_RI_LATCHED) { - icount->rng++; - if ( status & SerialSignal_RI ) - info->input_signal_events.ri_up++; - else - info->input_signal_events.ri_down++; - } - if (status & MISCSTATUS_DSR_LATCHED) { - icount->dsr++; - if ( status & SerialSignal_DSR ) - info->input_signal_events.dsr_up++; - else - info->input_signal_events.dsr_down++; - } - if (status & MISCSTATUS_DCD_LATCHED) { - if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) { - info->ie1_value &= ~CDCD; - write_reg(info, IE1, info->ie1_value); - } - icount->dcd++; - if (status & SerialSignal_DCD) { - info->input_signal_events.dcd_up++; - } else - info->input_signal_events.dcd_down++; -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) { - if (status & SerialSignal_DCD) - netif_carrier_on(info->netdev); - else - netif_carrier_off(info->netdev); - } -#endif - } - if (status & MISCSTATUS_CTS_LATCHED) - { - if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) { - info->ie1_value &= ~CCTS; - write_reg(info, IE1, info->ie1_value); - } - icount->cts++; - if ( status & SerialSignal_CTS ) - info->input_signal_events.cts_up++; - else - info->input_signal_events.cts_down++; - } - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - - if ( (info->port.flags & ASYNC_CHECK_CD) && - (status & MISCSTATUS_DCD_LATCHED) ) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s CD now %s...", info->device_name, - (status & SerialSignal_DCD) ? "on" : "off"); - if (status & SerialSignal_DCD) - wake_up_interruptible(&info->port.open_wait); - else { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("doing serial hangup..."); - if (info->port.tty) - tty_hangup(info->port.tty); - } - } - - if ( (info->port.flags & ASYNC_CTS_FLOW) && - (status & MISCSTATUS_CTS_LATCHED) ) { - if ( info->port.tty ) { - if (info->port.tty->hw_stopped) { - if (status & SerialSignal_CTS) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("CTS tx start..."); - info->port.tty->hw_stopped = 0; - tx_start(info); - info->pending_bh |= BH_TRANSMIT; - return; - } - } else { - if (!(status & SerialSignal_CTS)) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("CTS tx stop..."); - info->port.tty->hw_stopped = 1; - tx_stop(info); - } - } - } - } - } - - info->pending_bh |= BH_STATUS; -} - -/* Interrupt service routine entry point. - * - * Arguments: - * irq interrupt number that caused interrupt - * dev_id device ID supplied during interrupt registration - * regs interrupted processor context - */ -static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id) -{ - SLMP_INFO *info = dev_id; - unsigned char status, status0, status1=0; - unsigned char dmastatus, dmastatus0, dmastatus1=0; - unsigned char timerstatus0, timerstatus1=0; - unsigned char shift; - unsigned int i; - unsigned short tmp; - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n", - __FILE__, __LINE__, info->irq_level); - - spin_lock(&info->lock); - - for(;;) { - - /* get status for SCA0 (ports 0-1) */ - tmp = read_reg16(info, ISR0); /* get ISR0 and ISR1 in one read */ - status0 = (unsigned char)tmp; - dmastatus0 = (unsigned char)(tmp>>8); - timerstatus0 = read_reg(info, ISR2); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n", - __FILE__, __LINE__, info->device_name, - status0, dmastatus0, timerstatus0); - - if (info->port_count == 4) { - /* get status for SCA1 (ports 2-3) */ - tmp = read_reg16(info->port_array[2], ISR0); - status1 = (unsigned char)tmp; - dmastatus1 = (unsigned char)(tmp>>8); - timerstatus1 = read_reg(info->port_array[2], ISR2); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s status1=%02x, dmastatus1=%02x, timerstatus1=%02x\n", - __FILE__,__LINE__,info->device_name, - status1,dmastatus1,timerstatus1); - } - - if (!status0 && !dmastatus0 && !timerstatus0 && - !status1 && !dmastatus1 && !timerstatus1) - break; - - for(i=0; i < info->port_count ; i++) { - if (info->port_array[i] == NULL) - continue; - if (i < 2) { - status = status0; - dmastatus = dmastatus0; - } else { - status = status1; - dmastatus = dmastatus1; - } - - shift = i & 1 ? 4 :0; - - if (status & BIT0 << shift) - isr_rxrdy(info->port_array[i]); - if (status & BIT1 << shift) - isr_txrdy(info->port_array[i]); - if (status & BIT2 << shift) - isr_rxint(info->port_array[i]); - if (status & BIT3 << shift) - isr_txint(info->port_array[i]); - - if (dmastatus & BIT0 << shift) - isr_rxdmaerror(info->port_array[i]); - if (dmastatus & BIT1 << shift) - isr_rxdmaok(info->port_array[i]); - if (dmastatus & BIT2 << shift) - isr_txdmaerror(info->port_array[i]); - if (dmastatus & BIT3 << shift) - isr_txdmaok(info->port_array[i]); - } - - if (timerstatus0 & (BIT5 | BIT4)) - isr_timer(info->port_array[0]); - if (timerstatus0 & (BIT7 | BIT6)) - isr_timer(info->port_array[1]); - if (timerstatus1 & (BIT5 | BIT4)) - isr_timer(info->port_array[2]); - if (timerstatus1 & (BIT7 | BIT6)) - isr_timer(info->port_array[3]); - } - - for(i=0; i < info->port_count ; i++) { - SLMP_INFO * port = info->port_array[i]; - - /* Request bottom half processing if there's something - * for it to do and the bh is not already running. - * - * Note: startup adapter diags require interrupts. - * do not request bottom half processing if the - * device is not open in a normal mode. - */ - if ( port && (port->port.count || port->netcount) && - port->pending_bh && !port->bh_running && - !port->bh_requested ) { - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s queueing bh task.\n", - __FILE__,__LINE__,port->device_name); - schedule_work(&port->task); - port->bh_requested = true; - } - } - - spin_unlock(&info->lock); - - if ( debug_level >= DEBUG_LEVEL_ISR ) - printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n", - __FILE__, __LINE__, info->irq_level); - return IRQ_HANDLED; -} - -/* Initialize and start device. - */ -static int startup(SLMP_INFO * info) -{ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s(%d):%s tx_releaseup()\n",__FILE__,__LINE__,info->device_name); - - if (info->port.flags & ASYNC_INITIALIZED) - return 0; - - if (!info->tx_buf) { - info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); - if (!info->tx_buf) { - printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", - __FILE__,__LINE__,info->device_name); - return -ENOMEM; - } - } - - info->pending_bh = 0; - - memset(&info->icount, 0, sizeof(info->icount)); - - /* program hardware for current parameters */ - reset_port(info); - - change_params(info); - - mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); - - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags |= ASYNC_INITIALIZED; - - return 0; -} - -/* Called by close() and hangup() to shutdown hardware - */ -static void shutdown(SLMP_INFO * info) -{ - unsigned long flags; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s synclinkmp_shutdown()\n", - __FILE__,__LINE__, info->device_name ); - - /* clear status wait queue because status changes */ - /* can't happen after shutting down the hardware */ - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - - del_timer(&info->tx_timer); - del_timer(&info->status_timer); - - kfree(info->tx_buf); - info->tx_buf = NULL; - - spin_lock_irqsave(&info->lock,flags); - - reset_port(info); - - if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { - info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - set_signals(info); - } - - spin_unlock_irqrestore(&info->lock,flags); - - if (info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->port.flags &= ~ASYNC_INITIALIZED; -} - -static void program_hw(SLMP_INFO *info) -{ - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - - rx_stop(info); - tx_stop(info); - - info->tx_count = info->tx_put = info->tx_get = 0; - - if (info->params.mode == MGSL_MODE_HDLC || info->netcount) - hdlc_mode(info); - else - async_mode(info); - - set_signals(info); - - info->dcd_chkcount = 0; - info->cts_chkcount = 0; - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - - info->ie1_value |= (CDCD|CCTS); - write_reg(info, IE1, info->ie1_value); - - get_signals(info); - - if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) ) - rx_start(info); - - spin_unlock_irqrestore(&info->lock,flags); -} - -/* Reconfigure adapter based on new parameters - */ -static void change_params(SLMP_INFO *info) -{ - unsigned cflag; - int bits_per_char; - - if (!info->port.tty || !info->port.tty->termios) - return; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s change_params()\n", - __FILE__,__LINE__, info->device_name ); - - cflag = info->port.tty->termios->c_cflag; - - /* if B0 rate (hangup) specified then negate DTR and RTS */ - /* otherwise assert DTR and RTS */ - if (cflag & CBAUD) - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - - /* byte size and parity */ - - switch (cflag & CSIZE) { - case CS5: info->params.data_bits = 5; break; - case CS6: info->params.data_bits = 6; break; - case CS7: info->params.data_bits = 7; break; - case CS8: info->params.data_bits = 8; break; - /* Never happens, but GCC is too dumb to figure it out */ - default: info->params.data_bits = 7; break; - } - - if (cflag & CSTOPB) - info->params.stop_bits = 2; - else - info->params.stop_bits = 1; - - info->params.parity = ASYNC_PARITY_NONE; - if (cflag & PARENB) { - if (cflag & PARODD) - info->params.parity = ASYNC_PARITY_ODD; - else - info->params.parity = ASYNC_PARITY_EVEN; -#ifdef CMSPAR - if (cflag & CMSPAR) - info->params.parity = ASYNC_PARITY_SPACE; -#endif - } - - /* calculate number of jiffies to transmit a full - * FIFO (32 bytes) at specified data rate - */ - bits_per_char = info->params.data_bits + - info->params.stop_bits + 1; - - /* if port data rate is set to 460800 or less then - * allow tty settings to override, otherwise keep the - * current data rate. - */ - if (info->params.data_rate <= 460800) { - info->params.data_rate = tty_get_baud_rate(info->port.tty); - } - - if ( info->params.data_rate ) { - info->timeout = (32*HZ*bits_per_char) / - info->params.data_rate; - } - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - if (cflag & CRTSCTS) - info->port.flags |= ASYNC_CTS_FLOW; - else - info->port.flags &= ~ASYNC_CTS_FLOW; - - if (cflag & CLOCAL) - info->port.flags &= ~ASYNC_CHECK_CD; - else - info->port.flags |= ASYNC_CHECK_CD; - - /* process tty input control flags */ - - info->read_status_mask2 = OVRN; - if (I_INPCK(info->port.tty)) - info->read_status_mask2 |= PE | FRME; - if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) - info->read_status_mask1 |= BRKD; - if (I_IGNPAR(info->port.tty)) - info->ignore_status_mask2 |= PE | FRME; - if (I_IGNBRK(info->port.tty)) { - info->ignore_status_mask1 |= BRKD; - /* If ignoring parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->port.tty)) - info->ignore_status_mask2 |= OVRN; - } - - program_hw(info); -} - -static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) -{ - int err; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s get_params()\n", - __FILE__,__LINE__, info->device_name); - - if (!user_icount) { - memset(&info->icount, 0, sizeof(info->icount)); - } else { - mutex_lock(&info->port.mutex); - COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); - mutex_unlock(&info->port.mutex); - if (err) - return -EFAULT; - } - - return 0; -} - -static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params) -{ - int err; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s get_params()\n", - __FILE__,__LINE__, info->device_name); - - mutex_lock(&info->port.mutex); - COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); - mutex_unlock(&info->port.mutex); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s get_params() user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; - } - - return 0; -} - -static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params) -{ - unsigned long flags; - MGSL_PARAMS tmp_params; - int err; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s set_params\n", - __FILE__,__LINE__,info->device_name ); - COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s set_params() user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; - } - - mutex_lock(&info->port.mutex); - spin_lock_irqsave(&info->lock,flags); - memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); - spin_unlock_irqrestore(&info->lock,flags); - - change_params(info); - mutex_unlock(&info->port.mutex); - - return 0; -} - -static int get_txidle(SLMP_INFO * info, int __user *idle_mode) -{ - int err; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s get_txidle()=%d\n", - __FILE__,__LINE__, info->device_name, info->idle_mode); - - COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s get_txidle() user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; - } - - return 0; -} - -static int set_txidle(SLMP_INFO * info, int idle_mode) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s set_txidle(%d)\n", - __FILE__,__LINE__,info->device_name, idle_mode ); - - spin_lock_irqsave(&info->lock,flags); - info->idle_mode = idle_mode; - tx_set_idle( info ); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int tx_enable(SLMP_INFO * info, int enable) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s tx_enable(%d)\n", - __FILE__,__LINE__,info->device_name, enable); - - spin_lock_irqsave(&info->lock,flags); - if ( enable ) { - if ( !info->tx_enabled ) { - tx_start(info); - } - } else { - if ( info->tx_enabled ) - tx_stop(info); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* abort send HDLC frame - */ -static int tx_abort(SLMP_INFO * info) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s tx_abort()\n", - __FILE__,__LINE__,info->device_name); - - spin_lock_irqsave(&info->lock,flags); - if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) { - info->ie1_value &= ~UDRN; - info->ie1_value |= IDLE; - write_reg(info, IE1, info->ie1_value); /* disable tx status interrupts */ - write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); /* clear pending */ - - write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ - write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ - - write_reg(info, CMD, TXABORT); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int rx_enable(SLMP_INFO * info, int enable) -{ - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s rx_enable(%d)\n", - __FILE__,__LINE__,info->device_name,enable); - - spin_lock_irqsave(&info->lock,flags); - if ( enable ) { - if ( !info->rx_enabled ) - rx_start(info); - } else { - if ( info->rx_enabled ) - rx_stop(info); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* wait for specified event to occur - */ -static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) -{ - unsigned long flags; - int s; - int rc=0; - struct mgsl_icount cprev, cnow; - int events; - int mask; - struct _input_signal_events oldsigs, newsigs; - DECLARE_WAITQUEUE(wait, current); - - COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int)); - if (rc) { - return -EFAULT; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s wait_mgsl_event(%d)\n", - __FILE__,__LINE__,info->device_name,mask); - - spin_lock_irqsave(&info->lock,flags); - - /* return immediately if state matches requested events */ - get_signals(info); - s = info->serial_signals; - - events = mask & - ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + - ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + - ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + - ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); - if (events) { - spin_unlock_irqrestore(&info->lock,flags); - goto exit; - } - - /* save current irq counts */ - cprev = info->icount; - oldsigs = info->input_signal_events; - - /* enable hunt and idle irqs if needed */ - if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) { - unsigned char oldval = info->ie1_value; - unsigned char newval = oldval + - (mask & MgslEvent_ExitHuntMode ? FLGD:0) + - (mask & MgslEvent_IdleReceived ? IDLD:0); - if ( oldval != newval ) { - info->ie1_value = newval; - write_reg(info, IE1, info->ie1_value); - } - } - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&info->event_wait_q, &wait); - - spin_unlock_irqrestore(&info->lock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get current irq counts */ - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - newsigs = info->input_signal_events; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - /* if no change, wait aborted for some reason */ - if (newsigs.dsr_up == oldsigs.dsr_up && - newsigs.dsr_down == oldsigs.dsr_down && - newsigs.dcd_up == oldsigs.dcd_up && - newsigs.dcd_down == oldsigs.dcd_down && - newsigs.cts_up == oldsigs.cts_up && - newsigs.cts_down == oldsigs.cts_down && - newsigs.ri_up == oldsigs.ri_up && - newsigs.ri_down == oldsigs.ri_down && - cnow.exithunt == cprev.exithunt && - cnow.rxidle == cprev.rxidle) { - rc = -EIO; - break; - } - - events = mask & - ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + - (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + - (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + - (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + - (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + - (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + - (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + - (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + - (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + - (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); - if (events) - break; - - cprev = cnow; - oldsigs = newsigs; - } - - remove_wait_queue(&info->event_wait_q, &wait); - set_current_state(TASK_RUNNING); - - - if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { - spin_lock_irqsave(&info->lock,flags); - if (!waitqueue_active(&info->event_wait_q)) { - /* disable enable exit hunt mode/idle rcvd IRQs */ - info->ie1_value &= ~(FLGD|IDLD); - write_reg(info, IE1, info->ie1_value); - } - spin_unlock_irqrestore(&info->lock,flags); - } -exit: - if ( rc == 0 ) - PUT_USER(rc, events, mask_ptr); - - return rc; -} - -static int modem_input_wait(SLMP_INFO *info,int arg) -{ - unsigned long flags; - int rc; - struct mgsl_icount cprev, cnow; - DECLARE_WAITQUEUE(wait, current); - - /* save current irq counts */ - spin_lock_irqsave(&info->lock,flags); - cprev = info->icount; - add_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get new irq counts */ - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - /* if no change, wait aborted for some reason */ - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - rc = -EIO; - break; - } - - /* check for change in caller specified modem input */ - if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || - (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || - (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || - (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { - rc = 0; - break; - } - - cprev = cnow; - } - remove_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_RUNNING); - return rc; -} - -/* return the state of the serial control and status signals - */ -static int tiocmget(struct tty_struct *tty) -{ - SLMP_INFO *info = tty->driver_data; - unsigned int result; - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) + - ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) + - ((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) + - ((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) + - ((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) + - ((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0); - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s tiocmget() value=%08X\n", - __FILE__,__LINE__, info->device_name, result ); - return result; -} - -/* set modem control signals (DTR/RTS) - */ -static int tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - SLMP_INFO *info = tty->driver_data; - unsigned long flags; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s tiocmset(%x,%x)\n", - __FILE__,__LINE__,info->device_name, set, clear); - - if (set & TIOCM_RTS) - info->serial_signals |= SerialSignal_RTS; - if (set & TIOCM_DTR) - info->serial_signals |= SerialSignal_DTR; - if (clear & TIOCM_RTS) - info->serial_signals &= ~SerialSignal_RTS; - if (clear & TIOCM_DTR) - info->serial_signals &= ~SerialSignal_DTR; - - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - return 0; -} - -static int carrier_raised(struct tty_port *port) -{ - SLMP_INFO *info = container_of(port, SLMP_INFO, port); - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; -} - -static void dtr_rts(struct tty_port *port, int on) -{ - SLMP_INFO *info = container_of(port, SLMP_INFO, port); - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - if (on) - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); -} - -/* Block the current process until the specified port is ready to open. - */ -static int block_til_ready(struct tty_struct *tty, struct file *filp, - SLMP_INFO *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - bool do_clocal = false; - bool extra_count = false; - unsigned long flags; - int cd; - struct tty_port *port = &info->port; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s block_til_ready()\n", - __FILE__,__LINE__, tty->driver->name ); - - if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ - /* nonblock mode is set or port is not enabled */ - /* just verify that callout device is not active */ - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = true; - - /* Wait for carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, port->count is dropped by one, so that - * close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - - retval = 0; - add_wait_queue(&port->open_wait, &wait); - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s block_til_ready() before block, count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); - - spin_lock_irqsave(&info->lock, flags); - if (!tty_hung_up_p(filp)) { - extra_count = true; - port->count--; - } - spin_unlock_irqrestore(&info->lock, flags); - port->blocked_open++; - - while (1) { - if (tty->termios->c_cflag & CBAUD) - tty_port_raise_dtr_rts(port); - - set_current_state(TASK_INTERRUPTIBLE); - - if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ - retval = (port->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - break; - } - - cd = tty_port_carrier_raised(port); - - if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd)) - break; - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s block_til_ready() count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); - - tty_unlock(); - schedule(); - tty_lock(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - - if (extra_count) - port->count++; - port->blocked_open--; - - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s block_til_ready() after, count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); - - if (!retval) - port->flags |= ASYNC_NORMAL_ACTIVE; - - return retval; -} - -static int alloc_dma_bufs(SLMP_INFO *info) -{ - unsigned short BuffersPerFrame; - unsigned short BufferCount; - - // Force allocation to start at 64K boundary for each port. - // This is necessary because *all* buffer descriptors for a port - // *must* be in the same 64K block. All descriptors on a port - // share a common 'base' address (upper 8 bits of 24 bits) programmed - // into the CBP register. - info->port_array[0]->last_mem_alloc = (SCA_MEM_SIZE/4) * info->port_num; - - /* Calculate the number of DMA buffers necessary to hold the */ - /* largest allowable frame size. Note: If the max frame size is */ - /* not an even multiple of the DMA buffer size then we need to */ - /* round the buffer count per frame up one. */ - - BuffersPerFrame = (unsigned short)(info->max_frame_size/SCABUFSIZE); - if ( info->max_frame_size % SCABUFSIZE ) - BuffersPerFrame++; - - /* calculate total number of data buffers (SCABUFSIZE) possible - * in one ports memory (SCA_MEM_SIZE/4) after allocating memory - * for the descriptor list (BUFFERLISTSIZE). - */ - BufferCount = (SCA_MEM_SIZE/4 - BUFFERLISTSIZE)/SCABUFSIZE; - - /* limit number of buffers to maximum amount of descriptors */ - if (BufferCount > BUFFERLISTSIZE/sizeof(SCADESC)) - BufferCount = BUFFERLISTSIZE/sizeof(SCADESC); - - /* use enough buffers to transmit one max size frame */ - info->tx_buf_count = BuffersPerFrame + 1; - - /* never use more than half the available buffers for transmit */ - if (info->tx_buf_count > (BufferCount/2)) - info->tx_buf_count = BufferCount/2; - - if (info->tx_buf_count > SCAMAXDESC) - info->tx_buf_count = SCAMAXDESC; - - /* use remaining buffers for receive */ - info->rx_buf_count = BufferCount - info->tx_buf_count; - - if (info->rx_buf_count > SCAMAXDESC) - info->rx_buf_count = SCAMAXDESC; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("%s(%d):%s Allocating %d TX and %d RX DMA buffers.\n", - __FILE__,__LINE__, info->device_name, - info->tx_buf_count,info->rx_buf_count); - - if ( alloc_buf_list( info ) < 0 || - alloc_frame_bufs(info, - info->rx_buf_list, - info->rx_buf_list_ex, - info->rx_buf_count) < 0 || - alloc_frame_bufs(info, - info->tx_buf_list, - info->tx_buf_list_ex, - info->tx_buf_count) < 0 || - alloc_tmp_rx_buf(info) < 0 ) { - printk("%s(%d):%s Can't allocate DMA buffer memory\n", - __FILE__,__LINE__, info->device_name); - return -ENOMEM; - } - - rx_reset_buffers( info ); - - return 0; -} - -/* Allocate DMA buffers for the transmit and receive descriptor lists. - */ -static int alloc_buf_list(SLMP_INFO *info) -{ - unsigned int i; - - /* build list in adapter shared memory */ - info->buffer_list = info->memory_base + info->port_array[0]->last_mem_alloc; - info->buffer_list_phys = info->port_array[0]->last_mem_alloc; - info->port_array[0]->last_mem_alloc += BUFFERLISTSIZE; - - memset(info->buffer_list, 0, BUFFERLISTSIZE); - - /* Save virtual address pointers to the receive and */ - /* transmit buffer lists. (Receive 1st). These pointers will */ - /* be used by the processor to access the lists. */ - info->rx_buf_list = (SCADESC *)info->buffer_list; - - info->tx_buf_list = (SCADESC *)info->buffer_list; - info->tx_buf_list += info->rx_buf_count; - - /* Build links for circular buffer entry lists (tx and rx) - * - * Note: links are physical addresses read by the SCA device - * to determine the next buffer entry to use. - */ - - for ( i = 0; i < info->rx_buf_count; i++ ) { - /* calculate and store physical address of this buffer entry */ - info->rx_buf_list_ex[i].phys_entry = - info->buffer_list_phys + (i * sizeof(SCABUFSIZE)); - - /* calculate and store physical address of */ - /* next entry in cirular list of entries */ - info->rx_buf_list[i].next = info->buffer_list_phys; - if ( i < info->rx_buf_count - 1 ) - info->rx_buf_list[i].next += (i + 1) * sizeof(SCADESC); - - info->rx_buf_list[i].length = SCABUFSIZE; - } - - for ( i = 0; i < info->tx_buf_count; i++ ) { - /* calculate and store physical address of this buffer entry */ - info->tx_buf_list_ex[i].phys_entry = info->buffer_list_phys + - ((info->rx_buf_count + i) * sizeof(SCADESC)); - - /* calculate and store physical address of */ - /* next entry in cirular list of entries */ - - info->tx_buf_list[i].next = info->buffer_list_phys + - info->rx_buf_count * sizeof(SCADESC); - - if ( i < info->tx_buf_count - 1 ) - info->tx_buf_list[i].next += (i + 1) * sizeof(SCADESC); - } - - return 0; -} - -/* Allocate the frame DMA buffers used by the specified buffer list. - */ -static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count) -{ - int i; - unsigned long phys_addr; - - for ( i = 0; i < count; i++ ) { - buf_list_ex[i].virt_addr = info->memory_base + info->port_array[0]->last_mem_alloc; - phys_addr = info->port_array[0]->last_mem_alloc; - info->port_array[0]->last_mem_alloc += SCABUFSIZE; - - buf_list[i].buf_ptr = (unsigned short)phys_addr; - buf_list[i].buf_base = (unsigned char)(phys_addr >> 16); - } - - return 0; -} - -static void free_dma_bufs(SLMP_INFO *info) -{ - info->buffer_list = NULL; - info->rx_buf_list = NULL; - info->tx_buf_list = NULL; -} - -/* allocate buffer large enough to hold max_frame_size. - * This buffer is used to pass an assembled frame to the line discipline. - */ -static int alloc_tmp_rx_buf(SLMP_INFO *info) -{ - info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); - if (info->tmp_rx_buf == NULL) - return -ENOMEM; - return 0; -} - -static void free_tmp_rx_buf(SLMP_INFO *info) -{ - kfree(info->tmp_rx_buf); - info->tmp_rx_buf = NULL; -} - -static int claim_resources(SLMP_INFO *info) -{ - if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) { - printk( "%s(%d):%s mem addr conflict, Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base); - info->init_error = DiagStatus_AddressConflict; - goto errout; - } - else - info->shared_mem_requested = true; - - if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) { - printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base); - info->init_error = DiagStatus_AddressConflict; - goto errout; - } - else - info->lcr_mem_requested = true; - - if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) { - printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_sca_base); - info->init_error = DiagStatus_AddressConflict; - goto errout; - } - else - info->sca_base_requested = true; - - if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) { - printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_statctrl_base); - info->init_error = DiagStatus_AddressConflict; - goto errout; - } - else - info->sca_statctrl_requested = true; - - info->memory_base = ioremap_nocache(info->phys_memory_base, - SCA_MEM_SIZE); - if (!info->memory_base) { - printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - info->init_error = DiagStatus_CantAssignPciResources; - goto errout; - } - - info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE); - if (!info->lcr_base) { - printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); - info->init_error = DiagStatus_CantAssignPciResources; - goto errout; - } - info->lcr_base += info->lcr_offset; - - info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE); - if (!info->sca_base) { - printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_sca_base ); - info->init_error = DiagStatus_CantAssignPciResources; - goto errout; - } - info->sca_base += info->sca_offset; - - info->statctrl_base = ioremap_nocache(info->phys_statctrl_base, - PAGE_SIZE); - if (!info->statctrl_base) { - printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_statctrl_base ); - info->init_error = DiagStatus_CantAssignPciResources; - goto errout; - } - info->statctrl_base += info->statctrl_offset; - - if ( !memory_test(info) ) { - printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - info->init_error = DiagStatus_MemoryError; - goto errout; - } - - return 0; - -errout: - release_resources( info ); - return -ENODEV; -} - -static void release_resources(SLMP_INFO *info) -{ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s release_resources() entry\n", - __FILE__,__LINE__,info->device_name ); - - if ( info->irq_requested ) { - free_irq(info->irq_level, info); - info->irq_requested = false; - } - - if ( info->shared_mem_requested ) { - release_mem_region(info->phys_memory_base,SCA_MEM_SIZE); - info->shared_mem_requested = false; - } - if ( info->lcr_mem_requested ) { - release_mem_region(info->phys_lcr_base + info->lcr_offset,128); - info->lcr_mem_requested = false; - } - if ( info->sca_base_requested ) { - release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE); - info->sca_base_requested = false; - } - if ( info->sca_statctrl_requested ) { - release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE); - info->sca_statctrl_requested = false; - } - - if (info->memory_base){ - iounmap(info->memory_base); - info->memory_base = NULL; - } - - if (info->sca_base) { - iounmap(info->sca_base - info->sca_offset); - info->sca_base=NULL; - } - - if (info->statctrl_base) { - iounmap(info->statctrl_base - info->statctrl_offset); - info->statctrl_base=NULL; - } - - if (info->lcr_base){ - iounmap(info->lcr_base - info->lcr_offset); - info->lcr_base = NULL; - } - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s release_resources() exit\n", - __FILE__,__LINE__,info->device_name ); -} - -/* Add the specified device instance data structure to the - * global linked list of devices and increment the device count. - */ -static void add_device(SLMP_INFO *info) -{ - info->next_device = NULL; - info->line = synclinkmp_device_count; - sprintf(info->device_name,"ttySLM%dp%d",info->adapter_num,info->port_num); - - if (info->line < MAX_DEVICES) { - if (maxframe[info->line]) - info->max_frame_size = maxframe[info->line]; - } - - synclinkmp_device_count++; - - if ( !synclinkmp_device_list ) - synclinkmp_device_list = info; - else { - SLMP_INFO *current_dev = synclinkmp_device_list; - while( current_dev->next_device ) - current_dev = current_dev->next_device; - current_dev->next_device = info; - } - - if ( info->max_frame_size < 4096 ) - info->max_frame_size = 4096; - else if ( info->max_frame_size > 65535 ) - info->max_frame_size = 65535; - - printk( "SyncLink MultiPort %s: " - "Mem=(%08x %08X %08x %08X) IRQ=%d MaxFrameSize=%u\n", - info->device_name, - info->phys_sca_base, - info->phys_memory_base, - info->phys_statctrl_base, - info->phys_lcr_base, - info->irq_level, - info->max_frame_size ); - -#if SYNCLINK_GENERIC_HDLC - hdlcdev_init(info); -#endif -} - -static const struct tty_port_operations port_ops = { - .carrier_raised = carrier_raised, - .dtr_rts = dtr_rts, -}; - -/* Allocate and initialize a device instance structure - * - * Return Value: pointer to SLMP_INFO if success, otherwise NULL - */ -static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) -{ - SLMP_INFO *info; - - info = kzalloc(sizeof(SLMP_INFO), - GFP_KERNEL); - - if (!info) { - printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n", - __FILE__,__LINE__, adapter_num, port_num); - } else { - tty_port_init(&info->port); - info->port.ops = &port_ops; - info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler); - info->max_frame_size = 4096; - info->port.close_delay = 5*HZ/10; - info->port.closing_wait = 30*HZ; - init_waitqueue_head(&info->status_event_wait_q); - init_waitqueue_head(&info->event_wait_q); - spin_lock_init(&info->netlock); - memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - info->idle_mode = HDLC_TXIDLE_FLAGS; - info->adapter_num = adapter_num; - info->port_num = port_num; - - /* Copy configuration info to device instance data */ - info->irq_level = pdev->irq; - info->phys_lcr_base = pci_resource_start(pdev,0); - info->phys_sca_base = pci_resource_start(pdev,2); - info->phys_memory_base = pci_resource_start(pdev,3); - info->phys_statctrl_base = pci_resource_start(pdev,4); - - /* Because veremap only works on page boundaries we must map - * a larger area than is actually implemented for the LCR - * memory range. We map a full page starting at the page boundary. - */ - info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); - info->phys_lcr_base &= ~(PAGE_SIZE-1); - - info->sca_offset = info->phys_sca_base & (PAGE_SIZE-1); - info->phys_sca_base &= ~(PAGE_SIZE-1); - - info->statctrl_offset = info->phys_statctrl_base & (PAGE_SIZE-1); - info->phys_statctrl_base &= ~(PAGE_SIZE-1); - - info->bus_type = MGSL_BUS_TYPE_PCI; - info->irq_flags = IRQF_SHARED; - - 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 - * BIOS assigns an LCR base address with bit 7 set. - * - * Only the misc control register is accessed for which only - * write access is needed, so set an initial value and change - * bits to the device instance data as we write the value - * to the actual misc control register. - */ - info->misc_ctrl_value = 0x087e4546; - - /* initial port state is unknown - if startup errors - * occur, init_error will be set to indicate the - * problem. Once the port is fully initialized, - * this value will be set to 0 to indicate the - * port is available. - */ - info->init_error = -1; - } - - return info; -} - -static void device_init(int adapter_num, struct pci_dev *pdev) -{ - SLMP_INFO *port_array[SCA_MAX_PORTS]; - int port; - - /* allocate device instances for up to SCA_MAX_PORTS devices */ - for ( port = 0; port < SCA_MAX_PORTS; ++port ) { - port_array[port] = alloc_dev(adapter_num,port,pdev); - if( port_array[port] == NULL ) { - for ( --port; port >= 0; --port ) - kfree(port_array[port]); - return; - } - } - - /* give copy of port_array to all ports and add to device list */ - for ( port = 0; port < SCA_MAX_PORTS; ++port ) { - memcpy(port_array[port]->port_array,port_array,sizeof(port_array)); - add_device( port_array[port] ); - spin_lock_init(&port_array[port]->lock); - } - - /* Allocate and claim adapter resources */ - if ( !claim_resources(port_array[0]) ) { - - alloc_dma_bufs(port_array[0]); - - /* copy resource information from first port to others */ - for ( port = 1; port < SCA_MAX_PORTS; ++port ) { - port_array[port]->lock = port_array[0]->lock; - port_array[port]->irq_level = port_array[0]->irq_level; - port_array[port]->memory_base = port_array[0]->memory_base; - port_array[port]->sca_base = port_array[0]->sca_base; - port_array[port]->statctrl_base = port_array[0]->statctrl_base; - port_array[port]->lcr_base = port_array[0]->lcr_base; - alloc_dma_bufs(port_array[port]); - } - - if ( request_irq(port_array[0]->irq_level, - synclinkmp_interrupt, - port_array[0]->irq_flags, - port_array[0]->device_name, - port_array[0]) < 0 ) { - printk( "%s(%d):%s Cant request interrupt, IRQ=%d\n", - __FILE__,__LINE__, - port_array[0]->device_name, - port_array[0]->irq_level ); - } - else { - port_array[0]->irq_requested = true; - adapter_test(port_array[0]); - } - } -} - -static const struct tty_operations ops = { - .open = open, - .close = close, - .write = write, - .put_char = put_char, - .flush_chars = flush_chars, - .write_room = write_room, - .chars_in_buffer = chars_in_buffer, - .flush_buffer = flush_buffer, - .ioctl = ioctl, - .throttle = throttle, - .unthrottle = unthrottle, - .send_xchar = send_xchar, - .break_ctl = set_break, - .wait_until_sent = wait_until_sent, - .set_termios = set_termios, - .stop = tx_hold, - .start = tx_release, - .hangup = hangup, - .tiocmget = tiocmget, - .tiocmset = tiocmset, - .get_icount = get_icount, - .proc_fops = &synclinkmp_proc_fops, -}; - - -static void synclinkmp_cleanup(void) -{ - int rc; - SLMP_INFO *info; - SLMP_INFO *tmp; - - printk("Unloading %s %s\n", driver_name, driver_version); - - if (serial_driver) { - if ((rc = tty_unregister_driver(serial_driver))) - printk("%s(%d) failed to unregister tty driver err=%d\n", - __FILE__,__LINE__,rc); - put_tty_driver(serial_driver); - } - - /* reset devices */ - info = synclinkmp_device_list; - while(info) { - reset_port(info); - info = info->next_device; - } - - /* release devices */ - info = synclinkmp_device_list; - while(info) { -#if SYNCLINK_GENERIC_HDLC - hdlcdev_exit(info); -#endif - free_dma_bufs(info); - free_tmp_rx_buf(info); - if ( info->port_num == 0 ) { - if (info->sca_base) - write_reg(info, LPR, 1); /* set low power mode */ - release_resources(info); - } - tmp = info; - info = info->next_device; - kfree(tmp); - } - - pci_unregister_driver(&synclinkmp_pci_driver); -} - -/* Driver initialization entry point. - */ - -static int __init synclinkmp_init(void) -{ - int rc; - - if (break_on_load) { - synclinkmp_get_text_ptr(); - BREAKPOINT(); - } - - printk("%s %s\n", driver_name, driver_version); - - if ((rc = pci_register_driver(&synclinkmp_pci_driver)) < 0) { - printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc); - return rc; - } - - serial_driver = alloc_tty_driver(128); - if (!serial_driver) { - rc = -ENOMEM; - goto error; - } - - /* Initialize the tty_driver structure */ - - serial_driver->owner = THIS_MODULE; - serial_driver->driver_name = "synclinkmp"; - serial_driver->name = "ttySLM"; - serial_driver->major = ttymajor; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->init_termios.c_ispeed = 9600; - serial_driver->init_termios.c_ospeed = 9600; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &ops); - if ((rc = tty_register_driver(serial_driver)) < 0) { - printk("%s(%d):Couldn't register serial driver\n", - __FILE__,__LINE__); - put_tty_driver(serial_driver); - serial_driver = NULL; - goto error; - } - - printk("%s %s, tty major#%d\n", - driver_name, driver_version, - serial_driver->major); - - return 0; - -error: - synclinkmp_cleanup(); - return rc; -} - -static void __exit synclinkmp_exit(void) -{ - synclinkmp_cleanup(); -} - -module_init(synclinkmp_init); -module_exit(synclinkmp_exit); - -/* Set the port for internal loopback mode. - * The TxCLK and RxCLK signals are generated from the BRG and - * the TxD is looped back to the RxD internally. - */ -static void enable_loopback(SLMP_INFO *info, int enable) -{ - if (enable) { - /* MD2 (Mode Register 2) - * 01..00 CNCT<1..0> Channel Connection 11=Local Loopback - */ - write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) | (BIT1 + BIT0))); - - /* degate external TxC clock source */ - info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2)); - write_control_reg(info); - - /* RXS/TXS (Rx/Tx clock source) - * 07 Reserved, must be 0 - * 06..04 Clock Source, 100=BRG - * 03..00 Clock Divisor, 0000=1 - */ - write_reg(info, RXS, 0x40); - write_reg(info, TXS, 0x40); - - } else { - /* MD2 (Mode Register 2) - * 01..00 CNCT<1..0> Channel connection, 0=normal - */ - write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) & ~(BIT1 + BIT0))); - - /* RXS/TXS (Rx/Tx clock source) - * 07 Reserved, must be 0 - * 06..04 Clock Source, 000=RxC/TxC Pin - * 03..00 Clock Divisor, 0000=1 - */ - write_reg(info, RXS, 0x00); - write_reg(info, TXS, 0x00); - } - - /* set LinkSpeed if available, otherwise default to 2Mbps */ - if (info->params.clock_speed) - set_rate(info, info->params.clock_speed); - else - set_rate(info, 3686400); -} - -/* Set the baud rate register to the desired speed - * - * data_rate data rate of clock in bits per second - * A data rate of 0 disables the AUX clock. - */ -static void set_rate( SLMP_INFO *info, u32 data_rate ) -{ - u32 TMCValue; - unsigned char BRValue; - u32 Divisor=0; - - /* fBRG = fCLK/(TMC * 2^BR) - */ - if (data_rate != 0) { - Divisor = 14745600/data_rate; - if (!Divisor) - Divisor = 1; - - TMCValue = Divisor; - - BRValue = 0; - if (TMCValue != 1 && TMCValue != 2) { - /* BRValue of 0 provides 50/50 duty cycle *only* when - * TMCValue is 1 or 2. BRValue of 1 to 9 always provides - * 50/50 duty cycle. - */ - BRValue = 1; - TMCValue >>= 1; - } - - /* while TMCValue is too big for TMC register, divide - * by 2 and increment BR exponent. - */ - for(; TMCValue > 256 && BRValue < 10; BRValue++) - TMCValue >>= 1; - - write_reg(info, TXS, - (unsigned char)((read_reg(info, TXS) & 0xf0) | BRValue)); - write_reg(info, RXS, - (unsigned char)((read_reg(info, RXS) & 0xf0) | BRValue)); - write_reg(info, TMC, (unsigned char)TMCValue); - } - else { - write_reg(info, TXS,0); - write_reg(info, RXS,0); - write_reg(info, TMC, 0); - } -} - -/* Disable receiver - */ -static void rx_stop(SLMP_INFO *info) -{ - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):%s rx_stop()\n", - __FILE__,__LINE__, info->device_name ); - - write_reg(info, CMD, RXRESET); - - info->ie0_value &= ~RXRDYE; - write_reg(info, IE0, info->ie0_value); /* disable Rx data interrupts */ - - write_reg(info, RXDMA + DSR, 0); /* disable Rx DMA */ - write_reg(info, RXDMA + DCMD, SWABORT); /* reset/init Rx DMA */ - write_reg(info, RXDMA + DIR, 0); /* disable Rx DMA interrupts */ - - info->rx_enabled = false; - info->rx_overflow = false; -} - -/* enable the receiver - */ -static void rx_start(SLMP_INFO *info) -{ - int i; - - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):%s rx_start()\n", - __FILE__,__LINE__, info->device_name ); - - write_reg(info, CMD, RXRESET); - - if ( info->params.mode == MGSL_MODE_HDLC ) { - /* HDLC, disabe IRQ on rxdata */ - info->ie0_value &= ~RXRDYE; - write_reg(info, IE0, info->ie0_value); - - /* Reset all Rx DMA buffers and program rx dma */ - write_reg(info, RXDMA + DSR, 0); /* disable Rx DMA */ - write_reg(info, RXDMA + DCMD, SWABORT); /* reset/init Rx DMA */ - - for (i = 0; i < info->rx_buf_count; i++) { - info->rx_buf_list[i].status = 0xff; - - // throttle to 4 shared memory writes at a time to prevent - // hogging local bus (keep latency time for DMA requests low). - if (!(i % 4)) - read_status_reg(info); - } - info->current_rx_buf = 0; - - /* set current/1st descriptor address */ - write_reg16(info, RXDMA + CDA, - info->rx_buf_list_ex[0].phys_entry); - - /* set new last rx descriptor address */ - write_reg16(info, RXDMA + EDA, - info->rx_buf_list_ex[info->rx_buf_count - 1].phys_entry); - - /* set buffer length (shared by all rx dma data buffers) */ - write_reg16(info, RXDMA + BFL, SCABUFSIZE); - - write_reg(info, RXDMA + DIR, 0x60); /* enable Rx DMA interrupts (EOM/BOF) */ - write_reg(info, RXDMA + DSR, 0xf2); /* clear Rx DMA IRQs, enable Rx DMA */ - } else { - /* async, enable IRQ on rxdata */ - info->ie0_value |= RXRDYE; - write_reg(info, IE0, info->ie0_value); - } - - write_reg(info, CMD, RXENABLE); - - info->rx_overflow = false; - info->rx_enabled = true; -} - -/* Enable the transmitter and send a transmit frame if - * one is loaded in the DMA buffers. - */ -static void tx_start(SLMP_INFO *info) -{ - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):%s tx_start() tx_count=%d\n", - __FILE__,__LINE__, info->device_name,info->tx_count ); - - if (!info->tx_enabled ) { - write_reg(info, CMD, TXRESET); - write_reg(info, CMD, TXENABLE); - info->tx_enabled = true; - } - - if ( info->tx_count ) { - - /* If auto RTS enabled and RTS is inactive, then assert */ - /* RTS and set a flag indicating that the driver should */ - /* negate RTS when the transmission completes. */ - - info->drop_rts_on_tx_done = false; - - if (info->params.mode != MGSL_MODE_ASYNC) { - - if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) { - get_signals( info ); - if ( !(info->serial_signals & SerialSignal_RTS) ) { - info->serial_signals |= SerialSignal_RTS; - set_signals( info ); - info->drop_rts_on_tx_done = true; - } - } - - write_reg16(info, TRC0, - (unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level)); - - write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ - write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ - - /* set TX CDA (current descriptor address) */ - write_reg16(info, TXDMA + CDA, - info->tx_buf_list_ex[0].phys_entry); - - /* set TX EDA (last descriptor address) */ - write_reg16(info, TXDMA + EDA, - info->tx_buf_list_ex[info->last_tx_buf].phys_entry); - - /* enable underrun IRQ */ - info->ie1_value &= ~IDLE; - info->ie1_value |= UDRN; - write_reg(info, IE1, info->ie1_value); - write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); - - write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ - write_reg(info, TXDMA + DSR, 0xf2); /* clear Tx DMA IRQs, enable Tx DMA */ - - mod_timer(&info->tx_timer, jiffies + - msecs_to_jiffies(5000)); - } - else { - tx_load_fifo(info); - /* async, enable IRQ on txdata */ - info->ie0_value |= TXRDYE; - write_reg(info, IE0, info->ie0_value); - } - - info->tx_active = true; - } -} - -/* stop the transmitter and DMA - */ -static void tx_stop( SLMP_INFO *info ) -{ - if (debug_level >= DEBUG_LEVEL_ISR) - printk("%s(%d):%s tx_stop()\n", - __FILE__,__LINE__, info->device_name ); - - del_timer(&info->tx_timer); - - write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ - write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ - - write_reg(info, CMD, TXRESET); - - info->ie1_value &= ~(UDRN + IDLE); - write_reg(info, IE1, info->ie1_value); /* disable tx status interrupts */ - write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); /* clear pending */ - - info->ie0_value &= ~TXRDYE; - write_reg(info, IE0, info->ie0_value); /* disable tx data interrupts */ - - info->tx_enabled = false; - info->tx_active = false; -} - -/* Fill the transmit FIFO until the FIFO is full or - * there is no more data to load. - */ -static void tx_load_fifo(SLMP_INFO *info) -{ - u8 TwoBytes[2]; - - /* do nothing is now tx data available and no XON/XOFF pending */ - - if ( !info->tx_count && !info->x_char ) - return; - - /* load the Transmit FIFO until FIFOs full or all data sent */ - - while( info->tx_count && (read_reg(info,SR0) & BIT1) ) { - - /* there is more space in the transmit FIFO and */ - /* there is more data in transmit buffer */ - - if ( (info->tx_count > 1) && !info->x_char ) { - /* write 16-bits */ - TwoBytes[0] = info->tx_buf[info->tx_get++]; - if (info->tx_get >= info->max_frame_size) - info->tx_get -= info->max_frame_size; - TwoBytes[1] = info->tx_buf[info->tx_get++]; - if (info->tx_get >= info->max_frame_size) - info->tx_get -= info->max_frame_size; - - write_reg16(info, TRB, *((u16 *)TwoBytes)); - - info->tx_count -= 2; - info->icount.tx += 2; - } else { - /* only 1 byte left to transmit or 1 FIFO slot left */ - - if (info->x_char) { - /* transmit pending high priority char */ - write_reg(info, TRB, info->x_char); - info->x_char = 0; - } else { - write_reg(info, TRB, info->tx_buf[info->tx_get++]); - if (info->tx_get >= info->max_frame_size) - info->tx_get -= info->max_frame_size; - info->tx_count--; - } - info->icount.tx++; - } - } -} - -/* Reset a port to a known state - */ -static void reset_port(SLMP_INFO *info) -{ - if (info->sca_base) { - - tx_stop(info); - rx_stop(info); - - info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - set_signals(info); - - /* disable all port interrupts */ - info->ie0_value = 0; - info->ie1_value = 0; - info->ie2_value = 0; - write_reg(info, IE0, info->ie0_value); - write_reg(info, IE1, info->ie1_value); - write_reg(info, IE2, info->ie2_value); - - write_reg(info, CMD, CHRESET); - } -} - -/* Reset all the ports to a known state. - */ -static void reset_adapter(SLMP_INFO *info) -{ - int i; - - for ( i=0; i < SCA_MAX_PORTS; ++i) { - if (info->port_array[i]) - reset_port(info->port_array[i]); - } -} - -/* Program port for asynchronous communications. - */ -static void async_mode(SLMP_INFO *info) -{ - - unsigned char RegValue; - - tx_stop(info); - rx_stop(info); - - /* MD0, Mode Register 0 - * - * 07..05 PRCTL<2..0>, Protocol Mode, 000=async - * 04 AUTO, Auto-enable (RTS/CTS/DCD) - * 03 Reserved, must be 0 - * 02 CRCCC, CRC Calculation, 0=disabled - * 01..00 STOP<1..0> Stop bits (00=1,10=2) - * - * 0000 0000 - */ - RegValue = 0x00; - if (info->params.stop_bits != 1) - RegValue |= BIT1; - write_reg(info, MD0, RegValue); - - /* MD1, Mode Register 1 - * - * 07..06 BRATE<1..0>, bit rate, 00=1/1 01=1/16 10=1/32 11=1/64 - * 05..04 TXCHR<1..0>, tx char size, 00=8 bits,01=7,10=6,11=5 - * 03..02 RXCHR<1..0>, rx char size - * 01..00 PMPM<1..0>, Parity mode, 00=none 10=even 11=odd - * - * 0100 0000 - */ - RegValue = 0x40; - switch (info->params.data_bits) { - case 7: RegValue |= BIT4 + BIT2; break; - case 6: RegValue |= BIT5 + BIT3; break; - case 5: RegValue |= BIT5 + BIT4 + BIT3 + BIT2; break; - } - if (info->params.parity != ASYNC_PARITY_NONE) { - RegValue |= BIT1; - if (info->params.parity == ASYNC_PARITY_ODD) - RegValue |= BIT0; - } - write_reg(info, MD1, RegValue); - - /* MD2, Mode Register 2 - * - * 07..02 Reserved, must be 0 - * 01..00 CNCT<1..0> Channel connection, 00=normal 11=local loopback - * - * 0000 0000 - */ - RegValue = 0x00; - if (info->params.loopback) - RegValue |= (BIT1 + BIT0); - write_reg(info, MD2, RegValue); - - /* RXS, Receive clock source - * - * 07 Reserved, must be 0 - * 06..04 RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL - * 03..00 RXBR<3..0>, rate divisor, 0000=1 - */ - RegValue=BIT6; - write_reg(info, RXS, RegValue); - - /* TXS, Transmit clock source - * - * 07 Reserved, must be 0 - * 06..04 RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock - * 03..00 RXBR<3..0>, rate divisor, 0000=1 - */ - RegValue=BIT6; - write_reg(info, TXS, RegValue); - - /* Control Register - * - * 6,4,2,0 CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out - */ - info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2)); - write_control_reg(info); - - tx_set_idle(info); - - /* RRC Receive Ready Control 0 - * - * 07..05 Reserved, must be 0 - * 04..00 RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte - */ - write_reg(info, RRC, 0x00); - - /* TRC0 Transmit Ready Control 0 - * - * 07..05 Reserved, must be 0 - * 04..00 TRC<4..0> Tx FIFO trigger active 0x10 = 16 bytes - */ - write_reg(info, TRC0, 0x10); - - /* TRC1 Transmit Ready Control 1 - * - * 07..05 Reserved, must be 0 - * 04..00 TRC<4..0> Tx FIFO trigger inactive 0x1e = 31 bytes (full-1) - */ - write_reg(info, TRC1, 0x1e); - - /* CTL, MSCI control register - * - * 07..06 Reserved, set to 0 - * 05 UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC) - * 04 IDLC, idle control, 0=mark 1=idle register - * 03 BRK, break, 0=off 1 =on (async) - * 02 SYNCLD, sync char load enable (BSC) 1=enabled - * 01 GOP, go active on poll (LOOP mode) 1=enabled - * 00 RTS, RTS output control, 0=active 1=inactive - * - * 0001 0001 - */ - RegValue = 0x10; - if (!(info->serial_signals & SerialSignal_RTS)) - RegValue |= 0x01; - write_reg(info, CTL, RegValue); - - /* enable status interrupts */ - info->ie0_value |= TXINTE + RXINTE; - write_reg(info, IE0, info->ie0_value); - - /* enable break detect interrupt */ - info->ie1_value = BRKD; - write_reg(info, IE1, info->ie1_value); - - /* enable rx overrun interrupt */ - info->ie2_value = OVRN; - write_reg(info, IE2, info->ie2_value); - - set_rate( info, info->params.data_rate * 16 ); -} - -/* Program the SCA for HDLC communications. - */ -static void hdlc_mode(SLMP_INFO *info) -{ - unsigned char RegValue; - u32 DpllDivisor; - - // Can't use DPLL because SCA outputs recovered clock on RxC when - // DPLL mode selected. This causes output contention with RxC receiver. - // Use of DPLL would require external hardware to disable RxC receiver - // when DPLL mode selected. - info->params.flags &= ~(HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL); - - /* disable DMA interrupts */ - write_reg(info, TXDMA + DIR, 0); - write_reg(info, RXDMA + DIR, 0); - - /* MD0, Mode Register 0 - * - * 07..05 PRCTL<2..0>, Protocol Mode, 100=HDLC - * 04 AUTO, Auto-enable (RTS/CTS/DCD) - * 03 Reserved, must be 0 - * 02 CRCCC, CRC Calculation, 1=enabled - * 01 CRC1, CRC selection, 0=CRC-16,1=CRC-CCITT-16 - * 00 CRC0, CRC initial value, 1 = all 1s - * - * 1000 0001 - */ - RegValue = 0x81; - if (info->params.flags & HDLC_FLAG_AUTO_CTS) - RegValue |= BIT4; - if (info->params.flags & HDLC_FLAG_AUTO_DCD) - RegValue |= BIT4; - if (info->params.crc_type == HDLC_CRC_16_CCITT) - RegValue |= BIT2 + BIT1; - write_reg(info, MD0, RegValue); - - /* MD1, Mode Register 1 - * - * 07..06 ADDRS<1..0>, Address detect, 00=no addr check - * 05..04 TXCHR<1..0>, tx char size, 00=8 bits - * 03..02 RXCHR<1..0>, rx char size, 00=8 bits - * 01..00 PMPM<1..0>, Parity mode, 00=no parity - * - * 0000 0000 - */ - RegValue = 0x00; - write_reg(info, MD1, RegValue); - - /* MD2, Mode Register 2 - * - * 07 NRZFM, 0=NRZ, 1=FM - * 06..05 CODE<1..0> Encoding, 00=NRZ - * 04..03 DRATE<1..0> DPLL Divisor, 00=8 - * 02 Reserved, must be 0 - * 01..00 CNCT<1..0> Channel connection, 0=normal - * - * 0000 0000 - */ - RegValue = 0x00; - switch(info->params.encoding) { - case HDLC_ENCODING_NRZI: RegValue |= BIT5; break; - case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT7 + BIT5; break; /* aka FM1 */ - case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT7 + BIT6; break; /* aka FM0 */ - case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT7; break; /* aka Manchester */ -#if 0 - case HDLC_ENCODING_NRZB: /* not supported */ - case HDLC_ENCODING_NRZI_MARK: /* not supported */ - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: /* not supported */ -#endif - } - if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { - DpllDivisor = 16; - RegValue |= BIT3; - } else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) { - DpllDivisor = 8; - } else { - DpllDivisor = 32; - RegValue |= BIT4; - } - write_reg(info, MD2, RegValue); - - - /* RXS, Receive clock source - * - * 07 Reserved, must be 0 - * 06..04 RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL - * 03..00 RXBR<3..0>, rate divisor, 0000=1 - */ - RegValue=0; - if (info->params.flags & HDLC_FLAG_RXC_BRG) - RegValue |= BIT6; - if (info->params.flags & HDLC_FLAG_RXC_DPLL) - RegValue |= BIT6 + BIT5; - write_reg(info, RXS, RegValue); - - /* TXS, Transmit clock source - * - * 07 Reserved, must be 0 - * 06..04 RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock - * 03..00 RXBR<3..0>, rate divisor, 0000=1 - */ - RegValue=0; - if (info->params.flags & HDLC_FLAG_TXC_BRG) - RegValue |= BIT6; - if (info->params.flags & HDLC_FLAG_TXC_DPLL) - RegValue |= BIT6 + BIT5; - write_reg(info, TXS, RegValue); - - if (info->params.flags & HDLC_FLAG_RXC_DPLL) - set_rate(info, info->params.clock_speed * DpllDivisor); - else - set_rate(info, info->params.clock_speed); - - /* GPDATA (General Purpose I/O Data Register) - * - * 6,4,2,0 CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out - */ - if (info->params.flags & HDLC_FLAG_TXC_BRG) - info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2)); - else - info->port_array[0]->ctrlreg_value &= ~(BIT0 << (info->port_num * 2)); - write_control_reg(info); - - /* RRC Receive Ready Control 0 - * - * 07..05 Reserved, must be 0 - * 04..00 RRC<4..0> Rx FIFO trigger active - */ - write_reg(info, RRC, rx_active_fifo_level); - - /* TRC0 Transmit Ready Control 0 - * - * 07..05 Reserved, must be 0 - * 04..00 TRC<4..0> Tx FIFO trigger active - */ - write_reg(info, TRC0, tx_active_fifo_level); - - /* TRC1 Transmit Ready Control 1 - * - * 07..05 Reserved, must be 0 - * 04..00 TRC<4..0> Tx FIFO trigger inactive 0x1f = 32 bytes (full) - */ - write_reg(info, TRC1, (unsigned char)(tx_negate_fifo_level - 1)); - - /* DMR, DMA Mode Register - * - * 07..05 Reserved, must be 0 - * 04 TMOD, Transfer Mode: 1=chained-block - * 03 Reserved, must be 0 - * 02 NF, Number of Frames: 1=multi-frame - * 01 CNTE, Frame End IRQ Counter enable: 0=disabled - * 00 Reserved, must be 0 - * - * 0001 0100 - */ - write_reg(info, TXDMA + DMR, 0x14); - write_reg(info, RXDMA + DMR, 0x14); - - /* Set chain pointer base (upper 8 bits of 24 bit addr) */ - write_reg(info, RXDMA + CPB, - (unsigned char)(info->buffer_list_phys >> 16)); - - /* Set chain pointer base (upper 8 bits of 24 bit addr) */ - write_reg(info, TXDMA + CPB, - (unsigned char)(info->buffer_list_phys >> 16)); - - /* enable status interrupts. other code enables/disables - * the individual sources for these two interrupt classes. - */ - info->ie0_value |= TXINTE + RXINTE; - write_reg(info, IE0, info->ie0_value); - - /* CTL, MSCI control register - * - * 07..06 Reserved, set to 0 - * 05 UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC) - * 04 IDLC, idle control, 0=mark 1=idle register - * 03 BRK, break, 0=off 1 =on (async) - * 02 SYNCLD, sync char load enable (BSC) 1=enabled - * 01 GOP, go active on poll (LOOP mode) 1=enabled - * 00 RTS, RTS output control, 0=active 1=inactive - * - * 0001 0001 - */ - RegValue = 0x10; - if (!(info->serial_signals & SerialSignal_RTS)) - RegValue |= 0x01; - write_reg(info, CTL, RegValue); - - /* preamble not supported ! */ - - tx_set_idle(info); - tx_stop(info); - rx_stop(info); - - set_rate(info, info->params.clock_speed); - - if (info->params.loopback) - enable_loopback(info,1); -} - -/* Set the transmit HDLC idle mode - */ -static void tx_set_idle(SLMP_INFO *info) -{ - unsigned char RegValue = 0xff; - - /* Map API idle mode to SCA register bits */ - switch(info->idle_mode) { - case HDLC_TXIDLE_FLAGS: RegValue = 0x7e; break; - case HDLC_TXIDLE_ALT_ZEROS_ONES: RegValue = 0xaa; break; - case HDLC_TXIDLE_ZEROS: RegValue = 0x00; break; - case HDLC_TXIDLE_ONES: RegValue = 0xff; break; - case HDLC_TXIDLE_ALT_MARK_SPACE: RegValue = 0xaa; break; - case HDLC_TXIDLE_SPACE: RegValue = 0x00; break; - case HDLC_TXIDLE_MARK: RegValue = 0xff; break; - } - - write_reg(info, IDL, RegValue); -} - -/* Query the adapter for the state of the V24 status (input) signals. - */ -static void get_signals(SLMP_INFO *info) -{ - u16 status = read_reg(info, SR3); - u16 gpstatus = read_status_reg(info); - u16 testbit; - - /* clear all serial signals except DTR and RTS */ - info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS; - - /* set serial signal bits to reflect MISR */ - - if (!(status & BIT3)) - info->serial_signals |= SerialSignal_CTS; - - if ( !(status & BIT2)) - info->serial_signals |= SerialSignal_DCD; - - testbit = BIT1 << (info->port_num * 2); // Port 0..3 RI is GPDATA<1,3,5,7> - if (!(gpstatus & testbit)) - info->serial_signals |= SerialSignal_RI; - - testbit = BIT0 << (info->port_num * 2); // Port 0..3 DSR is GPDATA<0,2,4,6> - if (!(gpstatus & testbit)) - info->serial_signals |= SerialSignal_DSR; -} - -/* Set the state of DTR and RTS based on contents of - * serial_signals member of device context. - */ -static void set_signals(SLMP_INFO *info) -{ - unsigned char RegValue; - u16 EnableBit; - - RegValue = read_reg(info, CTL); - if (info->serial_signals & SerialSignal_RTS) - RegValue &= ~BIT0; - else - RegValue |= BIT0; - write_reg(info, CTL, RegValue); - - // Port 0..3 DTR is ctrl reg <1,3,5,7> - EnableBit = BIT1 << (info->port_num*2); - if (info->serial_signals & SerialSignal_DTR) - info->port_array[0]->ctrlreg_value &= ~EnableBit; - else - info->port_array[0]->ctrlreg_value |= EnableBit; - write_control_reg(info); -} - -/*******************/ -/* DMA Buffer Code */ -/*******************/ - -/* Set the count for all receive buffers to SCABUFSIZE - * and set the current buffer to the first buffer. This effectively - * makes all buffers free and discards any data in buffers. - */ -static void rx_reset_buffers(SLMP_INFO *info) -{ - rx_free_frame_buffers(info, 0, info->rx_buf_count - 1); -} - -/* Free the buffers used by a received frame - * - * info pointer to device instance data - * first index of 1st receive buffer of frame - * last index of last receive buffer of frame - */ -static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last) -{ - bool done = false; - - while(!done) { - /* reset current buffer for reuse */ - info->rx_buf_list[first].status = 0xff; - - if (first == last) { - done = true; - /* set new last rx descriptor address */ - write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry); - } - - first++; - if (first == info->rx_buf_count) - first = 0; - } - - /* set current buffer to next buffer after last buffer of frame */ - info->current_rx_buf = first; -} - -/* Return a received frame from the receive DMA buffers. - * Only frames received without errors are returned. - * - * Return Value: true if frame returned, otherwise false - */ -static bool rx_get_frame(SLMP_INFO *info) -{ - unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ - unsigned short status; - unsigned int framesize = 0; - bool ReturnCode = false; - unsigned long flags; - struct tty_struct *tty = info->port.tty; - unsigned char addr_field = 0xff; - SCADESC *desc; - SCADESC_EX *desc_ex; - -CheckAgain: - /* assume no frame returned, set zero length */ - framesize = 0; - addr_field = 0xff; - - /* - * current_rx_buf points to the 1st buffer of the next available - * receive frame. To find the last buffer of the frame look for - * a non-zero status field in the buffer entries. (The status - * field is set by the 16C32 after completing a receive frame. - */ - StartIndex = EndIndex = info->current_rx_buf; - - for ( ;; ) { - desc = &info->rx_buf_list[EndIndex]; - desc_ex = &info->rx_buf_list_ex[EndIndex]; - - if (desc->status == 0xff) - goto Cleanup; /* current desc still in use, no frames available */ - - if (framesize == 0 && info->params.addr_filter != 0xff) - addr_field = desc_ex->virt_addr[0]; - - framesize += desc->length; - - /* Status != 0 means last buffer of frame */ - if (desc->status) - break; - - EndIndex++; - if (EndIndex == info->rx_buf_count) - EndIndex = 0; - - if (EndIndex == info->current_rx_buf) { - /* all buffers have been 'used' but none mark */ - /* the end of a frame. Reset buffers and receiver. */ - if ( info->rx_enabled ){ - spin_lock_irqsave(&info->lock,flags); - rx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } - goto Cleanup; - } - - } - - /* check status of receive frame */ - - /* frame status is byte stored after frame data - * - * 7 EOM (end of msg), 1 = last buffer of frame - * 6 Short Frame, 1 = short frame - * 5 Abort, 1 = frame aborted - * 4 Residue, 1 = last byte is partial - * 3 Overrun, 1 = overrun occurred during frame reception - * 2 CRC, 1 = CRC error detected - * - */ - status = desc->status; - - /* ignore CRC bit if not using CRC (bit is undefined) */ - /* Note:CRC is not save to data buffer */ - if (info->params.crc_type == HDLC_CRC_NONE) - status &= ~BIT2; - - if (framesize == 0 || - (addr_field != 0xff && addr_field != info->params.addr_filter)) { - /* discard 0 byte frames, this seems to occur sometime - * when remote is idling flags. - */ - rx_free_frame_buffers(info, StartIndex, EndIndex); - goto CheckAgain; - } - - if (framesize < 2) - status |= BIT6; - - if (status & (BIT6+BIT5+BIT3+BIT2)) { - /* received frame has errors, - * update counts and mark frame size as 0 - */ - if (status & BIT6) - info->icount.rxshort++; - else if (status & BIT5) - info->icount.rxabort++; - else if (status & BIT3) - info->icount.rxover++; - else - info->icount.rxcrc++; - - framesize = 0; -#if SYNCLINK_GENERIC_HDLC - { - info->netdev->stats.rx_errors++; - info->netdev->stats.rx_frame_errors++; - } -#endif - } - - if ( debug_level >= DEBUG_LEVEL_BH ) - printk("%s(%d):%s rx_get_frame() status=%04X size=%d\n", - __FILE__,__LINE__,info->device_name,status,framesize); - - if ( debug_level >= DEBUG_LEVEL_DATA ) - trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr, - min_t(int, framesize,SCABUFSIZE),0); - - if (framesize) { - if (framesize > info->max_frame_size) - info->icount.rxlong++; - else { - /* copy dma buffer(s) to contiguous intermediate buffer */ - int copy_count = framesize; - int index = StartIndex; - unsigned char *ptmp = info->tmp_rx_buf; - info->tmp_rx_buf_count = framesize; - - info->icount.rxok++; - - while(copy_count) { - int partial_count = min(copy_count,SCABUFSIZE); - memcpy( ptmp, - info->rx_buf_list_ex[index].virt_addr, - partial_count ); - ptmp += partial_count; - copy_count -= partial_count; - - if ( ++index == info->rx_buf_count ) - index = 0; - } - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_rx(info,info->tmp_rx_buf,framesize); - else -#endif - ldisc_receive_buf(tty,info->tmp_rx_buf, - info->flag_buf, framesize); - } - } - /* Free the buffers used by this frame. */ - rx_free_frame_buffers( info, StartIndex, EndIndex ); - - ReturnCode = true; - -Cleanup: - if ( info->rx_enabled && info->rx_overflow ) { - /* Receiver is enabled, but needs to restarted due to - * rx buffer overflow. If buffers are empty, restart receiver. - */ - if (info->rx_buf_list[EndIndex].status == 0xff) { - spin_lock_irqsave(&info->lock,flags); - rx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } - } - - return ReturnCode; -} - -/* load the transmit DMA buffer with data - */ -static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count) -{ - unsigned short copy_count; - unsigned int i = 0; - SCADESC *desc; - SCADESC_EX *desc_ex; - - if ( debug_level >= DEBUG_LEVEL_DATA ) - trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1); - - /* Copy source buffer to one or more DMA buffers, starting with - * the first transmit dma buffer. - */ - for(i=0;;) - { - copy_count = min_t(unsigned short,count,SCABUFSIZE); - - desc = &info->tx_buf_list[i]; - desc_ex = &info->tx_buf_list_ex[i]; - - load_pci_memory(info, desc_ex->virt_addr,buf,copy_count); - - desc->length = copy_count; - desc->status = 0; - - buf += copy_count; - count -= copy_count; - - if (!count) - break; - - i++; - if (i >= info->tx_buf_count) - i = 0; - } - - info->tx_buf_list[i].status = 0x81; /* set EOM and EOT status */ - info->last_tx_buf = ++i; -} - -static bool register_test(SLMP_INFO *info) -{ - static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96}; - static unsigned int count = ARRAY_SIZE(testval); - unsigned int i; - bool rc = true; - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - reset_port(info); - - /* assume failure */ - info->init_error = DiagStatus_AddressFailure; - - /* Write bit patterns to various registers but do it out of */ - /* sync, then read back and verify values. */ - - for (i = 0 ; i < count ; i++) { - write_reg(info, TMC, testval[i]); - write_reg(info, IDL, testval[(i+1)%count]); - write_reg(info, SA0, testval[(i+2)%count]); - write_reg(info, SA1, testval[(i+3)%count]); - - if ( (read_reg(info, TMC) != testval[i]) || - (read_reg(info, IDL) != testval[(i+1)%count]) || - (read_reg(info, SA0) != testval[(i+2)%count]) || - (read_reg(info, SA1) != testval[(i+3)%count]) ) - { - rc = false; - break; - } - } - - reset_port(info); - spin_unlock_irqrestore(&info->lock,flags); - - return rc; -} - -static bool irq_test(SLMP_INFO *info) -{ - unsigned long timeout; - unsigned long flags; - - unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0; - - spin_lock_irqsave(&info->lock,flags); - reset_port(info); - - /* assume failure */ - info->init_error = DiagStatus_IrqFailure; - info->irq_occurred = false; - - /* setup timer0 on SCA0 to interrupt */ - - /* IER2<7..4> = timer<3..0> interrupt enables (1=enabled) */ - write_reg(info, IER2, (unsigned char)((info->port_num & 1) ? BIT6 : BIT4)); - - write_reg(info, (unsigned char)(timer + TEPR), 0); /* timer expand prescale */ - write_reg16(info, (unsigned char)(timer + TCONR), 1); /* timer constant */ - - - /* TMCS, Timer Control/Status Register - * - * 07 CMF, Compare match flag (read only) 1=match - * 06 ECMI, CMF Interrupt Enable: 1=enabled - * 05 Reserved, must be 0 - * 04 TME, Timer Enable - * 03..00 Reserved, must be 0 - * - * 0101 0000 - */ - write_reg(info, (unsigned char)(timer + TMCS), 0x50); - - spin_unlock_irqrestore(&info->lock,flags); - - timeout=100; - while( timeout-- && !info->irq_occurred ) { - msleep_interruptible(10); - } - - spin_lock_irqsave(&info->lock,flags); - reset_port(info); - spin_unlock_irqrestore(&info->lock,flags); - - return info->irq_occurred; -} - -/* initialize individual SCA device (2 ports) - */ -static bool sca_init(SLMP_INFO *info) -{ - /* set wait controller to single mem partition (low), no wait states */ - write_reg(info, PABR0, 0); /* wait controller addr boundary 0 */ - write_reg(info, PABR1, 0); /* wait controller addr boundary 1 */ - write_reg(info, WCRL, 0); /* wait controller low range */ - write_reg(info, WCRM, 0); /* wait controller mid range */ - write_reg(info, WCRH, 0); /* wait controller high range */ - - /* DPCR, DMA Priority Control - * - * 07..05 Not used, must be 0 - * 04 BRC, bus release condition: 0=all transfers complete - * 03 CCC, channel change condition: 0=every cycle - * 02..00 PR<2..0>, priority 100=round robin - * - * 00000100 = 0x04 - */ - write_reg(info, DPCR, dma_priority); - - /* DMA Master Enable, BIT7: 1=enable all channels */ - write_reg(info, DMER, 0x80); - - /* enable all interrupt classes */ - write_reg(info, IER0, 0xff); /* TxRDY,RxRDY,TxINT,RxINT (ports 0-1) */ - write_reg(info, IER1, 0xff); /* DMIB,DMIA (channels 0-3) */ - write_reg(info, IER2, 0xf0); /* TIRQ (timers 0-3) */ - - /* ITCR, interrupt control register - * 07 IPC, interrupt priority, 0=MSCI->DMA - * 06..05 IAK<1..0>, Acknowledge cycle, 00=non-ack cycle - * 04 VOS, Vector Output, 0=unmodified vector - * 03..00 Reserved, must be 0 - */ - write_reg(info, ITCR, 0); - - return true; -} - -/* initialize adapter hardware - */ -static bool init_adapter(SLMP_INFO *info) -{ - int i; - - /* Set BIT30 of Local Control Reg 0x50 to reset SCA */ - volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); - u32 readval; - - info->misc_ctrl_value |= BIT30; - *MiscCtrl = info->misc_ctrl_value; - - /* - * Force at least 170ns delay before clearing - * reset bit. Each read from LCR takes at least - * 30ns so 10 times for 300ns to be safe. - */ - for(i=0;i<10;i++) - readval = *MiscCtrl; - - info->misc_ctrl_value &= ~BIT30; - *MiscCtrl = info->misc_ctrl_value; - - /* init control reg (all DTRs off, all clksel=input) */ - info->ctrlreg_value = 0xaa; - write_control_reg(info); - - { - volatile u32 *LCR1BRDR = (u32 *)(info->lcr_base + 0x2c); - lcr1_brdr_value &= ~(BIT5 + BIT4 + BIT3); - - switch(read_ahead_count) - { - case 16: - lcr1_brdr_value |= BIT5 + BIT4 + BIT3; - break; - case 8: - lcr1_brdr_value |= BIT5 + BIT4; - break; - case 4: - lcr1_brdr_value |= BIT5 + BIT3; - break; - case 0: - lcr1_brdr_value |= BIT5; - break; - } - - *LCR1BRDR = lcr1_brdr_value; - *MiscCtrl = misc_ctrl_value; - } - - sca_init(info->port_array[0]); - sca_init(info->port_array[2]); - - return true; -} - -/* Loopback an HDLC frame to test the hardware - * interrupt and DMA functions. - */ -static bool loopback_test(SLMP_INFO *info) -{ -#define TESTFRAMESIZE 20 - - unsigned long timeout; - u16 count = TESTFRAMESIZE; - unsigned char buf[TESTFRAMESIZE]; - bool rc = false; - unsigned long flags; - - struct tty_struct *oldtty = info->port.tty; - u32 speed = info->params.clock_speed; - - info->params.clock_speed = 3686400; - info->port.tty = NULL; - - /* assume failure */ - info->init_error = DiagStatus_DmaFailure; - - /* build and send transmit frame */ - for (count = 0; count < TESTFRAMESIZE;++count) - buf[count] = (unsigned char)count; - - memset(info->tmp_rx_buf,0,TESTFRAMESIZE); - - /* program hardware for HDLC and enabled receiver */ - spin_lock_irqsave(&info->lock,flags); - hdlc_mode(info); - enable_loopback(info,1); - rx_start(info); - info->tx_count = count; - tx_load_dma_buffer(info,buf,count); - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - - /* wait for receive complete */ - /* Set a timeout for waiting for interrupt. */ - for ( timeout = 100; timeout; --timeout ) { - msleep_interruptible(10); - - if (rx_get_frame(info)) { - rc = true; - break; - } - } - - /* verify received frame length and contents */ - if (rc && - ( info->tmp_rx_buf_count != count || - memcmp(buf, info->tmp_rx_buf,count))) { - rc = false; - } - - spin_lock_irqsave(&info->lock,flags); - reset_adapter(info); - spin_unlock_irqrestore(&info->lock,flags); - - info->params.clock_speed = speed; - info->port.tty = oldtty; - - return rc; -} - -/* Perform diagnostics on hardware - */ -static int adapter_test( SLMP_INFO *info ) -{ - unsigned long flags; - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):Testing device %s\n", - __FILE__,__LINE__,info->device_name ); - - spin_lock_irqsave(&info->lock,flags); - init_adapter(info); - spin_unlock_irqrestore(&info->lock,flags); - - info->port_array[0]->port_count = 0; - - if ( register_test(info->port_array[0]) && - register_test(info->port_array[1])) { - - info->port_array[0]->port_count = 2; - - if ( register_test(info->port_array[2]) && - register_test(info->port_array[3]) ) - info->port_array[0]->port_count += 2; - } - else { - printk( "%s(%d):Register test failure for device %s Addr=%08lX\n", - __FILE__,__LINE__,info->device_name, (unsigned long)(info->phys_sca_base)); - return -ENODEV; - } - - if ( !irq_test(info->port_array[0]) || - !irq_test(info->port_array[1]) || - (info->port_count == 4 && !irq_test(info->port_array[2])) || - (info->port_count == 4 && !irq_test(info->port_array[3]))) { - printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n", - __FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) ); - return -ENODEV; - } - - if (!loopback_test(info->port_array[0]) || - !loopback_test(info->port_array[1]) || - (info->port_count == 4 && !loopback_test(info->port_array[2])) || - (info->port_count == 4 && !loopback_test(info->port_array[3]))) { - printk( "%s(%d):DMA test failure for device %s\n", - __FILE__,__LINE__,info->device_name); - return -ENODEV; - } - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):device %s passed diagnostics\n", - __FILE__,__LINE__,info->device_name ); - - info->port_array[0]->init_error = 0; - info->port_array[1]->init_error = 0; - if ( info->port_count > 2 ) { - info->port_array[2]->init_error = 0; - info->port_array[3]->init_error = 0; - } - - return 0; -} - -/* Test the shared memory on a PCI adapter. - */ -static bool memory_test(SLMP_INFO *info) -{ - static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa, - 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; - unsigned long count = ARRAY_SIZE(testval); - unsigned long i; - unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long); - unsigned long * addr = (unsigned long *)info->memory_base; - - /* Test data lines with test pattern at one location. */ - - for ( i = 0 ; i < count ; i++ ) { - *addr = testval[i]; - if ( *addr != testval[i] ) - return false; - } - - /* Test address lines with incrementing pattern over */ - /* entire address range. */ - - for ( i = 0 ; i < limit ; i++ ) { - *addr = i * 4; - addr++; - } - - addr = (unsigned long *)info->memory_base; - - for ( i = 0 ; i < limit ; i++ ) { - if ( *addr != i * 4 ) - return false; - addr++; - } - - memset( info->memory_base, 0, SCA_MEM_SIZE ); - return true; -} - -/* Load data into PCI adapter shared memory. - * - * The PCI9050 releases control of the local bus - * after completing the current read or write operation. - * - * While the PCI9050 write FIFO not empty, the - * PCI9050 treats all of the writes as a single transaction - * and does not release the bus. This causes DMA latency problems - * at high speeds when copying large data blocks to the shared memory. - * - * This function breaks a write into multiple transations by - * interleaving a read which flushes the write FIFO and 'completes' - * the write transation. This allows any pending DMA request to gain control - * of the local bus in a timely fasion. - */ -static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count) -{ - /* A load interval of 16 allows for 4 32-bit writes at */ - /* 136ns each for a maximum latency of 542ns on the local bus.*/ - - unsigned short interval = count / sca_pci_load_interval; - unsigned short i; - - for ( i = 0 ; i < interval ; i++ ) - { - memcpy(dest, src, sca_pci_load_interval); - read_status_reg(info); - dest += sca_pci_load_interval; - src += sca_pci_load_interval; - } - - memcpy(dest, src, count % sca_pci_load_interval); -} - -static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit) -{ - int i; - int linecount; - if (xmit) - printk("%s tx data:\n",info->device_name); - else - printk("%s rx data:\n",info->device_name); - - while(count) { - if (count > 16) - linecount = 16; - else - linecount = count; - - for(i=0;i=040 && data[i]<=0176) - printk("%c",data[i]); - else - printk("."); - } - printk("\n"); - - data += linecount; - count -= linecount; - } -} /* end of trace_block() */ - -/* called when HDLC frame times out - * update stats and do tx completion processing - */ -static void tx_timeout(unsigned long context) -{ - SLMP_INFO *info = (SLMP_INFO*)context; - unsigned long flags; - - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):%s tx_timeout()\n", - __FILE__,__LINE__,info->device_name); - if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) { - info->icount.txtimeout++; - } - spin_lock_irqsave(&info->lock,flags); - info->tx_active = false; - info->tx_count = info->tx_put = info->tx_get = 0; - - spin_unlock_irqrestore(&info->lock,flags); - -#if SYNCLINK_GENERIC_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - bh_transmit(info); -} - -/* called to periodically check the DSR/RI modem signal input status - */ -static void status_timeout(unsigned long context) -{ - u16 status = 0; - SLMP_INFO *info = (SLMP_INFO*)context; - unsigned long flags; - unsigned char delta; - - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - /* check for DSR/RI state change */ - - delta = info->old_signals ^ info->serial_signals; - info->old_signals = info->serial_signals; - - if (delta & SerialSignal_DSR) - status |= MISCSTATUS_DSR_LATCHED|(info->serial_signals&SerialSignal_DSR); - - if (delta & SerialSignal_RI) - status |= MISCSTATUS_RI_LATCHED|(info->serial_signals&SerialSignal_RI); - - if (delta & SerialSignal_DCD) - status |= MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD); - - if (delta & SerialSignal_CTS) - status |= MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS); - - if (status) - isr_io_pin(info,status); - - mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); -} - - -/* Register Access Routines - - * All registers are memory mapped - */ -#define CALC_REGADDR() \ - unsigned char * RegAddr = (unsigned char*)(info->sca_base + Addr); \ - if (info->port_num > 1) \ - RegAddr += 256; /* port 0-1 SCA0, 2-3 SCA1 */ \ - if ( info->port_num & 1) { \ - if (Addr > 0x7f) \ - RegAddr += 0x40; /* DMA access */ \ - else if (Addr > 0x1f && Addr < 0x60) \ - RegAddr += 0x20; /* MSCI access */ \ - } - - -static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr) -{ - CALC_REGADDR(); - return *RegAddr; -} -static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value) -{ - CALC_REGADDR(); - *RegAddr = Value; -} - -static u16 read_reg16(SLMP_INFO * info, unsigned char Addr) -{ - CALC_REGADDR(); - return *((u16 *)RegAddr); -} - -static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value) -{ - CALC_REGADDR(); - *((u16 *)RegAddr) = Value; -} - -static unsigned char read_status_reg(SLMP_INFO * info) -{ - unsigned char *RegAddr = (unsigned char *)info->statctrl_base; - return *RegAddr; -} - -static void write_control_reg(SLMP_INFO * info) -{ - unsigned char *RegAddr = (unsigned char *)info->statctrl_base; - *RegAddr = info->port_array[0]->ctrlreg_value; -} - - -static int __devinit synclinkmp_init_one (struct pci_dev *dev, - const struct pci_device_id *ent) -{ - if (pci_enable_device(dev)) { - printk("error enabling pci device %p\n", dev); - return -EIO; - } - device_init( ++synclinkmp_adapter_count, dev ); - return 0; -} - -static void __devexit synclinkmp_remove_one (struct pci_dev *dev) -{ -} diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index 9cfbdb318ed9..3fd7199301b6 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -147,4 +147,175 @@ config LEGACY_PTY_COUNT When not in use, each legacy PTY occupies 12 bytes on 32-bit architectures and 24 bytes on 64-bit architectures. +config BFIN_JTAG_COMM + tristate "Blackfin JTAG Communication" + depends on BLACKFIN + help + Add support for emulating a TTY device over the Blackfin JTAG. + + To compile this driver as a module, choose M here: the + module will be called bfin_jtag_comm. + +config BFIN_JTAG_COMM_CONSOLE + bool "Console on Blackfin JTAG" + depends on BFIN_JTAG_COMM=y + +config SERIAL_NONSTANDARD + bool "Non-standard serial port support" + depends on HAS_IOMEM + ---help--- + Say Y here if you have any non-standard serial boards -- boards + which aren't supported using the standard "dumb" serial driver. + This includes intelligent serial boards such as Cyclades, + Digiboards, etc. These are usually used for systems that need many + serial ports because they serve many terminals or dial-in + connections. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about non-standard serial boards. + + Most people can say N here. + +config ROCKETPORT + tristate "Comtrol RocketPort support" + depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + help + This driver supports Comtrol RocketPort and RocketModem PCI boards. + These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or + modems. For information about the RocketPort/RocketModem boards + and this driver read . + + To compile this driver as a module, choose M here: the + module will be called rocket. + + If you want to compile this driver into the kernel, say Y here. If + you don't have a Comtrol RocketPort/RocketModem card installed, say N. + +config CYCLADES + tristate "Cyclades async mux support" + depends on SERIAL_NONSTANDARD && (PCI || ISA) + select FW_LOADER + ---help--- + This driver supports Cyclades Z and Y multiserial boards. + You would need something like this to connect more than two modems to + your Linux box, for instance in order to become a dial-in server. + + For information about the Cyclades-Z card, read + . + + To compile this driver as a module, choose M here: the + module will be called cyclades. + + If you haven't heard about it, it's safe to say N. + +config CYZ_INTR + bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)" + depends on EXPERIMENTAL && CYCLADES + help + The Cyclades-Z family of multiport cards allows 2 (two) driver op + modes: polling and interrupt. In polling mode, the driver will check + the status of the Cyclades-Z ports every certain amount of time + (which is called polling cycle and is configurable). In interrupt + mode, it will use an interrupt line (IRQ) in order to check the + status of the Cyclades-Z ports. The default op mode is polling. If + unsure, say N. + +config MOXA_INTELLIO + tristate "Moxa Intellio support" + depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + select FW_LOADER + help + Say Y here if you have a Moxa Intellio multiport serial card. + + To compile this driver as a module, choose M here: the + module will be called moxa. + +config MOXA_SMARTIO + 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 + want to help develop a new version of this driver. + + This is upgraded (1.9.1) driver from original Moxa drivers with + changes finally resulting in PCI probing. + + This driver can also be built as a module. The module will be called + mxser. If you want to do that, say M here. + +config SYNCLINK + tristate "Microgate SyncLink card support" + depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API + help + Provides support for the SyncLink ISA and PCI multiprotocol serial + adapters. These adapters support asynchronous and HDLC bit + synchronous communication up to 10Mbps (PCI adapter). + + This driver can only be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called synclink. If you want to do that, say M + here. + +config SYNCLINKMP + tristate "SyncLink Multiport support" + depends on SERIAL_NONSTANDARD && PCI + help + Enable support for the SyncLink Multiport (2 or 4 ports) + serial adapter, running asynchronous and HDLC communications up + to 2.048Mbps. Each ports is independently selectable for + RS-232, V.35, RS-449, RS-530, and X.21 + + This driver may be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called synclinkmp. If you want to do that, say M + here. + +config SYNCLINK_GT + tristate "SyncLink GT/AC support" + depends on SERIAL_NONSTANDARD && PCI + help + Support for SyncLink GT and SyncLink AC families of + synchronous and asynchronous serial adapters + manufactured by Microgate Systems, Ltd. (www.microgate.com) + +config NOZOMI + tristate "HSDPA Broadband Wireless Data Card - Globe Trotter" + depends on PCI && EXPERIMENTAL + help + If you have a HSDPA driver Broadband Wireless Data Card - + Globe Trotter PCMCIA card, say Y here. + + To compile this driver as a module, choose M here, the module + will be called nozomi. + +config ISI + tristate "Multi-Tech multiport card support (EXPERIMENTAL)" + depends on SERIAL_NONSTANDARD && PCI + select FW_LOADER + help + This is a driver for the Multi-Tech cards which provide several + serial ports. The driver is experimental and can currently only be + built as a module. The module will be called isicom. + If you want to do that, choose M here. + +config N_HDLC + tristate "HDLC line discipline support" + depends on SERIAL_NONSTANDARD + help + Allows synchronous HDLC communications with tty device drivers that + support synchronous HDLC such as the Microgate SyncLink adapter. + + This driver can be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called n_hdlc. If you want to do that, say M + here. + +config N_GSM + tristate "GSM MUX line discipline support (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on NET + help + This line discipline provides support for the GSM MUX protocol and + presents the mux as a set of 61 individual tty devices. diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 396277216e4f..e549da348a04 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -11,3 +11,16 @@ obj-$(CONFIG_R3964) += n_r3964.o obj-y += vt/ obj-$(CONFIG_HVC_DRIVER) += hvc/ obj-y += serial/ + +# tty drivers +obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o +obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o +obj-$(CONFIG_CYCLADES) += cyclades.o +obj-$(CONFIG_ISI) += isicom.o +obj-$(CONFIG_MOXA_INTELLIO) += moxa.o +obj-$(CONFIG_MOXA_SMARTIO) += mxser.o +obj-$(CONFIG_NOZOMI) += nozomi.o +obj-$(CONFIG_ROCKETPORT) += rocket.o +obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o +obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o +obj-$(CONFIG_SYNCLINK) += synclink.o diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c new file mode 100644 index 000000000000..f214e5022472 --- /dev/null +++ b/drivers/tty/amiserial.c @@ -0,0 +1,2178 @@ +/* + * linux/drivers/char/amiserial.c + * + * Serial driver for the amiga builtin port. + * + * This code was created by taking serial.c version 4.30 from kernel + * release 2.3.22, replacing all hardware related stuff with the + * corresponding amiga hardware actions, and removing all irrelevant + * code. As a consequence, it uses many of the constants and names + * associated with the registers and bits of 16550 compatible UARTS - + * but only to keep track of status, etc in the state variables. It + * was done this was to make it easier to keep the code in line with + * (non hardware specific) changes to serial.c. + * + * The port is registered with the tty driver as minor device 64, and + * therefore other ports should should only use 65 upwards. + * + * Richard Lucock 28/12/99 + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, + * 1998, 1999 Theodore Ts'o + * + */ + +/* + * Serial driver configuration section. Here are the various options: + * + * SERIAL_PARANOIA_CHECK + * Check the magic number for the async_structure where + * ever possible. + */ + +#include + +#undef SERIAL_PARANOIA_CHECK +#define SERIAL_DO_RESTART + +/* Set of debugging defines */ + +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + +/* Sanity checks */ + +#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) +#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ + tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s) +#else +#define DBG_CNT(s) +#endif + +/* + * End of serial driver configuration section. + */ + +#include + +#include +#include +#include +#include +static char *serial_version = "4.30"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#define custom amiga_custom +static char *serial_name = "Amiga-builtin serial driver"; + +static struct tty_driver *serial_driver; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +static struct async_struct *IRQ_ports; + +static unsigned char current_ctl_bits; + +static void change_speed(struct async_struct *info, struct ktermios *old); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); + + +static struct serial_state rs_table[1]; + +#define NR_PORTS ARRAY_SIZE(rs_table) + +#include + +#define serial_isroot() (capable(CAP_SYS_ADMIN)) + + +static inline int serial_paranoia_check(struct async_struct *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 async_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, name, routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, name, routine); + return 1; + } +#endif + return 0; +} + +/* some serial hardware definitions */ +#define SDR_OVRUN (1<<15) +#define SDR_RBF (1<<14) +#define SDR_TBE (1<<13) +#define SDR_TSRE (1<<12) + +#define SERPER_PARENB (1<<15) + +#define AC_SETCLR (1<<15) +#define AC_UARTBRK (1<<11) + +#define SER_DTR (1<<7) +#define SER_RTS (1<<6) +#define SER_DCD (1<<5) +#define SER_CTS (1<<4) +#define SER_DSR (1<<3) + +static __inline__ void rtsdtr_ctrl(int bits) +{ + ciab.pra = ((bits & (SER_RTS | SER_DTR)) ^ (SER_RTS | SER_DTR)) | (ciab.pra & ~(SER_RTS | SER_DTR)); +} + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_stop")) + return; + + local_irq_save(flags); + if (info->IER & UART_IER_THRI) { + info->IER &= ~UART_IER_THRI; + /* disable Tx interrupt and remove any pending interrupts */ + custom.intena = IF_TBE; + mb(); + custom.intreq = IF_TBE; + mb(); + } + local_irq_restore(flags); +} + +static void rs_start(struct tty_struct *tty) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_start")) + return; + + local_irq_save(flags); + if (info->xmit.head != info->xmit.tail + && info->xmit.buf + && !(info->IER & UART_IER_THRI)) { + info->IER |= UART_IER_THRI; + custom.intena = IF_SETCLR | IF_TBE; + mb(); + /* set a pending Tx Interrupt, transmitter should restart now */ + custom.intreq = IF_SETCLR | IF_TBE; + mb(); + } + local_irq_restore(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static void rs_sched_event(struct async_struct *info, + int event) +{ + info->event |= 1 << event; + tasklet_schedule(&info->tlet); +} + +static void receive_chars(struct async_struct *info) +{ + int status; + int serdatr; + struct tty_struct *tty = info->tty; + unsigned char ch, flag; + struct async_icount *icount; + int oe = 0; + + icount = &info->state->icount; + + status = UART_LSR_DR; /* We obviously have a character! */ + serdatr = custom.serdatr; + mb(); + custom.intreq = IF_RBF; + mb(); + + if((serdatr & 0x1ff) == 0) + status |= UART_LSR_BI; + if(serdatr & SDR_OVRUN) + status |= UART_LSR_OE; + + ch = serdatr & 0xff; + icount->rx++; + +#ifdef SERIAL_DEBUG_INTR + printk("DR%02x:%02x...", ch, status); +#endif + flag = TTY_NORMAL; + + /* + * We don't handle parity or frame errors - but I have left + * the code in, since I'm not sure that the errors can't be + * detected. + */ + + if (status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE)) { + /* + * For statistics only + */ + if (status & UART_LSR_BI) { + status &= ~(UART_LSR_FE | UART_LSR_PE); + icount->brk++; + } else if (status & UART_LSR_PE) + icount->parity++; + else if (status & UART_LSR_FE) + icount->frame++; + if (status & UART_LSR_OE) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (status & info->ignore_status_mask) + goto out; + + status &= info->read_status_mask; + + if (status & (UART_LSR_BI)) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + flag = TTY_BREAK; + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (status & UART_LSR_PE) + flag = TTY_PARITY; + else if (status & UART_LSR_FE) + flag = TTY_FRAME; + if (status & UART_LSR_OE) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + oe = 1; + } + } + tty_insert_flip_char(tty, ch, flag); + if (oe == 1) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_flip_buffer_push(tty); +out: + return; +} + +static void transmit_chars(struct async_struct *info) +{ + custom.intreq = IF_TBE; + mb(); + if (info->x_char) { + custom.serdat = info->x_char | 0x100; + mb(); + info->state->icount.tx++; + info->x_char = 0; + return; + } + if (info->xmit.head == info->xmit.tail + || info->tty->stopped + || info->tty->hw_stopped) { + info->IER &= ~UART_IER_THRI; + custom.intena = IF_TBE; + mb(); + return; + } + + custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100; + mb(); + info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1); + info->state->icount.tx++; + + if (CIRC_CNT(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + +#ifdef SERIAL_DEBUG_INTR + printk("THRE..."); +#endif + if (info->xmit.head == info->xmit.tail) { + custom.intena = IF_TBE; + mb(); + info->IER &= ~UART_IER_THRI; + } +} + +static void check_modem_status(struct async_struct *info) +{ + unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); + unsigned char dstatus; + struct async_icount *icount; + + /* Determine bits that have changed */ + dstatus = status ^ current_ctl_bits; + current_ctl_bits = status; + + if (dstatus) { + icount = &info->state->icount; + /* update input line counters */ + if (dstatus & SER_DSR) + icount->dsr++; + if (dstatus & SER_DCD) { + icount->dcd++; +#ifdef CONFIG_HARD_PPS + if ((info->flags & ASYNC_HARDPPS_CD) && + !(status & SER_DCD)) + hardpps(); +#endif + } + if (dstatus & SER_CTS) + icount->cts++; + wake_up_interruptible(&info->delta_msr_wait); + } + + if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { +#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) + printk("ttyS%d CD now %s...", info->line, + (!(status & SER_DCD)) ? "on" : "off"); +#endif + if (!(status & SER_DCD)) + wake_up_interruptible(&info->open_wait); + else { +#ifdef SERIAL_DEBUG_OPEN + printk("doing serial hangup..."); +#endif + if (info->tty) + tty_hangup(info->tty); + } + } + if (info->flags & ASYNC_CTS_FLOW) { + if (info->tty->hw_stopped) { + if (!(status & SER_CTS)) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx start..."); +#endif + info->tty->hw_stopped = 0; + info->IER |= UART_IER_THRI; + custom.intena = IF_SETCLR | IF_TBE; + mb(); + /* set a pending Tx Interrupt, transmitter should restart now */ + custom.intreq = IF_SETCLR | IF_TBE; + mb(); + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + return; + } + } else { + if ((status & SER_CTS)) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx stop..."); +#endif + info->tty->hw_stopped = 1; + info->IER &= ~UART_IER_THRI; + /* disable Tx interrupt and remove any pending interrupts */ + custom.intena = IF_TBE; + mb(); + custom.intreq = IF_TBE; + mb(); + } + } + } +} + +static irqreturn_t ser_vbl_int( int irq, void *data) +{ + /* vbl is just a periodic interrupt we tie into to update modem status */ + struct async_struct * info = IRQ_ports; + /* + * TBD - is it better to unregister from this interrupt or to + * ignore it if MSI is clear ? + */ + if(info->IER & UART_IER_MSI) + check_modem_status(info); + return IRQ_HANDLED; +} + +static irqreturn_t ser_rx_int(int irq, void *dev_id) +{ + struct async_struct * info; + +#ifdef SERIAL_DEBUG_INTR + printk("ser_rx_int..."); +#endif + + info = IRQ_ports; + if (!info || !info->tty) + return IRQ_NONE; + + receive_chars(info); + info->last_active = jiffies; +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif + return IRQ_HANDLED; +} + +static irqreturn_t ser_tx_int(int irq, void *dev_id) +{ + struct async_struct * info; + + if (custom.serdatr & SDR_TBE) { +#ifdef SERIAL_DEBUG_INTR + printk("ser_tx_int..."); +#endif + + info = IRQ_ports; + if (!info || !info->tty) + return IRQ_NONE; + + transmit_chars(info); + info->last_active = jiffies; +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif + } + return IRQ_HANDLED; +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ + +static void do_softint(unsigned long private_) +{ + struct async_struct *info = (struct async_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) + tty_wakeup(tty); +} + +/* + * --------------------------------------------------------------- + * Low level utility subroutines for the serial driver: routines to + * figure out the appropriate timeout for an interrupt chain, routines + * to initialize and startup a serial port, and routines to shutdown a + * serial port. Useful stuff like that. + * --------------------------------------------------------------- + */ + +static int startup(struct async_struct * info) +{ + unsigned long flags; + int retval=0; + unsigned long page; + + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + local_irq_save(flags); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + + if (info->xmit.buf) + free_page(page); + else + info->xmit.buf = (unsigned char *) page; + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttys%d ...", info->line); +#endif + + /* Clear anything in the input buffer */ + + custom.intreq = IF_RBF; + mb(); + + retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info); + if (retval) { + if (serial_isroot()) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + + /* enable both Rx and Tx interrupts */ + custom.intena = IF_SETCLR | IF_RBF | IF_TBE; + mb(); + info->IER = UART_IER_MSI; + + /* remember current state of the DCD and CTS bits */ + current_ctl_bits = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); + + IRQ_ports = info; + + info->MCR = 0; + if (info->tty->termios->c_cflag & CBAUD) + info->MCR = SER_DTR | SER_RTS; + rtsdtr_ctrl(info->MCR); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit.head = info->xmit.tail = 0; + + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + } + + /* + * and set the speed of the serial port + */ + change_speed(info, NULL); + + info->flags |= ASYNC_INITIALIZED; + local_irq_restore(flags); + return 0; + +errout: + local_irq_restore(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct async_struct * info) +{ + unsigned long flags; + struct serial_state *state; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + state = info->state; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d ....\n", info->line); +#endif + + local_irq_save(flags); /* Disable interrupts */ + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + IRQ_ports = NULL; + + /* + * Free the IRQ, if necessary + */ + free_irq(IRQ_AMIGA_VERTB, info); + + if (info->xmit.buf) { + free_page((unsigned long) info->xmit.buf); + info->xmit.buf = NULL; + } + + info->IER = 0; + custom.intena = IF_RBF | IF_TBE; + mb(); + + /* disable break condition */ + custom.adkcon = AC_UARTBRK; + mb(); + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + info->MCR &= ~(SER_DTR|SER_RTS); + rtsdtr_ctrl(info->MCR); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + local_irq_restore(flags); +} + + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct async_struct *info, + struct ktermios *old_termios) +{ + int quot = 0, baud_base, baud; + unsigned cflag, cval = 0; + int bits; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + + /* Byte size is always 8 bits plus parity bit if requested */ + + cval = 3; bits = 10; + if (cflag & CSTOPB) { + cval |= 0x04; + bits++; + } + if (cflag & PARENB) { + cval |= UART_LCR_PARITY; + bits++; + } + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(info->tty); + if (!baud) + baud = 9600; /* B0 transition handled in rs_set_termios */ + baud_base = info->state->baud_base; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->state->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + /* If the quotient is zero refuse the change */ + if (!quot && old_termios) { + /* FIXME: Will need updating for new tty in the end */ + info->tty->termios->c_cflag &= ~CBAUD; + info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); + baud = tty_get_baud_rate(info->tty); + if (!baud) + baud = 9600; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->state->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + } + /* As a last resort, if the quotient is zero, default to 9600 bps */ + if (!quot) + quot = baud_base / 9600; + info->quot = quot; + info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + if (info->flags & ASYNC_HARDPPS_CD) + info->IER |= UART_IER_MSI; + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + } else + info->flags &= ~ASYNC_CTS_FLOW; + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else { + info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + /* TBD: + * Does clearing IER_MSI imply that we should disable the VBL interrupt ? + */ + + /* + * Set up parity check flag + */ + + info->read_status_mask = UART_LSR_OE | UART_LSR_DR; + if (I_INPCK(info->tty)) + info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= UART_LSR_BI; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= UART_LSR_OE; + } + /* + * !!! ignore all characters if CREAD is not set + */ + if ((cflag & CREAD) == 0) + info->ignore_status_mask |= UART_LSR_DR; + local_irq_save(flags); + + { + short serper; + + /* Set up the baud rate */ + serper = quot - 1; + + /* Enable or disable parity bit */ + + if(cval & UART_LCR_PARITY) + serper |= (SERPER_PARENB); + + custom.serper = serper; + mb(); + } + + info->LCR = cval; /* Save LCR */ + local_irq_restore(flags); +} + +static int rs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct async_struct *info; + unsigned long flags; + + info = tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_put_char")) + return 0; + + if (!info->xmit.buf) + return 0; + + local_irq_save(flags); + if (CIRC_SPACE(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) == 0) { + local_irq_restore(flags); + return 0; + } + + info->xmit.buf[info->xmit.head++] = ch; + info->xmit.head &= SERIAL_XMIT_SIZE-1; + local_irq_restore(flags); + return 1; +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) + return; + + if (info->xmit.head == info->xmit.tail + || tty->stopped + || tty->hw_stopped + || !info->xmit.buf) + return; + + local_irq_save(flags); + info->IER |= UART_IER_THRI; + custom.intena = IF_SETCLR | IF_TBE; + mb(); + /* set a pending Tx Interrupt, transmitter should restart now */ + custom.intreq = IF_SETCLR | IF_TBE; + mb(); + local_irq_restore(flags); +} + +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) +{ + int c, ret = 0; + struct async_struct *info; + unsigned long flags; + + info = tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_write")) + return 0; + + if (!info->xmit.buf) + return 0; + + local_irq_save(flags); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; + } + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; + } + local_irq_restore(flags); + + if (info->xmit.head != info->xmit.tail + && !tty->stopped + && !tty->hw_stopped + && !(info->IER & UART_IER_THRI)) { + info->IER |= UART_IER_THRI; + local_irq_disable(); + custom.intena = IF_SETCLR | IF_TBE; + mb(); + /* set a pending Tx Interrupt, transmitter should restart now */ + custom.intreq = IF_SETCLR | IF_TBE; + mb(); + local_irq_restore(flags); + } + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct async_struct *info = tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_write_room")) + return 0; + return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct async_struct *info = tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) + return 0; + return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) + return; + local_irq_save(flags); + info->xmit.head = info->xmit.tail = 0; + local_irq_restore(flags); + tty_wakeup(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_send_xchar(struct tty_struct *tty, char ch) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_send_char")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + + /* Check this ! */ + local_irq_save(flags); + if(!(custom.intenar & IF_TBE)) { + custom.intena = IF_SETCLR | IF_TBE; + mb(); + /* set a pending Tx Interrupt, transmitter should restart now */ + custom.intreq = IF_SETCLR | IF_TBE; + mb(); + } + local_irq_restore(flags); + + info->IER |= UART_IER_THRI; + } +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_throttle")) + return; + + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) + info->MCR &= ~SER_RTS; + + local_irq_save(flags); + rtsdtr_ctrl(info->MCR); + local_irq_restore(flags); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } + if (tty->termios->c_cflag & CRTSCTS) + info->MCR |= SER_RTS; + local_irq_save(flags); + rtsdtr_ctrl(info->MCR); + local_irq_restore(flags); +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct async_struct * info, + struct serial_struct __user * retinfo) +{ + struct serial_struct tmp; + struct serial_state *state = info->state; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tty_lock(); + tmp.type = state->type; + tmp.line = state->line; + tmp.port = state->port; + tmp.irq = state->irq; + tmp.flags = state->flags; + tmp.xmit_fifo_size = state->xmit_fifo_size; + tmp.baud_base = state->baud_base; + tmp.close_delay = state->close_delay; + tmp.closing_wait = state->closing_wait; + tmp.custom_divisor = state->custom_divisor; + tty_unlock(); + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct async_struct * info, + struct serial_struct __user * new_info) +{ + struct serial_struct new_serial; + struct serial_state old_state, *state; + unsigned int change_irq,change_port; + int retval = 0; + + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) + return -EFAULT; + + tty_lock(); + state = info->state; + old_state = *state; + + change_irq = new_serial.irq != state->irq; + change_port = (new_serial.port != state->port); + if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { + tty_unlock(); + return -EINVAL; + } + + if (!serial_isroot()) { + if ((new_serial.baud_base != state->baud_base) || + (new_serial.close_delay != state->close_delay) || + (new_serial.xmit_fifo_size != state->xmit_fifo_size) || + ((new_serial.flags & ~ASYNC_USR_MASK) != + (state->flags & ~ASYNC_USR_MASK))) + return -EPERM; + state->flags = ((state->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + state->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (new_serial.baud_base < 9600) { + tty_unlock(); + return -EINVAL; + } + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + state->baud_base = new_serial.baud_base; + state->flags = ((state->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | + (info->flags & ASYNC_INTERNAL_FLAGS)); + state->custom_divisor = new_serial.custom_divisor; + state->close_delay = new_serial.close_delay * HZ/100; + state->closing_wait = new_serial.closing_wait * HZ/100; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + +check_and_exit: + if (info->flags & ASYNC_INITIALIZED) { + if (((old_state.flags & ASYNC_SPD_MASK) != + (state->flags & ASYNC_SPD_MASK)) || + (old_state.custom_divisor != state->custom_divisor)) { + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + change_speed(info, NULL); + } + } else + retval = startup(info); + tty_unlock(); + return retval; +} + + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct async_struct * info, unsigned int __user *value) +{ + unsigned char status; + unsigned int result; + unsigned long flags; + + local_irq_save(flags); + status = custom.serdatr; + mb(); + local_irq_restore(flags); + result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0); + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + + +static int rs_tiocmget(struct tty_struct *tty) +{ + struct async_struct * info = tty->driver_data; + unsigned char control, status; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + control = info->MCR; + local_irq_save(flags); + status = ciab.pra; + local_irq_restore(flags); + return ((control & SER_RTS) ? TIOCM_RTS : 0) + | ((control & SER_DTR) ? TIOCM_DTR : 0) + | (!(status & SER_DCD) ? TIOCM_CAR : 0) + | (!(status & SER_DSR) ? TIOCM_DSR : 0) + | (!(status & SER_CTS) ? TIOCM_CTS : 0); +} + +static int rs_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear) +{ + struct async_struct * info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + local_irq_save(flags); + if (set & TIOCM_RTS) + info->MCR |= SER_RTS; + if (set & TIOCM_DTR) + info->MCR |= SER_DTR; + if (clear & TIOCM_RTS) + info->MCR &= ~SER_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~SER_DTR; + rtsdtr_ctrl(info->MCR); + local_irq_restore(flags); + return 0; +} + +/* + * rs_break() --- routine which turns the break handling on or off + */ +static int rs_break(struct tty_struct *tty, int break_state) +{ + struct async_struct * info = tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_break")) + return -EINVAL; + + local_irq_save(flags); + if (break_state == -1) + custom.adkcon = AC_SETCLR | AC_UARTBRK; + else + custom.adkcon = AC_UARTBRK; + mb(); + local_irq_restore(flags); + return 0; +} + +/* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +static int rs_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + struct async_struct *info = tty->driver_data; + struct async_icount cnow; + unsigned long flags; + + local_irq_save(flags); + cnow = info->state->icount; + local_irq_restore(flags); + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->frame = cnow.frame; + icount->overrun = cnow.overrun; + icount->parity = cnow.parity; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + + return 0; +} + +static int rs_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct async_struct * info = tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + void __user *argp = (void __user *)arg; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(info, argp); + case TIOCSSERIAL: + return set_serial_info(info, argp); + case TIOCSERCONFIG: + return 0; + + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, argp); + + case TIOCSERGSTRUCT: + if (copy_to_user(argp, + info, sizeof(struct async_struct))) + return -EFAULT; + return 0; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + local_irq_save(flags); + /* note the counters on entry */ + cprev = info->state->icount; + local_irq_restore(flags); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + local_irq_save(flags); + cnow = info->state->icount; /* atomic copy */ + local_irq_restore(flags); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct async_struct *info = tty->driver_data; + unsigned long flags; + unsigned int cflag = tty->termios->c_cflag; + + change_speed(info, old_termios); + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && + !(cflag & CBAUD)) { + info->MCR &= ~(SER_DTR|SER_RTS); + local_irq_save(flags); + rtsdtr_ctrl(info->MCR); + local_irq_restore(flags); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + (cflag & CBAUD)) { + info->MCR |= SER_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->MCR |= SER_RTS; + } + local_irq_save(flags); + rtsdtr_ctrl(info->MCR); + local_irq_restore(flags); + } + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } + +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); +#endif +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct async_struct * info = tty->driver_data; + struct serial_state *state; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->name, "rs_close")) + return; + + state = info->state; + + local_irq_save(flags); + + if (tty_hung_up_p(filp)) { + DBG_CNT("before DEC-hung"); + local_irq_restore(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_close ttys%d, count = %d\n", info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->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("rs_close: bad serial port count; tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + DBG_CNT("before DEC-2"); + local_irq_restore(flags); + return; + } + info->flags |= ASYNC_CLOSING; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->read_status_mask &= ~UART_LSR_DR; + if (info->flags & ASYNC_INITIALIZED) { + /* disable receive interrupts */ + custom.intena = IF_RBF; + mb(); + /* clear any pending receive interrupt */ + custom.intreq = IF_RBF; + mb(); + + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + rs_wait_until_sent(tty, info->timeout); + } + shutdown(info); + rs_flush_buffer(tty); + + tty_ldisc_flush(tty); + tty->closing = 0; + 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); + local_irq_restore(flags); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct async_struct * info = tty->driver_data; + unsigned long orig_jiffies, char_time; + int tty_was_locked = tty_locked(); + int lsr; + + if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + + /* + * tty_wait_until_sent is called from lots of places, + * with or without the BTM. + */ + if (!tty_was_locked) + tty_lock(); + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout) + char_time = min_t(unsigned long, char_time, timeout); + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2*info->timeout) + timeout = 2*info->timeout; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + while(!((lsr = custom.serdatr) & SDR_TSRE)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("serdatr = %d (jiff=%lu)...", lsr, jiffies); +#endif + msleep_interruptible(jiffies_to_msecs(char_time)); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + __set_current_state(TASK_RUNNING); + if (!tty_was_locked) + tty_unlock(); +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct async_struct * info = tty->driver_data; + struct serial_state *state = info->state; + + if (serial_paranoia_check(info, tty->name, "rs_hangup")) + return; + + state = info->state; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + state->count = 0; + info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->tty = NULL; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct async_struct *info) +{ +#ifdef DECLARE_WAITQUEUE + DECLARE_WAITQUEUE(wait, current); +#else + struct wait_queue wait = { current, NULL }; +#endif + struct serial_state *state = info->state; + int retval; + int do_clocal = 0, extra_count = 0; + unsigned long flags; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + + /* + * 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, state->count is dropped by one, so that + * rs_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: ttys%d, count = %d\n", + state->line, state->count); +#endif + local_irq_save(flags); + if (!tty_hung_up_p(filp)) { + extra_count = 1; + state->count--; + } + local_irq_restore(flags); + info->blocked_open++; + while (1) { + local_irq_save(flags); + if (tty->termios->c_cflag & CBAUD) + rtsdtr_ctrl(SER_DTR|SER_RTS); + local_irq_restore(flags); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CLOSING) && + (do_clocal || (!(ciab.pra & SER_DCD)) )) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + tty_unlock(); + schedule(); + tty_lock(); + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(&info->open_wait, &wait); + if (extra_count) + state->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + struct serial_state *sstate; + + sstate = rs_table + line; + sstate->count++; + if (sstate->info) { + *ret_info = sstate->info; + return 0; + } + info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); + if (!info) { + sstate->count--; + return -ENOMEM; + } +#ifdef DECLARE_WAITQUEUE + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); +#endif + info->magic = SERIAL_MAGIC; + info->port = sstate->port; + info->flags = sstate->flags; + info->xmit_fifo_size = sstate->xmit_fifo_size; + info->line = line; + tasklet_init(&info->tlet, do_softint, (unsigned long)info); + info->state = sstate; + if (sstate->info) { + kfree(info); + *ret_info = sstate->info; + return 0; + } + *ret_info = sstate->info = info; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct async_struct *info; + int retval, line; + + line = tty->index; + if ((line < 0) || (line >= NR_PORTS)) { + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + return retval; + } + tty->driver_data = info; + info->tty = tty; + if (serial_paranoia_check(info, tty->name, "rs_open")) + return -ENODEV; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s, count = %d\n", tty->name, info->state->count); +#endif + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + return retval; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open returning after block_til_ready with %d\n", + retval); +#endif + return retval; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s successful...", tty->name); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline void line_info(struct seq_file *m, struct serial_state *state) +{ + struct async_struct *info = state->info, scr_info; + char stat_buf[30], control, status; + unsigned long flags; + + seq_printf(m, "%d: uart:amiga_builtin",state->line); + + /* + * Figure out the current RS-232 lines + */ + if (!info) { + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->flags = state->flags; + info->quot = 0; + info->tty = NULL; + } + local_irq_save(flags); + status = ciab.pra; + control = info ? info->MCR : status; + local_irq_restore(flags); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if(!(control & SER_RTS)) + strcat(stat_buf, "|RTS"); + if(!(status & SER_CTS)) + strcat(stat_buf, "|CTS"); + if(!(control & SER_DTR)) + strcat(stat_buf, "|DTR"); + if(!(status & SER_DSR)) + strcat(stat_buf, "|DSR"); + if(!(status & SER_DCD)) + strcat(stat_buf, "|CD"); + + if (info->quot) { + seq_printf(m, " baud:%d", state->baud_base / info->quot); + } + + seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx); + + if (state->icount.frame) + seq_printf(m, " fe:%d", state->icount.frame); + + if (state->icount.parity) + seq_printf(m, " pe:%d", state->icount.parity); + + if (state->icount.brk) + seq_printf(m, " brk:%d", state->icount.brk); + + if (state->icount.overrun) + seq_printf(m, " oe:%d", state->icount.overrun); + + /* + * Last thing is the RS-232 status lines + */ + seq_printf(m, " %s\n", stat_buf+1); +} + +static int rs_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); + line_info(m, &rs_table[0]); + return 0; +} + +static int rs_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, rs_proc_show, NULL); +} + +static const struct file_operations rs_proc_fops = { + .owner = THIS_MODULE, + .open = rs_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s\n", serial_name, serial_version); +} + + +static const struct tty_operations serial_ops = { + .open = rs_open, + .close = rs_close, + .write = rs_write, + .put_char = rs_put_char, + .flush_chars = rs_flush_chars, + .write_room = rs_write_room, + .chars_in_buffer = rs_chars_in_buffer, + .flush_buffer = rs_flush_buffer, + .ioctl = rs_ioctl, + .throttle = rs_throttle, + .unthrottle = rs_unthrottle, + .set_termios = rs_set_termios, + .stop = rs_stop, + .start = rs_start, + .hangup = rs_hangup, + .break_ctl = rs_break, + .send_xchar = rs_send_xchar, + .wait_until_sent = rs_wait_until_sent, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset, + .get_icount = rs_get_icount, + .proc_fops = &rs_proc_fops, +}; + +/* + * The serial driver boot-time initialization code! + */ +static int __init amiga_serial_probe(struct platform_device *pdev) +{ + unsigned long flags; + struct serial_state * state; + int error; + + serial_driver = alloc_tty_driver(1); + if (!serial_driver) + return -ENOMEM; + + IRQ_ports = NULL; + + show_serial_version(); + + /* Initialize the tty_driver structure */ + + serial_driver->owner = THIS_MODULE; + serial_driver->driver_name = "amiserial"; + serial_driver->name = "ttyS"; + serial_driver->major = TTY_MAJOR; + serial_driver->minor_start = 64; + serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_driver->subtype = SERIAL_TYPE_NORMAL; + serial_driver->init_termios = tty_std_termios; + serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(serial_driver, &serial_ops); + + error = tty_register_driver(serial_driver); + if (error) + goto fail_put_tty_driver; + + state = rs_table; + state->magic = SSTATE_MAGIC; + state->port = (int)&custom.serdatr; /* Just to give it a value */ + state->line = 0; + state->custom_divisor = 0; + state->close_delay = 5*HZ/10; + state->closing_wait = 30*HZ; + state->icount.cts = state->icount.dsr = + state->icount.rng = state->icount.dcd = 0; + state->icount.rx = state->icount.tx = 0; + state->icount.frame = state->icount.parity = 0; + state->icount.overrun = state->icount.brk = 0; + + printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", + state->line); + + /* Hardware set up */ + + state->baud_base = amiga_colorclock; + state->xmit_fifo_size = 1; + + /* set ISRs, and then disable the rx interrupts */ + error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state); + if (error) + goto fail_unregister; + + error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, + "serial RX", state); + if (error) + goto fail_free_irq; + + local_irq_save(flags); + + /* turn off Rx and Tx interrupts */ + custom.intena = IF_RBF | IF_TBE; + mb(); + + /* clear any pending interrupt */ + custom.intreq = IF_RBF | IF_TBE; + mb(); + + local_irq_restore(flags); + + /* + * set the appropriate directions for the modem control flags, + * and clear RTS and DTR + */ + ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ + ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ + + platform_set_drvdata(pdev, state); + + return 0; + +fail_free_irq: + free_irq(IRQ_AMIGA_TBE, state); +fail_unregister: + tty_unregister_driver(serial_driver); +fail_put_tty_driver: + put_tty_driver(serial_driver); + return error; +} + +static int __exit amiga_serial_remove(struct platform_device *pdev) +{ + int error; + struct serial_state *state = platform_get_drvdata(pdev); + struct async_struct *info = state->info; + + /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ + tasklet_kill(&info->tlet); + if ((error = tty_unregister_driver(serial_driver))) + printk("SERIAL: failed to unregister serial driver (%d)\n", + error); + put_tty_driver(serial_driver); + + rs_table[0].info = NULL; + kfree(info); + + free_irq(IRQ_AMIGA_TBE, rs_table); + free_irq(IRQ_AMIGA_RBF, rs_table); + + platform_set_drvdata(pdev, NULL); + + return error; +} + +static struct platform_driver amiga_serial_driver = { + .remove = __exit_p(amiga_serial_remove), + .driver = { + .name = "amiga-serial", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_serial_init(void) +{ + return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe); +} + +module_init(amiga_serial_init); + +static void __exit amiga_serial_exit(void) +{ + platform_driver_unregister(&amiga_serial_driver); +} + +module_exit(amiga_serial_exit); + + +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ + +static void amiga_serial_putc(char c) +{ + custom.serdat = (unsigned char)c | 0x100; + while (!(custom.serdatr & 0x2000)) + barrier(); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console must be locked when we get here. + */ +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + unsigned short intena = custom.intenar; + + custom.intena = IF_TBE; + + while (count--) { + if (*s == '\n') + amiga_serial_putc('\r'); + amiga_serial_putc(*s++); + } + + custom.intena = IF_SETCLR | (intena & IF_TBE); +} + +static struct tty_driver *serial_console_device(struct console *c, int *index) +{ + *index = 0; + return serial_driver; +} + +static struct console sercons = { + .name = "ttyS", + .write = serial_console_write, + .device = serial_console_device, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +/* + * Register console. + */ +static int __init amiserial_console_init(void) +{ + register_console(&sercons); + return 0; +} +console_initcall(amiserial_console_init); + +#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-serial"); diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c new file mode 100644 index 000000000000..16402445f2b2 --- /dev/null +++ b/drivers/tty/bfin_jtag_comm.c @@ -0,0 +1,366 @@ +/* + * TTY over Blackfin JTAG Communication + * + * Copyright 2008-2009 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#define DRV_NAME "bfin-jtag-comm" +#define DEV_NAME "ttyBFJC" +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) + +/* See the Debug/Emulation chapter in the HRM */ +#define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ +#define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ +#define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ +#define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ + +static inline uint32_t bfin_write_emudat(uint32_t emudat) +{ + __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); + return emudat; +} + +static inline uint32_t bfin_read_emudat(void) +{ + uint32_t emudat; + __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); + return emudat; +} + +static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d) +{ + return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24)); +} + +#define CIRC_SIZE 2048 /* see comment in tty_io.c:do_tty_write() */ +#define CIRC_MASK (CIRC_SIZE - 1) +#define circ_empty(circ) ((circ)->head == (circ)->tail) +#define circ_free(circ) CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE) +#define circ_cnt(circ) CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE) +#define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK]) + +static struct tty_driver *bfin_jc_driver; +static struct task_struct *bfin_jc_kthread; +static struct tty_struct * volatile bfin_jc_tty; +static unsigned long bfin_jc_count; +static DEFINE_MUTEX(bfin_jc_tty_mutex); +static volatile struct circ_buf bfin_jc_write_buf; + +static int +bfin_jc_emudat_manager(void *arg) +{ + uint32_t inbound_len = 0, outbound_len = 0; + + while (!kthread_should_stop()) { + /* no one left to give data to, so sleep */ + if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) { + pr_debug("waiting for readers\n"); + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + __set_current_state(TASK_RUNNING); + } + + /* no data available, so just chill */ + if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) { + pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n", + inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head); + if (inbound_len) + schedule(); + else + schedule_timeout_interruptible(HZ); + continue; + } + + /* if incoming data is ready, eat it */ + if (bfin_read_DBGSTAT() & EMUDIF) { + struct tty_struct *tty; + mutex_lock(&bfin_jc_tty_mutex); + tty = (struct tty_struct *)bfin_jc_tty; + if (tty != NULL) { + uint32_t emudat = bfin_read_emudat(); + if (inbound_len == 0) { + pr_debug("incoming length: 0x%08x\n", emudat); + inbound_len = emudat; + } else { + size_t num_chars = (4 <= inbound_len ? 4 : inbound_len); + pr_debug(" incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars); + inbound_len -= num_chars; + tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars); + tty_flip_buffer_push(tty); + } + } + mutex_unlock(&bfin_jc_tty_mutex); + } + + /* if outgoing data is ready, post it */ + if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) { + if (outbound_len == 0) { + outbound_len = circ_cnt(&bfin_jc_write_buf); + bfin_write_emudat(outbound_len); + pr_debug("outgoing length: 0x%08x\n", outbound_len); + } else { + struct tty_struct *tty; + int tail = bfin_jc_write_buf.tail; + size_t ate = (4 <= outbound_len ? 4 : outbound_len); + uint32_t emudat = + bfin_write_emudat_chars( + circ_byte(&bfin_jc_write_buf, tail + 0), + circ_byte(&bfin_jc_write_buf, tail + 1), + circ_byte(&bfin_jc_write_buf, tail + 2), + circ_byte(&bfin_jc_write_buf, tail + 3) + ); + bfin_jc_write_buf.tail += ate; + outbound_len -= ate; + mutex_lock(&bfin_jc_tty_mutex); + tty = (struct tty_struct *)bfin_jc_tty; + if (tty) + tty_wakeup(tty); + mutex_unlock(&bfin_jc_tty_mutex); + pr_debug(" outgoing data: 0x%08x (pushing %zu)\n", emudat, ate); + } + } + } + + __set_current_state(TASK_RUNNING); + return 0; +} + +static int +bfin_jc_open(struct tty_struct *tty, struct file *filp) +{ + mutex_lock(&bfin_jc_tty_mutex); + pr_debug("open %lu\n", bfin_jc_count); + ++bfin_jc_count; + bfin_jc_tty = tty; + wake_up_process(bfin_jc_kthread); + mutex_unlock(&bfin_jc_tty_mutex); + return 0; +} + +static void +bfin_jc_close(struct tty_struct *tty, struct file *filp) +{ + mutex_lock(&bfin_jc_tty_mutex); + pr_debug("close %lu\n", bfin_jc_count); + if (--bfin_jc_count == 0) + bfin_jc_tty = NULL; + wake_up_process(bfin_jc_kthread); + mutex_unlock(&bfin_jc_tty_mutex); +} + +/* XXX: we dont handle the put_char() case where we must handle count = 1 */ +static int +bfin_jc_circ_write(const unsigned char *buf, int count) +{ + int i; + count = min(count, circ_free(&bfin_jc_write_buf)); + pr_debug("going to write chunk of %i bytes\n", count); + for (i = 0; i < count; ++i) + circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i]; + bfin_jc_write_buf.head += i; + return i; +} + +#ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE +# define console_lock() +# define console_unlock() +#endif +static int +bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + int i; + console_lock(); + i = bfin_jc_circ_write(buf, count); + console_unlock(); + wake_up_process(bfin_jc_kthread); + return i; +} + +static void +bfin_jc_flush_chars(struct tty_struct *tty) +{ + wake_up_process(bfin_jc_kthread); +} + +static int +bfin_jc_write_room(struct tty_struct *tty) +{ + return circ_free(&bfin_jc_write_buf); +} + +static int +bfin_jc_chars_in_buffer(struct tty_struct *tty) +{ + return circ_cnt(&bfin_jc_write_buf); +} + +static void +bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) +{ + unsigned long expire = jiffies + timeout; + while (!circ_empty(&bfin_jc_write_buf)) { + if (signal_pending(current)) + break; + if (time_after(jiffies, expire)) + break; + } +} + +static const struct tty_operations bfin_jc_ops = { + .open = bfin_jc_open, + .close = bfin_jc_close, + .write = bfin_jc_write, + /*.put_char = bfin_jc_put_char,*/ + .flush_chars = bfin_jc_flush_chars, + .write_room = bfin_jc_write_room, + .chars_in_buffer = bfin_jc_chars_in_buffer, + .wait_until_sent = bfin_jc_wait_until_sent, +}; + +static int __init bfin_jc_init(void) +{ + int ret; + + bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME); + if (IS_ERR(bfin_jc_kthread)) + return PTR_ERR(bfin_jc_kthread); + + ret = -ENOMEM; + + bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0; + bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL); + if (!bfin_jc_write_buf.buf) + goto err; + + bfin_jc_driver = alloc_tty_driver(1); + if (!bfin_jc_driver) + goto err; + + bfin_jc_driver->owner = THIS_MODULE; + bfin_jc_driver->driver_name = DRV_NAME; + bfin_jc_driver->name = DEV_NAME; + bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; + bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL; + bfin_jc_driver->init_termios = tty_std_termios; + tty_set_operations(bfin_jc_driver, &bfin_jc_ops); + + ret = tty_register_driver(bfin_jc_driver); + if (ret) + goto err; + + pr_init(KERN_INFO DRV_NAME ": initialized\n"); + + return 0; + + err: + put_tty_driver(bfin_jc_driver); + kfree(bfin_jc_write_buf.buf); + kthread_stop(bfin_jc_kthread); + return ret; +} +module_init(bfin_jc_init); + +static void __exit bfin_jc_exit(void) +{ + kthread_stop(bfin_jc_kthread); + kfree(bfin_jc_write_buf.buf); + tty_unregister_driver(bfin_jc_driver); + put_tty_driver(bfin_jc_driver); +} +module_exit(bfin_jc_exit); + +#if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK) +static void +bfin_jc_straight_buffer_write(const char *buf, unsigned count) +{ + unsigned ate = 0; + while (bfin_read_DBGSTAT() & EMUDOF) + continue; + bfin_write_emudat(count); + while (ate < count) { + while (bfin_read_DBGSTAT() & EMUDOF) + continue; + bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]); + ate += 4; + } +} +#endif + +#ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE +static void +bfin_jc_console_write(struct console *co, const char *buf, unsigned count) +{ + if (bfin_jc_kthread == NULL) + bfin_jc_straight_buffer_write(buf, count); + else + bfin_jc_circ_write(buf, count); +} + +static struct tty_driver * +bfin_jc_console_device(struct console *co, int *index) +{ + *index = co->index; + return bfin_jc_driver; +} + +static struct console bfin_jc_console = { + .name = DEV_NAME, + .write = bfin_jc_console_write, + .device = bfin_jc_console_device, + .flags = CON_ANYTIME | CON_PRINTBUFFER, + .index = -1, +}; + +static int __init bfin_jc_console_init(void) +{ + register_console(&bfin_jc_console); + return 0; +} +console_initcall(bfin_jc_console_init); +#endif + +#ifdef CONFIG_EARLY_PRINTK +static void __init +bfin_jc_early_write(struct console *co, const char *buf, unsigned int count) +{ + bfin_jc_straight_buffer_write(buf, count); +} + +static struct __initdata console bfin_jc_early_console = { + .name = "early_BFJC", + .write = bfin_jc_early_write, + .flags = CON_ANYTIME | CON_PRINTBUFFER, + .index = -1, +}; + +struct console * __init +bfin_jc_early_init(unsigned int port, unsigned int cflag) +{ + return &bfin_jc_early_console; +} +#endif + +MODULE_AUTHOR("Mike Frysinger "); +MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c new file mode 100644 index 000000000000..c99728f0cd9f --- /dev/null +++ b/drivers/tty/cyclades.c @@ -0,0 +1,4200 @@ +#undef BLOCKMOVE +#define Z_WAKE +#undef Z_EXT_CHARS_IN_BUFFER + +/* + * linux/drivers/char/cyclades.c + * + * This file contains the driver for the Cyclades async multiport + * serial boards. + * + * Initially written by Randolph Bentson . + * Modified and maintained by Marcio Saito . + * + * Copyright (C) 2007-2009 Jiri Slaby + * + * Much of the design and some of the code came from serial.c + * which was copyright (C) 1991, 1992 Linus Torvalds. It was + * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, + * and then fixed as suggested by Michael K. Johnson 12/12/92. + * Converted to pci probing and cleaned up by Jiri Slaby. + * + */ + +#define CY_VERSION "2.6" + +/* If you need to install more boards than NR_CARDS, change the constant + in the definition below. No other change is necessary to support up to + eight boards. Beyond that you'll have to extend cy_isa_addresses. */ + +#define NR_CARDS 4 + +/* + If the total number of ports is larger than NR_PORTS, change this + constant in the definition below. No other change is necessary to + support more boards/ports. */ + +#define NR_PORTS 256 + +#define ZO_V1 0 +#define ZO_V2 1 +#define ZE_V1 2 + +#define SERIAL_PARANOIA_CHECK +#undef CY_DEBUG_OPEN +#undef CY_DEBUG_THROTTLE +#undef CY_DEBUG_OTHER +#undef CY_DEBUG_IO +#undef CY_DEBUG_COUNT +#undef CY_DEBUG_DTR +#undef CY_DEBUG_WAIT_UNTIL_SENT +#undef CY_DEBUG_INTERRUPTS +#undef CY_16Y_HACK +#undef CY_ENABLE_MONITORING +#undef CY_PCI_DEBUG + +/* + * Include section + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +static void cy_send_xchar(struct tty_struct *tty, char ch); + +#ifndef SERIAL_XMIT_SIZE +#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) +#endif + +#define STD_COM_FLAGS (0) + +/* firmware stuff */ +#define ZL_MAX_BLOCKS 16 +#define DRIVER_VERSION 0x02010203 +#define RAM_SIZE 0x80000 + +enum zblock_type { + ZBLOCK_PRG = 0, + ZBLOCK_FPGA = 1 +}; + +struct zfile_header { + char name[64]; + char date[32]; + char aux[32]; + u32 n_config; + u32 config_offset; + u32 n_blocks; + u32 block_offset; + u32 reserved[9]; +} __attribute__ ((packed)); + +struct zfile_config { + char name[64]; + u32 mailbox; + u32 function; + u32 n_blocks; + u32 block_list[ZL_MAX_BLOCKS]; +} __attribute__ ((packed)); + +struct zfile_block { + u32 type; + u32 file_offset; + u32 ram_offset; + u32 size; +} __attribute__ ((packed)); + +static struct tty_driver *cy_serial_driver; + +#ifdef CONFIG_ISA +/* This is the address lookup table. The driver will probe for + Cyclom-Y/ISA boards at all addresses in here. If you want the + driver to probe addresses at a different address, add it to + this table. If the driver is probing some other board and + causing problems, remove the offending address from this table. +*/ + +static unsigned int cy_isa_addresses[] = { + 0xD0000, + 0xD2000, + 0xD4000, + 0xD6000, + 0xD8000, + 0xDA000, + 0xDC000, + 0xDE000, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) + +static long maddr[NR_CARDS]; +static int irq[NR_CARDS]; + +module_param_array(maddr, long, NULL, 0); +module_param_array(irq, int, NULL, 0); + +#endif /* CONFIG_ISA */ + +/* This is the per-card data structure containing address, irq, number of + channels, etc. This driver supports a maximum of NR_CARDS cards. +*/ +static struct cyclades_card cy_card[NR_CARDS]; + +static int cy_next_channel; /* next minor available */ + +/* + * This is used to look up the divisor speeds and the timeouts + * We're normally limited to 15 distinct baud rates. The extra + * are accessed via settings in info->port.flags. + * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + * HI VHI + * 20 + */ +static const int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, + 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, + 230400, 0 +}; + +static const char baud_co_25[] = { /* 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 const char baud_bpr_25[] = { /* 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 const char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, + 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static const char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ + 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, + 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, + 0x21 +}; + +static const char baud_cor3[] = { /* receive threshold */ + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, + 0x07 +}; + +/* + * The Cyclades driver implements HW flow control as any serial driver. + * The cyclades_port structure member rflow and the vector rflow_thr + * allows us to take advantage of a special feature in the CD1400 to avoid + * data loss even when the system interrupt latency is too high. These flags + * are to be used only with very special applications. Setting these flags + * requires the use of a special cable (DTR and RTS reversed). In the new + * CD1400-based boards (rev. 6.00 or later), there is no need for special + * cables. + */ + +static const char rflow_thr[] = { /* rflow threshold */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a +}; + +/* The Cyclom-Ye has placed the sequential chips in non-sequential + * address order. This look-up table overcomes that problem. + */ +static const unsigned int cy_chip_offset[] = { 0x0000, + 0x0400, + 0x0800, + 0x0C00, + 0x0200, + 0x0600, + 0x0A00, + 0x0E00 +}; + +/* PCI related definitions */ + +#ifdef CONFIG_PCI +static const struct pci_device_id cy_pci_dev_id[] = { + /* PCI < 1Mb */ + { 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) }, + /* 4Y 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) }, + /* 8Y 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) }, + /* Z 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) }, + { } /* end of table */ +}; +MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); +#endif + +static void cy_start(struct tty_struct *); +static void cy_set_line_char(struct cyclades_port *, struct tty_struct *); +static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); +#ifdef CONFIG_ISA +static unsigned detect_isa_irq(void __iomem *); +#endif /* CONFIG_ISA */ + +#ifndef CONFIG_CYZ_INTR +static void cyz_poll(unsigned long); + +/* The Cyclades-Z polling cycle is defined by this variable */ +static long cyz_polling_cycle = CZ_DEF_POLL; + +static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); + +#else /* CONFIG_CYZ_INTR */ +static void cyz_rx_restart(unsigned long); +static struct timer_list cyz_rx_full_timer[NR_PORTS]; +#endif /* CONFIG_CYZ_INTR */ + +static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val) +{ + struct cyclades_card *card = port->card; + + cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val); +} + +static inline u8 cyy_readb(struct cyclades_port *port, u32 reg) +{ + struct cyclades_card *card = port->card; + + return readb(port->u.cyy.base_addr + (reg << card->bus_index)); +} + +static inline bool cy_is_Z(struct cyclades_card *card) +{ + return card->num_chips == (unsigned int)-1; +} + +static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr) +{ + return readl(&ctl_addr->init_ctrl) & (1 << 17); +} + +static inline bool cyz_fpga_loaded(struct cyclades_card *card) +{ + return __cyz_fpga_loaded(card->ctl_addr.p9060); +} + +static inline bool cyz_is_loaded(struct cyclades_card *card) +{ + struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS; + + return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) && + readl(&fw_id->signature) == ZFIRM_ID; +} + +static inline int serial_paranoia_check(struct cyclades_port *info, + const char *name, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + if (!info) { + printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) " + "in %s\n", name, routine); + return 1; + } + + if (info->magic != CYCLADES_MAGIC) { + printk(KERN_WARNING "cyc Warning: bad magic number for serial " + "struct (%s) in %s\n", name, routine); + return 1; + } +#endif + return 0; +} + +/***********************************************************/ +/********* Start of block of Cyclom-Y specific code ********/ + +/* This routine waits up to 1000 micro-seconds for the previous + command to the Cirrus chip to complete and then issues the + new command. An error is returned if the previous command + didn't finish within the time limit. + + This function is only called from inside spinlock-protected code. + */ +static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index) +{ + void __iomem *ccr = base_addr + (CyCCR << index); + unsigned int i; + + /* Check to see that the previous command has completed */ + for (i = 0; i < 100; i++) { + if (readb(ccr) == 0) + break; + udelay(10L); + } + /* if the CCR never cleared, the previous command + didn't finish within the "reasonable time" */ + if (i == 100) + return -1; + + /* Issue the new command */ + cy_writeb(ccr, cmd); + + return 0; +} + +static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd) +{ + return __cyy_issue_cmd(port->u.cyy.base_addr, cmd, + port->card->bus_index); +} + +#ifdef CONFIG_ISA +/* ISA interrupt detection code */ +static unsigned detect_isa_irq(void __iomem *address) +{ + int irq; + unsigned long irqs, flags; + int save_xir, save_car; + int index = 0; /* IRQ probing is only for ISA */ + + /* forget possible initially masked and pending IRQ */ + irq = probe_irq_off(probe_irq_on()); + + /* Clear interrupts on the board first */ + cy_writeb(address + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + + irqs = probe_irq_on(); + /* Wait ... */ + msleep(5); + + /* Enable the Tx interrupts on the CD1400 */ + local_irq_save(flags); + cy_writeb(address + (CyCAR << index), 0); + __cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index); + + cy_writeb(address + (CyCAR << index), 0); + cy_writeb(address + (CySRER << index), + readb(address + (CySRER << index)) | CyTxRdy); + local_irq_restore(flags); + + /* Wait ... */ + msleep(5); + + /* Check which interrupt is in use */ + irq = probe_irq_off(irqs); + + /* Clean up */ + save_xir = (u_char) readb(address + (CyTIR << index)); + save_car = readb(address + (CyCAR << index)); + cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); + cy_writeb(address + (CySRER << index), + readb(address + (CySRER << index)) & ~CyTxRdy); + cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); + cy_writeb(address + (CyCAR << index), (save_car)); + cy_writeb(address + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + + return (irq > 0) ? irq : 0; +} +#endif /* CONFIG_ISA */ + +static void cyy_chip_rx(struct cyclades_card *cinfo, int chip, + void __iomem *base_addr) +{ + struct cyclades_port *info; + struct tty_struct *tty; + int len, index = cinfo->bus_index; + u8 ivr, save_xir, channel, save_car, data, char_count; + +#ifdef CY_DEBUG_INTERRUPTS + printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip); +#endif + /* determine the channel & change to that context */ + save_xir = readb(base_addr + (CyRIR << index)); + channel = save_xir & CyIRChannel; + info = &cinfo->ports[channel + chip * 4]; + save_car = cyy_readb(info, CyCAR); + cyy_writeb(info, CyCAR, save_xir); + ivr = cyy_readb(info, CyRIVR) & CyIVRMask; + + tty = tty_port_tty_get(&info->port); + /* if there is nowhere to put the data, discard it */ + if (tty == NULL) { + if (ivr == CyIVRRxEx) { /* exception */ + data = cyy_readb(info, CyRDSR); + } else { /* normal character reception */ + char_count = cyy_readb(info, CyRDCR); + while (char_count--) + data = cyy_readb(info, CyRDSR); + } + goto end; + } + /* there is an open port for this data */ + if (ivr == CyIVRRxEx) { /* exception */ + data = cyy_readb(info, CyRDSR); + + /* For statistics only */ + if (data & CyBREAK) + info->icount.brk++; + else if (data & CyFRAME) + info->icount.frame++; + else if (data & CyPARITY) + info->icount.parity++; + else if (data & CyOVERRUN) + info->icount.overrun++; + + if (data & info->ignore_status_mask) { + info->icount.rx++; + tty_kref_put(tty); + return; + } + if (tty_buffer_request_room(tty, 1)) { + if (data & info->read_status_mask) { + if (data & CyBREAK) { + tty_insert_flip_char(tty, + cyy_readb(info, CyRDSR), + TTY_BREAK); + info->icount.rx++; + if (info->port.flags & ASYNC_SAK) + do_SAK(tty); + } else if (data & CyFRAME) { + tty_insert_flip_char(tty, + cyy_readb(info, CyRDSR), + TTY_FRAME); + info->icount.rx++; + info->idle_stats.frame_errs++; + } else if (data & CyPARITY) { + /* Pieces of seven... */ + tty_insert_flip_char(tty, + cyy_readb(info, CyRDSR), + TTY_PARITY); + info->icount.rx++; + info->idle_stats.parity_errs++; + } else if (data & CyOVERRUN) { + tty_insert_flip_char(tty, 0, + TTY_OVERRUN); + info->icount.rx++; + /* If the flip buffer itself is + overflowing, we still lose + the next incoming character. + */ + tty_insert_flip_char(tty, + cyy_readb(info, CyRDSR), + TTY_FRAME); + info->icount.rx++; + info->idle_stats.overruns++; + /* 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); + info->icount.rx++; + } + } else { + tty_insert_flip_char(tty, 0, TTY_NORMAL); + info->icount.rx++; + } + } else { + /* there was a software buffer overrun and nothing + * could be done about it!!! */ + info->icount.buf_overrun++; + info->idle_stats.overruns++; + } + } else { /* normal character reception */ + /* load # chars available from the chip */ + char_count = cyy_readb(info, CyRDCR); + +#ifdef CY_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 = cyy_readb(info, CyRDSR); + tty_insert_flip_char(tty, data, TTY_NORMAL); + info->idle_stats.recv_bytes++; + info->icount.rx++; +#ifdef CY_16Y_HACK + udelay(10L); +#endif + } + info->idle_stats.recv_idle = jiffies; + } + tty_schedule_flip(tty); + tty_kref_put(tty); +end: + /* end of service */ + cyy_writeb(info, CyRIR, save_xir & 0x3f); + cyy_writeb(info, CyCAR, save_car); +} + +static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, + void __iomem *base_addr) +{ + struct cyclades_port *info; + struct tty_struct *tty; + int char_count, index = cinfo->bus_index; + u8 save_xir, channel, save_car, outch; + + /* Since we only get here when the transmit buffer + is empty, we know we can always stuff a dozen + characters. */ +#ifdef CY_DEBUG_INTERRUPTS + printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip); +#endif + + /* determine the channel & change to that context */ + save_xir = readb(base_addr + (CyTIR << index)); + channel = save_xir & CyIRChannel; + save_car = readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + info = &cinfo->ports[channel + chip * 4]; + tty = tty_port_tty_get(&info->port); + if (tty == NULL) { + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); + goto end; + } + + /* load the on-chip space for outbound data */ + char_count = info->xmit_fifo_size; + + if (info->x_char) { /* send special char */ + outch = info->x_char; + cyy_writeb(info, CyTDR, outch); + char_count--; + info->icount.tx++; + info->x_char = 0; + } + + if (info->breakon || info->breakoff) { + if (info->breakon) { + cyy_writeb(info, CyTDR, 0); + cyy_writeb(info, CyTDR, 0x81); + info->breakon = 0; + char_count -= 2; + } + if (info->breakoff) { + cyy_writeb(info, CyTDR, 0); + cyy_writeb(info, CyTDR, 0x83); + info->breakoff = 0; + char_count -= 2; + } + } + + while (char_count-- > 0) { + if (!info->xmit_cnt) { + if (cyy_readb(info, CySRER) & CyTxMpty) { + cyy_writeb(info, CySRER, + cyy_readb(info, CySRER) & ~CyTxMpty); + } else { + cyy_writeb(info, CySRER, CyTxMpty | + (cyy_readb(info, CySRER) & ~CyTxRdy)); + } + goto done; + } + if (info->port.xmit_buf == NULL) { + cyy_writeb(info, CySRER, + cyy_readb(info, CySRER) & ~CyTxRdy); + goto done; + } + if (tty->stopped || tty->hw_stopped) { + cyy_writeb(info, CySRER, + cyy_readb(info, CySRER) & ~CyTxRdy); + goto done; + } + /* 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->port.xmit_buf[info->xmit_tail]; + if (outch) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + cyy_writeb(info, CyTDR, outch); + info->icount.tx++; + } else { + if (char_count > 1) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + cyy_writeb(info, CyTDR, outch); + cyy_writeb(info, CyTDR, 0); + info->icount.tx++; + char_count--; + } + } + } + +done: + tty_wakeup(tty); + tty_kref_put(tty); +end: + /* end of service */ + cyy_writeb(info, CyTIR, save_xir & 0x3f); + cyy_writeb(info, CyCAR, save_car); +} + +static void cyy_chip_modem(struct cyclades_card *cinfo, int chip, + void __iomem *base_addr) +{ + struct cyclades_port *info; + struct tty_struct *tty; + int index = cinfo->bus_index; + u8 save_xir, channel, save_car, mdm_change, mdm_status; + + /* determine the channel & change to that context */ + save_xir = readb(base_addr + (CyMIR << index)); + channel = save_xir & CyIRChannel; + info = &cinfo->ports[channel + chip * 4]; + save_car = cyy_readb(info, CyCAR); + cyy_writeb(info, CyCAR, save_xir); + + mdm_change = cyy_readb(info, CyMISR); + mdm_status = cyy_readb(info, CyMSVR1); + + tty = tty_port_tty_get(&info->port); + if (!tty) + goto end; + + if (mdm_change & CyANY_DELTA) { + /* For statistics only */ + if (mdm_change & CyDCD) + info->icount.dcd++; + if (mdm_change & CyCTS) + info->icount.cts++; + if (mdm_change & CyDSR) + info->icount.dsr++; + if (mdm_change & CyRI) + info->icount.rng++; + + wake_up_interruptible(&info->port.delta_msr_wait); + } + + if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) { + if (mdm_status & CyDCD) + wake_up_interruptible(&info->port.open_wait); + else + tty_hangup(tty); + } + if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) { + if (tty->hw_stopped) { + if (mdm_status & CyCTS) { + /* cy_start isn't used + because... !!! */ + tty->hw_stopped = 0; + cyy_writeb(info, CySRER, + cyy_readb(info, CySRER) | CyTxRdy); + tty_wakeup(tty); + } + } else { + if (!(mdm_status & CyCTS)) { + /* cy_stop isn't used + because ... !!! */ + tty->hw_stopped = 1; + cyy_writeb(info, CySRER, + cyy_readb(info, CySRER) & ~CyTxRdy); + } + } + } +/* if (mdm_change & CyDSR) { + } + if (mdm_change & CyRI) { + }*/ + tty_kref_put(tty); +end: + /* end of service */ + cyy_writeb(info, CyMIR, save_xir & 0x3f); + cyy_writeb(info, CyCAR, save_car); +} + +/* The real interrupt service routine is called + whenever the card wants its hand held--chars + received, out buffer empty, modem change, etc. + */ +static irqreturn_t cyy_interrupt(int irq, void *dev_id) +{ + int status; + struct cyclades_card *cinfo = dev_id; + void __iomem *base_addr, *card_base_addr; + unsigned int chip, too_many, had_work; + int index; + + if (unlikely(cinfo == NULL)) { +#ifdef CY_DEBUG_INTERRUPTS + printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n", + irq); +#endif + return IRQ_NONE; /* spurious interrupt */ + } + + card_base_addr = cinfo->base_addr; + index = cinfo->bus_index; + + /* card was not initialized yet (e.g. DEBUG_SHIRQ) */ + if (unlikely(card_base_addr == NULL)) + return IRQ_HANDLED; + + /* This loop checks all chips in the card. Make a note whenever + _any_ chip had some work to do, as this is considered an + indication that there will be more to do. Only when no chip + has any work does this outermost loop exit. + */ + do { + had_work = 0; + for (chip = 0; chip < cinfo->num_chips; chip++) { + base_addr = cinfo->base_addr + + (cy_chip_offset[chip] << index); + too_many = 0; + while ((status = readb(base_addr + + (CySVRR << index))) != 0x00) { + had_work++; + /* The purpose of the following test is to ensure that + no chip can monopolize the driver. This forces the + chips to be checked in a round-robin fashion (after + draining each of a bunch (1000) of characters). + */ + if (1000 < too_many++) + break; + spin_lock(&cinfo->card_lock); + if (status & CySRReceive) /* rx intr */ + cyy_chip_rx(cinfo, chip, base_addr); + if (status & CySRTransmit) /* tx intr */ + cyy_chip_tx(cinfo, chip, base_addr); + if (status & CySRModem) /* modem intr */ + cyy_chip_modem(cinfo, chip, base_addr); + spin_unlock(&cinfo->card_lock); + } + } + } while (had_work); + + /* clear interrupts */ + spin_lock(&cinfo->card_lock); + cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + spin_unlock(&cinfo->card_lock); + return IRQ_HANDLED; +} /* cyy_interrupt */ + +static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set, + unsigned int clear) +{ + struct cyclades_card *card = info->card; + int channel = info->line - card->first_line; + u32 rts, dtr, msvrr, msvrd; + + channel &= 0x03; + + if (info->rtsdtr_inv) { + msvrr = CyMSVR2; + msvrd = CyMSVR1; + rts = CyDTR; + dtr = CyRTS; + } else { + msvrr = CyMSVR1; + msvrd = CyMSVR2; + rts = CyRTS; + dtr = CyDTR; + } + if (set & TIOCM_RTS) { + cyy_writeb(info, CyCAR, channel); + cyy_writeb(info, msvrr, rts); + } + if (clear & TIOCM_RTS) { + cyy_writeb(info, CyCAR, channel); + cyy_writeb(info, msvrr, ~rts); + } + if (set & TIOCM_DTR) { + cyy_writeb(info, CyCAR, channel); + cyy_writeb(info, msvrd, dtr); +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + cyy_readb(info, CyMSVR1), + cyy_readb(info, CyMSVR2)); +#endif + } + if (clear & TIOCM_DTR) { + cyy_writeb(info, CyCAR, channel); + cyy_writeb(info, msvrd, ~dtr); +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + cyy_readb(info, CyMSVR1), + cyy_readb(info, CyMSVR2)); +#endif + } +} + +/***********************************************************/ +/********* End of block of Cyclom-Y specific code **********/ +/******** Start of block of Cyclades-Z specific code *******/ +/***********************************************************/ + +static int +cyz_fetch_msg(struct cyclades_card *cinfo, + __u32 *channel, __u8 *cmd, __u32 *param) +{ + struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; + unsigned long loc_doorbell; + + loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); + if (loc_doorbell) { + *cmd = (char)(0xff & loc_doorbell); + *channel = readl(&board_ctrl->fwcmd_channel); + *param = (__u32) readl(&board_ctrl->fwcmd_param); + cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff); + return 1; + } + return 0; +} /* cyz_fetch_msg */ + +static int +cyz_issue_cmd(struct cyclades_card *cinfo, + __u32 channel, __u8 cmd, __u32 param) +{ + struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; + __u32 __iomem *pci_doorbell; + unsigned int index; + + if (!cyz_is_loaded(cinfo)) + return -1; + + index = 0; + pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell; + while ((readl(pci_doorbell) & 0xff) != 0) { + if (index++ == 1000) + return (int)(readl(pci_doorbell) & 0xff); + udelay(50L); + } + cy_writel(&board_ctrl->hcmd_channel, channel); + cy_writel(&board_ctrl->hcmd_param, param); + cy_writel(pci_doorbell, (long)cmd); + + return 0; +} /* cyz_issue_cmd */ + +static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty) +{ + struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; + struct cyclades_card *cinfo = info->card; + unsigned int char_count; + int len; +#ifdef BLOCKMOVE + unsigned char *buf; +#else + char data; +#endif + __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; + + rx_get = new_rx_get = readl(&buf_ctrl->rx_get); + rx_put = readl(&buf_ctrl->rx_put); + rx_bufsize = readl(&buf_ctrl->rx_bufsize); + rx_bufaddr = readl(&buf_ctrl->rx_bufaddr); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; + + if (char_count) { +#ifdef CY_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 + if (tty == NULL) { + /* flush received characters */ + new_rx_get = (new_rx_get + char_count) & + (rx_bufsize - 1); + info->rflush_count++; + } else { +#ifdef BLOCKMOVE + /* we'd like to use memcpy(t, f, n) and memset(s, c, count) + for performance, but because of buffer boundaries, there + may be several steps to the operation */ + while (1) { + len = tty_prepare_flip_string(tty, &buf, + char_count); + if (!len) + break; + + len = min_t(unsigned int, min(len, char_count), + rx_bufsize - new_rx_get); + + memcpy_fromio(buf, cinfo->base_addr + + rx_bufaddr + new_rx_get, len); + + new_rx_get = (new_rx_get + len) & + (rx_bufsize - 1); + char_count -= len; + info->icount.rx += len; + info->idle_stats.recv_bytes += len; + } +#else + len = tty_buffer_request_room(tty, char_count); + while (len--) { + data = readb(cinfo->base_addr + rx_bufaddr + + new_rx_get); + new_rx_get = (new_rx_get + 1) & + (rx_bufsize - 1); + tty_insert_flip_char(tty, data, TTY_NORMAL); + info->idle_stats.recv_bytes++; + info->icount.rx++; + } +#endif +#ifdef CONFIG_CYZ_INTR + /* Recalculate the number of chars in the RX buffer and issue + a cmd in case it's higher than the RX high water mark */ + rx_put = readl(&buf_ctrl->rx_put); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; + if (char_count >= readl(&buf_ctrl->rx_threshold) && + !timer_pending(&cyz_rx_full_timer[ + info->line])) + mod_timer(&cyz_rx_full_timer[info->line], + jiffies + 1); +#endif + info->idle_stats.recv_idle = jiffies; + tty_schedule_flip(tty); + } + /* Update rx_get */ + cy_writel(&buf_ctrl->rx_get, new_rx_get); + } +} + +static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty) +{ + struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; + struct cyclades_card *cinfo = info->card; + u8 data; + unsigned int char_count; +#ifdef BLOCKMOVE + int small_count; +#endif + __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr; + + if (info->xmit_cnt <= 0) /* Nothing to transmit */ + return; + + tx_get = readl(&buf_ctrl->tx_get); + tx_put = readl(&buf_ctrl->tx_put); + tx_bufsize = readl(&buf_ctrl->tx_bufsize); + tx_bufaddr = readl(&buf_ctrl->tx_bufaddr); + if (tx_put >= tx_get) + char_count = tx_get - tx_put - 1 + tx_bufsize; + else + char_count = tx_get - tx_put - 1; + + if (char_count) { + + if (tty == NULL) + goto ztxdone; + + if (info->x_char) { /* send special char */ + data = info->x_char; + + cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + info->x_char = 0; + char_count--; + info->icount.tx++; + } +#ifdef BLOCKMOVE + while (0 < (small_count = min_t(unsigned int, + tx_bufsize - tx_put, min_t(unsigned int, + (SERIAL_XMIT_SIZE - info->xmit_tail), + min_t(unsigned int, info->xmit_cnt, + char_count))))) { + + memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + + tx_put), + &info->port.xmit_buf[info->xmit_tail], + small_count); + + tx_put = (tx_put + small_count) & (tx_bufsize - 1); + char_count -= small_count; + info->icount.tx += small_count; + info->xmit_cnt -= small_count; + info->xmit_tail = (info->xmit_tail + small_count) & + (SERIAL_XMIT_SIZE - 1); + } +#else + while (info->xmit_cnt && char_count) { + data = info->port.xmit_buf[info->xmit_tail]; + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + + cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + char_count--; + info->icount.tx++; + } +#endif + tty_wakeup(tty); +ztxdone: + /* Update tx_put */ + cy_writel(&buf_ctrl->tx_put, tx_put); + } +} + +static void cyz_handle_cmd(struct cyclades_card *cinfo) +{ + struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; + struct tty_struct *tty; + struct cyclades_port *info; + __u32 channel, param, fw_ver; + __u8 cmd; + int special_count; + int delta_count; + + fw_ver = readl(&board_ctrl->fw_version); + + while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { + special_count = 0; + delta_count = 0; + info = &cinfo->ports[channel]; + tty = tty_port_tty_get(&info->port); + if (tty == NULL) + continue; + + switch (cmd) { + case C_CM_PR_ERROR: + tty_insert_flip_char(tty, 0, TTY_PARITY); + info->icount.rx++; + special_count++; + break; + case C_CM_FR_ERROR: + tty_insert_flip_char(tty, 0, TTY_FRAME); + info->icount.rx++; + special_count++; + break; + case C_CM_RXBRK: + tty_insert_flip_char(tty, 0, TTY_BREAK); + info->icount.rx++; + special_count++; + break; + case C_CM_MDCD: + info->icount.dcd++; + delta_count++; + if (info->port.flags & ASYNC_CHECK_CD) { + u32 dcd = fw_ver > 241 ? param : + readl(&info->u.cyz.ch_ctrl->rs_status); + if (dcd & C_RS_DCD) + wake_up_interruptible(&info->port.open_wait); + else + tty_hangup(tty); + } + break; + case C_CM_MCTS: + info->icount.cts++; + delta_count++; + break; + case C_CM_MRI: + info->icount.rng++; + delta_count++; + break; + case C_CM_MDSR: + info->icount.dsr++; + delta_count++; + break; +#ifdef Z_WAKE + case C_CM_IOCTLW: + complete(&info->shutdown_wait); + break; +#endif +#ifdef CONFIG_CYZ_INTR + case C_CM_RXHIWM: + case C_CM_RXNNDT: + case C_CM_INTBACK2: + /* Reception Interrupt */ +#ifdef CY_DEBUG_INTERRUPTS + printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " + "port %ld\n", info->card, channel); +#endif + cyz_handle_rx(info, tty); + break; + case C_CM_TXBEMPTY: + case C_CM_TXLOWWM: + case C_CM_INTBACK: + /* Transmission Interrupt */ +#ifdef CY_DEBUG_INTERRUPTS + printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " + "port %ld\n", info->card, channel); +#endif + cyz_handle_tx(info, tty); + break; +#endif /* CONFIG_CYZ_INTR */ + case C_CM_FATAL: + /* should do something with this !!! */ + break; + default: + break; + } + if (delta_count) + wake_up_interruptible(&info->port.delta_msr_wait); + if (special_count) + tty_schedule_flip(tty); + tty_kref_put(tty); + } +} + +#ifdef CONFIG_CYZ_INTR +static irqreturn_t cyz_interrupt(int irq, void *dev_id) +{ + struct cyclades_card *cinfo = dev_id; + + if (unlikely(!cyz_is_loaded(cinfo))) { +#ifdef CY_DEBUG_INTERRUPTS + printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " + "(IRQ%d).\n", irq); +#endif + return IRQ_NONE; + } + + /* Handle the interrupts */ + cyz_handle_cmd(cinfo); + + return IRQ_HANDLED; +} /* cyz_interrupt */ + +static void cyz_rx_restart(unsigned long arg) +{ + struct cyclades_port *info = (struct cyclades_port *)arg; + struct cyclades_card *card = info->card; + int retval; + __u32 channel = info->line - card->first_line; + unsigned long flags; + + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n", + info->line, retval); + } + spin_unlock_irqrestore(&card->card_lock, flags); +} + +#else /* CONFIG_CYZ_INTR */ + +static void cyz_poll(unsigned long arg) +{ + struct cyclades_card *cinfo; + struct cyclades_port *info; + unsigned long expires = jiffies + HZ; + unsigned int port, card; + + for (card = 0; card < NR_CARDS; card++) { + cinfo = &cy_card[card]; + + if (!cy_is_Z(cinfo)) + continue; + if (!cyz_is_loaded(cinfo)) + continue; + + /* Skip first polling cycle to avoid racing conditions with the FW */ + if (!cinfo->intr_enabled) { + cinfo->intr_enabled = 1; + continue; + } + + cyz_handle_cmd(cinfo); + + for (port = 0; port < cinfo->nports; port++) { + struct tty_struct *tty; + + info = &cinfo->ports[port]; + tty = tty_port_tty_get(&info->port); + /* OK to pass NULL to the handle functions below. + They need to drop the data in that case. */ + + if (!info->throttle) + cyz_handle_rx(info, tty); + cyz_handle_tx(info, tty); + tty_kref_put(tty); + } + /* poll every 'cyz_polling_cycle' period */ + expires = jiffies + cyz_polling_cycle; + } + mod_timer(&cyz_timerlist, expires); +} /* cyz_poll */ + +#endif /* CONFIG_CYZ_INTR */ + +/********** End of block of Cyclades-Z specific code *********/ +/***********************************************************/ + +/* This is called whenever a port becomes active; + interrupts are enabled and DTR & RTS are turned on. + */ +static int cy_startup(struct cyclades_port *info, struct tty_struct *tty) +{ + struct cyclades_card *card; + unsigned long flags; + int retval = 0; + int channel; + unsigned long page; + + card = info->card; + channel = info->line - card->first_line; + + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + spin_lock_irqsave(&card->card_lock, flags); + + if (info->port.flags & ASYNC_INITIALIZED) + goto errout; + + if (!info->type) { + set_bit(TTY_IO_ERROR, &tty->flags); + goto errout; + } + + if (info->port.xmit_buf) + free_page(page); + else + info->port.xmit_buf = (unsigned char *)page; + + spin_unlock_irqrestore(&card->card_lock, flags); + + cy_set_line_char(info, tty); + + if (!cy_is_Z(card)) { + channel &= 0x03; + + spin_lock_irqsave(&card->card_lock, flags); + + cyy_writeb(info, CyCAR, channel); + + cyy_writeb(info, CyRTPR, + (info->default_timeout ? info->default_timeout : 0x02)); + /* 10ms rx timeout */ + + cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR); + + cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0); + + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData); + } else { + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; + + if (!cyz_is_loaded(card)) + return -ENODEV; + +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " + "base_addr %p\n", card, channel, card->base_addr); +#endif + spin_lock_irqsave(&card->card_lock, flags); + + cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE); +#ifdef Z_WAKE +#ifdef CONFIG_CYZ_INTR + cy_writel(&ch_ctrl->intr_enable, + C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | + C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); +#else + cy_writel(&ch_ctrl->intr_enable, + C_IN_IOCTLW | C_IN_MDCD); +#endif /* CONFIG_CYZ_INTR */ +#else +#ifdef CONFIG_CYZ_INTR + cy_writel(&ch_ctrl->intr_enable, + C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | + C_IN_RXNNDT | C_IN_MDCD); +#else + cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD); +#endif /* CONFIG_CYZ_INTR */ +#endif /* Z_WAKE */ + + retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was " + "%x\n", info->line, retval); + } + + /* Flush RX buffers before raising DTR and RTS */ + retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was " + "%x\n", info->line, retval); + } + + /* set timeout !!! */ + /* set RTS and DTR !!! */ + tty_port_raise_dtr_rts(&info->port); + + /* enable send, recv, modem !!! */ + } + + info->port.flags |= ASYNC_INITIALIZED; + + clear_bit(TTY_IO_ERROR, &tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->breakon = info->breakoff = 0; + memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); + info->idle_stats.in_use = + info->idle_stats.recv_idle = + info->idle_stats.xmit_idle = jiffies; + + spin_unlock_irqrestore(&card->card_lock, flags); + +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc startup done\n"); +#endif + return 0; + +errout: + spin_unlock_irqrestore(&card->card_lock, flags); + free_page(page); + return retval; +} /* startup */ + +static void start_xmit(struct cyclades_port *info) +{ + struct cyclades_card *card = info->card; + unsigned long flags; + int channel = info->line - card->first_line; + + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + cyy_writeb(info, CyCAR, channel & 0x03); + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); + spin_unlock_irqrestore(&card->card_lock, flags); + } else { +#ifdef CONFIG_CYZ_INTR + int retval; + + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was " + "%x\n", info->line, retval); + } + spin_unlock_irqrestore(&card->card_lock, flags); +#else /* CONFIG_CYZ_INTR */ + /* Don't have to do anything at this time */ +#endif /* CONFIG_CYZ_INTR */ + } +} /* 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 cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) +{ + struct cyclades_card *card; + unsigned long flags; + int channel; + + if (!(info->port.flags & ASYNC_INITIALIZED)) + return; + + card = info->card; + channel = info->line - card->first_line; + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + + /* Clear delta_msr_wait queue to avoid mem leaks. */ + wake_up_interruptible(&info->port.delta_msr_wait); + + if (info->port.xmit_buf) { + unsigned char *temp; + temp = info->port.xmit_buf; + info->port.xmit_buf = NULL; + free_page((unsigned long)temp); + } + if (tty->termios->c_cflag & HUPCL) + cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); + + cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); + /* it may be appropriate to clear _XMIT at + some later date (after testing)!!! */ + + set_bit(TTY_IO_ERROR, &tty->flags); + info->port.flags &= ~ASYNC_INITIALIZED; + spin_unlock_irqrestore(&card->card_lock, flags); + } else { +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " + "base_addr %p\n", card, channel, card->base_addr); +#endif + + if (!cyz_is_loaded(card)) + return; + + spin_lock_irqsave(&card->card_lock, flags); + + if (info->port.xmit_buf) { + unsigned char *temp; + temp = info->port.xmit_buf; + info->port.xmit_buf = NULL; + free_page((unsigned long)temp); + } + + if (tty->termios->c_cflag & HUPCL) + tty_port_lower_dtr_rts(&info->port); + + set_bit(TTY_IO_ERROR, &tty->flags); + info->port.flags &= ~ASYNC_INITIALIZED; + + spin_unlock_irqrestore(&card->card_lock, flags); + } + +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc shutdown done\n"); +#endif +} /* shutdown */ + +/* + * ------------------------------------------------------------ + * cy_open() and friends + * ------------------------------------------------------------ + */ + +/* + * This routine is called whenever a serial port is opened. It + * performs the serial-specific initialization for the tty structure. + */ +static int cy_open(struct tty_struct *tty, struct file *filp) +{ + struct cyclades_port *info; + unsigned int i, line; + int retval; + + line = tty->index; + if (tty->index < 0 || NR_PORTS <= line) + return -ENODEV; + + for (i = 0; i < NR_CARDS; i++) + if (line < cy_card[i].first_line + cy_card[i].nports && + line >= cy_card[i].first_line) + break; + if (i >= NR_CARDS) + return -ENODEV; + info = &cy_card[i].ports[line - cy_card[i].first_line]; + if (info->line < 0) + return -ENODEV; + + /* If the card's firmware hasn't been loaded, + treat it as absent from the system. This + will make the user pay attention. + */ + if (cy_is_Z(info->card)) { + struct cyclades_card *cinfo = info->card; + struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; + + if (!cyz_is_loaded(cinfo)) { + if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && + readl(&firm_id->signature) == + ZFIRM_HLT) { + printk(KERN_ERR "cyc:Cyclades-Z Error: you " + "need an external power supply for " + "this number of ports.\nFirmware " + "halted.\n"); + } else { + printk(KERN_ERR "cyc:Cyclades-Z firmware not " + "yet loaded\n"); + } + return -ENODEV; + } +#ifdef CONFIG_CYZ_INTR + else { + /* In case this Z board is operating in interrupt mode, its + interrupts should be enabled as soon as the first open + happens to one of its ports. */ + if (!cinfo->intr_enabled) { + u16 intr; + + /* Enable interrupts on the PLX chip */ + intr = readw(&cinfo->ctl_addr.p9060-> + intr_ctrl_stat) | 0x0900; + cy_writew(&cinfo->ctl_addr.p9060-> + intr_ctrl_stat, intr); + /* Enable interrupts on the FW */ + retval = cyz_issue_cmd(cinfo, 0, + C_CM_IRQ_ENBL, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:IRQ enable retval " + "was %x\n", retval); + } + cinfo->intr_enabled = 1; + } + } +#endif /* CONFIG_CYZ_INTR */ + /* Make sure this Z port really exists in hardware */ + if (info->line > (cinfo->first_line + cinfo->nports - 1)) + return -ENODEV; + } +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); +#endif + tty->driver_data = info; + if (serial_paranoia_check(info, tty->name, "cy_open")) + return -ENODEV; + +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, + info->port.count); +#endif + info->port.count++; +#ifdef CY_DEBUG_COUNT + printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", + current->pid, info->port.count); +#endif + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { + wait_event_interruptible_tty(info->port.close_wait, + !(info->port.flags & ASYNC_CLOSING)); + return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; + } + + /* + * Start up serial port + */ + retval = cy_startup(info, tty); + if (retval) + return retval; + + retval = tty_port_block_til_ready(&info->port, tty, filp); + if (retval) { +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " + "with %d\n", retval); +#endif + return retval; + } + + info->throttle = 0; + tty_port_tty_set(&info->port, tty); + +#ifdef CY_DEBUG_OPEN + printk(KERN_DEBUG "cyc:cy_open done\n"); +#endif + return 0; +} /* cy_open */ + +/* + * cy_wait_until_sent() --- wait until the transmitter is empty + */ +static void cy_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct cyclades_card *card; + struct cyclades_port *info = tty->driver_data; + unsigned long orig_jiffies; + int char_time; + + if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time <= 0) + char_time = 1; + if (timeout < 0) + timeout = 0; + if (timeout) + char_time = min(char_time, timeout); + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; +#ifdef CY_DEBUG_WAIT_UNTIL_SENT + printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...", + timeout, char_time, jiffies); +#endif + card = info->card; + if (!cy_is_Z(card)) { + while (cyy_readb(info, CySRER) & CyTxRdy) { +#ifdef CY_DEBUG_WAIT_UNTIL_SENT + printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies); +#endif + if (msleep_interruptible(jiffies_to_msecs(char_time))) + break; + if (timeout && time_after(jiffies, orig_jiffies + + timeout)) + break; + } + } + /* Run one more char cycle */ + msleep_interruptible(jiffies_to_msecs(char_time * 5)); +#ifdef CY_DEBUG_WAIT_UNTIL_SENT + printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); +#endif +} + +static void cy_flush_buffer(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int channel, retval; + unsigned long flags; + +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) + return; + + card = info->card; + channel = info->line - card->first_line; + + spin_lock_irqsave(&card->card_lock, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + spin_unlock_irqrestore(&card->card_lock, flags); + + if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board + buffers as well */ + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d " + "was %x\n", info->line, retval); + } + spin_unlock_irqrestore(&card->card_lock, flags); + } + tty_wakeup(tty); +} /* cy_flush_buffer */ + + +static void cy_do_close(struct tty_port *port) +{ + struct cyclades_port *info = container_of(port, struct cyclades_port, + port); + struct cyclades_card *card; + unsigned long flags; + int channel; + + card = info->card; + channel = info->line - card->first_line; + spin_lock_irqsave(&card->card_lock, flags); + + if (!cy_is_Z(card)) { + /* Stop accepting input */ + cyy_writeb(info, CyCAR, channel & 0x03); + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData); + if (info->port.flags & ASYNC_INITIALIZED) { + /* Waiting for on-board buffers to be empty before + closing the port */ + spin_unlock_irqrestore(&card->card_lock, flags); + cy_wait_until_sent(port->tty, info->timeout); + spin_lock_irqsave(&card->card_lock, flags); + } + } else { +#ifdef Z_WAKE + /* Waiting for on-board buffers to be empty before closing + the port */ + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; + int retval; + + if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) { + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); + if (retval != 0) { + printk(KERN_DEBUG "cyc:cy_close retval on " + "ttyC%d was %x\n", info->line, retval); + } + spin_unlock_irqrestore(&card->card_lock, flags); + wait_for_completion_interruptible(&info->shutdown_wait); + spin_lock_irqsave(&card->card_lock, flags); + } +#endif + } + spin_unlock_irqrestore(&card->card_lock, flags); + cy_shutdown(info, port->tty); +} + +/* + * This routine is called when a particular tty device is closed. + */ +static void cy_close(struct tty_struct *tty, struct file *filp) +{ + struct cyclades_port *info = tty->driver_data; + if (!info || serial_paranoia_check(info, tty->name, "cy_close")) + return; + tty_port_close(&info->port, tty, filp); +} /* cy_close */ + +/* This routine gets called when tty_write has put something into + * the write_queue. The characters may come from user space or + * kernel space. + * + * This routine will return the number of characters actually + * accepted for writing. + * + * If the port is not already transmitting stuff, start it off by + * enabling interrupts. The interrupt service 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) +{ + struct cyclades_port *info = tty->driver_data; + unsigned long flags; + int c, ret = 0; + +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_write")) + return 0; + + if (!info->port.xmit_buf) + return 0; + + spin_lock_irqsave(&info->card->card_lock, flags); + while (1) { + c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1)); + c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head)); + + if (c <= 0) + break; + + memcpy(info->port.xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; + } + spin_unlock_irqrestore(&info->card->card_lock, flags); + + info->idle_stats.xmit_bytes += ret; + info->idle_stats.xmit_idle = jiffies; + + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) + start_xmit(info); + + return ret; +} /* cy_write */ + +/* + * This routine is called by the kernel to write a single + * character to the tty device. If the kernel uses this routine, + * it must call the flush_chars() routine (if defined) when it is + * done stuffing characters into the driver. If there is no room + * in the queue, the character is ignored. + */ +static int cy_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct cyclades_port *info = tty->driver_data; + unsigned long flags; + +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_put_char")) + return 0; + + if (!info->port.xmit_buf) + return 0; + + spin_lock_irqsave(&info->card->card_lock, flags); + if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { + spin_unlock_irqrestore(&info->card->card_lock, flags); + return 0; + } + + info->port.xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE - 1; + info->xmit_cnt++; + info->idle_stats.xmit_bytes++; + info->idle_stats.xmit_idle = jiffies; + spin_unlock_irqrestore(&info->card->card_lock, flags); + return 1; +} /* cy_put_char */ + +/* + * This routine is called by the kernel after it has written a + * series of characters to the tty device using put_char(). + */ +static void cy_flush_chars(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->port.xmit_buf) + return; + + start_xmit(info); +} /* cy_flush_chars */ + +/* + * This routine returns the numbers of characters the tty driver + * will accept for queuing to be written. This number is subject + * to change as output buffers get emptied, or if the output flow + * control is activated. + */ +static int cy_write_room(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + int ret; + +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_write_room")) + return 0; + ret = SERIAL_XMIT_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) +{ + struct cyclades_port *info = tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) + return 0; + +#ifdef Z_EXT_CHARS_IN_BUFFER + if (!cy_is_Z(info->card)) { +#endif /* Z_EXT_CHARS_IN_BUFFER */ +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", + info->line, info->xmit_cnt); +#endif + return info->xmit_cnt; +#ifdef Z_EXT_CHARS_IN_BUFFER + } else { + struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; + int char_count; + __u32 tx_put, tx_get, tx_bufsize; + + tx_get = readl(&buf_ctrl->tx_get); + tx_put = readl(&buf_ctrl->tx_put); + tx_bufsize = readl(&buf_ctrl->tx_bufsize); + if (tx_put >= tx_get) + char_count = tx_put - tx_get; + else + char_count = tx_put - tx_get + tx_bufsize; +#ifdef CY_DEBUG_IO + printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", + info->line, info->xmit_cnt + char_count); +#endif + return info->xmit_cnt + char_count; + } +#endif /* Z_EXT_CHARS_IN_BUFFER */ +} /* cy_chars_in_buffer */ + +/* + * ------------------------------------------------------------ + * cy_ioctl() and friends + * ------------------------------------------------------------ + */ + +static void cyy_baud_calc(struct cyclades_port *info, __u32 baud) +{ + int co, co_val, bpr; + __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : + 25000000); + + if (baud == 0) { + info->tbpr = info->tco = info->rbpr = info->rco = 0; + return; + } + + /* determine which prescaler to use */ + for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { + if (cy_clock / co_val / baud > 63) + break; + } + + bpr = (cy_clock / co_val * 2 / baud + 1) / 2; + if (bpr > 255) + bpr = 255; + + info->tbpr = info->rbpr = bpr; + info->tco = info->rco = co; +} + +/* + * This routine finds or computes the various line characteristics. + * It used to be called config_setup + */ +static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) +{ + struct cyclades_card *card; + unsigned long flags; + int channel; + unsigned cflag, iflag; + int baud, baud_rate = 0; + int i; + + if (!tty->termios) /* XXX can this happen at all? */ + return; + + if (info->line == -1) + return; + + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; + + /* + * Set up the tty->alt_speed kludge + */ + if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + tty->alt_speed = 57600; + if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + tty->alt_speed = 115200; + if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + tty->alt_speed = 230400; + if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + tty->alt_speed = 460800; + + card = info->card; + channel = info->line - card->first_line; + + if (!cy_is_Z(card)) { + u32 cflags; + + /* baud rate */ + baud = tty_get_baud_rate(tty); + if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CD1400_MAX_SPEED) { + baud = CD1400_MAX_SPEED; + } + /* find the baud index */ + for (i = 0; i < 20; i++) { + if (baud == baud_table[i]) + break; + } + if (i == 20) + i = 19; /* CD1400_MAX_SPEED */ + + if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + cyy_baud_calc(info, baud_rate); + } else { + if (info->chip_rev >= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[i]; /* Tx BPR */ + info->tco = baud_co_60[i]; /* Tx CO */ + info->rbpr = baud_bpr_60[i]; /* Rx BPR */ + info->rco = baud_co_60[i]; /* Rx CO */ + } else { + info->tbpr = baud_bpr_25[i]; /* Tx BPR */ + info->tco = baud_co_25[i]; /* Tx CO */ + info->rbpr = baud_bpr_25[i]; /* Rx BPR */ + info->rco = baud_co_25[i]; /* Rx CO */ + } + } + if (baud_table[i] == 134) { + /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + + 2; + } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_rate) + 2; + } 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->cor5 = 0; + info->cor4 = 0; + /* receive threshold */ + info->cor3 = (info->default_threshold ? + info->default_threshold : baud_cor3[i]); + 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 & CSTOPB) + info->cor1 |= Cy_2_STOP; + + 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 (cflag & CRTSCTS) { + info->port.flags |= ASYNC_CTS_FLOW; + info->cor2 |= CyCtsAE; + } else { + info->port.flags &= ~ASYNC_CTS_FLOW; + info->cor2 &= ~CyCtsAE; + } + if (cflag & CLOCAL) + info->port.flags &= ~ASYNC_CHECK_CD; + else + info->port.flags |= ASYNC_CHECK_CD; + + /*********************************************** + The hardware option, CyRtsAO, presents RTS when + the chip has characters to send. Since most modems + use RTS as reverse (inbound) flow control, this + option is not used. If inbound flow control is + necessary, DTR can be programmed to provide the + appropriate signals for use with a non-standard + cable. Contact Marcio Saito for details. + ***********************************************/ + + channel &= 0x03; + + spin_lock_irqsave(&card->card_lock, flags); + cyy_writeb(info, CyCAR, channel); + + /* tx and rx baud rate */ + + cyy_writeb(info, CyTCOR, info->tco); + cyy_writeb(info, CyTBPR, info->tbpr); + cyy_writeb(info, CyRCOR, info->rco); + cyy_writeb(info, CyRBPR, info->rbpr); + + /* set line characteristics according configuration */ + + cyy_writeb(info, CySCHR1, START_CHAR(tty)); + cyy_writeb(info, CySCHR2, STOP_CHAR(tty)); + cyy_writeb(info, CyCOR1, info->cor1); + cyy_writeb(info, CyCOR2, info->cor2); + cyy_writeb(info, CyCOR3, info->cor3); + cyy_writeb(info, CyCOR4, info->cor4); + cyy_writeb(info, CyCOR5, info->cor5); + + cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | + CyCOR3ch); + + /* !!! Is this needed? */ + cyy_writeb(info, CyCAR, channel); + cyy_writeb(info, CyRTPR, + (info->default_timeout ? info->default_timeout : 0x02)); + /* 10ms rx timeout */ + + cflags = CyCTS; + if (!C_CLOCAL(tty)) + cflags |= CyDSR | CyRI | CyDCD; + /* without modem intr */ + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh); + /* act on 1->0 modem transitions */ + if ((cflag & CRTSCTS) && info->rflow) + cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]); + else + cyy_writeb(info, CyMCOR1, cflags); + /* act on 0->1 modem transitions */ + cyy_writeb(info, CyMCOR2, cflags); + + if (i == 0) /* baud rate is zero, turn off line */ + cyy_change_rts_dtr(info, 0, TIOCM_DTR); + else + cyy_change_rts_dtr(info, TIOCM_DTR, 0); + + clear_bit(TTY_IO_ERROR, &tty->flags); + spin_unlock_irqrestore(&card->card_lock, flags); + + } else { + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; + __u32 sw_flow; + int retval; + + if (!cyz_is_loaded(card)) + return; + + /* baud rate */ + baud = tty_get_baud_rate(tty); + if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CYZ_MAX_SPEED) { + baud = CYZ_MAX_SPEED; + } + cy_writel(&ch_ctrl->comm_baud, baud); + + if (baud == 134) { + /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + + 2; + } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_rate) + 2; + } else if (baud) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud) + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5); + break; + case CS6: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6); + break; + case CS7: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7); + break; + case CS8: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8); + break; + } + if (cflag & CSTOPB) { + cy_writel(&ch_ctrl->comm_data_l, + readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); + } else { + cy_writel(&ch_ctrl->comm_data_l, + readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); + } + if (cflag & PARENB) { + if (cflag & PARODD) + cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); + else + cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); + } else + cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); + + /* CTS flow control flag */ + if (cflag & CRTSCTS) { + cy_writel(&ch_ctrl->hw_flow, + readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); + } else { + cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & + ~(C_RS_CTS | C_RS_RTS)); + } + /* As the HW flow control is done in firmware, the driver + doesn't need to care about it */ + info->port.flags &= ~ASYNC_CTS_FLOW; + + /* XON/XOFF/XANY flow control flags */ + sw_flow = 0; + if (iflag & IXON) { + sw_flow |= C_FL_OXX; + if (iflag & IXANY) + sw_flow |= C_FL_OIXANY; + } + cy_writel(&ch_ctrl->sw_flow, sw_flow); + + retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " + "was %x\n", info->line, retval); + } + + /* CD sensitivity */ + if (cflag & CLOCAL) + info->port.flags &= ~ASYNC_CHECK_CD; + else + info->port.flags |= ASYNC_CHECK_CD; + + if (baud == 0) { /* baud rate is zero, turn off line */ + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) & ~C_RS_DTR); +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n"); +#endif + } else { + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) | C_RS_DTR); +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n"); +#endif + } + + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " + "was %x\n", info->line, retval); + } + + clear_bit(TTY_IO_ERROR, &tty->flags); + } +} /* set_line_char */ + +static int cy_get_serial_info(struct cyclades_port *info, + struct serial_struct __user *retinfo) +{ + struct cyclades_card *cinfo = info->card; + struct serial_struct tmp = { + .type = info->type, + .line = info->line, + .port = (info->card - cy_card) * 0x100 + info->line - + cinfo->first_line, + .irq = cinfo->irq, + .flags = info->port.flags, + .close_delay = info->port.close_delay, + .closing_wait = info->port.closing_wait, + .baud_base = info->baud, + .custom_divisor = info->custom_divisor, + .hub6 = 0, /*!!! */ + }; + return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; +} + +static int +cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, + struct serial_struct __user *new_info) +{ + struct serial_struct new_serial; + int ret; + + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + + mutex_lock(&info->port.mutex); + if (!capable(CAP_SYS_ADMIN)) { + if (new_serial.close_delay != info->port.close_delay || + new_serial.baud_base != info->baud || + (new_serial.flags & ASYNC_FLAGS & + ~ASYNC_USR_MASK) != + (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) + { + mutex_unlock(&info->port.mutex); + return -EPERM; + } + info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK); + info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; + info->port.flags = (info->port.flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS); + info->port.close_delay = new_serial.close_delay * HZ / 100; + info->port.closing_wait = new_serial.closing_wait * HZ / 100; + +check_and_exit: + if (info->port.flags & ASYNC_INITIALIZED) { + cy_set_line_char(info, tty); + ret = 0; + } else { + ret = cy_startup(info, tty); + } + mutex_unlock(&info->port.mutex); + return ret; +} /* set_serial_info */ + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) +{ + struct cyclades_card *card = info->card; + unsigned int result; + unsigned long flags; + u8 status; + + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty); + spin_unlock_irqrestore(&card->card_lock, flags); + result = (status ? 0 : TIOCSER_TEMT); + } else { + /* Not supported yet */ + return -EINVAL; + } + return put_user(result, (unsigned long __user *)value); +} + +static int cy_tiocmget(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int result; + + if (serial_paranoia_check(info, tty->name, __func__)) + return -ENODEV; + + card = info->card; + + if (!cy_is_Z(card)) { + unsigned long flags; + int channel = info->line - card->first_line; + u8 status; + + spin_lock_irqsave(&card->card_lock, flags); + cyy_writeb(info, CyCAR, channel & 0x03); + status = cyy_readb(info, CyMSVR1); + status |= cyy_readb(info, CyMSVR2); + spin_unlock_irqrestore(&card->card_lock, flags); + + if (info->rtsdtr_inv) { + result = ((status & CyRTS) ? TIOCM_DTR : 0) | + ((status & CyDTR) ? TIOCM_RTS : 0); + } else { + result = ((status & CyRTS) ? TIOCM_RTS : 0) | + ((status & CyDTR) ? TIOCM_DTR : 0); + } + result |= ((status & CyDCD) ? TIOCM_CAR : 0) | + ((status & CyRI) ? TIOCM_RNG : 0) | + ((status & CyDSR) ? TIOCM_DSR : 0) | + ((status & CyCTS) ? TIOCM_CTS : 0); + } else { + u32 lstatus; + + if (!cyz_is_loaded(card)) { + result = -ENODEV; + goto end; + } + + lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); + result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | + ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | + ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | + ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | + ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | + ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); + } +end: + return result; +} /* cy_tiomget */ + +static int +cy_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, __func__)) + return -ENODEV; + + card = info->card; + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + cyy_change_rts_dtr(info, set, clear); + spin_unlock_irqrestore(&card->card_lock, flags); + } else { + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; + int retval, channel = info->line - card->first_line; + u32 rs; + + if (!cyz_is_loaded(card)) + return -ENODEV; + + spin_lock_irqsave(&card->card_lock, flags); + rs = readl(&ch_ctrl->rs_control); + if (set & TIOCM_RTS) + rs |= C_RS_RTS; + if (clear & TIOCM_RTS) + rs &= ~C_RS_RTS; + if (set & TIOCM_DTR) { + rs |= C_RS_DTR; +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n"); +#endif + } + if (clear & TIOCM_DTR) { + rs &= ~C_RS_DTR; +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "cyc:set_modem_info clearing " + "Z DTR\n"); +#endif + } + cy_writel(&ch_ctrl->rs_control, rs); + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); + spin_unlock_irqrestore(&card->card_lock, flags); + if (retval != 0) { + printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " + "was %x\n", info->line, retval); + } + } + return 0; +} + +/* + * cy_break() --- routine which turns the break handling on or off + */ +static int cy_break(struct tty_struct *tty, int break_state) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + unsigned long flags; + int retval = 0; + + if (serial_paranoia_check(info, tty->name, "cy_break")) + return -EINVAL; + + card = info->card; + + spin_lock_irqsave(&card->card_lock, flags); + if (!cy_is_Z(card)) { + /* Let the transmit ISR take care of this (since it + requires stuffing characters into the output stream). + */ + if (break_state == -1) { + if (!info->breakon) { + info->breakon = 1; + if (!info->xmit_cnt) { + spin_unlock_irqrestore(&card->card_lock, flags); + start_xmit(info); + spin_lock_irqsave(&card->card_lock, flags); + } + } + } else { + if (!info->breakoff) { + info->breakoff = 1; + if (!info->xmit_cnt) { + spin_unlock_irqrestore(&card->card_lock, flags); + start_xmit(info); + spin_lock_irqsave(&card->card_lock, flags); + } + } + } + } else { + if (break_state == -1) { + retval = cyz_issue_cmd(card, + info->line - card->first_line, + C_CM_SET_BREAK, 0L); + if (retval != 0) { + printk(KERN_ERR "cyc:cy_break (set) retval on " + "ttyC%d was %x\n", info->line, retval); + } + } else { + retval = cyz_issue_cmd(card, + info->line - card->first_line, + C_CM_CLR_BREAK, 0L); + if (retval != 0) { + printk(KERN_DEBUG "cyc:cy_break (clr) retval " + "on ttyC%d was %x\n", info->line, + retval); + } + } + } + spin_unlock_irqrestore(&card->card_lock, flags); + return retval; +} /* cy_break */ + +static int set_threshold(struct cyclades_port *info, unsigned long value) +{ + struct cyclades_card *card = info->card; + unsigned long flags; + + if (!cy_is_Z(card)) { + info->cor3 &= ~CyREC_FIFO; + info->cor3 |= value & CyREC_FIFO; + + spin_lock_irqsave(&card->card_lock, flags); + cyy_writeb(info, CyCOR3, info->cor3); + cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch); + spin_unlock_irqrestore(&card->card_lock, flags); + } + return 0; +} /* set_threshold */ + +static int get_threshold(struct cyclades_port *info, + unsigned long __user *value) +{ + struct cyclades_card *card = info->card; + + if (!cy_is_Z(card)) { + u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO; + return put_user(tmp, value); + } + return 0; +} /* get_threshold */ + +static int set_timeout(struct cyclades_port *info, unsigned long value) +{ + struct cyclades_card *card = info->card; + unsigned long flags; + + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + cyy_writeb(info, CyRTPR, value & 0xff); + spin_unlock_irqrestore(&card->card_lock, flags); + } + return 0; +} /* set_timeout */ + +static int get_timeout(struct cyclades_port *info, + unsigned long __user *value) +{ + struct cyclades_card *card = info->card; + + if (!cy_is_Z(card)) { + u8 tmp = cyy_readb(info, CyRTPR); + return put_user(tmp, value); + } + return 0; +} /* get_timeout */ + +static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg, + struct cyclades_icount *cprev) +{ + struct cyclades_icount cnow; + unsigned long flags; + int ret; + + spin_lock_irqsave(&info->card->card_lock, flags); + cnow = info->icount; /* atomic copy */ + spin_unlock_irqrestore(&info->card->card_lock, flags); + + ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); + + *cprev = cnow; + + return ret; +} + +/* + * This routine allows the tty driver to implement device- + * specific ioctl's. If the ioctl number passed in cmd is + * not recognized by the driver, it should return ENOIOCTLCMD. + */ +static int +cy_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_icount cnow; /* kernel counter temps */ + int ret_val = 0; + unsigned long flags; + void __user *argp = (void __user *)arg; + + if (serial_paranoia_check(info, tty->name, "cy_ioctl")) + return -ENODEV; + +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", + info->line, cmd, arg); +#endif + + switch (cmd) { + case CYGETMON: + if (copy_to_user(argp, &info->mon, sizeof(info->mon))) { + ret_val = -EFAULT; + break; + } + memset(&info->mon, 0, sizeof(info->mon)); + break; + case CYGETTHRESH: + ret_val = get_threshold(info, argp); + break; + case CYSETTHRESH: + ret_val = set_threshold(info, arg); + break; + case CYGETDEFTHRESH: + ret_val = put_user(info->default_threshold, + (unsigned long __user *)argp); + break; + case CYSETDEFTHRESH: + info->default_threshold = arg & 0x0f; + break; + case CYGETTIMEOUT: + ret_val = get_timeout(info, argp); + break; + case CYSETTIMEOUT: + ret_val = set_timeout(info, arg); + break; + case CYGETDEFTIMEOUT: + ret_val = put_user(info->default_timeout, + (unsigned long __user *)argp); + break; + case CYSETDEFTIMEOUT: + info->default_timeout = arg & 0xff; + break; + case CYSETRFLOW: + info->rflow = (int)arg; + break; + case CYGETRFLOW: + ret_val = info->rflow; + break; + case CYSETRTSDTR_INV: + info->rtsdtr_inv = (int)arg; + break; + case CYGETRTSDTR_INV: + ret_val = info->rtsdtr_inv; + break; + case CYGETCD1400VER: + ret_val = info->chip_rev; + break; +#ifndef CONFIG_CYZ_INTR + case CYZSETPOLLCYCLE: + cyz_polling_cycle = (arg * HZ) / 1000; + break; + case CYZGETPOLLCYCLE: + ret_val = (cyz_polling_cycle * 1000) / HZ; + break; +#endif /* CONFIG_CYZ_INTR */ + case CYSETWAIT: + info->port.closing_wait = (unsigned short)arg * HZ / 100; + break; + case CYGETWAIT: + ret_val = info->port.closing_wait / (HZ / 100); + break; + case TIOCGSERIAL: + ret_val = cy_get_serial_info(info, argp); + break; + case TIOCSSERIAL: + ret_val = cy_set_serial_info(info, tty, argp); + break; + case TIOCSERGETLSR: /* Get line status register */ + ret_val = get_lsr_info(info, argp); + break; + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + spin_lock_irqsave(&info->card->card_lock, flags); + /* note the counters on entry */ + cnow = info->icount; + spin_unlock_irqrestore(&info->card->card_lock, flags); + ret_val = wait_event_interruptible(info->port.delta_msr_wait, + cy_cflags_changed(info, arg, &cnow)); + break; + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + default: + ret_val = -ENOIOCTLCMD; + } + +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_ioctl done\n"); +#endif + return ret_val; +} /* cy_ioctl */ + +static int cy_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *sic) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_icount cnow; /* Used to snapshot */ + unsigned long flags; + + spin_lock_irqsave(&info->card->card_lock, flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->card->card_lock, flags); + + sic->cts = cnow.cts; + sic->dsr = cnow.dsr; + sic->rng = cnow.rng; + sic->dcd = cnow.dcd; + sic->rx = cnow.rx; + sic->tx = cnow.tx; + sic->frame = cnow.frame; + sic->overrun = cnow.overrun; + sic->parity = cnow.parity; + sic->brk = cnow.brk; + sic->buf_overrun = cnow.buf_overrun; + return 0; +} + +/* + * This routine allows the tty driver to be notified when + * device's termios settings have changed. Note that a + * well-designed tty driver should be prepared to accept the case + * where old == NULL, and try to do something rational. + */ +static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct cyclades_port *info = tty->driver_data; + +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); +#endif + + cy_set_line_char(info, tty); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + cy_start(tty); + } +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->port.open_wait); +#endif +} /* cy_set_termios */ + +/* This function is used to send a high-priority XON/XOFF character to + the device. +*/ +static void cy_send_xchar(struct tty_struct *tty, char ch) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int channel; + + if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) + return; + + info->x_char = ch; + + if (ch) + cy_start(tty); + + card = info->card; + channel = info->line - card->first_line; + + if (cy_is_Z(card)) { + if (ch == STOP_CHAR(tty)) + cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); + else if (ch == START_CHAR(tty)) + cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); + } +} + +/* This routine is called by the upper-layer tty layer to signal + that incoming characters should be throttled because the input + buffers are close to full. + */ +static void cy_throttle(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + unsigned long flags; + +#ifdef CY_DEBUG_THROTTLE + char buf[64]; + + printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_throttle")) + return; + + card = info->card; + + if (I_IXOFF(tty)) { + if (!cy_is_Z(card)) + cy_send_xchar(tty, STOP_CHAR(tty)); + else + info->throttle = 1; + } + + if (tty->termios->c_cflag & CRTSCTS) { + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + cyy_change_rts_dtr(info, 0, TIOCM_RTS); + spin_unlock_irqrestore(&card->card_lock, flags); + } else { + info->throttle = 1; + } + } +} /* cy_throttle */ + +/* + * This routine notifies the tty driver that it should signal + * that characters can now be sent to the tty without fear of + * overrunning the input buffers of the line disciplines. + */ +static void cy_unthrottle(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + unsigned long flags; + +#ifdef CY_DEBUG_THROTTLE + char buf[64]; + + printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", + tty_name(tty, buf), tty_chars_in_buffer(tty), info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + cy_send_xchar(tty, START_CHAR(tty)); + } + + if (tty->termios->c_cflag & CRTSCTS) { + card = info->card; + if (!cy_is_Z(card)) { + spin_lock_irqsave(&card->card_lock, flags); + cyy_change_rts_dtr(info, TIOCM_RTS, 0); + spin_unlock_irqrestore(&card->card_lock, flags); + } else { + info->throttle = 0; + } + } +} /* cy_unthrottle */ + +/* 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) +{ + struct cyclades_card *cinfo; + struct cyclades_port *info = tty->driver_data; + int channel; + unsigned long flags; + +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_stop")) + return; + + cinfo = info->card; + channel = info->line - cinfo->first_line; + if (!cy_is_Z(cinfo)) { + spin_lock_irqsave(&cinfo->card_lock, flags); + cyy_writeb(info, CyCAR, channel & 0x03); + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy); + spin_unlock_irqrestore(&cinfo->card_lock, flags); + } +} /* cy_stop */ + +static void cy_start(struct tty_struct *tty) +{ + struct cyclades_card *cinfo; + struct cyclades_port *info = tty->driver_data; + int channel; + unsigned long flags; + +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_start")) + return; + + cinfo = info->card; + channel = info->line - cinfo->first_line; + if (!cy_is_Z(cinfo)) { + spin_lock_irqsave(&cinfo->card_lock, flags); + cyy_writeb(info, CyCAR, channel & 0x03); + cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy); + spin_unlock_irqrestore(&cinfo->card_lock, flags); + } +} /* cy_start */ + +/* + * cy_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void cy_hangup(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + +#ifdef CY_DEBUG_OTHER + printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_hangup")) + return; + + cy_flush_buffer(tty); + cy_shutdown(info, tty); + tty_port_hangup(&info->port); +} /* cy_hangup */ + +static int cyy_carrier_raised(struct tty_port *port) +{ + struct cyclades_port *info = container_of(port, struct cyclades_port, + port); + struct cyclades_card *cinfo = info->card; + unsigned long flags; + int channel = info->line - cinfo->first_line; + u32 cd; + + spin_lock_irqsave(&cinfo->card_lock, flags); + cyy_writeb(info, CyCAR, channel & 0x03); + cd = cyy_readb(info, CyMSVR1) & CyDCD; + spin_unlock_irqrestore(&cinfo->card_lock, flags); + + return cd; +} + +static void cyy_dtr_rts(struct tty_port *port, int raise) +{ + struct cyclades_port *info = container_of(port, struct cyclades_port, + port); + struct cyclades_card *cinfo = info->card; + unsigned long flags; + + spin_lock_irqsave(&cinfo->card_lock, flags); + cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0, + raise ? 0 : TIOCM_RTS | TIOCM_DTR); + spin_unlock_irqrestore(&cinfo->card_lock, flags); +} + +static int cyz_carrier_raised(struct tty_port *port) +{ + struct cyclades_port *info = container_of(port, struct cyclades_port, + port); + + return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD; +} + +static void cyz_dtr_rts(struct tty_port *port, int raise) +{ + struct cyclades_port *info = container_of(port, struct cyclades_port, + port); + struct cyclades_card *cinfo = info->card; + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; + int ret, channel = info->line - cinfo->first_line; + u32 rs; + + rs = readl(&ch_ctrl->rs_control); + if (raise) + rs |= C_RS_RTS | C_RS_DTR; + else + rs &= ~(C_RS_RTS | C_RS_DTR); + cy_writel(&ch_ctrl->rs_control, rs); + ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); + if (ret != 0) + printk(KERN_ERR "%s: retval on ttyC%d was %x\n", + __func__, info->line, ret); +#ifdef CY_DEBUG_DTR + printk(KERN_DEBUG "%s: raising Z DTR\n", __func__); +#endif +} + +static const struct tty_port_operations cyy_port_ops = { + .carrier_raised = cyy_carrier_raised, + .dtr_rts = cyy_dtr_rts, + .shutdown = cy_do_close, +}; + +static const struct tty_port_operations cyz_port_ops = { + .carrier_raised = cyz_carrier_raised, + .dtr_rts = cyz_dtr_rts, + .shutdown = cy_do_close, +}; + +/* + * --------------------------------------------------------------------- + * cy_init() and friends + * + * cy_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +static int __devinit cy_init_card(struct cyclades_card *cinfo) +{ + struct cyclades_port *info; + unsigned int channel, port; + + spin_lock_init(&cinfo->card_lock); + cinfo->intr_enabled = 0; + + cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), + GFP_KERNEL); + if (cinfo->ports == NULL) { + printk(KERN_ERR "Cyclades: cannot allocate ports\n"); + return -ENOMEM; + } + + for (channel = 0, port = cinfo->first_line; channel < cinfo->nports; + channel++, port++) { + info = &cinfo->ports[channel]; + tty_port_init(&info->port); + info->magic = CYCLADES_MAGIC; + info->card = cinfo; + info->line = port; + + info->port.closing_wait = CLOSING_WAIT_DELAY; + info->port.close_delay = 5 * HZ / 10; + info->port.flags = STD_COM_FLAGS; + init_completion(&info->shutdown_wait); + + if (cy_is_Z(cinfo)) { + struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS; + struct ZFW_CTRL *zfw_ctrl; + + info->port.ops = &cyz_port_ops; + info->type = PORT_STARTECH; + + zfw_ctrl = cinfo->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); + info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel]; + info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; + + if (cinfo->hw_ver == ZO_V1) + info->xmit_fifo_size = CYZ_FIFO_SIZE; + else + info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; +#ifdef CONFIG_CYZ_INTR + setup_timer(&cyz_rx_full_timer[port], + cyz_rx_restart, (unsigned long)info); +#endif + } else { + unsigned short chip_number; + int index = cinfo->bus_index; + + info->port.ops = &cyy_port_ops; + info->type = PORT_CIRRUS; + info->xmit_fifo_size = CyMAX_CHAR_FIFO; + info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; + info->cor2 = CyETC; + info->cor3 = 0x08; /* _very_ small rcv threshold */ + + chip_number = channel / CyPORTS_PER_CHIP; + info->u.cyy.base_addr = cinfo->base_addr + + (cy_chip_offset[chip_number] << index); + info->chip_rev = cyy_readb(info, CyGFRCR); + + if (info->chip_rev >= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[13]; /* Tx BPR */ + info->tco = baud_co_60[13]; /* Tx CO */ + info->rbpr = baud_bpr_60[13]; /* Rx BPR */ + info->rco = baud_co_60[13]; /* Rx CO */ + info->rtsdtr_inv = 1; + } else { + info->tbpr = baud_bpr_25[13]; /* Tx BPR */ + info->tco = baud_co_25[13]; /* Tx CO */ + info->rbpr = baud_bpr_25[13]; /* Rx BPR */ + info->rco = baud_co_25[13]; /* Rx CO */ + info->rtsdtr_inv = 0; + } + info->read_status_mask = CyTIMEOUT | CySPECHAR | + CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; + } + + } + +#ifndef CONFIG_CYZ_INTR + if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { + mod_timer(&cyz_timerlist, jiffies + 1); +#ifdef CY_PCI_DEBUG + printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); +#endif + } +#endif + return 0; +} + +/* initialize chips on Cyclom-Y card -- return number of valid + chips (which is number of ports/4) */ +static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, + int index) +{ + unsigned int chip_number; + void __iomem *base_addr; + + cy_writeb(true_base_addr + (Cy_HwReset << index), 0); + /* Cy_HwReset is 0x1400 */ + cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + udelay(500L); + + for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; + chip_number++) { + base_addr = + true_base_addr + (cy_chip_offset[chip_number] << index); + mdelay(1); + if (readb(base_addr + (CyCCR << index)) != 0x00) { + /************* + printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", + chip_number, (unsigned long)base_addr); + *************/ + return chip_number; + } + + cy_writeb(base_addr + (CyGFRCR << index), 0); + udelay(10L); + + /* The Cyclom-16Y does not decode address bit 9 and therefore + cannot distinguish between references to chip 0 and a non- + existent chip 4. If the preceding clearing of the supposed + chip 4 GFRCR register appears at chip 0, there is no chip 4 + and this must be a Cyclom-16Y, not a Cyclom-32Ye. + */ + if (chip_number == 4 && readb(true_base_addr + + (cy_chip_offset[0] << index) + + (CyGFRCR << index)) == 0) { + return chip_number; + } + + cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); + mdelay(1); + + if (readb(base_addr + (CyGFRCR << index)) == 0x00) { + /* + printk(" chip #%d at %#6lx is not responding ", + chip_number, (unsigned long)base_addr); + printk("(GFRCR stayed 0)\n", + */ + return chip_number; + } + if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != + 0x40) { + /* + printk(" chip #%d at %#6lx is not valid (GFRCR == " + "%#2x)\n", + chip_number, (unsigned long)base_addr, + base_addr[CyGFRCR<= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + /* Impossible to reach 5ms with this chip. + Changed to 2ms instead (f = 500 Hz). */ + cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS); + } else { + /* f = 200 Hz */ + cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS); + } + + /* + printk(" chip #%d at %#6lx is rev 0x%2x\n", + chip_number, (unsigned long)base_addr, + readb(base_addr+(CyGFRCR< NR_PORTS) { + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " + "more channels are available. Change NR_PORTS " + "in cyclades.c and recompile kernel.\n", + (unsigned long)cy_isa_address); + iounmap(cy_isa_address); + return nboard; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == NULL) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " + "more cards can be used. Change NR_CARDS in " + "cyclades.c and recompile kernel.\n", + (unsigned long)cy_isa_address); + iounmap(cy_isa_address); + return nboard; + } + + /* allocate IRQ */ + if (request_irq(cy_isa_irq, cyy_interrupt, + IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " + "could not allocate IRQ#%d.\n", + (unsigned long)cy_isa_address, cy_isa_irq); + iounmap(cy_isa_address); + return nboard; + } + + /* set cy_card */ + cy_card[j].base_addr = cy_isa_address; + cy_card[j].ctl_addr.p9050 = NULL; + cy_card[j].irq = (int)cy_isa_irq; + cy_card[j].bus_index = 0; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; + cy_card[j].nports = cy_isa_nchan; + if (cy_init_card(&cy_card[j])) { + cy_card[j].base_addr = NULL; + free_irq(cy_isa_irq, &cy_card[j]); + iounmap(cy_isa_address); + continue; + } + nboard++; + + printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: " + "%d channels starting from port %d\n", + j + 1, (unsigned long)cy_isa_address, + (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), + cy_isa_irq, cy_isa_nchan, cy_next_channel); + + for (j = cy_next_channel; + j < cy_next_channel + cy_isa_nchan; j++) + tty_register_device(cy_serial_driver, j, NULL); + cy_next_channel += cy_isa_nchan; + } + return nboard; +#else + return 0; +#endif /* CONFIG_ISA */ +} /* cy_detect_isa */ + +#ifdef CONFIG_PCI +static inline int __devinit cyc_isfwstr(const char *str, unsigned int size) +{ + unsigned int a; + + for (a = 0; a < size && *str; a++, str++) + if (*str & 0x80) + return -EINVAL; + + for (; a < size; a++, str++) + if (*str) + return -EINVAL; + + return 0; +} + +static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data, + unsigned int size) +{ + for (; size > 0; size--) { + cy_writel(fpga, *data++); + udelay(10); + } +} + +static void __devinit plx_init(struct pci_dev *pdev, int irq, + struct RUNTIME_9060 __iomem *addr) +{ + /* Reset PLX */ + cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000); + udelay(100L); + cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000); + + /* Reload Config. Registers from EEPROM */ + cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000); + udelay(100L); + cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000); + + /* For some yet unknown reason, once the PLX9060 reloads the EEPROM, + * the IRQ is lost and, thus, we have to re-write it to the PCI config. + * registers. This will remain here until we find a permanent fix. + */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); +} + +static int __devinit __cyz_load_fw(const struct firmware *fw, + const char *name, const u32 mailbox, void __iomem *base, + void __iomem *fpga) +{ + const void *ptr = fw->data; + const struct zfile_header *h = ptr; + const struct zfile_config *c, *cs; + const struct zfile_block *b, *bs; + unsigned int a, tmp, len = fw->size; +#define BAD_FW KERN_ERR "Bad firmware: " + if (len < sizeof(*h)) { + printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h)); + return -EINVAL; + } + + cs = ptr + h->config_offset; + bs = ptr + h->block_offset; + + if ((void *)(cs + h->n_config) > ptr + len || + (void *)(bs + h->n_blocks) > ptr + len) { + printk(BAD_FW "too short"); + return -EINVAL; + } + + if (cyc_isfwstr(h->name, sizeof(h->name)) || + cyc_isfwstr(h->date, sizeof(h->date))) { + printk(BAD_FW "bad formatted header string\n"); + return -EINVAL; + } + + if (strncmp(name, h->name, sizeof(h->name))) { + printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name); + return -EINVAL; + } + + tmp = 0; + for (c = cs; c < cs + h->n_config; c++) { + for (a = 0; a < c->n_blocks; a++) + if (c->block_list[a] > h->n_blocks) { + printk(BAD_FW "bad block ref number in cfgs\n"); + return -EINVAL; + } + if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */ + tmp++; + } + if (!tmp) { + printk(BAD_FW "nothing appropriate\n"); + return -EINVAL; + } + + for (b = bs; b < bs + h->n_blocks; b++) + if (b->file_offset + b->size > len) { + printk(BAD_FW "bad block data offset\n"); + return -EINVAL; + } + + /* everything is OK, let's seek'n'load it */ + for (c = cs; c < cs + h->n_config; c++) + if (c->mailbox == mailbox && c->function == 0) + break; + + for (a = 0; a < c->n_blocks; a++) { + b = &bs[c->block_list[a]]; + if (b->type == ZBLOCK_FPGA) { + if (fpga != NULL) + cyz_fpga_copy(fpga, ptr + b->file_offset, + b->size); + } else { + if (base != NULL) + memcpy_toio(base + b->ram_offset, + ptr + b->file_offset, b->size); + } + } +#undef BAD_FW + return 0; +} + +static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, + struct RUNTIME_9060 __iomem *ctl_addr, int irq) +{ + const struct firmware *fw; + struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS; + struct CUSTOM_REG __iomem *cust = base_addr; + struct ZFW_CTRL __iomem *pt_zfwctrl; + void __iomem *tmp; + u32 mailbox, status, nchan; + unsigned int i; + int retval; + + retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev); + if (retval) { + dev_err(&pdev->dev, "can't get firmware\n"); + goto err; + } + + /* Check whether the firmware is already loaded and running. If + positive, skip this board */ + if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { + u32 cntval = readl(base_addr + 0x190); + + udelay(100); + if (cntval != readl(base_addr + 0x190)) { + /* FW counter is working, FW is running */ + dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. " + "Skipping board.\n"); + retval = 0; + goto err_rel; + } + } + + /* start boot */ + cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) & + ~0x00030800UL); + + mailbox = readl(&ctl_addr->mail_box_0); + + if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { + /* stops CPU and set window to beginning of RAM */ + cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); + cy_writel(&cust->cpu_stop, 0); + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); + udelay(100); + } + + plx_init(pdev, irq, ctl_addr); + + if (mailbox != 0) { + /* load FPGA */ + retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL, + base_addr); + if (retval) + goto err_rel; + if (!__cyz_fpga_loaded(ctl_addr)) { + dev_err(&pdev->dev, "fw upload successful, but fw is " + "not loaded\n"); + goto err_rel; + } + } + + /* stops CPU and set window to beginning of RAM */ + cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); + cy_writel(&cust->cpu_stop, 0); + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); + udelay(100); + + /* clear memory */ + for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) + cy_writeb(tmp, 255); + if (mailbox != 0) { + /* set window to last 512K of RAM */ + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE); + for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++) + cy_writeb(tmp, 255); + /* set window to beginning of RAM */ + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); + } + + retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL); + release_firmware(fw); + if (retval) + goto err; + + /* finish boot and start boards */ + cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); + cy_writel(&cust->cpu_start, 0); + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); + i = 0; + while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40) + msleep(100); + if (status != ZFIRM_ID) { + if (status == ZFIRM_HLT) { + dev_err(&pdev->dev, "you need an external power supply " + "for this number of ports. Firmware halted and " + "board reset.\n"); + retval = -EIO; + goto err; + } + dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting " + "some more time\n", status); + while ((status = readl(&fid->signature)) != ZFIRM_ID && + i++ < 200) + msleep(100); + if (status != ZFIRM_ID) { + dev_err(&pdev->dev, "Board not started in 20 seconds! " + "Giving up. (fid->signature = 0x%x)\n", + status); + dev_info(&pdev->dev, "*** Warning ***: if you are " + "upgrading the FW, please power cycle the " + "system before loading the new FW to the " + "Cyclades-Z.\n"); + + if (__cyz_fpga_loaded(ctl_addr)) + plx_init(pdev, irq, ctl_addr); + + retval = -EIO; + goto err; + } + dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n", + i / 10); + } + pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr); + + dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n", + base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), + base_addr + readl(&fid->zfwctrl_addr)); + + nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); + dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", + readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); + + if (nchan == 0) { + dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " + "check the connection between the Z host card and the " + "serial expanders.\n"); + + if (__cyz_fpga_loaded(ctl_addr)) + plx_init(pdev, irq, ctl_addr); + + dev_info(&pdev->dev, "Null number of ports detected. Board " + "reset.\n"); + retval = 0; + goto err; + } + + cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX); + cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION); + + /* + Early firmware failed to start looking for commands. + This enables firmware interrupts for those commands. + */ + cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | + (1 << 17)); + cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | + 0x00030800UL); + + return nchan; +err_rel: + release_firmware(fw); +err: + return retval; +} + +static int __devinit cy_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + void __iomem *addr0 = NULL, *addr2 = NULL; + char *card_name = NULL; + u32 uninitialized_var(mailbox); + unsigned int device_id, nchan = 0, card_no, i; + unsigned char plx_ver; + int retval, irq; + + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "cannot enable device\n"); + goto err; + } + + /* read PCI configuration area */ + irq = pdev->irq; + device_id = pdev->device & ~PCI_DEVICE_ID_MASK; + +#if defined(__alpha__) + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ + dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low " + "addresses on Alpha systems.\n"); + retval = -EIO; + goto err_dis; + } +#endif + if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { + dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low " + "addresses\n"); + retval = -EIO; + goto err_dis; + } + + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { + dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring " + "it...\n"); + pdev->resource[2].flags &= ~IORESOURCE_IO; + } + + retval = pci_request_regions(pdev, "cyclades"); + if (retval) { + dev_err(&pdev->dev, "failed to reserve resources\n"); + goto err_dis; + } + + retval = -EIO; + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { + card_name = "Cyclom-Y"; + + addr0 = ioremap_nocache(pci_resource_start(pdev, 0), + CyPCI_Yctl); + if (addr0 == NULL) { + dev_err(&pdev->dev, "can't remap ctl region\n"); + goto err_reg; + } + addr2 = ioremap_nocache(pci_resource_start(pdev, 2), + CyPCI_Ywin); + if (addr2 == NULL) { + dev_err(&pdev->dev, "can't remap base region\n"); + goto err_unmap; + } + + nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); + if (nchan == 0) { + dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " + "Serial-Modules\n"); + goto err_unmap; + } + } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { + struct RUNTIME_9060 __iomem *ctl_addr; + + ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), + CyPCI_Zctl); + if (addr0 == NULL) { + dev_err(&pdev->dev, "can't remap ctl region\n"); + goto err_reg; + } + + /* Disable interrupts on the PLX before resetting it */ + cy_writew(&ctl_addr->intr_ctrl_stat, + readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); + + plx_init(pdev, irq, addr0); + + mailbox = readl(&ctl_addr->mail_box_0); + + addr2 = ioremap_nocache(pci_resource_start(pdev, 2), + mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); + if (addr2 == NULL) { + dev_err(&pdev->dev, "can't remap base region\n"); + goto err_unmap; + } + + if (mailbox == ZE_V1) { + card_name = "Cyclades-Ze"; + } else { + card_name = "Cyclades-8Zo"; +#ifdef CY_PCI_DEBUG + if (mailbox == ZO_V1) { + cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); + dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA " + "id %lx, ver %lx\n", (ulong)(0xff & + readl(&((struct CUSTOM_REG *)addr2)-> + fpga_id)), (ulong)(0xff & + readl(&((struct CUSTOM_REG *)addr2)-> + fpga_version))); + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); + } else { + dev_info(&pdev->dev, "Cyclades-Z/PCI: New " + "Cyclades-Z board. FPGA not loaded\n"); + } +#endif + /* The following clears the firmware id word. This + ensures that the driver will not attempt to talk to + the board until it has been properly initialized. + */ + if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) + cy_writel(addr2 + ID_ADDRESS, 0L); + } + + retval = cyz_load_fw(pdev, addr2, addr0, irq); + if (retval <= 0) + goto err_unmap; + nchan = retval; + } + + if ((cy_next_channel + nchan) > NR_PORTS) { + dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " + "channels are available. Change NR_PORTS in " + "cyclades.c and recompile kernel.\n"); + goto err_unmap; + } + /* fill the next cy_card structure available */ + for (card_no = 0; card_no < NR_CARDS; card_no++) { + if (cy_card[card_no].base_addr == NULL) + break; + } + if (card_no == NR_CARDS) { /* no more cy_cards available */ + dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " + "more cards can be used. Change NR_CARDS in " + "cyclades.c and recompile kernel.\n"); + goto err_unmap; + } + + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { + /* allocate IRQ */ + retval = request_irq(irq, cyy_interrupt, + IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); + if (retval) { + dev_err(&pdev->dev, "could not allocate IRQ\n"); + goto err_unmap; + } + cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; + } else { + struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS; + struct ZFW_CTRL __iomem *zfw_ctrl; + + zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); + + cy_card[card_no].hw_ver = mailbox; + cy_card[card_no].num_chips = (unsigned int)-1; + cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; +#ifdef CONFIG_CYZ_INTR + /* allocate IRQ only if board has an IRQ */ + if (irq != 0 && irq != 255) { + retval = request_irq(irq, cyz_interrupt, + IRQF_SHARED, "Cyclades-Z", + &cy_card[card_no]); + if (retval) { + dev_err(&pdev->dev, "could not allocate IRQ\n"); + goto err_unmap; + } + } +#endif /* CONFIG_CYZ_INTR */ + } + + /* set cy_card */ + cy_card[card_no].base_addr = addr2; + cy_card[card_no].ctl_addr.p9050 = addr0; + cy_card[card_no].irq = irq; + cy_card[card_no].bus_index = 1; + cy_card[card_no].first_line = cy_next_channel; + cy_card[card_no].nports = nchan; + retval = cy_init_card(&cy_card[card_no]); + if (retval) + goto err_null; + + pci_set_drvdata(pdev, &cy_card[card_no]); + + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { + /* enable interrupts in the PCI interface */ + plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; + switch (plx_ver) { + case PLX_9050: + cy_writeb(addr0 + 0x4c, 0x43); + break; + + case PLX_9060: + case PLX_9080: + default: /* Old boards, use PLX_9060 */ + { + struct RUNTIME_9060 __iomem *ctl_addr = addr0; + plx_init(pdev, irq, ctl_addr); + cy_writew(&ctl_addr->intr_ctrl_stat, + readw(&ctl_addr->intr_ctrl_stat) | 0x0900); + break; + } + } + } + + dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " + "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); + for (i = cy_next_channel; i < cy_next_channel + nchan; i++) + tty_register_device(cy_serial_driver, i, &pdev->dev); + cy_next_channel += nchan; + + return 0; +err_null: + cy_card[card_no].base_addr = NULL; + free_irq(irq, &cy_card[card_no]); +err_unmap: + iounmap(addr0); + if (addr2) + iounmap(addr2); +err_reg: + pci_release_regions(pdev); +err_dis: + pci_disable_device(pdev); +err: + return retval; +} + +static void __devexit cy_pci_remove(struct pci_dev *pdev) +{ + struct cyclades_card *cinfo = pci_get_drvdata(pdev); + unsigned int i; + + /* non-Z with old PLX */ + if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == + PLX_9050) + cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); + else +#ifndef CONFIG_CYZ_INTR + if (!cy_is_Z(cinfo)) +#endif + cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat, + readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) & + ~0x0900); + + iounmap(cinfo->base_addr); + if (cinfo->ctl_addr.p9050) + iounmap(cinfo->ctl_addr.p9050); + if (cinfo->irq +#ifndef CONFIG_CYZ_INTR + && !cy_is_Z(cinfo) +#endif /* CONFIG_CYZ_INTR */ + ) + free_irq(cinfo->irq, cinfo); + pci_release_regions(pdev); + + cinfo->base_addr = NULL; + for (i = cinfo->first_line; i < cinfo->first_line + + cinfo->nports; i++) + tty_unregister_device(cy_serial_driver, i); + cinfo->nports = 0; + kfree(cinfo->ports); +} + +static struct pci_driver cy_pci_driver = { + .name = "cyclades", + .id_table = cy_pci_dev_id, + .probe = cy_pci_probe, + .remove = __devexit_p(cy_pci_remove) +}; +#endif + +static int cyclades_proc_show(struct seq_file *m, void *v) +{ + struct cyclades_port *info; + unsigned int i, j; + __u32 cur_jifs = jiffies; + + seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " + "IdleIn Overruns Ldisc\n"); + + /* Output one line for each known port */ + for (i = 0; i < NR_CARDS; i++) + for (j = 0; j < cy_card[i].nports; j++) { + info = &cy_card[i].ports[j]; + + if (info->port.count) { + /* XXX is the ldisc num worth this? */ + struct tty_struct *tty; + struct tty_ldisc *ld; + int num = 0; + tty = tty_port_tty_get(&info->port); + if (tty) { + ld = tty_ldisc_ref(tty); + if (ld) { + num = ld->ops->num; + tty_ldisc_deref(ld); + } + tty_kref_put(tty); + } + seq_printf(m, "%3d %8lu %10lu %8lu " + "%10lu %8lu %9lu %6d\n", info->line, + (cur_jifs - info->idle_stats.in_use) / + HZ, info->idle_stats.xmit_bytes, + (cur_jifs - info->idle_stats.xmit_idle)/ + HZ, info->idle_stats.recv_bytes, + (cur_jifs - info->idle_stats.recv_idle)/ + HZ, info->idle_stats.overruns, + num); + } else + seq_printf(m, "%3d %8lu %10lu %8lu " + "%10lu %8lu %9lu %6ld\n", + info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + } + return 0; +} + +static int cyclades_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, cyclades_proc_show, NULL); +} + +static const struct file_operations cyclades_proc_fops = { + .owner = THIS_MODULE, + .open = cyclades_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* 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 + for Cyclom cards in the system. As each is found, it is probed + to discover how many chips (and thus how many ports) are present. + These ports are mapped to the tty ports 32 and upward in monotonic + fashion. If an 8-port card is replaced with a 16-port card, the + port mapping on a following card will shift. + + This approach is different from what is used in the other serial + device driver because the Cyclom is more properly a multiplexer, + not just an aggregation of serial ports on one card. + + 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 const struct tty_operations cy_ops = { + .open = cy_open, + .close = cy_close, + .write = cy_write, + .put_char = cy_put_char, + .flush_chars = cy_flush_chars, + .write_room = cy_write_room, + .chars_in_buffer = cy_chars_in_buffer, + .flush_buffer = cy_flush_buffer, + .ioctl = cy_ioctl, + .throttle = cy_throttle, + .unthrottle = cy_unthrottle, + .set_termios = cy_set_termios, + .stop = cy_stop, + .start = cy_start, + .hangup = cy_hangup, + .break_ctl = cy_break, + .wait_until_sent = cy_wait_until_sent, + .tiocmget = cy_tiocmget, + .tiocmset = cy_tiocmset, + .get_icount = cy_get_icount, + .proc_fops = &cyclades_proc_fops, +}; + +static int __init cy_init(void) +{ + unsigned int nboards; + int retval = -ENOMEM; + + cy_serial_driver = alloc_tty_driver(NR_PORTS); + if (!cy_serial_driver) + goto err; + + printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n", + __DATE__, __TIME__); + + /* Initialize the tty_driver structure */ + + cy_serial_driver->owner = THIS_MODULE; + cy_serial_driver->driver_name = "cyclades"; + cy_serial_driver->name = "ttyC"; + cy_serial_driver->major = CYCLADES_MAJOR; + cy_serial_driver->minor_start = 0; + 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_DRIVER_DYNAMIC_DEV; + tty_set_operations(cy_serial_driver, &cy_ops); + + retval = tty_register_driver(cy_serial_driver); + if (retval) { + printk(KERN_ERR "Couldn't register Cyclades serial driver\n"); + goto err_frtty; + } + + /* the code below is responsible to find the boards. Each different + type of board has its own detection routine. If a board is found, + the next cy_card structure available is set by the detection + routine. These functions are responsible for checking the + availability of cy_card and cy_port data structures and updating + the cy_next_channel. */ + + /* look for isa boards */ + nboards = cy_detect_isa(); + +#ifdef CONFIG_PCI + /* look for pci boards */ + retval = pci_register_driver(&cy_pci_driver); + if (retval && !nboards) { + tty_unregister_driver(cy_serial_driver); + goto err_frtty; + } +#endif + + return 0; +err_frtty: + put_tty_driver(cy_serial_driver); +err: + return retval; +} /* cy_init */ + +static void __exit cy_cleanup_module(void) +{ + struct cyclades_card *card; + unsigned int i, e1; + +#ifndef CONFIG_CYZ_INTR + del_timer_sync(&cyz_timerlist); +#endif /* CONFIG_CYZ_INTR */ + + e1 = tty_unregister_driver(cy_serial_driver); + if (e1) + printk(KERN_ERR "failed to unregister Cyclades serial " + "driver(%d)\n", e1); + +#ifdef CONFIG_PCI + pci_unregister_driver(&cy_pci_driver); +#endif + + for (i = 0; i < NR_CARDS; i++) { + card = &cy_card[i]; + if (card->base_addr) { + /* clear interrupt */ + cy_writeb(card->base_addr + Cy_ClrIntr, 0); + iounmap(card->base_addr); + if (card->ctl_addr.p9050) + iounmap(card->ctl_addr.p9050); + if (card->irq +#ifndef CONFIG_CYZ_INTR + && !cy_is_Z(card) +#endif /* CONFIG_CYZ_INTR */ + ) + free_irq(card->irq, card); + for (e1 = card->first_line; e1 < card->first_line + + card->nports; e1++) + tty_unregister_device(cy_serial_driver, e1); + kfree(card->ports); + } + } + + put_tty_driver(cy_serial_driver); +} /* cy_cleanup_module */ + +module_init(cy_init); +module_exit(cy_cleanup_module); + +MODULE_LICENSE("GPL"); +MODULE_VERSION(CY_VERSION); +MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); +MODULE_FIRMWARE("cyzfirm.bin"); diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c new file mode 100644 index 000000000000..db1cf9c328d8 --- /dev/null +++ b/drivers/tty/isicom.c @@ -0,0 +1,1736 @@ +/* + * 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. + * + * Original driver code supplied by Multi-Tech + * + * Changes + * 1/9/98 alan@lxorguk.ukuu.org.uk + * Merge to 2.0.x kernel tree + * Obtain and use official major/minors + * Loader switched to a misc device + * (fixed range check bug as a side effect) + * Printk clean up + * 9/12/98 alan@lxorguk.ukuu.org.uk + * Rough port to 2.1.x + * + * 10/6/99 sameer Merged the ISA and PCI drivers to + * a new unified driver. + * + * 3/9/99 sameer Added support for ISI4616 cards. + * + * 16/9/99 sameer We do not force RTS low anymore. + * This is to prevent the firmware + * from getting confused. + * + * 26/10/99 sameer Cosmetic changes:The driver now + * dumps the Port Count information + * along with I/O address and IRQ. + * + * 13/12/99 sameer Fixed the problem with IRQ sharing. + * + * 10/5/00 sameer Fixed isicom_shutdown_board() + * to not lower DTR on all the ports + * when the last port on the card is + * closed. + * + * 10/5/00 sameer Signal mask setup command added + * to isicom_setup_port and + * isicom_shutdown_port. + * + * 24/5/00 sameer The driver is now SMP aware. + * + * + * 27/11/00 Vinayak P Risbud Fixed the Driver Crash Problem + * + * + * 03/01/01 anil .s Added support for resetting the + * internal modems on ISI cards. + * + * 08/02/01 anil .s Upgraded the driver for kernel + * 2.4.x + * + * 11/04/01 Kevin Fixed firmware load problem with + * ISIHP-4X card + * + * 30/04/01 anil .s Fixed the remote login through + * ISI port problem. Now the link + * does not go down before password + * prompt. + * + * 03/05/01 anil .s Fixed the problem with IRQ sharing + * among ISI-PCI cards. + * + * 03/05/01 anil .s Added support to display the version + * info during insmod as well as module + * listing by lsmod. + * + * 10/05/01 anil .s Done the modifications to the source + * file and Install script so that the + * same installation can be used for + * 2.2.x and 2.4.x kernel. + * + * 06/06/01 anil .s Now we drop both dtr and rts during + * shutdown_port as well as raise them + * during isicom_config_port. + * + * 09/06/01 acme@conectiva.com.br use capable, not suser, do + * restore_flags on failure in + * isicom_send_break, verify put_user + * result + * + * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps + * Baud index extended to 21 + * + * 20/03/03 ranjeeth Made to work for Linux Advanced server. + * Taken care of license warning. + * + * 10/12/03 Ravindra Made to work for Fedora Core 1 of + * Red Hat Distribution + * + * 06/01/05 Alan Cox Merged the ISI and base kernel strands + * into a single 2.6 driver + * + * *********************************************************** + * + * To use this driver you also need the support package. You + * can find this in RPM format on + * ftp://ftp.linux.org.uk/pub/linux/alan + * + * You can find the original tools for this direct from Multitech + * ftp://ftp.multitech.com/ISI-Cards/ + * + * Having installed the cards the module options (/etc/modprobe.conf) + * + * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4 + * + * Omit those entries for boards you don't have installed. + * + * TODO + * Merge testing + * 64-bit verification + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#define InterruptTheCard(base) outw(0, (base) + 0xc) +#define ClearInterrupt(base) inw((base) + 0x0a) + +#ifdef DEBUG +#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) +#else +#define isicom_paranoia_check(a, b, c) 0 +#endif + +static int isicom_probe(struct pci_dev *, const struct pci_device_id *); +static void __devexit isicom_remove(struct pci_dev *); + +static struct pci_device_id isicom_pci_tbl[] = { + { PCI_DEVICE(VENDOR_ID, 0x2028) }, + { PCI_DEVICE(VENDOR_ID, 0x2051) }, + { PCI_DEVICE(VENDOR_ID, 0x2052) }, + { PCI_DEVICE(VENDOR_ID, 0x2053) }, + { PCI_DEVICE(VENDOR_ID, 0x2054) }, + { PCI_DEVICE(VENDOR_ID, 0x2055) }, + { PCI_DEVICE(VENDOR_ID, 0x2056) }, + { PCI_DEVICE(VENDOR_ID, 0x2057) }, + { PCI_DEVICE(VENDOR_ID, 0x2058) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, isicom_pci_tbl); + +static struct pci_driver isicom_driver = { + .name = "isicom", + .id_table = isicom_pci_tbl, + .probe = isicom_probe, + .remove = __devexit_p(isicom_remove) +}; + +static int prev_card = 3; /* start servicing isi_card[0] */ +static struct tty_driver *isicom_normal; + +static void isicom_tx(unsigned long _data); +static void isicom_start(struct tty_struct *tty); + +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, 20, 21 +}; + +struct isi_board { + unsigned long base; + int irq; + unsigned char port_count; + unsigned short status; + unsigned short port_status; /* each bit for each port */ + unsigned short shift_count; + struct isi_port *ports; + signed char count; + spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */ + unsigned long flags; + unsigned int index; +}; + +struct isi_port { + unsigned short magic; + struct tty_port port; + u16 channel; + u16 status; + struct isi_board *card; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; +}; + +static struct isi_board isi_card[BOARD_COUNT]; +static struct isi_port isi_ports[PORT_COUNT]; + +/* + * Locking functions for card level locking. We need to own both + * the kernel lock for the card and have the card in a position that + * it wants to talk. + */ + +static inline int WaitTillCardIsFree(unsigned long base) +{ + unsigned int count = 0; + unsigned int a = in_atomic(); /* do we run under spinlock? */ + + while (!(inw(base + 0xe) & 0x1) && count++ < 100) + if (a) + mdelay(1); + else + msleep(1); + + return !(inw(base + 0xe) & 0x1); +} + +static int lock_card(struct isi_board *card) +{ + unsigned long base = card->base; + unsigned int retries, a; + + for (retries = 0; retries < 10; retries++) { + spin_lock_irqsave(&card->card_lock, card->flags); + for (a = 0; a < 10; a++) { + if (inw(base + 0xe) & 0x1) + return 1; + udelay(10); + } + spin_unlock_irqrestore(&card->card_lock, card->flags); + msleep(10); + } + pr_warning("Failed to lock Card (0x%lx)\n", card->base); + + return 0; /* Failed to acquire the card! */ +} + +static void unlock_card(struct isi_board *card) +{ + spin_unlock_irqrestore(&card->card_lock, card->flags); +} + +/* + * ISI Card specific ops ... + */ + +/* card->lock HAS to be held */ +static void raise_dtr(struct isi_port *port) +{ + struct isi_board *card = port->card; + unsigned long base = card->base; + u16 channel = port->channel; + + if (WaitTillCardIsFree(base)) + return; + + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0504, base); + InterruptTheCard(base); + port->status |= ISI_DTR; +} + +/* card->lock HAS to be held */ +static inline void drop_dtr(struct isi_port *port) +{ + struct isi_board *card = port->card; + unsigned long base = card->base; + u16 channel = port->channel; + + if (WaitTillCardIsFree(base)) + return; + + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0404, base); + InterruptTheCard(base); + port->status &= ~ISI_DTR; +} + +/* card->lock HAS to be held */ +static inline void raise_rts(struct isi_port *port) +{ + struct isi_board *card = port->card; + unsigned long base = card->base; + u16 channel = port->channel; + + if (WaitTillCardIsFree(base)) + return; + + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0a04, base); + InterruptTheCard(base); + port->status |= ISI_RTS; +} + +/* card->lock HAS to be held */ +static inline void drop_rts(struct isi_port *port) +{ + struct isi_board *card = port->card; + unsigned long base = card->base; + u16 channel = port->channel; + + if (WaitTillCardIsFree(base)) + return; + + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0804, base); + InterruptTheCard(base); + port->status &= ~ISI_RTS; +} + +/* card->lock MUST NOT be held */ + +static void isicom_dtr_rts(struct tty_port *port, int on) +{ + struct isi_port *ip = container_of(port, struct isi_port, port); + struct isi_board *card = ip->card; + unsigned long base = card->base; + u16 channel = ip->channel; + + if (!lock_card(card)) + return; + + if (on) { + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0f04, base); + InterruptTheCard(base); + ip->status |= (ISI_DTR | ISI_RTS); + } else { + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0C04, base); + InterruptTheCard(base); + ip->status &= ~(ISI_DTR | ISI_RTS); + } + unlock_card(card); +} + +/* card->lock HAS to be held */ +static void drop_dtr_rts(struct isi_port *port) +{ + struct isi_board *card = port->card; + unsigned long base = card->base; + u16 channel = port->channel; + + if (WaitTillCardIsFree(base)) + return; + + outw(0x8000 | (channel << card->shift_count) | 0x02, base); + outw(0x0c04, base); + InterruptTheCard(base); + port->status &= ~(ISI_RTS | ISI_DTR); +} + +/* + * ISICOM Driver specific routines ... + * + */ + +static inline int __isicom_paranoia_check(struct isi_port const *port, + char *name, const char *routine) +{ + if (!port) { + pr_warning("Warning: bad isicom magic for dev %s in %s.\n", + name, routine); + return 1; + } + if (port->magic != ISICOM_MAGIC) { + pr_warning("Warning: NULL isicom port for dev %s in %s.\n", + name, routine); + return 1; + } + + return 0; +} + +/* + * Transmitter. + * + * We shovel data into the card buffers on a regular basis. The card + * will do the rest of the work for us. + */ + +static void isicom_tx(unsigned long _data) +{ + unsigned long flags, base; + unsigned int retries; + short count = (BOARD_COUNT-1), card; + short txcount, wrd, residue, word_count, cnt; + struct isi_port *port; + struct tty_struct *tty; + + /* find next active board */ + card = (prev_card + 1) & 0x0003; + while (count-- > 0) { + if (isi_card[card].status & BOARD_ACTIVE) + break; + card = (card + 1) & 0x0003; + } + if (!(isi_card[card].status & BOARD_ACTIVE)) + goto sched_again; + + prev_card = card; + + count = isi_card[card].port_count; + port = isi_card[card].ports; + base = isi_card[card].base; + + spin_lock_irqsave(&isi_card[card].card_lock, flags); + for (retries = 0; retries < 100; retries++) { + if (inw(base + 0xe) & 0x1) + break; + udelay(2); + } + if (retries >= 100) + goto unlock; + + tty = tty_port_tty_get(&port->port); + if (tty == NULL) + goto put_unlock; + + for (; count > 0; count--, port++) { + /* port not active or tx disabled to force flow control */ + if (!(port->port.flags & ASYNC_INITIALIZED) || + !(port->status & ISI_TXOK)) + continue; + + txcount = min_t(short, TX_SIZE, port->xmit_cnt); + if (txcount <= 0 || tty->stopped || tty->hw_stopped) + continue; + + if (!(inw(base + 0x02) & (1 << port->channel))) + continue; + + pr_debug("txing %d bytes, port%d.\n", + txcount, port->channel + 1); + outw((port->channel << isi_card[card].shift_count) | txcount, + base); + residue = NO; + wrd = 0; + while (1) { + cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE + - port->xmit_tail)); + if (residue == YES) { + residue = NO; + if (cnt > 0) { + wrd |= (port->port.xmit_buf[port->xmit_tail] + << 8); + port->xmit_tail = (port->xmit_tail + 1) + & (SERIAL_XMIT_SIZE - 1); + port->xmit_cnt--; + txcount--; + cnt--; + outw(wrd, base); + } else { + outw(wrd, base); + break; + } + } + if (cnt <= 0) + break; + word_count = cnt >> 1; + outsw(base, port->port.xmit_buf+port->xmit_tail, word_count); + port->xmit_tail = (port->xmit_tail + + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1); + txcount -= (word_count << 1); + port->xmit_cnt -= (word_count << 1); + if (cnt & 0x0001) { + residue = YES; + wrd = port->port.xmit_buf[port->xmit_tail]; + port->xmit_tail = (port->xmit_tail + 1) + & (SERIAL_XMIT_SIZE - 1); + port->xmit_cnt--; + txcount--; + } + } + + InterruptTheCard(base); + if (port->xmit_cnt <= 0) + port->status &= ~ISI_TXOK; + if (port->xmit_cnt <= WAKEUP_CHARS) + tty_wakeup(tty); + } + +put_unlock: + tty_kref_put(tty); +unlock: + spin_unlock_irqrestore(&isi_card[card].card_lock, flags); + /* schedule another tx for hopefully in about 10ms */ +sched_again: + mod_timer(&tx, jiffies + msecs_to_jiffies(10)); +} + +/* + * Main interrupt handler routine + */ + +static irqreturn_t isicom_interrupt(int irq, void *dev_id) +{ + struct isi_board *card = dev_id; + struct isi_port *port; + struct tty_struct *tty; + unsigned long base; + u16 header, word_count, count, channel; + short byte_count; + unsigned char *rp; + + if (!card || !(card->status & FIRMWARE_LOADED)) + return IRQ_NONE; + + base = card->base; + + /* did the card interrupt us? */ + if (!(inw(base + 0x0e) & 0x02)) + return IRQ_NONE; + + spin_lock(&card->card_lock); + + /* + * disable any interrupts from the PCI card and lower the + * interrupt line + */ + outw(0x8000, base+0x04); + ClearInterrupt(base); + + inw(base); /* get the dummy word out */ + header = inw(base); + channel = (header & 0x7800) >> card->shift_count; + byte_count = header & 0xff; + + if (channel + 1 > card->port_count) { + pr_warning("%s(0x%lx): %d(channel) > port_count.\n", + __func__, base, channel+1); + outw(0x0000, base+0x04); /* enable interrupts */ + spin_unlock(&card->card_lock); + return IRQ_HANDLED; + } + port = card->ports + channel; + if (!(port->port.flags & ASYNC_INITIALIZED)) { + outw(0x0000, base+0x04); /* enable interrupts */ + spin_unlock(&card->card_lock); + return IRQ_HANDLED; + } + + tty = tty_port_tty_get(&port->port); + if (tty == NULL) { + word_count = byte_count >> 1; + while (byte_count > 1) { + inw(base); + byte_count -= 2; + } + if (byte_count & 0x01) + inw(base); + outw(0x0000, base+0x04); /* enable interrupts */ + spin_unlock(&card->card_lock); + return IRQ_HANDLED; + } + + if (header & 0x8000) { /* Status Packet */ + header = inw(base); + switch (header & 0xff) { + case 0: /* Change in EIA signals */ + if (port->port.flags & ASYNC_CHECK_CD) { + if (port->status & ISI_DCD) { + if (!(header & ISI_DCD)) { + /* Carrier has been lost */ + pr_debug("%s: DCD->low.\n", + __func__); + port->status &= ~ISI_DCD; + tty_hangup(tty); + } + } else if (header & ISI_DCD) { + /* Carrier has been detected */ + pr_debug("%s: DCD->high.\n", + __func__); + port->status |= ISI_DCD; + wake_up_interruptible(&port->port.open_wait); + } + } else { + if (header & ISI_DCD) + port->status |= ISI_DCD; + else + port->status &= ~ISI_DCD; + } + + if (port->port.flags & ASYNC_CTS_FLOW) { + if (tty->hw_stopped) { + if (header & ISI_CTS) { + port->port.tty->hw_stopped = 0; + /* start tx ing */ + port->status |= (ISI_TXOK + | ISI_CTS); + tty_wakeup(tty); + } + } else if (!(header & ISI_CTS)) { + tty->hw_stopped = 1; + /* stop tx ing */ + port->status &= ~(ISI_TXOK | ISI_CTS); + } + } else { + if (header & ISI_CTS) + port->status |= ISI_CTS; + else + port->status &= ~ISI_CTS; + } + + if (header & ISI_DSR) + port->status |= ISI_DSR; + else + port->status &= ~ISI_DSR; + + if (header & ISI_RI) + port->status |= ISI_RI; + else + port->status &= ~ISI_RI; + + break; + + case 1: /* Received Break !!! */ + tty_insert_flip_char(tty, 0, TTY_BREAK); + if (port->port.flags & ASYNC_SAK) + do_SAK(tty); + tty_flip_buffer_push(tty); + break; + + case 2: /* Statistics */ + pr_debug("%s: stats!!!\n", __func__); + break; + + default: + pr_debug("%s: Unknown code in status packet.\n", + __func__); + break; + } + } else { /* Data Packet */ + + count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); + pr_debug("%s: Can rx %d of %d bytes.\n", + __func__, count, byte_count); + word_count = count >> 1; + insw(base, rp, word_count); + byte_count -= (word_count << 1); + if (count & 0x0001) { + tty_insert_flip_char(tty, inw(base) & 0xff, + TTY_NORMAL); + byte_count -= 2; + } + if (byte_count > 0) { + pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n", + __func__, base, channel + 1); + /* drain out unread xtra data */ + while (byte_count > 0) { + inw(base); + byte_count -= 2; + } + } + tty_flip_buffer_push(tty); + } + outw(0x0000, base+0x04); /* enable interrupts */ + spin_unlock(&card->card_lock); + tty_kref_put(tty); + + return IRQ_HANDLED; +} + +static void isicom_config_port(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + unsigned long baud; + unsigned long base = card->base; + u16 channel_setup, channel = port->channel, + shift_count = card->shift_count; + unsigned char flow_ctrl; + + /* FIXME: Switch to new tty baud API */ + baud = C_BAUD(tty); + if (baud & CBAUDEX) { + baud &= ~CBAUDEX; + + /* if CBAUDEX bit is on and the baud is set to either 50 or 75 + * then the card is programmed for 57.6Kbps or 115Kbps + * respectively. + */ + + /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ + if (baud < 1 || baud > 4) + tty->termios->c_cflag &= ~CBAUDEX; + else + baud += 15; + } + if (baud == 15) { + + /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set + * by the set_serial_info ioctl ... this is done by + * the 'setserial' utility. + */ + + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baud++; /* 57.6 Kbps */ + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baud += 2; /* 115 Kbps */ + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + baud += 3; /* 230 kbps*/ + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + baud += 4; /* 460 kbps*/ + } + if (linuxb_to_isib[baud] == -1) { + /* hang up */ + drop_dtr(port); + return; + } else + raise_dtr(port); + + if (WaitTillCardIsFree(base) == 0) { + outw(0x8000 | (channel << shift_count) | 0x03, base); + outw(linuxb_to_isib[baud] << 8 | 0x03, base); + channel_setup = 0; + switch (C_CSIZE(tty)) { + case CS5: + channel_setup |= ISICOM_CS5; + break; + case CS6: + channel_setup |= ISICOM_CS6; + break; + case CS7: + channel_setup |= ISICOM_CS7; + break; + case CS8: + channel_setup |= ISICOM_CS8; + break; + } + + if (C_CSTOPB(tty)) + channel_setup |= ISICOM_2SB; + if (C_PARENB(tty)) { + channel_setup |= ISICOM_EVPAR; + if (C_PARODD(tty)) + channel_setup |= ISICOM_ODPAR; + } + outw(channel_setup, base); + InterruptTheCard(base); + } + if (C_CLOCAL(tty)) + port->port.flags &= ~ASYNC_CHECK_CD; + else + port->port.flags |= ASYNC_CHECK_CD; + + /* flow control settings ...*/ + flow_ctrl = 0; + port->port.flags &= ~ASYNC_CTS_FLOW; + if (C_CRTSCTS(tty)) { + port->port.flags |= ASYNC_CTS_FLOW; + flow_ctrl |= ISICOM_CTSRTS; + } + if (I_IXON(tty)) + flow_ctrl |= ISICOM_RESPOND_XONXOFF; + if (I_IXOFF(tty)) + flow_ctrl |= ISICOM_INITIATE_XONXOFF; + + if (WaitTillCardIsFree(base) == 0) { + outw(0x8000 | (channel << shift_count) | 0x04, base); + outw(flow_ctrl << 8 | 0x05, base); + outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base); + InterruptTheCard(base); + } + + /* rx enabled -> enable port for rx on the card */ + if (C_CREAD(tty)) { + card->port_status |= (1 << channel); + outw(card->port_status, base + 0x02); + } +} + +/* open et all */ + +static inline void isicom_setup_board(struct isi_board *bp) +{ + int channel; + struct isi_port *port; + + bp->count++; + if (!(bp->status & BOARD_INIT)) { + port = bp->ports; + for (channel = 0; channel < bp->port_count; channel++, port++) + drop_dtr_rts(port); + } + bp->status |= BOARD_ACTIVE | BOARD_INIT; +} + +/* Activate and thus setup board are protected from races against shutdown + by the tty_port mutex */ + +static int isicom_activate(struct tty_port *tport, struct tty_struct *tty) +{ + struct isi_port *port = container_of(tport, struct isi_port, port); + struct isi_board *card = port->card; + unsigned long flags; + + if (tty_port_alloc_xmit_buf(tport) < 0) + return -ENOMEM; + + spin_lock_irqsave(&card->card_lock, flags); + isicom_setup_board(card); + + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + + /* discard any residual data */ + if (WaitTillCardIsFree(card->base) == 0) { + outw(0x8000 | (port->channel << card->shift_count) | 0x02, + card->base); + outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); + InterruptTheCard(card->base); + } + isicom_config_port(tty); + spin_unlock_irqrestore(&card->card_lock, flags); + + return 0; +} + +static int isicom_carrier_raised(struct tty_port *port) +{ + struct isi_port *ip = container_of(port, struct isi_port, port); + return (ip->status & ISI_DCD)?1 : 0; +} + +static struct tty_port *isicom_find_port(struct tty_struct *tty) +{ + struct isi_port *port; + struct isi_board *card; + unsigned int board; + int line = tty->index; + + if (line < 0 || line > PORT_COUNT-1) + return NULL; + board = BOARD(line); + card = &isi_card[board]; + + if (!(card->status & FIRMWARE_LOADED)) + return NULL; + + /* open on a port greater than the port count for the card !!! */ + if (line > ((board * 16) + card->port_count - 1)) + return NULL; + + port = &isi_ports[line]; + if (isicom_paranoia_check(port, tty->name, "isicom_open")) + return NULL; + + return &port->port; +} + +static int isicom_open(struct tty_struct *tty, struct file *filp) +{ + struct isi_port *port; + struct tty_port *tport; + + tport = isicom_find_port(tty); + if (tport == NULL) + return -ENODEV; + port = container_of(tport, struct isi_port, port); + + tty->driver_data = port; + return tty_port_open(tport, tty, filp); +} + +/* close et all */ + +/* card->lock HAS to be held */ +static void isicom_shutdown_port(struct isi_port *port) +{ + struct isi_board *card = port->card; + + if (--card->count < 0) { + pr_debug("%s: bad board(0x%lx) count %d.\n", + __func__, card->base, card->count); + card->count = 0; + } + /* last port was closed, shutdown that board too */ + if (!card->count) + card->status &= BOARD_ACTIVE; +} + +static void isicom_flush_buffer(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + unsigned long flags; + + if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer")) + return; + + spin_lock_irqsave(&card->card_lock, flags); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + spin_unlock_irqrestore(&card->card_lock, flags); + + tty_wakeup(tty); +} + +static void isicom_shutdown(struct tty_port *port) +{ + struct isi_port *ip = container_of(port, struct isi_port, port); + struct isi_board *card = ip->card; + unsigned long flags; + + /* indicate to the card that no more data can be received + on this port */ + spin_lock_irqsave(&card->card_lock, flags); + card->port_status &= ~(1 << ip->channel); + outw(card->port_status, card->base + 0x02); + isicom_shutdown_port(ip); + spin_unlock_irqrestore(&card->card_lock, flags); + tty_port_free_xmit_buf(port); +} + +static void isicom_close(struct tty_struct *tty, struct file *filp) +{ + struct isi_port *ip = tty->driver_data; + struct tty_port *port; + + if (ip == NULL) + return; + + port = &ip->port; + if (isicom_paranoia_check(ip, tty->name, "isicom_close")) + return; + tty_port_close(port, tty, filp); +} + +/* write et all */ +static int isicom_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + unsigned long flags; + int cnt, total = 0; + + if (isicom_paranoia_check(port, tty->name, "isicom_write")) + return 0; + + spin_lock_irqsave(&card->card_lock, flags); + + while (1) { + cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt + - 1, SERIAL_XMIT_SIZE - port->xmit_head)); + if (cnt <= 0) + break; + + memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt); + port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE + - 1); + port->xmit_cnt += cnt; + buf += cnt; + count -= cnt; + total += cnt; + } + if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped) + port->status |= ISI_TXOK; + spin_unlock_irqrestore(&card->card_lock, flags); + return total; +} + +/* put_char et all */ +static int isicom_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + unsigned long flags; + + if (isicom_paranoia_check(port, tty->name, "isicom_put_char")) + return 0; + + spin_lock_irqsave(&card->card_lock, flags); + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + spin_unlock_irqrestore(&card->card_lock, flags); + return 0; + } + + port->port.xmit_buf[port->xmit_head++] = ch; + port->xmit_head &= (SERIAL_XMIT_SIZE - 1); + port->xmit_cnt++; + spin_unlock_irqrestore(&card->card_lock, flags); + return 1; +} + +/* flush_chars et all */ +static void isicom_flush_chars(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + + if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars")) + return; + + if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !port->port.xmit_buf) + return; + + /* this tells the transmitter to consider this port for + data output to the card ... that's the best we can do. */ + port->status |= ISI_TXOK; +} + +/* write_room et all */ +static int isicom_write_room(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + int free; + + if (isicom_paranoia_check(port, tty->name, "isicom_write_room")) + return 0; + + free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; + if (free < 0) + free = 0; + return free; +} + +/* chars_in_buffer et all */ +static int isicom_chars_in_buffer(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer")) + return 0; + return port->xmit_cnt; +} + +/* ioctl et all */ +static int isicom_send_break(struct tty_struct *tty, int length) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + unsigned long base = card->base; + + if (length == -1) + return -EOPNOTSUPP; + + if (!lock_card(card)) + return -EINVAL; + + outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base); + outw((length & 0xff) << 8 | 0x00, base); + outw((length & 0xff00), base); + InterruptTheCard(base); + + unlock_card(card); + return 0; +} + +static int isicom_tiocmget(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + /* just send the port status */ + u16 status = port->status; + + if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) + return -ENODEV; + + return ((status & ISI_RTS) ? TIOCM_RTS : 0) | + ((status & ISI_DTR) ? TIOCM_DTR : 0) | + ((status & ISI_DCD) ? TIOCM_CAR : 0) | + ((status & ISI_DSR) ? TIOCM_DSR : 0) | + ((status & ISI_CTS) ? TIOCM_CTS : 0) | + ((status & ISI_RI ) ? TIOCM_RI : 0); +} + +static int isicom_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct isi_port *port = tty->driver_data; + unsigned long flags; + + if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) + return -ENODEV; + + spin_lock_irqsave(&port->card->card_lock, flags); + if (set & TIOCM_RTS) + raise_rts(port); + if (set & TIOCM_DTR) + raise_dtr(port); + + if (clear & TIOCM_RTS) + drop_rts(port); + if (clear & TIOCM_DTR) + drop_dtr(port); + spin_unlock_irqrestore(&port->card->card_lock, flags); + + return 0; +} + +static int isicom_set_serial_info(struct tty_struct *tty, + struct serial_struct __user *info) +{ + struct isi_port *port = tty->driver_data; + struct serial_struct newinfo; + int reconfig_port; + + if (copy_from_user(&newinfo, info, sizeof(newinfo))) + return -EFAULT; + + mutex_lock(&port->port.mutex); + reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != + (newinfo.flags & ASYNC_SPD_MASK)); + + if (!capable(CAP_SYS_ADMIN)) { + if ((newinfo.close_delay != port->port.close_delay) || + (newinfo.closing_wait != port->port.closing_wait) || + ((newinfo.flags & ~ASYNC_USR_MASK) != + (port->port.flags & ~ASYNC_USR_MASK))) { + mutex_unlock(&port->port.mutex); + return -EPERM; + } + port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | + (newinfo.flags & ASYNC_USR_MASK)); + } else { + port->port.close_delay = newinfo.close_delay; + port->port.closing_wait = newinfo.closing_wait; + port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | + (newinfo.flags & ASYNC_FLAGS)); + } + if (reconfig_port) { + unsigned long flags; + spin_lock_irqsave(&port->card->card_lock, flags); + isicom_config_port(tty); + spin_unlock_irqrestore(&port->card->card_lock, flags); + } + mutex_unlock(&port->port.mutex); + return 0; +} + +static int isicom_get_serial_info(struct isi_port *port, + struct serial_struct __user *info) +{ + struct serial_struct out_info; + + mutex_lock(&port->port.mutex); + memset(&out_info, 0, sizeof(out_info)); +/* out_info.type = ? */ + out_info.line = port - isi_ports; + out_info.port = port->card->base; + out_info.irq = port->card->irq; + out_info.flags = port->port.flags; +/* out_info.baud_base = ? */ + out_info.close_delay = port->port.close_delay; + out_info.closing_wait = port->port.closing_wait; + mutex_unlock(&port->port.mutex); + if (copy_to_user(info, &out_info, sizeof(out_info))) + return -EFAULT; + return 0; +} + +static int isicom_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct isi_port *port = tty->driver_data; + void __user *argp = (void __user *)arg; + + if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) + return -ENODEV; + + switch (cmd) { + case TIOCGSERIAL: + return isicom_get_serial_info(port, argp); + + case TIOCSSERIAL: + return isicom_set_serial_info(tty, argp); + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* set_termios et all */ +static void isicom_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) +{ + struct isi_port *port = tty->driver_data; + unsigned long flags; + + if (isicom_paranoia_check(port, tty->name, "isicom_set_termios")) + return; + + if (tty->termios->c_cflag == old_termios->c_cflag && + tty->termios->c_iflag == old_termios->c_iflag) + return; + + spin_lock_irqsave(&port->card->card_lock, flags); + isicom_config_port(tty); + spin_unlock_irqrestore(&port->card->card_lock, flags); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + isicom_start(tty); + } +} + +/* throttle et all */ +static void isicom_throttle(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + + if (isicom_paranoia_check(port, tty->name, "isicom_throttle")) + return; + + /* tell the card that this port cannot handle any more data for now */ + card->port_status &= ~(1 << port->channel); + outw(card->port_status, card->base + 0x02); +} + +/* unthrottle et all */ +static void isicom_unthrottle(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + struct isi_board *card = port->card; + + if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle")) + return; + + /* tell the card that this port is ready to accept more data */ + card->port_status |= (1 << port->channel); + outw(card->port_status, card->base + 0x02); +} + +/* stop et all */ +static void isicom_stop(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + + if (isicom_paranoia_check(port, tty->name, "isicom_stop")) + return; + + /* this tells the transmitter not to consider this port for + data output to the card. */ + port->status &= ~ISI_TXOK; +} + +/* start et all */ +static void isicom_start(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + + if (isicom_paranoia_check(port, tty->name, "isicom_start")) + return; + + /* this tells the transmitter to consider this port for + data output to the card. */ + port->status |= ISI_TXOK; +} + +static void isicom_hangup(struct tty_struct *tty) +{ + struct isi_port *port = tty->driver_data; + + if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) + return; + tty_port_hangup(&port->port); +} + + +/* + * Driver init and deinit functions + */ + +static const struct tty_operations isicom_ops = { + .open = isicom_open, + .close = isicom_close, + .write = isicom_write, + .put_char = isicom_put_char, + .flush_chars = isicom_flush_chars, + .write_room = isicom_write_room, + .chars_in_buffer = isicom_chars_in_buffer, + .ioctl = isicom_ioctl, + .set_termios = isicom_set_termios, + .throttle = isicom_throttle, + .unthrottle = isicom_unthrottle, + .stop = isicom_stop, + .start = isicom_start, + .hangup = isicom_hangup, + .flush_buffer = isicom_flush_buffer, + .tiocmget = isicom_tiocmget, + .tiocmset = isicom_tiocmset, + .break_ctl = isicom_send_break, +}; + +static const struct tty_port_operations isicom_port_ops = { + .carrier_raised = isicom_carrier_raised, + .dtr_rts = isicom_dtr_rts, + .activate = isicom_activate, + .shutdown = isicom_shutdown, +}; + +static int __devinit reset_card(struct pci_dev *pdev, + const unsigned int card, unsigned int *signature) +{ + struct isi_board *board = pci_get_drvdata(pdev); + unsigned long base = board->base; + unsigned int sig, portcount = 0; + int retval = 0; + + dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, + base); + + inw(base + 0x8); + + msleep(10); + + outw(0, base + 0x8); /* Reset */ + + msleep(1000); + + 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 && portcount != 16)) { + dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n", + card + 1); + retval = -EIO; + goto end; + } + + switch (sig) { + case 0xa5: + case 0xbb: + case 0xdd: + board->port_count = (portcount == 4) ? 4 : 8; + board->shift_count = 12; + break; + case 0xcc: + case 0xee: + board->port_count = 16; + board->shift_count = 11; + break; + } + dev_info(&pdev->dev, "-Done\n"); + *signature = sig; + +end: + return retval; +} + +static int __devinit load_firmware(struct pci_dev *pdev, + const unsigned int index, const unsigned int signature) +{ + struct isi_board *board = pci_get_drvdata(pdev); + const struct firmware *fw; + unsigned long base = board->base; + unsigned int a; + u16 word_count, status; + int retval = -EIO; + char *name; + u8 *data; + + struct stframe { + u16 addr; + u16 count; + u8 data[0]; + } *frame; + + switch (signature) { + case 0xa5: + name = "isi608.bin"; + break; + case 0xbb: + name = "isi608em.bin"; + break; + case 0xcc: + name = "isi616em.bin"; + break; + case 0xdd: + name = "isi4608.bin"; + break; + case 0xee: + name = "isi4616.bin"; + break; + default: + dev_err(&pdev->dev, "Unknown signature.\n"); + goto end; + } + + retval = request_firmware(&fw, name, &pdev->dev); + if (retval) + goto end; + + retval = -EIO; + + for (frame = (struct stframe *)fw->data; + frame < (struct stframe *)(fw->data + fw->size); + frame = (struct stframe *)((u8 *)(frame + 1) + + frame->count)) { + if (WaitTillCardIsFree(base)) + goto errrelfw; + + outw(0xf0, base); /* start upload sequence */ + outw(0x00, base); + outw(frame->addr, base); /* lsb of address */ + + word_count = frame->count / 2 + frame->count % 2; + outw(word_count, base); + InterruptTheCard(base); + + udelay(100); /* 0x2f */ + + if (WaitTillCardIsFree(base)) + goto errrelfw; + + status = inw(base + 0x4); + if (status != 0) { + dev_warn(&pdev->dev, "Card%d rejected load header:\n" + "Address:0x%x\n" + "Count:0x%x\n" + "Status:0x%x\n", + index + 1, frame->addr, frame->count, status); + goto errrelfw; + } + outsw(base, frame->data, word_count); + + InterruptTheCard(base); + + udelay(50); /* 0x0f */ + + if (WaitTillCardIsFree(base)) + goto errrelfw; + + status = inw(base + 0x4); + if (status != 0) { + dev_err(&pdev->dev, "Card%d got out of sync.Card " + "Status:0x%x\n", index + 1, status); + goto errrelfw; + } + } + +/* XXX: should we test it by reading it back and comparing with original like + * in load firmware package? */ + for (frame = (struct stframe *)fw->data; + frame < (struct stframe *)(fw->data + fw->size); + frame = (struct stframe *)((u8 *)(frame + 1) + + frame->count)) { + if (WaitTillCardIsFree(base)) + goto errrelfw; + + outw(0xf1, base); /* start download sequence */ + outw(0x00, base); + outw(frame->addr, base); /* lsb of address */ + + word_count = (frame->count >> 1) + frame->count % 2; + outw(word_count + 1, base); + InterruptTheCard(base); + + udelay(50); /* 0xf */ + + if (WaitTillCardIsFree(base)) + goto errrelfw; + + status = inw(base + 0x4); + if (status != 0) { + dev_warn(&pdev->dev, "Card%d rejected verify header:\n" + "Address:0x%x\n" + "Count:0x%x\n" + "Status: 0x%x\n", + index + 1, frame->addr, frame->count, status); + goto errrelfw; + } + + data = kmalloc(word_count * 2, GFP_KERNEL); + if (data == NULL) { + dev_err(&pdev->dev, "Card%d, firmware upload " + "failed, not enough memory\n", index + 1); + goto errrelfw; + } + inw(base); + insw(base, data, word_count); + InterruptTheCard(base); + + for (a = 0; a < frame->count; a++) + if (data[a] != frame->data[a]) { + kfree(data); + dev_err(&pdev->dev, "Card%d, firmware upload " + "failed\n", index + 1); + goto errrelfw; + } + kfree(data); + + udelay(50); /* 0xf */ + + if (WaitTillCardIsFree(base)) + goto errrelfw; + + status = inw(base + 0x4); + if (status != 0) { + dev_err(&pdev->dev, "Card%d verify got out of sync. " + "Card Status:0x%x\n", index + 1, status); + goto errrelfw; + } + } + + /* xfer ctrl */ + if (WaitTillCardIsFree(base)) + goto errrelfw; + + outw(0xf2, base); + outw(0x800, base); + outw(0x0, base); + outw(0x0, base); + InterruptTheCard(base); + outw(0x0, base + 0x4); /* for ISI4608 cards */ + + board->status |= FIRMWARE_LOADED; + retval = 0; + +errrelfw: + release_firmware(fw); +end: + return retval; +} + +/* + * Insmod can set static symbols so keep these static + */ +static unsigned int card_count; + +static int __devinit isicom_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + unsigned int uninitialized_var(signature), index; + int retval = -EPERM; + struct isi_board *board = NULL; + + if (card_count >= BOARD_COUNT) + goto err; + + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "failed to enable\n"); + goto err; + } + + dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); + + /* allot the first empty slot in the array */ + for (index = 0; index < BOARD_COUNT; index++) { + if (isi_card[index].base == 0) { + board = &isi_card[index]; + break; + } + } + if (index == BOARD_COUNT) { + retval = -ENODEV; + goto err_disable; + } + + board->index = index; + board->base = pci_resource_start(pdev, 3); + board->irq = pdev->irq; + card_count++; + + pci_set_drvdata(pdev, board); + + retval = pci_request_region(pdev, 3, ISICOM_NAME); + if (retval) { + dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " + "will be disabled.\n", board->base, board->base + 15, + index + 1); + retval = -EBUSY; + goto errdec; + } + + retval = request_irq(board->irq, isicom_interrupt, + IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); + if (retval < 0) { + dev_err(&pdev->dev, "Could not install handler at Irq %d. " + "Card%d will be disabled.\n", board->irq, index + 1); + goto errunrr; + } + + retval = reset_card(pdev, index, &signature); + if (retval < 0) + goto errunri; + + retval = load_firmware(pdev, index, signature); + if (retval < 0) + goto errunri; + + for (index = 0; index < board->port_count; index++) + tty_register_device(isicom_normal, board->index * 16 + index, + &pdev->dev); + + return 0; + +errunri: + free_irq(board->irq, board); +errunrr: + pci_release_region(pdev, 3); +errdec: + board->base = 0; + card_count--; +err_disable: + pci_disable_device(pdev); +err: + return retval; +} + +static void __devexit isicom_remove(struct pci_dev *pdev) +{ + struct isi_board *board = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < board->port_count; i++) + tty_unregister_device(isicom_normal, board->index * 16 + i); + + free_irq(board->irq, board); + pci_release_region(pdev, 3); + board->base = 0; + card_count--; + pci_disable_device(pdev); +} + +static int __init isicom_init(void) +{ + int retval, idx, channel; + struct isi_port *port; + + for (idx = 0; idx < BOARD_COUNT; idx++) { + port = &isi_ports[idx * 16]; + isi_card[idx].ports = port; + spin_lock_init(&isi_card[idx].card_lock); + for (channel = 0; channel < 16; channel++, port++) { + tty_port_init(&port->port); + port->port.ops = &isicom_port_ops; + port->magic = ISICOM_MAGIC; + port->card = &isi_card[idx]; + port->channel = channel; + port->port.close_delay = 50 * HZ/100; + port->port.closing_wait = 3000 * HZ/100; + port->status = 0; + /* . . . */ + } + isi_card[idx].base = 0; + isi_card[idx].irq = 0; + } + + /* tty driver structure initialization */ + isicom_normal = alloc_tty_driver(PORT_COUNT); + if (!isicom_normal) { + retval = -ENOMEM; + goto error; + } + + isicom_normal->owner = THIS_MODULE; + isicom_normal->name = "ttyM"; + isicom_normal->major = ISICOM_NMAJOR; + isicom_normal->minor_start = 0; + isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; + isicom_normal->subtype = SERIAL_TYPE_NORMAL; + isicom_normal->init_termios = tty_std_termios; + isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | + CLOCAL; + isicom_normal->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK; + tty_set_operations(isicom_normal, &isicom_ops); + + retval = tty_register_driver(isicom_normal); + if (retval) { + pr_debug("Couldn't register the dialin driver\n"); + goto err_puttty; + } + + retval = pci_register_driver(&isicom_driver); + if (retval < 0) { + pr_err("Unable to register pci driver.\n"); + goto err_unrtty; + } + + mod_timer(&tx, jiffies + 1); + + return 0; +err_unrtty: + tty_unregister_driver(isicom_normal); +err_puttty: + put_tty_driver(isicom_normal); +error: + return retval; +} + +static void __exit isicom_exit(void) +{ + del_timer_sync(&tx); + + pci_unregister_driver(&isicom_driver); + tty_unregister_driver(isicom_normal); + put_tty_driver(isicom_normal); +} + +module_init(isicom_init); +module_exit(isicom_exit); + +MODULE_AUTHOR("MultiTech"); +MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("isi608.bin"); +MODULE_FIRMWARE("isi608em.bin"); +MODULE_FIRMWARE("isi616em.bin"); +MODULE_FIRMWARE("isi4608.bin"); +MODULE_FIRMWARE("isi4616.bin"); diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c new file mode 100644 index 000000000000..35b0c38590e6 --- /dev/null +++ b/drivers/tty/moxa.c @@ -0,0 +1,2092 @@ +/*****************************************************************************/ +/* + * moxa.c -- MOXA Intellio family multiport serial driver. + * + * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com). + * Copyright (c) 2007 Jiri Slaby + * + * This code is loosely based on the Linux serial driver, written by + * Linus Torvalds, Theodore T'so and others. + * + * 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. + */ + +/* + * MOXA Intellio Series Driver + * for : LINUX + * date : 1999/1/7 + * version : 5.1 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "moxa.h" + +#define MOXA_VERSION "6.0k" + +#define MOXA_FW_HDRLEN 32 + +#define MOXAMAJOR 172 + +#define MAX_BOARDS 4 /* Don't change this value */ +#define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ +#define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) + +#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \ + (brd)->boardType == MOXA_BOARD_C320_PCI) + +/* + * Define the Moxa PCI vendor and device IDs. + */ +#define MOXA_BUS_TYPE_ISA 0 +#define MOXA_BUS_TYPE_PCI 1 + +enum { + MOXA_BOARD_C218_PCI = 1, + MOXA_BOARD_C218_ISA, + MOXA_BOARD_C320_PCI, + MOXA_BOARD_C320_ISA, + MOXA_BOARD_CP204J, +}; + +static char *moxa_brdname[] = +{ + "C218 Turbo PCI series", + "C218 Turbo ISA series", + "C320 Turbo PCI series", + "C320 Turbo ISA series", + "CP-204J series", +}; + +#ifdef CONFIG_PCI +static struct pci_device_id moxa_pcibrds[] = { + { 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 */ + +struct moxa_port; + +static struct moxa_board_conf { + int boardType; + int numPorts; + int busType; + + unsigned int ready; + + struct moxa_port *ports; + + 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_port { + struct tty_port port; + struct moxa_board_conf *board; + void __iomem *tableAddr; + + int type; + int cflag; + unsigned long statusflags; + + u8 DCDState; /* Protected by the port lock */ + u8 lineCtrl; + u8 lowChkFlag; +}; + +struct mon_str { + int tick; + int rxcnt[MAX_PORTS]; + int txcnt[MAX_PORTS]; +}; + +/* statusflags */ +#define TXSTOPPED 1 +#define LOWWAIT 2 +#define EMPTYWAIT 3 + +#define SERIAL_DO_RESTART + +#define WAKEUP_CHARS 256 + +static int ttymajor = MOXAMAJOR; +static struct mon_str moxaLog; +static unsigned int moxaFuncTout = HZ / 2; +static unsigned int moxaLowWaterChk; +static DEFINE_MUTEX(moxa_openlock); +static DEFINE_SPINLOCK(moxa_lock); + +static unsigned long baseaddr[MAX_BOARDS]; +static unsigned int type[MAX_BOARDS]; +static unsigned int numports[MAX_BOARDS]; + +MODULE_AUTHOR("William Chen"); +MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("c218tunx.cod"); +MODULE_FIRMWARE("cp204unx.cod"); +MODULE_FIRMWARE("c320tunx.cod"); + +module_param_array(type, uint, NULL, 0); +MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); +module_param_array(baseaddr, ulong, NULL, 0); +MODULE_PARM_DESC(baseaddr, "base address"); +module_param_array(numports, uint, NULL, 0); +MODULE_PARM_DESC(numports, "numports (ignored for C218)"); + +module_param(ttymajor, int, 0); + +/* + * static functions: + */ +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); +static int moxa_write_room(struct tty_struct *); +static void moxa_flush_buffer(struct tty_struct *); +static int moxa_chars_in_buffer(struct tty_struct *); +static void moxa_set_termios(struct tty_struct *, struct ktermios *); +static void moxa_stop(struct tty_struct *); +static void moxa_start(struct tty_struct *); +static void moxa_hangup(struct tty_struct *); +static int moxa_tiocmget(struct tty_struct *tty); +static int moxa_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); +static void moxa_poll(unsigned long); +static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); +static void moxa_shutdown(struct tty_port *); +static int moxa_carrier_raised(struct tty_port *); +static void moxa_dtr_rts(struct tty_port *, int); +/* + * moxa board interface functions: + */ +static void MoxaPortEnable(struct moxa_port *); +static void MoxaPortDisable(struct moxa_port *); +static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t); +static int MoxaPortGetLineOut(struct moxa_port *, int *, int *); +static void MoxaPortLineCtrl(struct moxa_port *, int, int); +static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); +static int MoxaPortLineStatus(struct moxa_port *); +static void MoxaPortFlushData(struct moxa_port *, int); +static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int); +static int MoxaPortReadData(struct moxa_port *); +static int MoxaPortTxQueue(struct moxa_port *); +static int MoxaPortRxQueue(struct moxa_port *); +static int MoxaPortTxFree(struct moxa_port *); +static void MoxaPortTxDisable(struct moxa_port *); +static void MoxaPortTxEnable(struct moxa_port *); +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(struct moxa_port *port, int enable); + +/* + * I/O functions + */ + +static DEFINE_SPINLOCK(moxafunc_lock); + +static void moxa_wait_finish(void __iomem *ofsAddr) +{ + unsigned long end = jiffies + moxaFuncTout; + + while (readw(ofsAddr + FuncCode) != 0) + if (time_after(jiffies, end)) + return; + if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit()) + printk(KERN_WARNING "moxa function expired\n"); +} + +static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) +{ + unsigned long flags; + spin_lock_irqsave(&moxafunc_lock, flags); + writew(arg, ofsAddr + FuncArg); + writew(cmd, ofsAddr + FuncCode); + moxa_wait_finish(ofsAddr); + spin_unlock_irqrestore(&moxafunc_lock, flags); +} + +static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) +{ + unsigned long flags; + u16 ret; + spin_lock_irqsave(&moxafunc_lock, flags); + writew(arg, ofsAddr + FuncArg); + writew(cmd, ofsAddr + FuncCode); + moxa_wait_finish(ofsAddr); + ret = readw(ofsAddr + FuncArg); + spin_unlock_irqrestore(&moxafunc_lock, flags); + return ret; +} + +static void moxa_low_water_check(void __iomem *ofsAddr) +{ + u16 rptr, wptr, mask, len; + + if (readb(ofsAddr + FlagStat) & Xoff_state) { + rptr = readw(ofsAddr + RXrptr); + wptr = readw(ofsAddr + RXwptr); + mask = readw(ofsAddr + RX_mask); + len = (wptr - rptr) & mask; + if (len <= Low_water) + moxafunc(ofsAddr, FC_SendXon, 0); + } +} + +/* + * TTY operations + */ + +static int moxa_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct moxa_port *ch = tty->driver_data; + void __user *argp = (void __user *)arg; + int status, ret = 0; + + if (tty->index == MAX_PORTS) { + if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE && + cmd != MOXA_GETMSTATUS) + return -EINVAL; + } else if (!ch) + return -ENODEV; + + switch (cmd) { + case MOXA_GETDATACOUNT: + moxaLog.tick = jiffies; + if (copy_to_user(argp, &moxaLog, sizeof(moxaLog))) + ret = -EFAULT; + break; + case MOXA_FLUSH_QUEUE: + MoxaPortFlushData(ch, arg); + break; + case MOXA_GET_IOQUEUE: { + struct moxaq_str __user *argm = argp; + struct moxaq_str tmp; + struct moxa_port *p; + unsigned int i, j; + + for (i = 0; i < MAX_BOARDS; i++) { + p = moxa_boards[i].ports; + for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { + memset(&tmp, 0, sizeof(tmp)); + spin_lock_bh(&moxa_lock); + if (moxa_boards[i].ready) { + tmp.inq = MoxaPortRxQueue(p); + tmp.outq = MoxaPortTxQueue(p); + } + spin_unlock_bh(&moxa_lock); + if (copy_to_user(argm, &tmp, sizeof(tmp))) + return -EFAULT; + } + } + break; + } case MOXA_GET_OQUEUE: + status = MoxaPortTxQueue(ch); + ret = put_user(status, (unsigned long __user *)argp); + break; + case MOXA_GET_IQUEUE: + status = MoxaPortRxQueue(ch); + ret = put_user(status, (unsigned long __user *)argp); + break; + case MOXA_GETMSTATUS: { + struct mxser_mstatus __user *argm = argp; + struct mxser_mstatus tmp; + struct moxa_port *p; + unsigned int i, j; + + for (i = 0; i < MAX_BOARDS; i++) { + p = moxa_boards[i].ports; + for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { + struct tty_struct *ttyp; + memset(&tmp, 0, sizeof(tmp)); + spin_lock_bh(&moxa_lock); + if (!moxa_boards[i].ready) { + spin_unlock_bh(&moxa_lock); + goto copy; + } + + status = MoxaPortLineStatus(p); + spin_unlock_bh(&moxa_lock); + + if (status & 1) + tmp.cts = 1; + if (status & 2) + tmp.dsr = 1; + if (status & 4) + tmp.dcd = 1; + + ttyp = tty_port_tty_get(&p->port); + if (!ttyp || !ttyp->termios) + tmp.cflag = p->cflag; + else + tmp.cflag = ttyp->termios->c_cflag; + tty_kref_put(tty); +copy: + if (copy_to_user(argm, &tmp, sizeof(tmp))) + return -EFAULT; + } + } + break; + } + case TIOCGSERIAL: + mutex_lock(&ch->port.mutex); + ret = moxa_get_serial_info(ch, argp); + mutex_unlock(&ch->port.mutex); + break; + case TIOCSSERIAL: + mutex_lock(&ch->port.mutex); + ret = moxa_set_serial_info(ch, argp); + mutex_unlock(&ch->port.mutex); + break; + default: + ret = -ENOIOCTLCMD; + } + return ret; +} + +static int moxa_break_ctl(struct tty_struct *tty, int state) +{ + struct moxa_port *port = tty->driver_data; + + moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, + Magic_code); + return 0; +} + +static const struct tty_operations moxa_ops = { + .open = moxa_open, + .close = moxa_close, + .write = moxa_write, + .write_room = moxa_write_room, + .flush_buffer = moxa_flush_buffer, + .chars_in_buffer = moxa_chars_in_buffer, + .ioctl = moxa_ioctl, + .set_termios = moxa_set_termios, + .stop = moxa_stop, + .start = moxa_start, + .hangup = moxa_hangup, + .break_ctl = moxa_break_ctl, + .tiocmget = moxa_tiocmget, + .tiocmset = moxa_tiocmset, +}; + +static const struct tty_port_operations moxa_port_ops = { + .carrier_raised = moxa_carrier_raised, + .dtr_rts = moxa_dtr_rts, + .shutdown = moxa_shutdown, +}; + +static struct tty_driver *moxaDriver; +static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); + +/* + * HW init + */ + +static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) +{ + switch (brd->boardType) { + case MOXA_BOARD_C218_ISA: + case MOXA_BOARD_C218_PCI: + if (model != 1) + goto err; + break; + case MOXA_BOARD_CP204J: + if (model != 3) + goto err; + break; + default: + if (model != 2) + goto err; + break; + } + return 0; +err: + return -EINVAL; +} + +static int moxa_check_fw(const void *ptr) +{ + const __le16 *lptr = ptr; + + if (*lptr != cpu_to_le16(0x7980)) + return -EINVAL; + + return 0; +} + +static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, + size_t len) +{ + void __iomem *baseAddr = brd->basemem; + u16 tmp; + + writeb(HW_reset, baseAddr + Control_reg); /* reset */ + msleep(10); + memset_io(baseAddr, 0, 4096); + memcpy_toio(baseAddr, buf, len); /* download BIOS */ + writeb(0, baseAddr + Control_reg); /* restart */ + + msleep(2000); + + switch (brd->boardType) { + case MOXA_BOARD_C218_ISA: + case MOXA_BOARD_C218_PCI: + tmp = readw(baseAddr + C218_key); + if (tmp != C218_KeyCode) + goto err; + break; + case MOXA_BOARD_CP204J: + tmp = readw(baseAddr + C218_key); + if (tmp != CP204J_KeyCode) + goto err; + break; + default: + tmp = readw(baseAddr + C320_key); + if (tmp != C320_KeyCode) + goto err; + tmp = readw(baseAddr + C320_status); + if (tmp != STS_init) { + printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic " + "module not found\n"); + return -EIO; + } + break; + } + + return 0; +err: + printk(KERN_ERR "MOXA: bios upload failed -- board not found\n"); + return -EIO; +} + +static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr, + size_t len) +{ + void __iomem *baseAddr = brd->basemem; + + if (len < 7168) { + printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n"); + return -EINVAL; + } + + writew(len - 7168 - 2, baseAddr + C320bapi_len); + writeb(1, baseAddr + Control_reg); /* Select Page 1 */ + memcpy_toio(baseAddr + DynPage_addr, ptr, 7168); + writeb(2, baseAddr + Control_reg); /* Select Page 2 */ + memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168); + + return 0; +} + +static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, + size_t len) +{ + void __iomem *baseAddr = brd->basemem; + const __le16 *uptr = ptr; + size_t wlen, len2, j; + unsigned long key, loadbuf, loadlen, checksum, checksum_ok; + unsigned int i, retry; + u16 usum, keycode; + + keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode : + C218_KeyCode; + + switch (brd->boardType) { + case MOXA_BOARD_CP204J: + case MOXA_BOARD_C218_ISA: + case MOXA_BOARD_C218_PCI: + key = C218_key; + loadbuf = C218_LoadBuf; + loadlen = C218DLoad_len; + checksum = C218check_sum; + checksum_ok = C218chksum_ok; + break; + default: + key = C320_key; + keycode = C320_KeyCode; + loadbuf = C320_LoadBuf; + loadlen = C320DLoad_len; + checksum = C320check_sum; + checksum_ok = C320chksum_ok; + break; + } + + usum = 0; + wlen = len >> 1; + for (i = 0; i < wlen; i++) + usum += le16_to_cpu(uptr[i]); + retry = 0; + do { + wlen = len >> 1; + j = 0; + while (wlen) { + len2 = (wlen > 2048) ? 2048 : wlen; + wlen -= len2; + memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1); + j += len2 << 1; + + writew(len2, baseAddr + loadlen); + writew(0, baseAddr + key); + for (i = 0; i < 100; i++) { + if (readw(baseAddr + key) == keycode) + break; + msleep(10); + } + if (readw(baseAddr + key) != keycode) + return -EIO; + } + writew(0, baseAddr + loadlen); + writew(usum, baseAddr + checksum); + writew(0, baseAddr + key); + for (i = 0; i < 100; i++) { + if (readw(baseAddr + key) == keycode) + break; + msleep(10); + } + retry++; + } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3)); + if (readb(baseAddr + checksum_ok) != 1) + return -EIO; + + writew(0, baseAddr + key); + for (i = 0; i < 600; i++) { + if (readw(baseAddr + Magic_no) == Magic_code) + break; + msleep(10); + } + if (readw(baseAddr + Magic_no) != Magic_code) + return -EIO; + + if (MOXA_IS_320(brd)) { + if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ + writew(0x3800, baseAddr + TMS320_PORT1); + writew(0x3900, baseAddr + TMS320_PORT2); + writew(28499, baseAddr + TMS320_CLOCK); + } else { + writew(0x3200, baseAddr + TMS320_PORT1); + writew(0x3400, baseAddr + TMS320_PORT2); + writew(19999, baseAddr + TMS320_CLOCK); + } + } + writew(1, baseAddr + Disable_IRQ); + writew(0, baseAddr + Magic_no); + for (i = 0; i < 500; i++) { + if (readw(baseAddr + Magic_no) == Magic_code) + break; + msleep(10); + } + if (readw(baseAddr + Magic_no) != Magic_code) + return -EIO; + + if (MOXA_IS_320(brd)) { + j = readw(baseAddr + Module_cnt); + if (j <= 0) + return -EIO; + brd->numPorts = j * 8; + writew(j, baseAddr + Module_no); + writew(0, baseAddr + Magic_no); + for (i = 0; i < 600; i++) { + if (readw(baseAddr + Magic_no) == Magic_code) + break; + msleep(10); + } + if (readw(baseAddr + Magic_no) != Magic_code) + return -EIO; + } + brd->intNdx = baseAddr + IRQindex; + brd->intPend = baseAddr + IRQpending; + brd->intTable = baseAddr + IRQtable; + + return 0; +} + +static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, + size_t len) +{ + void __iomem *ofsAddr, *baseAddr = brd->basemem; + struct moxa_port *port; + int retval, i; + + if (len % 2) { + printk(KERN_ERR "MOXA: bios length is not even\n"); + return -EINVAL; + } + + retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */ + if (retval) + return retval; + + switch (brd->boardType) { + case MOXA_BOARD_C218_ISA: + case MOXA_BOARD_C218_PCI: + case MOXA_BOARD_CP204J: + port = brd->ports; + for (i = 0; i < brd->numPorts; i++, port++) { + port->board = brd; + port->DCDState = 0; + port->tableAddr = baseAddr + Extern_table + + Extern_size * i; + ofsAddr = port->tableAddr; + writew(C218rx_mask, ofsAddr + RX_mask); + writew(C218tx_mask, ofsAddr + TX_mask); + writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); + writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); + + writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); + writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); + + } + break; + default: + port = brd->ports; + for (i = 0; i < brd->numPorts; i++, port++) { + port->board = brd; + port->DCDState = 0; + port->tableAddr = baseAddr + Extern_table + + Extern_size * i; + ofsAddr = port->tableAddr; + switch (brd->numPorts) { + case 8: + writew(C320p8rx_mask, ofsAddr + RX_mask); + writew(C320p8tx_mask, ofsAddr + TX_mask); + writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); + writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); + writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); + writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); + + break; + case 16: + writew(C320p16rx_mask, ofsAddr + RX_mask); + writew(C320p16tx_mask, ofsAddr + TX_mask); + writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); + writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); + writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); + writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); + break; + + case 24: + writew(C320p24rx_mask, ofsAddr + RX_mask); + writew(C320p24tx_mask, ofsAddr + TX_mask); + writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); + writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); + writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); + writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); + break; + case 32: + writew(C320p32rx_mask, ofsAddr + RX_mask); + writew(C320p32tx_mask, ofsAddr + TX_mask); + writew(C320p32tx_ofs, ofsAddr + Ofs_txb); + writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); + writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); + writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); + writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); + break; + } + } + break; + } + return 0; +} + +static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw) +{ + const void *ptr = fw->data; + char rsn[64]; + u16 lens[5]; + size_t len; + unsigned int a, lenp, lencnt; + int ret = -EINVAL; + struct { + __le32 magic; /* 0x34303430 */ + u8 reserved1[2]; + u8 type; /* UNIX = 3 */ + u8 model; /* C218T=1, C320T=2, CP204=3 */ + u8 reserved2[8]; + __le16 len[5]; + } const *hdr = ptr; + + BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens)); + + if (fw->size < MOXA_FW_HDRLEN) { + strcpy(rsn, "too short (even header won't fit)"); + goto err; + } + if (hdr->magic != cpu_to_le32(0x30343034)) { + sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic)); + goto err; + } + if (hdr->type != 3) { + sprintf(rsn, "not for linux, type is %u", hdr->type); + goto err; + } + if (moxa_check_fw_model(brd, hdr->model)) { + sprintf(rsn, "not for this card, model is %u", hdr->model); + goto err; + } + + len = MOXA_FW_HDRLEN; + lencnt = hdr->model == 2 ? 5 : 3; + for (a = 0; a < ARRAY_SIZE(lens); a++) { + lens[a] = le16_to_cpu(hdr->len[a]); + if (lens[a] && len + lens[a] <= fw->size && + moxa_check_fw(&fw->data[len])) + printk(KERN_WARNING "MOXA firmware: unexpected input " + "at offset %u, but going on\n", (u32)len); + if (!lens[a] && a < lencnt) { + sprintf(rsn, "too few entries in fw file"); + goto err; + } + len += lens[a]; + } + + if (len != fw->size) { + sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size, + (u32)len); + goto err; + } + + ptr += MOXA_FW_HDRLEN; + lenp = 0; /* bios */ + + strcpy(rsn, "read above"); + + ret = moxa_load_bios(brd, ptr, lens[lenp]); + if (ret) + goto err; + + /* we skip the tty section (lens[1]), since we don't need it */ + ptr += lens[lenp] + lens[lenp + 1]; + lenp += 2; /* comm */ + + if (hdr->model == 2) { + ret = moxa_load_320b(brd, ptr, lens[lenp]); + if (ret) + goto err; + /* skip another tty */ + ptr += lens[lenp] + lens[lenp + 1]; + lenp += 2; + } + + ret = moxa_load_code(brd, ptr, lens[lenp]); + if (ret) + goto err; + + return 0; +err: + printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn); + return ret; +} + +static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) +{ + const struct firmware *fw; + const char *file; + struct moxa_port *p; + unsigned int i; + int ret; + + brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports), + GFP_KERNEL); + if (brd->ports == NULL) { + printk(KERN_ERR "cannot allocate memory for ports\n"); + ret = -ENOMEM; + goto err; + } + + for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { + tty_port_init(&p->port); + p->port.ops = &moxa_port_ops; + p->type = PORT_16550A; + p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; + } + + switch (brd->boardType) { + case MOXA_BOARD_C218_ISA: + case MOXA_BOARD_C218_PCI: + file = "c218tunx.cod"; + break; + case MOXA_BOARD_CP204J: + file = "cp204unx.cod"; + break; + default: + file = "c320tunx.cod"; + break; + } + + ret = request_firmware(&fw, file, dev); + if (ret) { + printk(KERN_ERR "MOXA: request_firmware failed. Make sure " + "you've placed '%s' file into your firmware " + "loader directory (e.g. /lib/firmware)\n", + file); + goto err_free; + } + + ret = moxa_load_fw(brd, fw); + + release_firmware(fw); + + if (ret) + goto err_free; + + spin_lock_bh(&moxa_lock); + brd->ready = 1; + if (!timer_pending(&moxaTimer)) + mod_timer(&moxaTimer, jiffies + HZ / 50); + spin_unlock_bh(&moxa_lock); + + return 0; +err_free: + kfree(brd->ports); +err: + return ret; +} + +static void moxa_board_deinit(struct moxa_board_conf *brd) +{ + unsigned int a, opened; + + mutex_lock(&moxa_openlock); + spin_lock_bh(&moxa_lock); + brd->ready = 0; + spin_unlock_bh(&moxa_lock); + + /* pci hot-un-plug support */ + for (a = 0; a < brd->numPorts; a++) + if (brd->ports[a].port.flags & ASYNC_INITIALIZED) { + struct tty_struct *tty = tty_port_tty_get( + &brd->ports[a].port); + if (tty) { + tty_hangup(tty); + tty_kref_put(tty); + } + } + while (1) { + opened = 0; + for (a = 0; a < brd->numPorts; a++) + if (brd->ports[a].port.flags & ASYNC_INITIALIZED) + opened++; + mutex_unlock(&moxa_openlock); + if (!opened) + break; + msleep(50); + mutex_lock(&moxa_openlock); + } + + iounmap(brd->basemem); + brd->basemem = NULL; + kfree(brd->ports); +} + +#ifdef CONFIG_PCI +static int __devinit moxa_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct moxa_board_conf *board; + unsigned int i; + int board_type = ent->driver_data; + int retval; + + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "can't enable pci device\n"); + goto err; + } + + for (i = 0; i < MAX_BOARDS; i++) + if (moxa_boards[i].basemem == NULL) + break; + + retval = -ENODEV; + if (i >= MAX_BOARDS) { + dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards " + "found. Board is ignored.\n", MAX_BOARDS); + goto err; + } + + board = &moxa_boards[i]; + + retval = pci_request_region(pdev, 2, "moxa-base"); + if (retval) { + dev_err(&pdev->dev, "can't request pci region 2\n"); + goto err; + } + + board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000); + if (board->basemem == NULL) { + dev_err(&pdev->dev, "can't remap io space 2\n"); + goto err_reg; + } + + board->boardType = board_type; + switch (board_type) { + case MOXA_BOARD_C218_ISA: + case MOXA_BOARD_C218_PCI: + board->numPorts = 8; + break; + + case MOXA_BOARD_CP204J: + board->numPorts = 4; + break; + default: + board->numPorts = 0; + break; + } + board->busType = MOXA_BUS_TYPE_PCI; + + retval = moxa_init_board(board, &pdev->dev); + if (retval) + goto err_base; + + pci_set_drvdata(pdev, board); + + dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n", + moxa_brdname[board_type - 1], board->numPorts); + + return 0; +err_base: + iounmap(board->basemem); + board->basemem = NULL; +err_reg: + pci_release_region(pdev, 2); +err: + return retval; +} + +static void __devexit moxa_pci_remove(struct pci_dev *pdev) +{ + struct moxa_board_conf *brd = pci_get_drvdata(pdev); + + moxa_board_deinit(brd); + + pci_release_region(pdev, 2); +} + +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) +{ + unsigned int isabrds = 0; + int retval = 0; + struct moxa_board_conf *brd = moxa_boards; + unsigned int i; + + printk(KERN_INFO "MOXA Intellio family driver version %s\n", + MOXA_VERSION); + moxaDriver = alloc_tty_driver(MAX_PORTS + 1); + if (!moxaDriver) + return -ENOMEM; + + moxaDriver->owner = THIS_MODULE; + moxaDriver->name = "ttyMX"; + moxaDriver->major = ttymajor; + moxaDriver->minor_start = 0; + moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; + moxaDriver->subtype = SERIAL_TYPE_NORMAL; + moxaDriver->init_termios = tty_std_termios; + moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; + moxaDriver->init_termios.c_ispeed = 9600; + moxaDriver->init_termios.c_ospeed = 9600; + moxaDriver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(moxaDriver, &moxa_ops); + + if (tty_register_driver(moxaDriver)) { + printk(KERN_ERR "can't register MOXA Smartio tty driver!\n"); + put_tty_driver(moxaDriver); + return -1; + } + + /* Find the boards defined from module args. */ + + for (i = 0; i < MAX_BOARDS; i++) { + if (!baseaddr[i]) + break; + if (type[i] == MOXA_BOARD_C218_ISA || + type[i] == MOXA_BOARD_C320_ISA) { + pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n", + isabrds + 1, moxa_brdname[type[i] - 1], + baseaddr[i]); + brd->boardType = type[i]; + brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : + numports[i]; + brd->busType = MOXA_BUS_TYPE_ISA; + brd->basemem = ioremap_nocache(baseaddr[i], 0x4000); + if (!brd->basemem) { + printk(KERN_ERR "MOXA: can't remap %lx\n", + baseaddr[i]); + continue; + } + if (moxa_init_board(brd, NULL)) { + iounmap(brd->basemem); + brd->basemem = NULL; + continue; + } + + printk(KERN_INFO "MOXA isa board found at 0x%.8lu and " + "ready (%u ports, firmware loaded)\n", + baseaddr[i], brd->numPorts); + + brd++; + isabrds++; + } + } + +#ifdef CONFIG_PCI + retval = pci_register_driver(&moxa_pci_driver); + if (retval) { + printk(KERN_ERR "Can't register MOXA pci driver!\n"); + if (isabrds) + retval = 0; + } +#endif + + return retval; +} + +static void __exit moxa_exit(void) +{ + unsigned int i; + +#ifdef CONFIG_PCI + pci_unregister_driver(&moxa_pci_driver); +#endif + + for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */ + if (moxa_boards[i].ready) + moxa_board_deinit(&moxa_boards[i]); + + del_timer_sync(&moxaTimer); + + if (tty_unregister_driver(moxaDriver)) + printk(KERN_ERR "Couldn't unregister MOXA Intellio family " + "serial driver\n"); + put_tty_driver(moxaDriver); +} + +module_init(moxa_init); +module_exit(moxa_exit); + +static void moxa_shutdown(struct tty_port *port) +{ + struct moxa_port *ch = container_of(port, struct moxa_port, port); + MoxaPortDisable(ch); + MoxaPortFlushData(ch, 2); + clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); +} + +static int moxa_carrier_raised(struct tty_port *port) +{ + struct moxa_port *ch = container_of(port, struct moxa_port, port); + int dcd; + + spin_lock_irq(&port->lock); + dcd = ch->DCDState; + spin_unlock_irq(&port->lock); + return dcd; +} + +static void moxa_dtr_rts(struct tty_port *port, int onoff) +{ + struct moxa_port *ch = container_of(port, struct moxa_port, port); + MoxaPortLineCtrl(ch, onoff, onoff); +} + + +static int moxa_open(struct tty_struct *tty, struct file *filp) +{ + struct moxa_board_conf *brd; + struct moxa_port *ch; + int port; + int retval; + + port = tty->index; + if (port == MAX_PORTS) { + return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; + } + if (mutex_lock_interruptible(&moxa_openlock)) + return -ERESTARTSYS; + brd = &moxa_boards[port / MAX_PORTS_PER_BOARD]; + if (!brd->ready) { + mutex_unlock(&moxa_openlock); + return -ENODEV; + } + + if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) { + mutex_unlock(&moxa_openlock); + return -ENODEV; + } + + ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; + ch->port.count++; + tty->driver_data = ch; + tty_port_tty_set(&ch->port, tty); + mutex_lock(&ch->port.mutex); + if (!(ch->port.flags & ASYNC_INITIALIZED)) { + ch->statusflags = 0; + moxa_set_tty_param(tty, tty->termios); + MoxaPortLineCtrl(ch, 1, 1); + MoxaPortEnable(ch); + MoxaSetFifo(ch, ch->type == PORT_16550A); + ch->port.flags |= ASYNC_INITIALIZED; + } + mutex_unlock(&ch->port.mutex); + mutex_unlock(&moxa_openlock); + + retval = tty_port_block_til_ready(&ch->port, tty, filp); + if (retval == 0) + set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); + return retval; +} + +static void moxa_close(struct tty_struct *tty, struct file *filp) +{ + struct moxa_port *ch = tty->driver_data; + ch->cflag = tty->termios->c_cflag; + tty_port_close(&ch->port, tty, filp); +} + +static int moxa_write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + struct moxa_port *ch = tty->driver_data; + int len; + + if (ch == NULL) + return 0; + + spin_lock_bh(&moxa_lock); + len = MoxaPortWriteData(tty, buf, count); + spin_unlock_bh(&moxa_lock); + + set_bit(LOWWAIT, &ch->statusflags); + return len; +} + +static int moxa_write_room(struct tty_struct *tty) +{ + struct moxa_port *ch; + + if (tty->stopped) + return 0; + ch = tty->driver_data; + if (ch == NULL) + return 0; + return MoxaPortTxFree(ch); +} + +static void moxa_flush_buffer(struct tty_struct *tty) +{ + struct moxa_port *ch = tty->driver_data; + + if (ch == NULL) + return; + MoxaPortFlushData(ch, 1); + tty_wakeup(tty); +} + +static int moxa_chars_in_buffer(struct tty_struct *tty) +{ + struct moxa_port *ch = tty->driver_data; + int chars; + + chars = MoxaPortTxQueue(ch); + if (chars) + /* + * Make it possible to wakeup anything waiting for output + * in tty_ioctl.c, etc. + */ + set_bit(EMPTYWAIT, &ch->statusflags); + return chars; +} + +static int moxa_tiocmget(struct tty_struct *tty) +{ + struct moxa_port *ch = tty->driver_data; + int flag = 0, dtr, rts; + + MoxaPortGetLineOut(ch, &dtr, &rts); + if (dtr) + flag |= TIOCM_DTR; + if (rts) + flag |= TIOCM_RTS; + dtr = MoxaPortLineStatus(ch); + if (dtr & 1) + flag |= TIOCM_CTS; + if (dtr & 2) + flag |= TIOCM_DSR; + if (dtr & 4) + flag |= TIOCM_CD; + return flag; +} + +static int moxa_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct moxa_port *ch; + int port; + int dtr, rts; + + port = tty->index; + mutex_lock(&moxa_openlock); + ch = tty->driver_data; + if (!ch) { + mutex_unlock(&moxa_openlock); + return -EINVAL; + } + + MoxaPortGetLineOut(ch, &dtr, &rts); + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + MoxaPortLineCtrl(ch, dtr, rts); + mutex_unlock(&moxa_openlock); + return 0; +} + +static void moxa_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) +{ + struct moxa_port *ch = tty->driver_data; + + if (ch == NULL) + return; + moxa_set_tty_param(tty, old_termios); + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) + wake_up_interruptible(&ch->port.open_wait); +} + +static void moxa_stop(struct tty_struct *tty) +{ + struct moxa_port *ch = tty->driver_data; + + if (ch == NULL) + return; + MoxaPortTxDisable(ch); + set_bit(TXSTOPPED, &ch->statusflags); +} + + +static void moxa_start(struct tty_struct *tty) +{ + struct moxa_port *ch = tty->driver_data; + + if (ch == NULL) + return; + + if (!(ch->statusflags & TXSTOPPED)) + return; + + MoxaPortTxEnable(ch); + clear_bit(TXSTOPPED, &ch->statusflags); +} + +static void moxa_hangup(struct tty_struct *tty) +{ + struct moxa_port *ch = tty->driver_data; + tty_port_hangup(&ch->port); +} + +static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) +{ + struct tty_struct *tty; + unsigned long flags; + dcd = !!dcd; + + spin_lock_irqsave(&p->port.lock, flags); + if (dcd != p->DCDState) { + p->DCDState = dcd; + spin_unlock_irqrestore(&p->port.lock, flags); + tty = tty_port_tty_get(&p->port); + if (tty && C_CLOCAL(tty) && !dcd) + tty_hangup(tty); + tty_kref_put(tty); + } + else + spin_unlock_irqrestore(&p->port.lock, flags); +} + +static int moxa_poll_port(struct moxa_port *p, unsigned int handle, + u16 __iomem *ip) +{ + struct tty_struct *tty = tty_port_tty_get(&p->port); + void __iomem *ofsAddr; + unsigned int inited = p->port.flags & ASYNC_INITIALIZED; + u16 intr; + + if (tty) { + if (test_bit(EMPTYWAIT, &p->statusflags) && + MoxaPortTxQueue(p) == 0) { + clear_bit(EMPTYWAIT, &p->statusflags); + tty_wakeup(tty); + } + if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && + MoxaPortTxQueue(p) <= WAKEUP_CHARS) { + clear_bit(LOWWAIT, &p->statusflags); + tty_wakeup(tty); + } + + if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && + MoxaPortRxQueue(p) > 0) { /* RX */ + MoxaPortReadData(p); + tty_schedule_flip(tty); + } + } else { + clear_bit(EMPTYWAIT, &p->statusflags); + MoxaPortFlushData(p, 0); /* flush RX */ + } + + if (!handle) /* nothing else to do */ + goto put; + + intr = readw(ip); /* port irq status */ + if (intr == 0) + goto put; + + writew(0, ip); /* ACK port */ + ofsAddr = p->tableAddr; + if (intr & IntrTx) /* disable tx intr */ + writew(readw(ofsAddr + HostStat) & ~WakeupTx, + ofsAddr + HostStat); + + if (!inited) + goto put; + + if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ + tty_insert_flip_char(tty, 0, TTY_BREAK); + tty_schedule_flip(tty); + } + + if (intr & IntrLine) + moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); +put: + tty_kref_put(tty); + + return 0; +} + +static void moxa_poll(unsigned long ignored) +{ + struct moxa_board_conf *brd; + u16 __iomem *ip; + unsigned int card, port, served = 0; + + spin_lock(&moxa_lock); + for (card = 0; card < MAX_BOARDS; card++) { + brd = &moxa_boards[card]; + if (!brd->ready) + continue; + + served++; + + ip = NULL; + if (readb(brd->intPend) == 0xff) + ip = brd->intTable + readb(brd->intNdx); + + for (port = 0; port < brd->numPorts; port++) + moxa_poll_port(&brd->ports[port], !!ip, ip + port); + + if (ip) + writeb(0, brd->intPend); /* ACK */ + + if (moxaLowWaterChk) { + struct moxa_port *p = brd->ports; + for (port = 0; port < brd->numPorts; port++, p++) + if (p->lowChkFlag) { + p->lowChkFlag = 0; + moxa_low_water_check(p->tableAddr); + } + } + } + moxaLowWaterChk = 0; + + if (served) + mod_timer(&moxaTimer, jiffies + HZ / 50); + spin_unlock(&moxa_lock); +} + +/******************************************************************************/ + +static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios) +{ + register struct ktermios *ts = tty->termios; + struct moxa_port *ch = tty->driver_data; + int rts, cts, txflow, rxflow, xany, baud; + + rts = cts = txflow = rxflow = xany = 0; + if (ts->c_cflag & CRTSCTS) + rts = cts = 1; + if (ts->c_iflag & IXON) + txflow = 1; + if (ts->c_iflag & IXOFF) + rxflow = 1; + if (ts->c_iflag & IXANY) + xany = 1; + + /* Clear the features we don't support */ + ts->c_cflag &= ~CMSPAR; + MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany); + baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty)); + if (baud == -1) + baud = tty_termios_baud_rate(old_termios); + /* Not put the baud rate into the termios data */ + tty_encode_baud_rate(tty, baud, baud); +} + +/***************************************************************************** + * Driver level functions: * + *****************************************************************************/ + +static void MoxaPortFlushData(struct moxa_port *port, int mode) +{ + void __iomem *ofsAddr; + if (mode < 0 || mode > 2) + return; + ofsAddr = port->tableAddr; + moxafunc(ofsAddr, FC_FlushQueue, mode); + if (mode != 1) { + port->lowChkFlag = 0; + moxa_low_water_check(ofsAddr); + } +} + +/* + * Moxa Port Number Description: + * + * MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And, + * the port number using in MOXA driver functions will be 0 to 31 for + * first MOXA board, 32 to 63 for second, 64 to 95 for third and 96 + * to 127 for fourth. For example, if you setup three MOXA boards, + * first board is C218, second board is C320-16 and third board is + * C320-32. The port number of first board (C218 - 8 ports) is from + * 0 to 7. The port number of second board (C320 - 16 ports) is form + * 32 to 47. The port number of third board (C320 - 32 ports) is from + * 64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to + * 127 will be invalid. + * + * + * Moxa Functions Description: + * + * Function 1: Driver initialization routine, this routine must be + * called when initialized driver. + * Syntax: + * void MoxaDriverInit(); + * + * + * Function 2: Moxa driver private IOCTL command processing. + * Syntax: + * int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); + * + * unsigned int cmd : IOCTL command + * unsigned long arg : IOCTL argument + * int port : port number (0 - 127) + * + * return: 0 (OK) + * -EINVAL + * -ENOIOCTLCMD + * + * + * Function 6: Enable this port to start Tx/Rx data. + * Syntax: + * void MoxaPortEnable(int port); + * int port : port number (0 - 127) + * + * + * Function 7: Disable this port + * Syntax: + * void MoxaPortDisable(int port); + * int port : port number (0 - 127) + * + * + * Function 10: Setting baud rate of this port. + * Syntax: + * speed_t MoxaPortSetBaud(int port, speed_t baud); + * int port : port number (0 - 127) + * long baud : baud rate (50 - 115200) + * + * return: 0 : this port is invalid or baud < 50 + * 50 - 115200 : the real baud rate set to the port, if + * the argument baud is large than maximun + * available baud rate, the real setting + * baud rate will be the maximun baud rate. + * + * + * Function 12: Configure the port. + * Syntax: + * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); + * int port : port number (0 - 127) + * struct ktermios * termio : termio structure pointer + * speed_t baud : baud rate + * + * return: -1 : this port is invalid or termio == NULL + * 0 : setting O.K. + * + * + * Function 13: Get the DTR/RTS state of this port. + * Syntax: + * int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); + * int port : port number (0 - 127) + * int * dtrState : pointer to INT to receive the current DTR + * state. (if NULL, this function will not + * write to this address) + * int * rtsState : pointer to INT to receive the current RTS + * state. (if NULL, this function will not + * write to this address) + * + * return: -1 : this port is invalid + * 0 : O.K. + * + * + * Function 14: Setting the DTR/RTS output state of this port. + * Syntax: + * void MoxaPortLineCtrl(int port, int dtrState, int rtsState); + * int port : port number (0 - 127) + * int dtrState : DTR output state (0: off, 1: on) + * int rtsState : RTS output state (0: off, 1: on) + * + * + * Function 15: Setting the flow control of this port. + * Syntax: + * void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow, + * int txFlow,int xany); + * int port : port number (0 - 127) + * int rtsFlow : H/W RTS flow control (0: no, 1: yes) + * int ctsFlow : H/W CTS flow control (0: no, 1: yes) + * int rxFlow : S/W Rx XON/XOFF flow control (0: no, 1: yes) + * int txFlow : S/W Tx XON/XOFF flow control (0: no, 1: yes) + * int xany : S/W XANY flow control (0: no, 1: yes) + * + * + * Function 16: Get ths line status of this port + * Syntax: + * int MoxaPortLineStatus(int port); + * int port : port number (0 - 127) + * + * return: Bit 0 - CTS state (0: off, 1: on) + * Bit 1 - DSR state (0: off, 1: on) + * Bit 2 - DCD state (0: off, 1: on) + * + * + * Function 19: Flush the Rx/Tx buffer data of this port. + * Syntax: + * void MoxaPortFlushData(int port, int mode); + * int port : port number (0 - 127) + * int mode + * 0 : flush the Rx buffer + * 1 : flush the Tx buffer + * 2 : flush the Rx and Tx buffer + * + * + * Function 20: Write data. + * Syntax: + * int MoxaPortWriteData(int port, unsigned char * buffer, int length); + * int port : port number (0 - 127) + * unsigned char * buffer : pointer to write data buffer. + * int length : write data length + * + * return: 0 - length : real write data length + * + * + * Function 21: Read data. + * Syntax: + * int MoxaPortReadData(int port, struct tty_struct *tty); + * int port : port number (0 - 127) + * struct tty_struct *tty : tty for data + * + * return: 0 - length : real read data length + * + * + * Function 24: Get the Tx buffer current queued data bytes + * Syntax: + * int MoxaPortTxQueue(int port); + * int port : port number (0 - 127) + * + * return: .. : Tx buffer current queued data bytes + * + * + * Function 25: Get the Tx buffer current free space + * Syntax: + * int MoxaPortTxFree(int port); + * int port : port number (0 - 127) + * + * return: .. : Tx buffer current free space + * + * + * Function 26: Get the Rx buffer current queued data bytes + * Syntax: + * int MoxaPortRxQueue(int port); + * int port : port number (0 - 127) + * + * return: .. : Rx buffer current queued data bytes + * + * + * Function 28: Disable port data transmission. + * Syntax: + * void MoxaPortTxDisable(int port); + * int port : port number (0 - 127) + * + * + * Function 29: Enable port data transmission. + * Syntax: + * void MoxaPortTxEnable(int port); + * int port : port number (0 - 127) + * + * + * Function 31: Get the received BREAK signal count and reset it. + * Syntax: + * int MoxaPortResetBrkCnt(int port); + * int port : port number (0 - 127) + * + * return: 0 - .. : BREAK signal count + * + * + */ + +static void MoxaPortEnable(struct moxa_port *port) +{ + void __iomem *ofsAddr; + u16 lowwater = 512; + + ofsAddr = port->tableAddr; + writew(lowwater, ofsAddr + Low_water); + if (MOXA_IS_320(port->board)) + moxafunc(ofsAddr, FC_SetBreakIrq, 0); + else + writew(readw(ofsAddr + HostStat) | WakeupBreak, + ofsAddr + HostStat); + + moxafunc(ofsAddr, FC_SetLineIrq, Magic_code); + moxafunc(ofsAddr, FC_FlushQueue, 2); + + moxafunc(ofsAddr, FC_EnableCH, Magic_code); + MoxaPortLineStatus(port); +} + +static void MoxaPortDisable(struct moxa_port *port) +{ + void __iomem *ofsAddr = port->tableAddr; + + moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ + moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); + writew(0, ofsAddr + HostStat); + moxafunc(ofsAddr, FC_DisableCH, Magic_code); +} + +static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud) +{ + void __iomem *ofsAddr = port->tableAddr; + unsigned int clock, val; + speed_t max; + + max = MOXA_IS_320(port->board) ? 460800 : 921600; + if (baud < 50) + return 0; + if (baud > max) + baud = max; + clock = 921600; + val = clock / baud; + moxafunc(ofsAddr, FC_SetBaud, val); + baud = clock / val; + return baud; +} + +static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, + speed_t baud) +{ + void __iomem *ofsAddr; + tcflag_t cflag; + tcflag_t mode = 0; + + ofsAddr = port->tableAddr; + cflag = termio->c_cflag; /* termio->c_cflag */ + + mode = termio->c_cflag & CSIZE; + if (mode == CS5) + mode = MX_CS5; + else if (mode == CS6) + mode = MX_CS6; + else if (mode == CS7) + mode = MX_CS7; + else if (mode == CS8) + mode = MX_CS8; + + if (termio->c_cflag & CSTOPB) { + if (mode == MX_CS5) + mode |= MX_STOP15; + else + mode |= MX_STOP2; + } else + mode |= MX_STOP1; + + if (termio->c_cflag & PARENB) { + if (termio->c_cflag & PARODD) + mode |= MX_PARODD; + else + mode |= MX_PAREVEN; + } else + mode |= MX_PARNONE; + + moxafunc(ofsAddr, FC_SetDataMode, (u16)mode); + + if (MOXA_IS_320(port->board) && baud >= 921600) + return -1; + + baud = MoxaPortSetBaud(port, baud); + + if (termio->c_iflag & (IXON | IXOFF | IXANY)) { + spin_lock_irq(&moxafunc_lock); + writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); + writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); + writeb(FC_SetXonXoff, ofsAddr + FuncCode); + moxa_wait_finish(ofsAddr); + spin_unlock_irq(&moxafunc_lock); + + } + return baud; +} + +static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState, + int *rtsState) +{ + if (dtrState) + *dtrState = !!(port->lineCtrl & DTR_ON); + if (rtsState) + *rtsState = !!(port->lineCtrl & RTS_ON); + + return 0; +} + +static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts) +{ + u8 mode = 0; + + if (dtr) + mode |= DTR_ON; + if (rts) + mode |= RTS_ON; + port->lineCtrl = mode; + moxafunc(port->tableAddr, FC_LineControl, mode); +} + +static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts, + int txflow, int rxflow, int txany) +{ + int mode = 0; + + if (rts) + mode |= RTS_FlowCtl; + if (cts) + mode |= CTS_FlowCtl; + if (txflow) + mode |= Tx_FlowCtl; + if (rxflow) + mode |= Rx_FlowCtl; + if (txany) + mode |= IXM_IXANY; + moxafunc(port->tableAddr, FC_SetFlowCtl, mode); +} + +static int MoxaPortLineStatus(struct moxa_port *port) +{ + void __iomem *ofsAddr; + int val; + + ofsAddr = port->tableAddr; + if (MOXA_IS_320(port->board)) + val = moxafuncret(ofsAddr, FC_LineStatus, 0); + else + val = readw(ofsAddr + FlagStat) >> 4; + val &= 0x0B; + if (val & 8) + val |= 4; + moxa_new_dcdstate(port, val & 8); + val &= 7; + return val; +} + +static int MoxaPortWriteData(struct tty_struct *tty, + const unsigned char *buffer, int len) +{ + struct moxa_port *port = tty->driver_data; + void __iomem *baseAddr, *ofsAddr, *ofs; + unsigned int c, total; + u16 head, tail, tx_mask, spage, epage; + u16 pageno, pageofs, bufhead; + + ofsAddr = port->tableAddr; + baseAddr = port->board->basemem; + tx_mask = readw(ofsAddr + TX_mask); + spage = readw(ofsAddr + Page_txb); + epage = readw(ofsAddr + EndPage_txb); + tail = readw(ofsAddr + TXwptr); + head = readw(ofsAddr + TXrptr); + c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask); + if (c > len) + c = len; + moxaLog.txcnt[port->port.tty->index] += c; + total = c; + if (spage == epage) { + bufhead = readw(ofsAddr + Ofs_txb); + writew(spage, baseAddr + Control_reg); + while (c > 0) { + if (head > tail) + len = head - tail - 1; + else + len = tx_mask + 1 - tail; + len = (c > len) ? len : c; + ofs = baseAddr + DynPage_addr + bufhead + tail; + memcpy_toio(ofs, buffer, len); + buffer += len; + tail = (tail + len) & tx_mask; + c -= len; + } + } else { + pageno = spage + (tail >> 13); + pageofs = tail & Page_mask; + while (c > 0) { + len = Page_size - pageofs; + if (len > c) + len = c; + writeb(pageno, baseAddr + Control_reg); + ofs = baseAddr + DynPage_addr + pageofs; + memcpy_toio(ofs, buffer, len); + buffer += len; + if (++pageno == epage) + pageno = spage; + pageofs = 0; + c -= len; + } + tail = (tail + total) & tx_mask; + } + writew(tail, ofsAddr + TXwptr); + writeb(1, ofsAddr + CD180TXirq); /* start to send */ + return total; +} + +static int MoxaPortReadData(struct moxa_port *port) +{ + struct tty_struct *tty = port->port.tty; + unsigned char *dst; + void __iomem *baseAddr, *ofsAddr, *ofs; + unsigned int count, len, total; + u16 tail, rx_mask, spage, epage; + u16 pageno, pageofs, bufhead, head; + + ofsAddr = port->tableAddr; + baseAddr = port->board->basemem; + head = readw(ofsAddr + RXrptr); + tail = readw(ofsAddr + RXwptr); + rx_mask = readw(ofsAddr + RX_mask); + spage = readw(ofsAddr + Page_rxb); + epage = readw(ofsAddr + EndPage_rxb); + count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1); + if (count == 0) + return 0; + + total = count; + moxaLog.rxcnt[tty->index] += total; + if (spage == epage) { + bufhead = readw(ofsAddr + Ofs_rxb); + writew(spage, baseAddr + Control_reg); + while (count > 0) { + ofs = baseAddr + DynPage_addr + bufhead + head; + len = (tail >= head) ? (tail - head) : + (rx_mask + 1 - head); + len = tty_prepare_flip_string(tty, &dst, + min(len, count)); + memcpy_fromio(dst, ofs, len); + head = (head + len) & rx_mask; + count -= len; + } + } else { + pageno = spage + (head >> 13); + pageofs = head & Page_mask; + while (count > 0) { + writew(pageno, baseAddr + Control_reg); + ofs = baseAddr + DynPage_addr + pageofs; + len = tty_prepare_flip_string(tty, &dst, + min(Page_size - pageofs, count)); + memcpy_fromio(dst, ofs, len); + + count -= len; + pageofs = (pageofs + len) & Page_mask; + if (pageofs == 0 && ++pageno == epage) + pageno = spage; + } + head = (head + total) & rx_mask; + } + writew(head, ofsAddr + RXrptr); + if (readb(ofsAddr + FlagStat) & Xoff_state) { + moxaLowWaterChk = 1; + port->lowChkFlag = 1; + } + return total; +} + + +static int MoxaPortTxQueue(struct moxa_port *port) +{ + void __iomem *ofsAddr = port->tableAddr; + u16 rptr, wptr, mask; + + rptr = readw(ofsAddr + TXrptr); + wptr = readw(ofsAddr + TXwptr); + mask = readw(ofsAddr + TX_mask); + return (wptr - rptr) & mask; +} + +static int MoxaPortTxFree(struct moxa_port *port) +{ + void __iomem *ofsAddr = port->tableAddr; + u16 rptr, wptr, mask; + + rptr = readw(ofsAddr + TXrptr); + wptr = readw(ofsAddr + TXwptr); + mask = readw(ofsAddr + TX_mask); + return mask - ((wptr - rptr) & mask); +} + +static int MoxaPortRxQueue(struct moxa_port *port) +{ + void __iomem *ofsAddr = port->tableAddr; + u16 rptr, wptr, mask; + + rptr = readw(ofsAddr + RXrptr); + wptr = readw(ofsAddr + RXwptr); + mask = readw(ofsAddr + RX_mask); + return (wptr - rptr) & mask; +} + +static void MoxaPortTxDisable(struct moxa_port *port) +{ + moxafunc(port->tableAddr, FC_SetXoffState, Magic_code); +} + +static void MoxaPortTxEnable(struct moxa_port *port) +{ + moxafunc(port->tableAddr, FC_SetXonState, Magic_code); +} + +static int moxa_get_serial_info(struct moxa_port *info, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp = { + .type = info->type, + .line = info->port.tty->index, + .flags = info->port.flags, + .baud_base = 921600, + .close_delay = info->port.close_delay + }; + return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; +} + + +static int moxa_set_serial_info(struct moxa_port *info, + struct serial_struct __user *new_info) +{ + struct serial_struct new_serial; + + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + + if (new_serial.irq != 0 || new_serial.port != 0 || + new_serial.custom_divisor != 0 || + new_serial.baud_base != 921600) + return -EPERM; + + if (!capable(CAP_SYS_ADMIN)) { + if (((new_serial.flags & ~ASYNC_USR_MASK) != + (info->port.flags & ~ASYNC_USR_MASK))) + return -EPERM; + } else + info->port.close_delay = new_serial.close_delay * HZ / 100; + + new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS); + new_serial.flags |= (info->port.flags & ASYNC_FLAGS); + + MoxaSetFifo(info, new_serial.type == PORT_16550A); + + info->type = new_serial.type; + return 0; +} + + + +/***************************************************************************** + * Static local functions: * + *****************************************************************************/ + +static void MoxaSetFifo(struct moxa_port *port, int enable) +{ + void __iomem *ofsAddr = port->tableAddr; + + if (!enable) { + moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); + moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1); + } else { + moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3); + moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); + } +} diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h new file mode 100644 index 000000000000..87d16ce57be7 --- /dev/null +++ b/drivers/tty/moxa.h @@ -0,0 +1,304 @@ +#ifndef MOXA_H_FILE +#define MOXA_H_FILE + +#define MOXA 0x400 +#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ +#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ +#define MOXA_GETDATACOUNT (MOXA + 23) +#define MOXA_GET_IOQUEUE (MOXA + 27) +#define MOXA_FLUSH_QUEUE (MOXA + 28) +#define MOXA_GETMSTATUS (MOXA + 65) + +/* + * System Configuration + */ + +#define Magic_code 0x404 + +/* + * for C218 BIOS initialization + */ +#define C218_ConfBase 0x800 +#define C218_status (C218_ConfBase + 0) /* BIOS running status */ +#define C218_diag (C218_ConfBase + 2) /* diagnostic status */ +#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */ +#define C218DLoad_len (C218_ConfBase + 6) /* WORD */ +#define C218check_sum (C218_ConfBase + 8) /* BYTE */ +#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */ +#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */ +#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */ +#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */ +#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */ + +#define C218_LoadBuf 0x0F00 +#define C218_KeyCode 0x218 +#define CP204J_KeyCode 0x204 + +/* + * for C320 BIOS initialization + */ +#define C320_ConfBase 0x800 +#define C320_LoadBuf 0x0f00 +#define STS_init 0x05 /* for C320_status */ + +#define C320_status C320_ConfBase + 0 /* BIOS running status */ +#define C320_diag C320_ConfBase + 2 /* diagnostic status */ +#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */ +#define C320DLoad_len C320_ConfBase + 6 /* WORD */ +#define C320check_sum C320_ConfBase + 8 /* WORD */ +#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */ +#define C320bapi_len C320_ConfBase + 0x0c /* WORD */ +#define C320UART_no C320_ConfBase + 0x0e /* WORD */ + +#define C320_KeyCode 0x320 + +#define FixPage_addr 0x0000 /* starting addr of static page */ +#define DynPage_addr 0x2000 /* starting addr of dynamic page */ +#define C218_start 0x3000 /* starting addr of C218 BIOS prg */ +#define Control_reg 0x1ff0 /* select page and reset control */ +#define HW_reset 0x80 + +/* + * Function Codes + */ +#define FC_CardReset 0x80 +#define FC_ChannelReset 1 /* C320 firmware not supported */ +#define FC_EnableCH 2 +#define FC_DisableCH 3 +#define FC_SetParam 4 +#define FC_SetMode 5 +#define FC_SetRate 6 +#define FC_LineControl 7 +#define FC_LineStatus 8 +#define FC_XmitControl 9 +#define FC_FlushQueue 10 +#define FC_SendBreak 11 +#define FC_StopBreak 12 +#define FC_LoopbackON 13 +#define FC_LoopbackOFF 14 +#define FC_ClrIrqTable 15 +#define FC_SendXon 16 +#define FC_SetTermIrq 17 /* C320 firmware not supported */ +#define FC_SetCntIrq 18 /* C320 firmware not supported */ +#define FC_SetBreakIrq 19 +#define FC_SetLineIrq 20 +#define FC_SetFlowCtl 21 +#define FC_GenIrq 22 +#define FC_InCD180 23 +#define FC_OutCD180 24 +#define FC_InUARTreg 23 +#define FC_OutUARTreg 24 +#define FC_SetXonXoff 25 +#define FC_OutCD180CCR 26 +#define FC_ExtIQueue 27 +#define FC_ExtOQueue 28 +#define FC_ClrLineIrq 29 +#define FC_HWFlowCtl 30 +#define FC_GetClockRate 35 +#define FC_SetBaud 36 +#define FC_SetDataMode 41 +#define FC_GetCCSR 43 +#define FC_GetDataError 45 +#define FC_RxControl 50 +#define FC_ImmSend 51 +#define FC_SetXonState 52 +#define FC_SetXoffState 53 +#define FC_SetRxFIFOTrig 54 +#define FC_SetTxFIFOCnt 55 +#define FC_UnixRate 56 +#define FC_UnixResetTimer 57 + +#define RxFIFOTrig1 0 +#define RxFIFOTrig4 1 +#define RxFIFOTrig8 2 +#define RxFIFOTrig14 3 + +/* + * Dual-Ported RAM + */ +#define DRAM_global 0 +#define INT_data (DRAM_global + 0) +#define Config_base (DRAM_global + 0x108) + +#define IRQindex (INT_data + 0) +#define IRQpending (INT_data + 4) +#define IRQtable (INT_data + 8) + +/* + * Interrupt Status + */ +#define IntrRx 0x01 /* receiver data O.K. */ +#define IntrTx 0x02 /* transmit buffer empty */ +#define IntrFunc 0x04 /* function complete */ +#define IntrBreak 0x08 /* received break */ +#define IntrLine 0x10 /* line status change + for transmitter */ +#define IntrIntr 0x20 /* received INTR code */ +#define IntrQuit 0x40 /* received QUIT code */ +#define IntrEOF 0x80 /* received EOF code */ + +#define IntrRxTrigger 0x100 /* rx data count reach tigger value */ +#define IntrTxTrigger 0x200 /* tx data count below trigger value */ + +#define Magic_no (Config_base + 0) +#define Card_model_no (Config_base + 2) +#define Total_ports (Config_base + 4) +#define Module_cnt (Config_base + 8) +#define Module_no (Config_base + 10) +#define Timer_10ms (Config_base + 14) +#define Disable_IRQ (Config_base + 20) +#define TMS320_PORT1 (Config_base + 22) +#define TMS320_PORT2 (Config_base + 24) +#define TMS320_CLOCK (Config_base + 26) + +/* + * DATA BUFFER in DRAM + */ +#define Extern_table 0x400 /* Base address of the external table + (24 words * 64) total 3K bytes + (24 words * 128) total 6K bytes */ +#define Extern_size 0x60 /* 96 bytes */ +#define RXrptr 0x00 /* read pointer for RX buffer */ +#define RXwptr 0x02 /* write pointer for RX buffer */ +#define TXrptr 0x04 /* read pointer for TX buffer */ +#define TXwptr 0x06 /* write pointer for TX buffer */ +#define HostStat 0x08 /* IRQ flag and general flag */ +#define FlagStat 0x0A +#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */ + /* x x x x | | | | */ + /* | | | + CTS flow */ + /* | | +--- RTS flow */ + /* | +------ TX Xon/Xoff */ + /* +--------- RX Xon/Xoff */ +#define Break_cnt 0x0E /* received break count */ +#define CD180TXirq 0x10 /* if non-0: enable TX irq */ +#define RX_mask 0x12 +#define TX_mask 0x14 +#define Ofs_rxb 0x16 +#define Ofs_txb 0x18 +#define Page_rxb 0x1A +#define Page_txb 0x1C +#define EndPage_rxb 0x1E +#define EndPage_txb 0x20 +#define Data_error 0x22 +#define RxTrigger 0x28 +#define TxTrigger 0x2a + +#define rRXwptr 0x34 +#define Low_water 0x36 + +#define FuncCode 0x40 +#define FuncArg 0x42 +#define FuncArg1 0x44 + +#define C218rx_size 0x2000 /* 8K bytes */ +#define C218tx_size 0x8000 /* 32K bytes */ + +#define C218rx_mask (C218rx_size - 1) +#define C218tx_mask (C218tx_size - 1) + +#define C320p8rx_size 0x2000 +#define C320p8tx_size 0x8000 +#define C320p8rx_mask (C320p8rx_size - 1) +#define C320p8tx_mask (C320p8tx_size - 1) + +#define C320p16rx_size 0x2000 +#define C320p16tx_size 0x4000 +#define C320p16rx_mask (C320p16rx_size - 1) +#define C320p16tx_mask (C320p16tx_size - 1) + +#define C320p24rx_size 0x2000 +#define C320p24tx_size 0x2000 +#define C320p24rx_mask (C320p24rx_size - 1) +#define C320p24tx_mask (C320p24tx_size - 1) + +#define C320p32rx_size 0x1000 +#define C320p32tx_size 0x1000 +#define C320p32rx_mask (C320p32rx_size - 1) +#define C320p32tx_mask (C320p32tx_size - 1) + +#define Page_size 0x2000U +#define Page_mask (Page_size - 1) +#define C218rx_spage 3 +#define C218tx_spage 4 +#define C218rx_pageno 1 +#define C218tx_pageno 4 +#define C218buf_pageno 5 + +#define C320p8rx_spage 3 +#define C320p8tx_spage 4 +#define C320p8rx_pgno 1 +#define C320p8tx_pgno 4 +#define C320p8buf_pgno 5 + +#define C320p16rx_spage 3 +#define C320p16tx_spage 4 +#define C320p16rx_pgno 1 +#define C320p16tx_pgno 2 +#define C320p16buf_pgno 3 + +#define C320p24rx_spage 3 +#define C320p24tx_spage 4 +#define C320p24rx_pgno 1 +#define C320p24tx_pgno 1 +#define C320p24buf_pgno 2 + +#define C320p32rx_spage 3 +#define C320p32tx_ofs C320p32rx_size +#define C320p32tx_spage 3 +#define C320p32buf_pgno 1 + +/* + * Host Status + */ +#define WakeupRx 0x01 +#define WakeupTx 0x02 +#define WakeupBreak 0x08 +#define WakeupLine 0x10 +#define WakeupIntr 0x20 +#define WakeupQuit 0x40 +#define WakeupEOF 0x80 /* used in VTIME control */ +#define WakeupRxTrigger 0x100 +#define WakeupTxTrigger 0x200 +/* + * Flag status + */ +#define Rx_over 0x01 +#define Xoff_state 0x02 +#define Tx_flowOff 0x04 +#define Tx_enable 0x08 +#define CTS_state 0x10 +#define DSR_state 0x20 +#define DCD_state 0x80 +/* + * FlowControl + */ +#define CTS_FlowCtl 1 +#define RTS_FlowCtl 2 +#define Tx_FlowCtl 4 +#define Rx_FlowCtl 8 +#define IXM_IXANY 0x10 + +#define LowWater 128 + +#define DTR_ON 1 +#define RTS_ON 2 +#define CTS_ON 1 +#define DSR_ON 2 +#define DCD_ON 8 + +/* mode definition */ +#define MX_CS8 0x03 +#define MX_CS7 0x02 +#define MX_CS6 0x01 +#define MX_CS5 0x00 + +#define MX_STOP1 0x00 +#define MX_STOP15 0x04 +#define MX_STOP2 0x08 + +#define MX_PARNONE 0x00 +#define MX_PAREVEN 0x40 +#define MX_PARODD 0xC0 + +#endif diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c new file mode 100644 index 000000000000..d188f378684d --- /dev/null +++ b/drivers/tty/mxser.c @@ -0,0 +1,2757 @@ +/* + * mxser.c -- MOXA Smartio/Industio family multiport serial driver. + * + * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com). + * Copyright (C) 2006-2008 Jiri Slaby + * + * This code is loosely based on the 1.8 moxa driver which is based on + * Linux serial driver, written by Linus Torvalds, Theodore T'so and + * others. + * + * 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. + * + * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox + * . The original 1.8 code is available on + * www.moxa.com. + * - Fixed x86_64 cleanness + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mxser.h" + +#define MXSER_VERSION "2.0.5" /* 1.14 */ +#define MXSERMAJOR 174 + +#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 100 + +/*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 +#define UART_LSR_SPECIAL 0x1E + +#define PCI_DEVICE_ID_POS104UL 0x1044 +#define PCI_DEVICE_ID_CB108 0x1080 +#define PCI_DEVICE_ID_CP102UF 0x1023 +#define PCI_DEVICE_ID_CP112UL 0x1120 +#define PCI_DEVICE_ID_CB114 0x1142 +#define PCI_DEVICE_ID_CP114UL 0x1143 +#define PCI_DEVICE_ID_CB134I 0x1341 +#define PCI_DEVICE_ID_CP138U 0x1380 + + +#define C168_ASIC_ID 1 +#define C104_ASIC_ID 2 +#define C102_ASIC_ID 0xB +#define CI132_ASIC_ID 4 +#define CI134_ASIC_ID 3 +#define CI104J_ASIC_ID 5 + +#define MXSER_HIGHBAUD 1 +#define MXSER_HAS2 2 + +/* This is only for PCI */ +static const struct { + int type; + int tx_fifo; + int rx_fifo; + int xmit_fifo_size; + int rx_high_water; + int rx_trigger; + int rx_low_water; + long max_baud; +} Gpci_uart_info[] = { + {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, + {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, + {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} +}; +#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) + +struct mxser_cardinfo { + char *name; + unsigned int nports; + unsigned int flags; +}; + +static const struct mxser_cardinfo mxser_cards[] = { +/* 0*/ { "C168 series", 8, }, + { "C104 series", 4, }, + { "CI-104J series", 4, }, + { "C168H/PCI series", 8, }, + { "C104H/PCI series", 4, }, +/* 5*/ { "C102 series", 4, MXSER_HAS2 }, /* C102-ISA */ + { "CI-132 series", 4, MXSER_HAS2 }, + { "CI-134 series", 4, }, + { "CP-132 series", 2, }, + { "CP-114 series", 4, }, +/*10*/ { "CT-114 series", 4, }, + { "CP-102 series", 2, MXSER_HIGHBAUD }, + { "CP-104U series", 4, }, + { "CP-168U series", 8, }, + { "CP-132U series", 2, }, +/*15*/ { "CP-134U series", 4, }, + { "CP-104JU series", 4, }, + { "Moxa UC7000 Serial", 8, }, /* RC7000 */ + { "CP-118U series", 8, }, + { "CP-102UL series", 2, }, +/*20*/ { "CP-102U series", 2, }, + { "CP-118EL series", 8, }, + { "CP-168EL series", 8, }, + { "CP-104EL series", 4, }, + { "CB-108 series", 8, }, +/*25*/ { "CB-114 series", 4, }, + { "CB-134I series", 4, }, + { "CP-138U series", 8, }, + { "POS-104UL series", 4, }, + { "CP-114UL series", 4, }, +/*30*/ { "CP-102UF series", 2, }, + { "CP-112UL series", 2, }, +}; + +/* driver_data correspond to the lines in the structure above + see also ISA probe function before you change something */ +static struct pci_device_id mxser_pcibrds[] = { + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 31 }, + { } +}; +MODULE_DEVICE_TABLE(pci, mxser_pcibrds); + +static unsigned long ioaddr[MXSER_BOARDS]; +static int ttymajor = MXSERMAJOR; + +/* Variables for insmod */ + +MODULE_AUTHOR("Casper Yang"); +MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); +module_param_array(ioaddr, ulong, NULL, 0); +MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); +module_param(ttymajor, int, 0); +MODULE_LICENSE("GPL"); + +struct mxser_log { + int tick; + unsigned long rxcnt[MXSER_PORTS]; + unsigned long txcnt[MXSER_PORTS]; +}; + +struct mxser_mon { + unsigned long rxcnt; + unsigned long txcnt; + unsigned long up_rxcnt; + unsigned long up_txcnt; + int modem_status; + unsigned char hold_reason; +}; + +struct mxser_mon_ext { + unsigned long rx_cnt[32]; + unsigned long tx_cnt[32]; + unsigned long up_rxcnt[32]; + unsigned long up_txcnt[32]; + int modem_status[32]; + + long baudrate[32]; + int databits[32]; + int stopbits[32]; + int parity[32]; + int flowctrl[32]; + int fifo[32]; + int iftype[32]; +}; + +struct mxser_board; + +struct mxser_port { + struct tty_port port; + struct mxser_board *board; + + unsigned long ioaddr; + unsigned long opmode_ioaddr; + int max_baud; + + int rx_high_water; + int rx_trigger; /* Rx fifo trigger level */ + int rx_low_water; + int baud_base; /* max. speed */ + int type; /* UART type */ + + int x_char; /* xon/xoff character */ + int IER; /* Interrupt Enable Register */ + int MCR; /* Modem control register */ + + unsigned char stop_rx; + unsigned char ldisc_stop_rx; + + int custom_divisor; + unsigned char err_shadow; + + struct async_icount icount; /* kernel counters for 4 input interrupts */ + int timeout; + + int read_status_mask; + int ignore_status_mask; + int xmit_fifo_size; + int xmit_head; + int xmit_tail; + int xmit_cnt; + + struct ktermios normal_termios; + + struct mxser_mon mon_data; + + spinlock_t slock; +}; + +struct mxser_board { + unsigned int idx; + int irq; + const struct mxser_cardinfo *info; + unsigned long vector; + unsigned long vector_mask; + + int chip_flag; + int uart_type; + + struct mxser_port ports[MXSER_PORTS_PER_BOARD]; +}; + +struct mxser_mstatus { + tcflag_t cflag; + int cts; + int dsr; + int ri; + int dcd; +}; + +static struct mxser_board mxser_boards[MXSER_BOARDS]; +static struct tty_driver *mxvar_sdriver; +static struct mxser_log mxvar_log; +static int mxser_set_baud_method[MXSER_PORTS + 1]; + +static void mxser_enable_must_enchance_mode(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} + +#ifdef CONFIG_PCI +static void mxser_disable_must_enchance_mode(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} +#endif + +static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) +{ + u8 oldlcr; + u8 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(value, baseio + MOXA_MUST_XON1_REGISTER); + outb(oldlcr, baseio + UART_LCR); +} + +static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value) +{ + u8 oldlcr; + u8 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(value, baseio + MOXA_MUST_XOFF1_REGISTER); + outb(oldlcr, baseio + UART_LCR); +} + +static void mxser_set_must_fifo_value(struct mxser_port *info) +{ + u8 oldlcr; + u8 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; + + 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); +} + +static void mxser_set_must_enum_value(unsigned long baseio, u8 value) +{ + u8 oldlcr; + u8 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); + outb(value, baseio + MOXA_MUST_ENUM_REGISTER); + outb(oldlcr, baseio + UART_LCR); +} + +#ifdef CONFIG_PCI +static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) +{ + u8 oldlcr; + u8 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); +} +#endif + +static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} + +static void mxser_enable_must_tx_software_flow_control(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} + +static void mxser_disable_must_tx_software_flow_control(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} + +static void mxser_enable_must_rx_software_flow_control(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} + +static void mxser_disable_must_rx_software_flow_control(unsigned long baseio) +{ + u8 oldlcr; + u8 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); +} + +#ifdef CONFIG_PCI +static int __devinit CheckIsMoxaMust(unsigned long io) +{ + u8 oldmcr, hwid; + int i; + + outb(0, io + UART_LCR); + mxser_disable_must_enchance_mode(io); + oldmcr = inb(io + UART_MCR); + outb(0, io + UART_MCR); + mxser_set_must_xon1_value(io, 0x11); + if ((hwid = inb(io + UART_MCR)) != 0) { + outb(oldmcr, io + UART_MCR); + return MOXA_OTHER_UART; + } + + mxser_get_must_hardware_id(io, &hwid); + for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ + if (hwid == Gpci_uart_info[i].type) + return (int)hwid; + } + return MOXA_OTHER_UART; +} +#endif + +static void process_txrx_fifo(struct mxser_port *info) +{ + int i; + + if ((info->type == PORT_16450) || (info->type == PORT_8250)) { + info->rx_trigger = 1; + info->rx_high_water = 1; + info->rx_low_water = 1; + info->xmit_fifo_size = 1; + } else + for (i = 0; i < UART_INFO_NUM; i++) + if (info->board->chip_flag == Gpci_uart_info[i].type) { + info->rx_trigger = Gpci_uart_info[i].rx_trigger; + info->rx_low_water = Gpci_uart_info[i].rx_low_water; + info->rx_high_water = Gpci_uart_info[i].rx_high_water; + info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; + break; + } +} + +static unsigned char mxser_get_msr(int baseaddr, int mode, int port) +{ + static unsigned char mxser_msr[MXSER_PORTS + 1]; + unsigned char status = 0; + + status = inb(baseaddr + UART_MSR); + + mxser_msr[port] &= 0x0F; + mxser_msr[port] |= status; + status = mxser_msr[port]; + if (mode) + mxser_msr[port] = 0; + + return status; +} + +static int mxser_carrier_raised(struct tty_port *port) +{ + struct mxser_port *mp = container_of(port, struct mxser_port, port); + return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; +} + +static void mxser_dtr_rts(struct tty_port *port, int on) +{ + struct mxser_port *mp = container_of(port, struct mxser_port, port); + unsigned long flags; + + spin_lock_irqsave(&mp->slock, flags); + if (on) + outb(inb(mp->ioaddr + UART_MCR) | + UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); + else + outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS), + mp->ioaddr + UART_MCR); + spin_unlock_irqrestore(&mp->slock, flags); +} + +static int mxser_set_baud(struct tty_struct *tty, long newspd) +{ + struct mxser_port *info = tty->driver_data; + int quot = 0, baud; + unsigned char cval; + + if (!info->ioaddr) + return -1; + + if (newspd > info->max_baud) + return -1; + + if (newspd == 134) { + quot = 2 * info->baud_base / 269; + tty_encode_baud_rate(tty, 134, 134); + } else if (newspd) { + quot = info->baud_base / newspd; + if (quot == 0) + quot = 1; + baud = info->baud_base/quot; + tty_encode_baud_rate(tty, baud, baud); + } 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) { + info->MCR |= UART_MCR_DTR; + outb(info->MCR, info->ioaddr + UART_MCR); + } else { + info->MCR &= ~UART_MCR_DTR; + outb(info->MCR, info->ioaddr + UART_MCR); + return 0; + } + + cval = inb(info->ioaddr + UART_LCR); + + outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */ + + outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */ + outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ + outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ + +#ifdef BOTHER + if (C_BAUD(tty) == BOTHER) { + quot = info->baud_base % newspd; + quot *= 8; + if (quot % newspd > newspd / 2) { + quot /= newspd; + quot++; + } else + quot /= newspd; + + mxser_set_must_enum_value(info->ioaddr, quot); + } else +#endif + mxser_set_must_enum_value(info->ioaddr, 0); + + return 0; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static int mxser_change_speed(struct tty_struct *tty, + struct ktermios *old_termios) +{ + struct mxser_port *info = tty->driver_data; + unsigned cflag, cval, fcr; + int ret = 0; + unsigned char status; + + cflag = tty->termios->c_cflag; + if (!info->ioaddr) + return ret; + + if (mxser_set_baud_method[tty->index] == 0) + mxser_set_baud(tty, tty_get_baud_rate(tty)); + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + cval = 0x00; + break; + case CS6: + cval = 0x01; + break; + case CS7: + cval = 0x02; + break; + case CS8: + cval = 0x03; + break; + default: + cval = 0x00; + break; /* too keep GCC shut... */ + } + if (cflag & CSTOPB) + cval |= 0x04; + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; + + if ((info->type == PORT_8250) || (info->type == PORT_16450)) { + if (info->board->chip_flag) { + fcr = UART_FCR_ENABLE_FIFO; + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + mxser_set_must_fifo_value(info); + } else + fcr = 0; + } else { + fcr = UART_FCR_ENABLE_FIFO; + if (info->board->chip_flag) { + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + mxser_set_must_fifo_value(info); + } else { + switch (info->rx_trigger) { + case 1: + fcr |= UART_FCR_TRIGGER_1; + break; + case 4: + fcr |= UART_FCR_TRIGGER_4; + break; + case 8: + fcr |= UART_FCR_TRIGGER_8; + break; + default: + fcr |= UART_FCR_TRIGGER_14; + break; + } + } + } + + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + info->MCR &= ~UART_MCR_AFE; + if (cflag & CRTSCTS) { + info->port.flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + if ((info->type == PORT_16550A) || (info->board->chip_flag)) { + info->MCR |= UART_MCR_AFE; + } else { + status = inb(info->ioaddr + UART_MSR); + if (tty->hw_stopped) { + if (status & UART_MSR_CTS) { + tty->hw_stopped = 0; + if (info->type != PORT_16550A && + !info->board->chip_flag) { + outb(info->IER & ~UART_IER_THRI, + info->ioaddr + + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + + UART_IER); + } + tty_wakeup(tty); + } + } else { + if (!(status & UART_MSR_CTS)) { + tty->hw_stopped = 1; + if ((info->type != PORT_16550A) && + (!info->board->chip_flag)) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + + UART_IER); + } + } + } + } + } else { + info->port.flags &= ~ASYNC_CTS_FLOW; + } + outb(info->MCR, info->ioaddr + UART_MCR); + if (cflag & CLOCAL) { + info->port.flags &= ~ASYNC_CHECK_CD; + } else { + info->port.flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + outb(info->IER, info->ioaddr + UART_IER); + + /* + * Set up parity check flag + */ + info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (I_INPCK(tty)) + info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (I_BRKINT(tty) || I_PARMRK(tty)) + info->read_status_mask |= UART_LSR_BI; + + info->ignore_status_mask = 0; + + if (I_IGNBRK(tty)) { + info->ignore_status_mask |= UART_LSR_BI; + info->read_status_mask |= UART_LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(tty)) { + info->ignore_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + info->read_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + } + } + if (info->board->chip_flag) { + mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty)); + mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty)); + if (I_IXON(tty)) { + mxser_enable_must_rx_software_flow_control( + info->ioaddr); + } else { + mxser_disable_must_rx_software_flow_control( + info->ioaddr); + } + if (I_IXOFF(tty)) { + mxser_enable_must_tx_software_flow_control( + info->ioaddr); + } else { + mxser_disable_must_tx_software_flow_control( + info->ioaddr); + } + } + + + outb(fcr, info->ioaddr + UART_FCR); /* set fcr */ + outb(cval, info->ioaddr + UART_LCR); + + return ret; +} + +static void mxser_check_modem_status(struct tty_struct *tty, + struct mxser_port *port, int status) +{ + /* update input line counters */ + if (status & UART_MSR_TERI) + port->icount.rng++; + if (status & UART_MSR_DDSR) + port->icount.dsr++; + if (status & UART_MSR_DDCD) + port->icount.dcd++; + if (status & UART_MSR_DCTS) + port->icount.cts++; + port->mon_data.modem_status = status; + wake_up_interruptible(&port->port.delta_msr_wait); + + if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { + if (status & UART_MSR_DCD) + wake_up_interruptible(&port->port.open_wait); + } + + if (port->port.flags & ASYNC_CTS_FLOW) { + if (tty->hw_stopped) { + if (status & UART_MSR_CTS) { + tty->hw_stopped = 0; + + if ((port->type != PORT_16550A) && + (!port->board->chip_flag)) { + outb(port->IER & ~UART_IER_THRI, + port->ioaddr + UART_IER); + port->IER |= UART_IER_THRI; + outb(port->IER, port->ioaddr + + UART_IER); + } + tty_wakeup(tty); + } + } else { + if (!(status & UART_MSR_CTS)) { + tty->hw_stopped = 1; + if (port->type != PORT_16550A && + !port->board->chip_flag) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + + UART_IER); + } + } + } + } +} + +static int mxser_activate(struct tty_port *port, struct tty_struct *tty) +{ + struct mxser_port *info = container_of(port, struct mxser_port, port); + unsigned long page; + unsigned long flags; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + spin_lock_irqsave(&info->slock, flags); + + if (!info->ioaddr || !info->type) { + set_bit(TTY_IO_ERROR, &tty->flags); + free_page(page); + spin_unlock_irqrestore(&info->slock, flags); + return 0; + } + info->port.xmit_buf = (unsigned char *) page; + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in mxser_change_speed()) + */ + if (info->board->chip_flag) + outb((UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); + else + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->ioaddr + UART_FCR); + + /* + * At this point there's no way the LSR could still be 0xFF; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (inb(info->ioaddr + UART_LSR) == 0xff) { + spin_unlock_irqrestore(&info->slock, flags); + if (capable(CAP_SYS_ADMIN)) { + set_bit(TTY_IO_ERROR, &tty->flags); + return 0; + } else + return -ENODEV; + } + + /* + * Clear the interrupt registers. + */ + (void) inb(info->ioaddr + UART_LSR); + (void) inb(info->ioaddr + UART_RX); + (void) inb(info->ioaddr + UART_IIR); + (void) inb(info->ioaddr + UART_MSR); + + /* + * Now, initialize the UART + */ + outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */ + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + + /* + * Finally, enable interrupts + */ + info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + + if (info->board->chip_flag) + info->IER |= MOXA_MUST_IER_EGDAI; + outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ + + /* + * And clear the interrupt registers again for luck. + */ + (void) inb(info->ioaddr + UART_LSR); + (void) inb(info->ioaddr + UART_RX); + (void) inb(info->ioaddr + UART_IIR); + (void) inb(info->ioaddr + UART_MSR); + + clear_bit(TTY_IO_ERROR, &tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * and set the speed of the serial port + */ + mxser_change_speed(tty, NULL); + spin_unlock_irqrestore(&info->slock, flags); + + return 0; +} + +/* + * This routine will shutdown a serial port + */ +static void mxser_shutdown_port(struct tty_port *port) +{ + struct mxser_port *info = container_of(port, struct mxser_port, port); + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->port.delta_msr_wait); + + /* + * Free the xmit buffer, if necessary + */ + if (info->port.xmit_buf) { + free_page((unsigned long) info->port.xmit_buf); + info->port.xmit_buf = NULL; + } + + info->IER = 0; + outb(0x00, info->ioaddr + UART_IER); + + /* clear Rx/Tx FIFO's */ + if (info->board->chip_flag) + outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE, + info->ioaddr + UART_FCR); + else + outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, + info->ioaddr + UART_FCR); + + /* read data port to reset things */ + (void) inb(info->ioaddr + UART_RX); + + + if (info->board->chip_flag) + SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); + + spin_unlock_irqrestore(&info->slock, flags); +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int mxser_open(struct tty_struct *tty, struct file *filp) +{ + struct mxser_port *info; + int line; + + line = tty->index; + if (line == MXSER_PORTS) + return 0; + if (line < 0 || line > MXSER_PORTS) + return -ENODEV; + info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; + if (!info->ioaddr) + return -ENODEV; + + tty->driver_data = info; + return tty_port_open(&info->port, tty, filp); +} + +static void mxser_flush_buffer(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + char fcr; + unsigned long flags; + + + spin_lock_irqsave(&info->slock, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + fcr = inb(info->ioaddr + UART_FCR); + outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->ioaddr + UART_FCR); + outb(fcr, info->ioaddr + UART_FCR); + + spin_unlock_irqrestore(&info->slock, flags); + + tty_wakeup(tty); +} + + +static void mxser_close_port(struct tty_port *port) +{ + struct mxser_port *info = container_of(port, struct mxser_port, port); + unsigned long timeout; + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~UART_IER_RLSI; + if (info->board->chip_flag) + info->IER &= ~MOXA_MUST_RECV_ISR; + + outb(info->IER, info->ioaddr + UART_IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + timeout = jiffies + HZ; + while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { + schedule_timeout_interruptible(5); + if (time_after(jiffies, timeout)) + break; + } +} + +/* + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + */ +static void mxser_close(struct tty_struct *tty, struct file *filp) +{ + struct mxser_port *info = tty->driver_data; + struct tty_port *port = &info->port; + + if (tty->index == MXSER_PORTS || info == NULL) + return; + if (tty_port_close_start(port, tty, filp) == 0) + return; + mutex_lock(&port->mutex); + mxser_close_port(port); + mxser_flush_buffer(tty); + mxser_shutdown_port(port); + clear_bit(ASYNCB_INITIALIZED, &port->flags); + mutex_unlock(&port->mutex); + /* Right now the tty_port set is done outside of the close_end helper + as we don't yet have everyone using refcounts */ + tty_port_close_end(port, tty); + tty_port_tty_set(port, NULL); +} + +static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + int c, total = 0; + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (!info->port.xmit_buf) + return 0; + + while (1) { + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + memcpy(info->port.xmit_buf + info->xmit_head, buf, c); + spin_lock_irqsave(&info->slock, flags); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->slock, flags); + + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + (info->board->chip_flag)) { + spin_lock_irqsave(&info->slock, flags); + outb(info->IER & ~UART_IER_THRI, info->ioaddr + + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } + return total; +} + +static int mxser_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (!info->port.xmit_buf) + return 0; + + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) + return 0; + + spin_lock_irqsave(&info->slock, flags); + info->port.xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE - 1; + info->xmit_cnt++; + spin_unlock_irqrestore(&info->slock, flags); + if (!tty->stopped) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } + return 1; +} + + +static void mxser_flush_chars(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || + (tty->hw_stopped && info->type != PORT_16550A && + !info->board->chip_flag)) + return; + + spin_lock_irqsave(&info->slock, flags); + + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + + spin_unlock_irqrestore(&info->slock, flags); +} + +static int mxser_write_room(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + int ret; + + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + return ret < 0 ? 0 : ret; +} + +static int mxser_chars_in_buffer(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + return info->xmit_cnt; +} + +/* + * ------------------------------------------------------------ + * friends of mxser_ioctl() + * ------------------------------------------------------------ + */ +static int mxser_get_serial_info(struct tty_struct *tty, + struct serial_struct __user *retinfo) +{ + struct mxser_port *info = tty->driver_data; + struct serial_struct tmp = { + .type = info->type, + .line = tty->index, + .port = info->ioaddr, + .irq = info->board->irq, + .flags = info->port.flags, + .baud_base = info->baud_base, + .close_delay = info->port.close_delay, + .closing_wait = info->port.closing_wait, + .custom_divisor = info->custom_divisor, + .hub6 = 0 + }; + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int mxser_set_serial_info(struct tty_struct *tty, + struct serial_struct __user *new_info) +{ + struct mxser_port *info = tty->driver_data; + struct tty_port *port = &info->port; + struct serial_struct new_serial; + speed_t baud; + unsigned long sl_flags; + unsigned int flags; + int retval = 0; + + if (!new_info || !info->ioaddr) + return -ENODEV; + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + + if (new_serial.irq != info->board->irq || + new_serial.port != info->ioaddr) + return -EINVAL; + + flags = port->flags & ASYNC_SPD_MASK; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.close_delay != info->port.close_delay) || + ((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) + return -EPERM; + info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + } else { + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + port->flags = ((port->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + port->close_delay = new_serial.close_delay * HZ / 100; + port->closing_wait = new_serial.closing_wait * HZ / 100; + tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && + (new_serial.baud_base != info->baud_base || + new_serial.custom_divisor != + info->custom_divisor)) { + if (new_serial.custom_divisor == 0) + return -EINVAL; + baud = new_serial.baud_base / new_serial.custom_divisor; + tty_encode_baud_rate(tty, baud, baud); + } + } + + info->type = new_serial.type; + + process_txrx_fifo(info); + + if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { + if (flags != (port->flags & ASYNC_SPD_MASK)) { + spin_lock_irqsave(&info->slock, sl_flags); + mxser_change_speed(tty, NULL); + spin_unlock_irqrestore(&info->slock, sl_flags); + } + } else { + retval = mxser_activate(port, tty); + if (retval == 0) + set_bit(ASYNCB_INITIALIZED, &port->flags); + } + return retval; +} + +/* + * mxser_get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int mxser_get_lsr_info(struct mxser_port *info, + unsigned int __user *value) +{ + unsigned char status; + unsigned int result; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + status = inb(info->ioaddr + UART_LSR); + spin_unlock_irqrestore(&info->slock, flags); + result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); + return put_user(result, value); +} + +static int mxser_tiocmget(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned char control, status; + unsigned long flags; + + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; + if (test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + control = info->MCR; + + spin_lock_irqsave(&info->slock, flags); + status = inb(info->ioaddr + UART_MSR); + if (status & UART_MSR_ANY_DELTA) + mxser_check_modem_status(tty, info, status); + spin_unlock_irqrestore(&info->slock, flags); + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | + ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | + ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | + ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | + ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | + ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); +} + +static int mxser_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; + if (test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + spin_lock_irqsave(&info->slock, flags); + + if (set & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; + + if (clear & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; + + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + return 0; +} + +static int __init mxser_program_mode(int port) +{ + int id, i, j, n; + + outb(0, port); + outb(0, port); + outb(0, port); + (void)inb(port); + (void)inb(port); + outb(0, port); + (void)inb(port); + + id = inb(port + 1) & 0x1F; + if ((id != C168_ASIC_ID) && + (id != C104_ASIC_ID) && + (id != C102_ASIC_ID) && + (id != CI132_ASIC_ID) && + (id != CI134_ASIC_ID) && + (id != CI104J_ASIC_ID)) + return -1; + for (i = 0, j = 0; i < 4; i++) { + n = inb(port + 2); + if (n == 'M') { + j = 1; + } else if ((j == 1) && (n == 1)) { + j = 2; + break; + } else + j = 0; + } + if (j != 2) + id = -2; + return id; +} + +static void __init mxser_normal_mode(int port) +{ + int i, n; + + outb(0xA5, port + 1); + outb(0x80, port + 3); + outb(12, port + 0); /* 9600 bps */ + outb(0, port + 1); + outb(0x03, port + 3); /* 8 data bits */ + outb(0x13, port + 4); /* loop back mode */ + for (i = 0; i < 16; i++) { + n = inb(port + 5); + if ((n & 0x61) == 0x60) + break; + if ((n & 1) == 1) + (void)inb(port); + } + outb(0x00, port + 4); +} + +#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ +#define CHIP_DO 0x02 /* Serial Data Output in Eprom */ +#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ +#define CHIP_DI 0x08 /* Serial Data Input in Eprom */ +#define EN_CCMD 0x000 /* Chip's command register */ +#define EN0_RSARLO 0x008 /* Remote start address reg 0 */ +#define EN0_RSARHI 0x009 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ +#define EN0_DCFG 0x00E /* Data configuration reg WR */ +#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 __init mxser_read_register(int port, unsigned short *regs) +{ + int i, k, value, id; + unsigned int j; + + id = mxser_program_mode(port); + if (id < 0) + return id; + for (i = 0; i < 14; i++) { + k = (i & 0x3F) | 0x180; + for (j = 0x100; j > 0; j >>= 1) { + outb(CHIP_CS, port); + if (k & j) { + outb(CHIP_CS | CHIP_DO, port); + outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ + } else { + outb(CHIP_CS, port); + outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ + } + } + (void)inb(port); + value = 0; + for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { + outb(CHIP_CS, port); + outb(CHIP_CS | CHIP_SK, port); + if (inb(port) & CHIP_DI) + value |= j; + } + regs[i] = value; + outb(0, port); + } + mxser_normal_mode(port); + return id; +} + +static int mxser_ioctl_special(unsigned int cmd, void __user *argp) +{ + struct mxser_port *ip; + struct tty_port *port; + struct tty_struct *tty; + int result, status; + unsigned int i, j; + int ret = 0; + + switch (cmd) { + case MOXA_GET_MAJOR: + if (printk_ratelimit()) + printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl " + "%x (GET_MAJOR), fix your userspace\n", + current->comm, cmd); + return put_user(ttymajor, (int __user *)argp); + + case MOXA_CHKPORTENABLE: + result = 0; + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) + if (mxser_boards[i].ports[j].ioaddr) + result |= (1 << i); + return put_user(result, (unsigned long __user *)argp); + case MOXA_GETDATACOUNT: + /* The receive side is locked by port->slock but it isn't + clear that an exact snapshot is worth copying here */ + if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) + ret = -EFAULT; + return ret; + case MOXA_GETMSTATUS: { + struct mxser_mstatus ms, __user *msu = argp; + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + ip = &mxser_boards[i].ports[j]; + port = &ip->port; + memset(&ms, 0, sizeof(ms)); + + mutex_lock(&port->mutex); + if (!ip->ioaddr) + goto copy; + + tty = tty_port_tty_get(port); + + if (!tty || !tty->termios) + ms.cflag = ip->normal_termios.c_cflag; + else + ms.cflag = tty->termios->c_cflag; + tty_kref_put(tty); + spin_lock_irq(&ip->slock); + status = inb(ip->ioaddr + UART_MSR); + spin_unlock_irq(&ip->slock); + if (status & UART_MSR_DCD) + ms.dcd = 1; + if (status & UART_MSR_DSR) + ms.dsr = 1; + if (status & UART_MSR_CTS) + ms.cts = 1; + copy: + mutex_unlock(&port->mutex); + if (copy_to_user(msu, &ms, sizeof(ms))) + return -EFAULT; + msu++; + } + return 0; + } + case MOXA_ASPP_MON_EXT: { + struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ + unsigned int cflag, iflag, p; + u8 opmode; + + me = kzalloc(sizeof(*me), GFP_KERNEL); + if (!me) + return -ENOMEM; + + for (i = 0, p = 0; i < MXSER_BOARDS; i++) { + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { + if (p >= ARRAY_SIZE(me->rx_cnt)) { + i = MXSER_BOARDS; + break; + } + ip = &mxser_boards[i].ports[j]; + port = &ip->port; + + mutex_lock(&port->mutex); + if (!ip->ioaddr) { + mutex_unlock(&port->mutex); + continue; + } + + spin_lock_irq(&ip->slock); + status = mxser_get_msr(ip->ioaddr, 0, p); + + if (status & UART_MSR_TERI) + ip->icount.rng++; + if (status & UART_MSR_DDSR) + ip->icount.dsr++; + if (status & UART_MSR_DDCD) + ip->icount.dcd++; + if (status & UART_MSR_DCTS) + ip->icount.cts++; + + ip->mon_data.modem_status = status; + me->rx_cnt[p] = ip->mon_data.rxcnt; + me->tx_cnt[p] = ip->mon_data.txcnt; + me->up_rxcnt[p] = ip->mon_data.up_rxcnt; + me->up_txcnt[p] = ip->mon_data.up_txcnt; + me->modem_status[p] = + ip->mon_data.modem_status; + spin_unlock_irq(&ip->slock); + + tty = tty_port_tty_get(&ip->port); + + if (!tty || !tty->termios) { + cflag = ip->normal_termios.c_cflag; + iflag = ip->normal_termios.c_iflag; + me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); + } else { + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; + me->baudrate[p] = tty_get_baud_rate(tty); + } + tty_kref_put(tty); + + me->databits[p] = cflag & CSIZE; + me->stopbits[p] = cflag & CSTOPB; + me->parity[p] = cflag & (PARENB | PARODD | + CMSPAR); + + if (cflag & CRTSCTS) + me->flowctrl[p] |= 0x03; + + if (iflag & (IXON | IXOFF)) + me->flowctrl[p] |= 0x0C; + + if (ip->type == PORT_16550A) + me->fifo[p] = 1; + + opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); + opmode &= OP_MODE_MASK; + me->iftype[p] = opmode; + mutex_unlock(&port->mutex); + } + } + if (copy_to_user(argp, me, sizeof(*me))) + ret = -EFAULT; + kfree(me); + return ret; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg, + struct async_icount *cprev) +{ + struct async_icount cnow; + unsigned long flags; + int ret; + + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; /* atomic copy */ + spin_unlock_irqrestore(&info->slock, flags); + + ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); + + *cprev = cnow; + + return ret; +} + +static int mxser_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct mxser_port *info = tty->driver_data; + struct tty_port *port = &info->port; + struct async_icount cnow; + unsigned long flags; + void __user *argp = (void __user *)arg; + int retval; + + if (tty->index == MXSER_PORTS) + return mxser_ioctl_special(cmd, argp); + + if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { + int p; + unsigned long opmode; + static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; + int shiftbit; + unsigned char val, mask; + + p = tty->index % 4; + if (cmd == MOXA_SET_OP_MODE) { + if (get_user(opmode, (int __user *) argp)) + return -EFAULT; + if (opmode != RS232_MODE && + opmode != RS485_2WIRE_MODE && + opmode != RS422_MODE && + opmode != RS485_4WIRE_MODE) + return -EFAULT; + mask = ModeMask[p]; + shiftbit = p * 2; + spin_lock_irq(&info->slock); + val = inb(info->opmode_ioaddr); + val &= mask; + val |= (opmode << shiftbit); + outb(val, info->opmode_ioaddr); + spin_unlock_irq(&info->slock); + } else { + shiftbit = p * 2; + spin_lock_irq(&info->slock); + opmode = inb(info->opmode_ioaddr) >> shiftbit; + spin_unlock_irq(&info->slock); + opmode &= OP_MODE_MASK; + if (put_user(opmode, (int __user *)argp)) + return -EFAULT; + } + return 0; + } + + if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && + test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + switch (cmd) { + case TIOCGSERIAL: + mutex_lock(&port->mutex); + retval = mxser_get_serial_info(tty, argp); + mutex_unlock(&port->mutex); + return retval; + case TIOCSSERIAL: + mutex_lock(&port->mutex); + retval = mxser_set_serial_info(tty, argp); + mutex_unlock(&port->mutex); + return retval; + case TIOCSERGETLSR: /* Get line status register */ + return mxser_get_lsr_info(info, argp); + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; /* note the counters on entry */ + spin_unlock_irqrestore(&info->slock, flags); + + return wait_event_interruptible(info->port.delta_msr_wait, + mxser_cflags_changed(info, arg, &cnow)); + case MOXA_HighSpeedOn: + return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); + case MOXA_SDS_RSTICOUNTER: + spin_lock_irq(&info->slock); + info->mon_data.rxcnt = 0; + info->mon_data.txcnt = 0; + spin_unlock_irq(&info->slock); + return 0; + + case MOXA_ASPP_OQUEUE:{ + int len, lsr; + + len = mxser_chars_in_buffer(tty); + spin_lock_irq(&info->slock); + lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; + spin_unlock_irq(&info->slock); + len += (lsr ? 0 : 1); + + return put_user(len, (int __user *)argp); + } + case MOXA_ASPP_MON: { + int mcr, status; + + spin_lock_irq(&info->slock); + status = mxser_get_msr(info->ioaddr, 1, tty->index); + mxser_check_modem_status(tty, info, status); + + mcr = inb(info->ioaddr + UART_MCR); + spin_unlock_irq(&info->slock); + + if (mcr & MOXA_MUST_MCR_XON_FLAG) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; + + if (mcr & MOXA_MUST_MCR_TX_XON) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; + + if (tty->hw_stopped) + info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; + else + info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; + + if (copy_to_user(argp, &info->mon_data, + sizeof(struct mxser_mon))) + return -EFAULT; + + return 0; + } + case MOXA_ASPP_LSTATUS: { + if (put_user(info->err_shadow, (unsigned char __user *)argp)) + return -EFAULT; + + info->err_shadow = 0; + return 0; + } + case MOXA_SET_BAUD_METHOD: { + int method; + + if (get_user(method, (int __user *)argp)) + return -EFAULT; + mxser_set_baud_method[tty->index] = method; + return put_user(method, (int __user *)argp); + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + +static int mxser_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) + +{ + struct mxser_port *info = tty->driver_data; + struct async_icount cnow; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->slock, flags); + + icount->frame = cnow.frame; + icount->brk = cnow.brk; + icount->overrun = cnow.overrun; + icount->buf_overrun = cnow.buf_overrun; + icount->parity = cnow.parity; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + return 0; +} + +static void mxser_stoprx(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + info->ldisc_stop_rx = 1; + if (I_IXOFF(tty)) { + if (info->board->chip_flag) { + info->IER &= ~MOXA_MUST_RECV_ISR; + outb(info->IER, info->ioaddr + UART_IER); + } else { + info->x_char = STOP_CHAR(tty); + outb(0, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + } + + if (tty->termios->c_cflag & CRTSCTS) { + info->MCR &= ~UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + } +} + +/* + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + */ +static void mxser_throttle(struct tty_struct *tty) +{ + mxser_stoprx(tty); +} + +static void mxser_unthrottle(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + /* startrx */ + info->ldisc_stop_rx = 0; + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else { + if (info->board->chip_flag) { + info->IER |= MOXA_MUST_RECV_ISR; + outb(info->IER, info->ioaddr + UART_IER); + } else { + info->x_char = START_CHAR(tty); + outb(0, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + } + } + + if (tty->termios->c_cflag & CRTSCTS) { + info->MCR |= UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + } +} + +/* + * mxser_stop() and mxser_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + */ +static void mxser_stop(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (info->IER & UART_IER_THRI) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_start(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (info->xmit_cnt && info->port.xmit_buf) { + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + mxser_change_speed(tty, old_termios); + spin_unlock_irqrestore(&info->slock, flags); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mxser_start(tty); + } + + /* Handle sw stopped */ + if ((old_termios->c_iflag & IXON) && + !(tty->termios->c_iflag & IXON)) { + tty->stopped = 0; + + if (info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + mxser_disable_must_rx_software_flow_control( + info->ioaddr); + spin_unlock_irqrestore(&info->slock, flags); + } + + mxser_start(tty); + } +} + +/* + * mxser_wait_until_sent() --- wait until the transmitter is empty + */ +static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct mxser_port *info = tty->driver_data; + unsigned long orig_jiffies, char_time; + unsigned long flags; + int lsr; + + if (info->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", + timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + spin_lock_irqsave(&info->slock, flags); + while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + spin_unlock_irqrestore(&info->slock, flags); + schedule_timeout_interruptible(char_time); + spin_lock_irqsave(&info->slock, flags); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + spin_unlock_irqrestore(&info->slock, flags); + set_current_state(TASK_RUNNING); + +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * This routine is called by tty_hangup() when a hangup is signaled. + */ +static void mxser_hangup(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + mxser_flush_buffer(tty); + tty_port_hangup(&info->port); +} + +/* + * mxser_rs_break() --- routine which turns the break handling on or off + */ +static int mxser_rs_break(struct tty_struct *tty, int break_state) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (break_state == -1) + outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, + info->ioaddr + UART_LCR); + else + outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); + return 0; +} + +static void mxser_receive_chars(struct tty_struct *tty, + struct mxser_port *port, int *status) +{ + unsigned char ch, gdl; + int ignored = 0; + int cnt = 0; + int recv_room; + int max = 256; + + recv_room = tty->receive_room; + if (recv_room == 0 && !port->ldisc_stop_rx) + mxser_stoprx(tty); + if (port->board->chip_flag != MOXA_OTHER_UART) { + + if (*status & UART_LSR_SPECIAL) + goto intr_old; + if (port->board->chip_flag == MOXA_MUST_MU860_HWID && + (*status & MOXA_MUST_LSR_RERR)) + goto intr_old; + if (*status & MOXA_MUST_LSR_RERR) + goto intr_old; + + gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); + + if (port->board->chip_flag == MOXA_MUST_MU150_HWID) + gdl &= MOXA_MUST_GDL_MASK; + if (gdl >= recv_room) { + if (!port->ldisc_stop_rx) + mxser_stoprx(tty); + } + while (gdl--) { + ch = inb(port->ioaddr + UART_RX); + tty_insert_flip_char(tty, ch, 0); + cnt++; + } + goto end_intr; + } +intr_old: + + do { + if (max-- < 0) + break; + + ch = inb(port->ioaddr + UART_RX); + if (port->board->chip_flag && (*status & UART_LSR_OE)) + outb(0x23, port->ioaddr + UART_FCR); + *status &= port->read_status_mask; + if (*status & port->ignore_status_mask) { + if (++ignored > 100) + break; + } else { + char flag = 0; + if (*status & UART_LSR_SPECIAL) { + if (*status & UART_LSR_BI) { + flag = TTY_BREAK; + port->icount.brk++; + + if (port->port.flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & UART_LSR_PE) { + flag = TTY_PARITY; + port->icount.parity++; + } else if (*status & UART_LSR_FE) { + flag = TTY_FRAME; + port->icount.frame++; + } else if (*status & UART_LSR_OE) { + flag = TTY_OVERRUN; + port->icount.overrun++; + } else + flag = TTY_BREAK; + } + tty_insert_flip_char(tty, ch, flag); + cnt++; + if (cnt >= recv_room) { + if (!port->ldisc_stop_rx) + mxser_stoprx(tty); + break; + } + + } + + if (port->board->chip_flag) + break; + + *status = inb(port->ioaddr + UART_LSR); + } while (*status & UART_LSR_DR); + +end_intr: + mxvar_log.rxcnt[tty->index] += cnt; + port->mon_data.rxcnt += cnt; + port->mon_data.up_rxcnt += cnt; + + /* + * We are called from an interrupt context with &port->slock + * being held. Drop it temporarily in order to prevent + * recursive locking. + */ + spin_unlock(&port->slock); + tty_flip_buffer_push(tty); + spin_lock(&port->slock); +} + +static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port) +{ + int count, cnt; + + if (port->x_char) { + outb(port->x_char, port->ioaddr + UART_TX); + port->x_char = 0; + mxvar_log.txcnt[tty->index]++; + port->mon_data.txcnt++; + port->mon_data.up_txcnt++; + port->icount.tx++; + return; + } + + if (port->port.xmit_buf == NULL) + return; + + if (port->xmit_cnt <= 0 || tty->stopped || + (tty->hw_stopped && + (port->type != PORT_16550A) && + (!port->board->chip_flag))) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + UART_IER); + return; + } + + cnt = port->xmit_cnt; + count = port->xmit_fifo_size; + do { + outb(port->port.xmit_buf[port->xmit_tail++], + port->ioaddr + UART_TX); + port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); + if (--port->xmit_cnt <= 0) + break; + } while (--count > 0); + mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt); + + port->mon_data.txcnt += (cnt - port->xmit_cnt); + port->mon_data.up_txcnt += (cnt - port->xmit_cnt); + port->icount.tx += (cnt - port->xmit_cnt); + + if (port->xmit_cnt < WAKEUP_CHARS) + tty_wakeup(tty); + + if (port->xmit_cnt <= 0) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + UART_IER); + } +} + +/* + * This is the serial driver's generic interrupt routine + */ +static irqreturn_t mxser_interrupt(int irq, void *dev_id) +{ + int status, iir, i; + struct mxser_board *brd = NULL; + struct mxser_port *port; + int max, irqbits, bits, msr; + unsigned int int_cnt, pass_counter = 0; + int handled = IRQ_NONE; + struct tty_struct *tty; + + for (i = 0; i < MXSER_BOARDS; i++) + if (dev_id == &mxser_boards[i]) { + brd = dev_id; + break; + } + + if (i == MXSER_BOARDS) + goto irq_stop; + if (brd == NULL) + goto irq_stop; + max = brd->info->nports; + while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { + irqbits = inb(brd->vector) & brd->vector_mask; + if (irqbits == brd->vector_mask) + break; + + handled = IRQ_HANDLED; + for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { + if (irqbits == brd->vector_mask) + break; + if (bits & irqbits) + continue; + 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; + tty = tty_port_tty_get(&port->port); + if (!tty || + (port->port.flags & ASYNC_CLOSING) || + !(port->port.flags & + ASYNC_INITIALIZED)) { + status = inb(port->ioaddr + UART_LSR); + outb(0x27, port->ioaddr + UART_FCR); + inb(port->ioaddr + UART_MSR); + tty_kref_put(tty); + break; + } + + status = inb(port->ioaddr + UART_LSR); + + if (status & UART_LSR_PE) + port->err_shadow |= NPPI_NOTIFY_PARITY; + if (status & UART_LSR_FE) + port->err_shadow |= NPPI_NOTIFY_FRAMING; + if (status & UART_LSR_OE) + port->err_shadow |= + NPPI_NOTIFY_HW_OVERRUN; + if (status & UART_LSR_BI) + port->err_shadow |= NPPI_NOTIFY_BREAK; + + if (port->board->chip_flag) { + if (iir == MOXA_MUST_IIR_GDA || + iir == MOXA_MUST_IIR_RDA || + iir == MOXA_MUST_IIR_RTO || + iir == MOXA_MUST_IIR_LSR) + mxser_receive_chars(tty, port, + &status); + + } else { + status &= port->read_status_mask; + if (status & UART_LSR_DR) + mxser_receive_chars(tty, port, + &status); + } + msr = inb(port->ioaddr + UART_MSR); + if (msr & UART_MSR_ANY_DELTA) + mxser_check_modem_status(tty, port, msr); + + if (port->board->chip_flag) { + if (iir == 0x02 && (status & + UART_LSR_THRE)) + mxser_transmit_chars(tty, port); + } else { + if (status & UART_LSR_THRE) + mxser_transmit_chars(tty, port); + } + tty_kref_put(tty); + } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); + spin_unlock(&port->slock); + } + } + +irq_stop: + return handled; +} + +static const struct tty_operations mxser_ops = { + .open = mxser_open, + .close = mxser_close, + .write = mxser_write, + .put_char = mxser_put_char, + .flush_chars = mxser_flush_chars, + .write_room = mxser_write_room, + .chars_in_buffer = mxser_chars_in_buffer, + .flush_buffer = mxser_flush_buffer, + .ioctl = mxser_ioctl, + .throttle = mxser_throttle, + .unthrottle = mxser_unthrottle, + .set_termios = mxser_set_termios, + .stop = mxser_stop, + .start = mxser_start, + .hangup = mxser_hangup, + .break_ctl = mxser_rs_break, + .wait_until_sent = mxser_wait_until_sent, + .tiocmget = mxser_tiocmget, + .tiocmset = mxser_tiocmset, + .get_icount = mxser_get_icount, +}; + +struct tty_port_operations mxser_port_ops = { + .carrier_raised = mxser_carrier_raised, + .dtr_rts = mxser_dtr_rts, + .activate = mxser_activate, + .shutdown = mxser_shutdown_port, +}; + +/* + * The MOXA Smartio/Industio serial driver boot-time initialization code! + */ + +static void mxser_release_ISA_res(struct mxser_board *brd) +{ + free_irq(brd->irq, brd); + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + release_region(brd->vector, 1); +} + +static int __devinit mxser_initbrd(struct mxser_board *brd, + struct pci_dev *pdev) +{ + struct mxser_port *info; + unsigned int i; + int retval; + + printk(KERN_INFO "mxser: max. baud rate = %d bps\n", + brd->ports[0].max_baud); + + for (i = 0; i < brd->info->nports; i++) { + info = &brd->ports[i]; + tty_port_init(&info->port); + info->port.ops = &mxser_port_ops; + info->board = brd; + info->stop_rx = 0; + info->ldisc_stop_rx = 0; + + /* Enhance mode enabled here */ + if (brd->chip_flag != MOXA_OTHER_UART) + mxser_enable_must_enchance_mode(info->ioaddr); + + info->port.flags = ASYNC_SHARE_IRQ; + info->type = brd->uart_type; + + process_txrx_fifo(info); + + info->custom_divisor = info->baud_base * 16; + info->port.close_delay = 5 * HZ / 10; + info->port.closing_wait = 30 * HZ; + info->normal_termios = mxvar_sdriver->init_termios; + memset(&info->mon_data, 0, sizeof(struct mxser_mon)); + info->err_shadow = 0; + spin_lock_init(&info->slock); + + /* before set INT ISR, disable all int */ + outb(inb(info->ioaddr + UART_IER) & 0xf0, + info->ioaddr + UART_IER); + } + + 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); + + return retval; +} + +static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) +{ + int id, i, bits; + unsigned short regs[16], irq; + unsigned char scratch, scratch2; + + brd->chip_flag = MOXA_OTHER_UART; + + id = mxser_read_register(cap, regs); + switch (id) { + case C168_ASIC_ID: + brd->info = &mxser_cards[0]; + break; + case C104_ASIC_ID: + brd->info = &mxser_cards[1]; + break; + case CI104J_ASIC_ID: + brd->info = &mxser_cards[2]; + break; + case C102_ASIC_ID: + brd->info = &mxser_cards[5]; + break; + case CI132_ASIC_ID: + brd->info = &mxser_cards[6]; + break; + case CI134_ASIC_ID: + brd->info = &mxser_cards[7]; + break; + default: + return 0; + } + + irq = 0; + /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) + Flag-hack checks if configuration should be read as 2-port here. */ + if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + if (irq != (regs[9] & 0xFF00)) + goto err_irqconflict; + } else if (brd->info->nports == 4) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if (irq != regs[9]) + goto err_irqconflict; + } else if (brd->info->nports == 8) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if ((irq != regs[9]) || (irq != regs[10])) + goto err_irqconflict; + } + + if (!irq) { + printk(KERN_ERR "mxser: interrupt number unset\n"); + return -EIO; + } + brd->irq = ((int)(irq & 0xF000) >> 12); + for (i = 0; i < 8; i++) + brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; + if ((regs[12] & 0x80) == 0) { + printk(KERN_ERR "mxser: invalid interrupt vector\n"); + return -EIO; + } + brd->vector = (int)regs[11]; /* interrupt vector */ + if (id == 1) + brd->vector_mask = 0x00FF; + else + brd->vector_mask = 0x000F; + for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { + if (regs[12] & bits) { + brd->ports[i].baud_base = 921600; + brd->ports[i].max_baud = 921600; + } else { + brd->ports[i].baud_base = 115200; + brd->ports[i].max_baud = 115200; + } + } + scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); + outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); + outb(0, cap + UART_EFR); /* EFR is the same as FCR */ + outb(scratch2, cap + UART_LCR); + outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); + scratch = inb(cap + UART_IIR); + + if (scratch & 0xC0) + brd->uart_type = PORT_16550A; + else + brd->uart_type = PORT_16450; + if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, + "mxser(IO)")) { + printk(KERN_ERR "mxser: can't request ports I/O region: " + "0x%.8lx-0x%.8lx\n", + brd->ports[0].ioaddr, brd->ports[0].ioaddr + + 8 * brd->info->nports - 1); + return -EIO; + } + if (!request_region(brd->vector, 1, "mxser(vector)")) { + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + printk(KERN_ERR "mxser: can't request interrupt vector region: " + "0x%.8lx-0x%.8lx\n", + brd->ports[0].ioaddr, brd->ports[0].ioaddr + + 8 * brd->info->nports - 1); + return -EIO; + } + return brd->info->nports; + +err_irqconflict: + printk(KERN_ERR "mxser: invalid interrupt number\n"); + return -EIO; +} + +static int __devinit mxser_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ +#ifdef CONFIG_PCI + struct mxser_board *brd; + unsigned int i, j; + unsigned long ioaddress; + int retval = -EINVAL; + + for (i = 0; i < MXSER_BOARDS; i++) + if (mxser_boards[i].info == NULL) + break; + + if (i >= MXSER_BOARDS) { + dev_err(&pdev->dev, "too many boards found (maximum %d), board " + "not configured\n", MXSER_BOARDS); + goto err; + } + + brd = &mxser_boards[i]; + brd->idx = i * MXSER_PORTS_PER_BOARD; + dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", + mxser_cards[ent->driver_data].name, + pdev->bus->number, PCI_SLOT(pdev->devfn)); + + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "PCI enable failed\n"); + goto err; + } + + /* io address */ + ioaddress = pci_resource_start(pdev, 2); + retval = pci_request_region(pdev, 2, "mxser(IO)"); + if (retval) + goto err_dis; + + brd->info = &mxser_cards[ent->driver_data]; + for (i = 0; i < brd->info->nports; i++) + brd->ports[i].ioaddr = ioaddress + 8 * i; + + /* vector */ + ioaddress = pci_resource_start(pdev, 3); + retval = pci_request_region(pdev, 3, "mxser(vector)"); + if (retval) + goto err_zero; + brd->vector = ioaddress; + + /* irq */ + brd->irq = pdev->irq; + + brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); + brd->uart_type = PORT_16550A; + brd->vector_mask = 0; + + for (i = 0; i < brd->info->nports; i++) { + for (j = 0; j < UART_INFO_NUM; j++) { + if (Gpci_uart_info[j].type == brd->chip_flag) { + brd->ports[i].max_baud = + Gpci_uart_info[j].max_baud; + + /* exception....CP-102 */ + if (brd->info->flags & MXSER_HIGHBAUD) + brd->ports[i].max_baud = 921600; + break; + } + } + } + + if (brd->chip_flag == MOXA_MUST_MU860_HWID) { + for (i = 0; i < brd->info->nports; i++) { + if (i < 4) + brd->ports[i].opmode_ioaddr = ioaddress + 4; + else + brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; + } + outb(0, ioaddress + 4); /* default set to RS232 mode */ + outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ + } + + for (i = 0; i < brd->info->nports; i++) { + brd->vector_mask |= (1 << i); + brd->ports[i].baud_base = 921600; + } + + /* mxser_initbrd will hook ISR. */ + retval = mxser_initbrd(brd, pdev); + if (retval) + goto err_rel3; + + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); + + pci_set_drvdata(pdev, brd); + + return 0; +err_rel3: + pci_release_region(pdev, 3); +err_zero: + brd->info = NULL; + pci_release_region(pdev, 2); +err_dis: + pci_disable_device(pdev); +err: + return retval; +#else + return -ENODEV; +#endif +} + +static void __devexit mxser_remove(struct pci_dev *pdev) +{ +#ifdef CONFIG_PCI + struct mxser_board *brd = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < brd->info->nports; i++) + tty_unregister_device(mxvar_sdriver, brd->idx + i); + + free_irq(pdev->irq, brd); + pci_release_region(pdev, 2); + pci_release_region(pdev, 3); + pci_disable_device(pdev); + brd->info = NULL; +#endif +} + +static struct pci_driver mxser_driver = { + .name = "mxser", + .id_table = mxser_pcibrds, + .probe = mxser_probe, + .remove = __devexit_p(mxser_remove) +}; + +static int __init mxser_module_init(void) +{ + struct mxser_board *brd; + unsigned int b, i, m; + int retval; + + mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); + if (!mxvar_sdriver) + return -ENOMEM; + + printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", + MXSER_VERSION); + + /* Initialize the tty_driver structure */ + mxvar_sdriver->owner = THIS_MODULE; + mxvar_sdriver->magic = TTY_DRIVER_MAGIC; + mxvar_sdriver->name = "ttyMI"; + mxvar_sdriver->major = ttymajor; + mxvar_sdriver->minor_start = 0; + mxvar_sdriver->num = MXSER_PORTS + 1; + mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; + mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; + mxvar_sdriver->init_termios = tty_std_termios; + mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(mxvar_sdriver, &mxser_ops); + + retval = tty_register_driver(mxvar_sdriver); + if (retval) { + printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family " + "tty driver !\n"); + goto err_put; + } + + /* Start finding ISA boards here */ + for (m = 0, b = 0; b < MXSER_BOARDS; b++) { + if (!ioaddr[b]) + continue; + + brd = &mxser_boards[m]; + retval = mxser_get_ISA_conf(ioaddr[b], brd); + if (retval <= 0) { + brd->info = NULL; + continue; + } + + printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", + brd->info->name, ioaddr[b]); + + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, NULL) < 0) { + brd->info = NULL; + continue; + } + + brd->idx = m * MXSER_PORTS_PER_BOARD; + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, NULL); + + m++; + } + + retval = pci_register_driver(&mxser_driver); + if (retval) { + printk(KERN_ERR "mxser: can't register pci driver\n"); + if (!m) { + retval = -ENODEV; + goto err_unr; + } /* else: we have some ISA cards under control */ + } + + return 0; +err_unr: + tty_unregister_driver(mxvar_sdriver); +err_put: + put_tty_driver(mxvar_sdriver); + return retval; +} + +static void __exit mxser_module_exit(void) +{ + unsigned int i, j; + + pci_unregister_driver(&mxser_driver); + + for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ + if (mxser_boards[i].info != NULL) + for (j = 0; j < mxser_boards[i].info->nports; j++) + tty_unregister_device(mxvar_sdriver, + mxser_boards[i].idx + j); + tty_unregister_driver(mxvar_sdriver); + put_tty_driver(mxvar_sdriver); + + for (i = 0; i < MXSER_BOARDS; i++) + if (mxser_boards[i].info != NULL) + mxser_release_ISA_res(&mxser_boards[i]); +} + +module_init(mxser_module_init); +module_exit(mxser_module_exit); diff --git a/drivers/tty/mxser.h b/drivers/tty/mxser.h new file mode 100644 index 000000000000..41878a69203d --- /dev/null +++ b/drivers/tty/mxser.h @@ -0,0 +1,150 @@ +#ifndef _MXSER_H +#define _MXSER_H + +/* + * Semi-public control interfaces + */ + +/* + * MOXA ioctls + */ + +#define MOXA 0x400 +#define MOXA_GETDATACOUNT (MOXA + 23) +#define MOXA_DIAGNOSE (MOXA + 50) +#define MOXA_CHKPORTENABLE (MOXA + 60) +#define MOXA_HighSpeedOn (MOXA + 61) +#define MOXA_GET_MAJOR (MOXA + 63) +#define MOXA_GETMSTATUS (MOXA + 65) +#define MOXA_SET_OP_MODE (MOXA + 66) +#define MOXA_GET_OP_MODE (MOXA + 67) + +#define RS232_MODE 0 +#define RS485_2WIRE_MODE 1 +#define RS422_MODE 2 +#define RS485_4WIRE_MODE 3 +#define OP_MODE_MASK 3 + +#define MOXA_SDS_RSTICOUNTER (MOXA + 69) +#define MOXA_ASPP_OQUEUE (MOXA + 70) +#define MOXA_ASPP_MON (MOXA + 73) +#define MOXA_ASPP_LSTATUS (MOXA + 74) +#define MOXA_ASPP_MON_EXT (MOXA + 75) +#define MOXA_SET_BAUD_METHOD (MOXA + 76) + +/* --------------------------------------------------- */ + +#define NPPI_NOTIFY_PARITY 0x01 +#define NPPI_NOTIFY_FRAMING 0x02 +#define NPPI_NOTIFY_HW_OVERRUN 0x04 +#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 */ + +/* 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 */ +#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_EFR_REGISTER 0x02 +/* enchance mode enable */ +#define MOXA_MUST_EFR_EFRB_ENABLE 0x10 +/* 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 */ +#define MOXA_MUST_XON1_REGISTER 0x04 + +/* 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 */ +#define MOXA_MUST_XOFF1_REGISTER 0x06 + +/* set XOFF2 value register, when LCR=0xBF and change to bank0 */ +#define MOXA_MUST_XOFF2_REGISTER 0x07 + +#define MOXA_MUST_RBRTL_REGISTER 0x04 +#define MOXA_MUST_RBRTH_REGISTER 0x05 +#define MOXA_MUST_RBRTI_REGISTER 0x06 +#define MOXA_MUST_THRTL_REGISTER 0x07 +#define MOXA_MUST_ENUM_REGISTER 0x04 +#define MOXA_MUST_HWID_REGISTER 0x05 +#define MOXA_MUST_ECR_REGISTER 0x06 +#define MOXA_MUST_CSR_REGISTER 0x07 + +/* good data mode enable */ +#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 +/* only good data put into RxFIFO */ +#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 + +/* enable CTS interrupt */ +#define MOXA_MUST_IER_ECTSI 0x80 +/* enable RTS interrupt */ +#define MOXA_MUST_IER_ERTSI 0x40 +/* enable Xon/Xoff interrupt */ +#define MOXA_MUST_IER_XINT 0x20 +/* enable GDA interrupt */ +#define MOXA_MUST_IER_EGDAI 0x10 + +#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) + +/* 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 */ +#define MOXA_MUST_IIR_XSC 0x10 + +/* RTS/CTS change state interrupt pending */ +#define MOXA_MUST_IIR_RTSCTS 0x20 +#define MOXA_MUST_IIR_MASK 0x3E + +#define MOXA_MUST_MCR_XON_FLAG 0x40 +#define MOXA_MUST_MCR_XON_ANY 0x80 +#define MOXA_MUST_MCR_TX_XON 0x08 + +/* software flow control on chip mask value */ +#define MOXA_MUST_EFR_SF_MASK 0x0F +/* send Xon1/Xoff1 */ +#define MOXA_MUST_EFR_SF_TX1 0x08 +/* send Xon2/Xoff2 */ +#define MOXA_MUST_EFR_SF_TX2 0x04 +/* send Xon1,Xon2/Xoff1,Xoff2 */ +#define MOXA_MUST_EFR_SF_TX12 0x0C +/* don't send Xon/Xoff */ +#define MOXA_MUST_EFR_SF_TX_NO 0x00 +/* Tx software flow control mask */ +#define MOXA_MUST_EFR_SF_TX_MASK 0x0C +/* don't receive Xon/Xoff */ +#define MOXA_MUST_EFR_SF_RX_NO 0x00 +/* receive Xon1/Xoff1 */ +#define MOXA_MUST_EFR_SF_RX1 0x02 +/* receive Xon2/Xoff2 */ +#define MOXA_MUST_EFR_SF_RX2 0x01 +/* receive Xon1,Xon2/Xoff1,Xoff2 */ +#define MOXA_MUST_EFR_SF_RX12 0x03 +/* Rx software flow control mask */ +#define MOXA_MUST_EFR_SF_RX_MASK 0x03 + +#endif diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c new file mode 100644 index 000000000000..513ba12064ea --- /dev/null +++ b/drivers/tty/nozomi.c @@ -0,0 +1,1993 @@ +/* + * nozomi.c -- HSDPA driver Broadband Wireless Data Card - Globe Trotter + * + * Written by: Ulf Jakobsson, + * Jan Ã…kerfeldt, + * Stefan Thomasson, + * + * Maintained by: Paul Hardwick (p.hardwick@option.com) + * + * Patches: + * Locking code changes for Vodafone by Sphere Systems Ltd, + * Andrew Bird (ajb@spheresystems.co.uk ) + * & Phil Sanderson + * + * Source has been ported from an implementation made by Filip Aben @ Option + * + * -------------------------------------------------------------------------- + * + * Copyright (c) 2005,2006 Option Wireless Sweden AB + * Copyright (c) 2006 Sphere Systems Ltd + * Copyright (c) 2006 Option Wireless n/v + * All rights Reserved. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + * -------------------------------------------------------------------------- + */ + +/* Enable this to have a lot of debug printouts */ +#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \ + __DATE__ " " __TIME__ ")" + +/* Macros definitions */ + +/* Default debug printout level */ +#define NOZOMI_DEBUG_LEVEL 0x00 + +#define P_BUF_SIZE 128 +#define NFO(_err_flag_, args...) \ +do { \ + char tmp[P_BUF_SIZE]; \ + snprintf(tmp, sizeof(tmp), ##args); \ + printk(_err_flag_ "[%d] %s(): %s\n", __LINE__, \ + __func__, tmp); \ +} while (0) + +#define DBG1(args...) D_(0x01, ##args) +#define DBG2(args...) D_(0x02, ##args) +#define DBG3(args...) D_(0x04, ##args) +#define DBG4(args...) D_(0x08, ##args) +#define DBG5(args...) D_(0x10, ##args) +#define DBG6(args...) D_(0x20, ##args) +#define DBG7(args...) D_(0x40, ##args) +#define DBG8(args...) D_(0x80, ##args) + +#ifdef DEBUG +/* Do we need this settable at runtime? */ +static int debug = NOZOMI_DEBUG_LEVEL; + +#define D(lvl, args...) do \ + {if (lvl & debug) NFO(KERN_DEBUG, ##args); } \ + while (0) +#define D_(lvl, args...) D(lvl, ##args) + +/* These printouts are always printed */ + +#else +static int debug; +#define D_(lvl, args...) +#endif + +/* TODO: rewrite to optimize macros... */ + +#define TMP_BUF_MAX 256 + +#define DUMP(buf__,len__) \ + do { \ + char tbuf[TMP_BUF_MAX] = {0};\ + if (len__ > 1) {\ + snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\ + if (tbuf[len__-2] == '\r') {\ + tbuf[len__-2] = 'r';\ + } \ + DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\ + } else {\ + DBG1("SENDING: '%s' (%d)", tbuf, len__);\ + } \ +} while (0) + +/* Defines */ +#define NOZOMI_NAME "nozomi" +#define NOZOMI_NAME_TTY "nozomi_tty" +#define DRIVER_DESC "Nozomi driver" + +#define NTTY_TTY_MAXMINORS 256 +#define NTTY_FIFO_BUFFER_SIZE 8192 + +/* Must be power of 2 */ +#define FIFO_BUFFER_SIZE_UL 8192 + +/* Size of tmp send buffer to card */ +#define SEND_BUF_MAX 1024 +#define RECEIVE_BUF_MAX 4 + + +#define R_IIR 0x0000 /* Interrupt Identity Register */ +#define R_FCR 0x0000 /* Flow Control Register */ +#define R_IER 0x0004 /* Interrupt Enable Register */ + +#define CONFIG_MAGIC 0xEFEFFEFE +#define TOGGLE_VALID 0x0000 + +/* Definition of interrupt tokens */ +#define MDM_DL1 0x0001 +#define MDM_UL1 0x0002 +#define MDM_DL2 0x0004 +#define MDM_UL2 0x0008 +#define DIAG_DL1 0x0010 +#define DIAG_DL2 0x0020 +#define DIAG_UL 0x0040 +#define APP1_DL 0x0080 +#define APP1_UL 0x0100 +#define APP2_DL 0x0200 +#define APP2_UL 0x0400 +#define CTRL_DL 0x0800 +#define CTRL_UL 0x1000 +#define RESET 0x8000 + +#define MDM_DL (MDM_DL1 | MDM_DL2) +#define MDM_UL (MDM_UL1 | MDM_UL2) +#define DIAG_DL (DIAG_DL1 | DIAG_DL2) + +/* modem signal definition */ +#define CTRL_DSR 0x0001 +#define CTRL_DCD 0x0002 +#define CTRL_RI 0x0004 +#define CTRL_CTS 0x0008 + +#define CTRL_DTR 0x0001 +#define CTRL_RTS 0x0002 + +#define MAX_PORT 4 +#define NOZOMI_MAX_PORTS 5 +#define NOZOMI_MAX_CARDS (NTTY_TTY_MAXMINORS / MAX_PORT) + +/* Type definitions */ + +/* + * There are two types of nozomi cards, + * one with 2048 memory and with 8192 memory + */ +enum card_type { + F32_2 = 2048, /* 512 bytes downlink + uplink * 2 -> 2048 */ + F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */ +}; + +/* Initialization states a card can be in */ +enum card_state { + NOZOMI_STATE_UKNOWN = 0, + NOZOMI_STATE_ENABLED = 1, /* pci device enabled */ + NOZOMI_STATE_ALLOCATED = 2, /* config setup done */ + NOZOMI_STATE_READY = 3, /* flowcontrols received */ +}; + +/* Two different toggle channels exist */ +enum channel_type { + CH_A = 0, + CH_B = 1, +}; + +/* Port definition for the card regarding flow control */ +enum ctrl_port_type { + CTRL_CMD = 0, + CTRL_MDM = 1, + CTRL_DIAG = 2, + CTRL_APP1 = 3, + CTRL_APP2 = 4, + CTRL_ERROR = -1, +}; + +/* Ports that the nozomi has */ +enum port_type { + PORT_MDM = 0, + PORT_DIAG = 1, + PORT_APP1 = 2, + PORT_APP2 = 3, + PORT_CTRL = 4, + PORT_ERROR = -1, +}; + +#ifdef __BIG_ENDIAN +/* Big endian */ + +struct toggles { + unsigned int enabled:5; /* + * Toggle fields are valid if enabled is 0, + * else A-channels must always be used. + */ + unsigned int diag_dl:1; + unsigned int mdm_dl:1; + unsigned int mdm_ul:1; +} __attribute__ ((packed)); + +/* Configuration table to read at startup of card */ +/* Is for now only needed during initialization phase */ +struct config_table { + u32 signature; + u16 product_information; + u16 version; + u8 pad3[3]; + struct toggles toggle; + u8 pad1[4]; + u16 dl_mdm_len1; /* + * If this is 64, it can hold + * 60 bytes + 4 that is length field + */ + u16 dl_start; + + u16 dl_diag_len1; + u16 dl_mdm_len2; /* + * If this is 64, it can hold + * 60 bytes + 4 that is length field + */ + u16 dl_app1_len; + + u16 dl_diag_len2; + u16 dl_ctrl_len; + u16 dl_app2_len; + u8 pad2[16]; + u16 ul_mdm_len1; + u16 ul_start; + u16 ul_diag_len; + u16 ul_mdm_len2; + u16 ul_app1_len; + u16 ul_app2_len; + u16 ul_ctrl_len; +} __attribute__ ((packed)); + +/* This stores all control downlink flags */ +struct ctrl_dl { + u8 port; + unsigned int reserved:4; + unsigned int CTS:1; + unsigned int RI:1; + unsigned int DCD:1; + unsigned int DSR:1; +} __attribute__ ((packed)); + +/* This stores all control uplink flags */ +struct ctrl_ul { + u8 port; + unsigned int reserved:6; + unsigned int RTS:1; + unsigned int DTR:1; +} __attribute__ ((packed)); + +#else +/* Little endian */ + +/* This represents the toggle information */ +struct toggles { + unsigned int mdm_ul:1; + unsigned int mdm_dl:1; + unsigned int diag_dl:1; + unsigned int enabled:5; /* + * Toggle fields are valid if enabled is 0, + * else A-channels must always be used. + */ +} __attribute__ ((packed)); + +/* Configuration table to read at startup of card */ +struct config_table { + u32 signature; + u16 version; + u16 product_information; + struct toggles toggle; + u8 pad1[7]; + u16 dl_start; + u16 dl_mdm_len1; /* + * If this is 64, it can hold + * 60 bytes + 4 that is length field + */ + u16 dl_mdm_len2; + u16 dl_diag_len1; + u16 dl_diag_len2; + u16 dl_app1_len; + u16 dl_app2_len; + u16 dl_ctrl_len; + u8 pad2[16]; + u16 ul_start; + u16 ul_mdm_len2; + u16 ul_mdm_len1; + u16 ul_diag_len; + u16 ul_app1_len; + u16 ul_app2_len; + u16 ul_ctrl_len; +} __attribute__ ((packed)); + +/* This stores all control downlink flags */ +struct ctrl_dl { + unsigned int DSR:1; + unsigned int DCD:1; + unsigned int RI:1; + unsigned int CTS:1; + unsigned int reserverd:4; + u8 port; +} __attribute__ ((packed)); + +/* This stores all control uplink flags */ +struct ctrl_ul { + unsigned int DTR:1; + unsigned int RTS:1; + unsigned int reserved:6; + u8 port; +} __attribute__ ((packed)); +#endif + +/* This holds all information that is needed regarding a port */ +struct port { + struct tty_port port; + u8 update_flow_control; + struct ctrl_ul ctrl_ul; + struct ctrl_dl ctrl_dl; + struct kfifo fifo_ul; + void __iomem *dl_addr[2]; + u32 dl_size[2]; + u8 toggle_dl; + void __iomem *ul_addr[2]; + u32 ul_size[2]; + u8 toggle_ul; + u16 token_dl; + + /* mutex to ensure one access patch to this port */ + struct mutex tty_sem; + wait_queue_head_t tty_wait; + struct async_icount tty_icount; + + struct nozomi *dc; +}; + +/* Private data one for each card in the system */ +struct nozomi { + void __iomem *base_addr; + unsigned long flip; + + /* Pointers to registers */ + void __iomem *reg_iir; + void __iomem *reg_fcr; + void __iomem *reg_ier; + + u16 last_ier; + enum card_type card_type; + struct config_table config_table; /* Configuration table */ + struct pci_dev *pdev; + struct port port[NOZOMI_MAX_PORTS]; + u8 *send_buf; + + spinlock_t spin_mutex; /* secures access to registers and tty */ + + unsigned int index_start; + enum card_state state; + u32 open_ttys; +}; + +/* This is a data packet that is read or written to/from card */ +struct buffer { + u32 size; /* size is the length of the data buffer */ + u8 *data; +} __attribute__ ((packed)); + +/* Global variables */ +static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { + {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ + {}, +}; + +MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); + +static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; +static struct tty_driver *ntty_driver; + +static const struct tty_port_operations noz_tty_port_ops; + +/* + * find card by tty_index + */ +static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty) +{ + return tty ? ndevs[tty->index / MAX_PORT] : NULL; +} + +static inline struct port *get_port_by_tty(const struct tty_struct *tty) +{ + struct nozomi *ndev = get_dc_by_tty(tty); + return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL; +} + +/* + * TODO: + * -Optimize + * -Rewrite cleaner + */ + +static void read_mem32(u32 *buf, const void __iomem *mem_addr_start, + u32 size_bytes) +{ + u32 i = 0; + const u32 __iomem *ptr = mem_addr_start; + u16 *buf16; + + if (unlikely(!ptr || !buf)) + goto out; + + /* shortcut for extremely often used cases */ + switch (size_bytes) { + case 2: /* 2 bytes */ + buf16 = (u16 *) buf; + *buf16 = __le16_to_cpu(readw(ptr)); + goto out; + break; + case 4: /* 4 bytes */ + *(buf) = __le32_to_cpu(readl(ptr)); + goto out; + break; + } + + while (i < size_bytes) { + if (size_bytes - i == 2) { + /* Handle 2 bytes in the end */ + buf16 = (u16 *) buf; + *(buf16) = __le16_to_cpu(readw(ptr)); + i += 2; + } else { + /* Read 4 bytes */ + *(buf) = __le32_to_cpu(readl(ptr)); + i += 4; + } + buf++; + ptr++; + } +out: + return; +} + +/* + * TODO: + * -Optimize + * -Rewrite cleaner + */ +static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, + u32 size_bytes) +{ + u32 i = 0; + u32 __iomem *ptr = mem_addr_start; + const u16 *buf16; + + if (unlikely(!ptr || !buf)) + return 0; + + /* shortcut for extremely often used cases */ + switch (size_bytes) { + case 2: /* 2 bytes */ + buf16 = (const u16 *)buf; + writew(__cpu_to_le16(*buf16), ptr); + return 2; + break; + case 1: /* + * also needs to write 4 bytes in this case + * so falling through.. + */ + case 4: /* 4 bytes */ + writel(__cpu_to_le32(*buf), ptr); + return 4; + break; + } + + while (i < size_bytes) { + if (size_bytes - i == 2) { + /* 2 bytes */ + buf16 = (const u16 *)buf; + writew(__cpu_to_le16(*buf16), ptr); + i += 2; + } else { + /* 4 bytes */ + writel(__cpu_to_le32(*buf), ptr); + i += 4; + } + buf++; + ptr++; + } + return i; +} + +/* Setup pointers to different channels and also setup buffer sizes. */ +static void setup_memory(struct nozomi *dc) +{ + void __iomem *offset = dc->base_addr + dc->config_table.dl_start; + /* The length reported is including the length field of 4 bytes, + * hence subtract with 4. + */ + const u16 buff_offset = 4; + + /* Modem port dl configuration */ + dc->port[PORT_MDM].dl_addr[CH_A] = offset; + dc->port[PORT_MDM].dl_addr[CH_B] = + (offset += dc->config_table.dl_mdm_len1); + dc->port[PORT_MDM].dl_size[CH_A] = + dc->config_table.dl_mdm_len1 - buff_offset; + dc->port[PORT_MDM].dl_size[CH_B] = + dc->config_table.dl_mdm_len2 - buff_offset; + + /* Diag port dl configuration */ + dc->port[PORT_DIAG].dl_addr[CH_A] = + (offset += dc->config_table.dl_mdm_len2); + dc->port[PORT_DIAG].dl_size[CH_A] = + dc->config_table.dl_diag_len1 - buff_offset; + dc->port[PORT_DIAG].dl_addr[CH_B] = + (offset += dc->config_table.dl_diag_len1); + dc->port[PORT_DIAG].dl_size[CH_B] = + dc->config_table.dl_diag_len2 - buff_offset; + + /* App1 port dl configuration */ + dc->port[PORT_APP1].dl_addr[CH_A] = + (offset += dc->config_table.dl_diag_len2); + dc->port[PORT_APP1].dl_size[CH_A] = + dc->config_table.dl_app1_len - buff_offset; + + /* App2 port dl configuration */ + dc->port[PORT_APP2].dl_addr[CH_A] = + (offset += dc->config_table.dl_app1_len); + dc->port[PORT_APP2].dl_size[CH_A] = + dc->config_table.dl_app2_len - buff_offset; + + /* Ctrl dl configuration */ + dc->port[PORT_CTRL].dl_addr[CH_A] = + (offset += dc->config_table.dl_app2_len); + dc->port[PORT_CTRL].dl_size[CH_A] = + dc->config_table.dl_ctrl_len - buff_offset; + + offset = dc->base_addr + dc->config_table.ul_start; + + /* Modem Port ul configuration */ + dc->port[PORT_MDM].ul_addr[CH_A] = offset; + dc->port[PORT_MDM].ul_size[CH_A] = + dc->config_table.ul_mdm_len1 - buff_offset; + dc->port[PORT_MDM].ul_addr[CH_B] = + (offset += dc->config_table.ul_mdm_len1); + dc->port[PORT_MDM].ul_size[CH_B] = + dc->config_table.ul_mdm_len2 - buff_offset; + + /* Diag port ul configuration */ + dc->port[PORT_DIAG].ul_addr[CH_A] = + (offset += dc->config_table.ul_mdm_len2); + dc->port[PORT_DIAG].ul_size[CH_A] = + dc->config_table.ul_diag_len - buff_offset; + + /* App1 port ul configuration */ + dc->port[PORT_APP1].ul_addr[CH_A] = + (offset += dc->config_table.ul_diag_len); + dc->port[PORT_APP1].ul_size[CH_A] = + dc->config_table.ul_app1_len - buff_offset; + + /* App2 port ul configuration */ + dc->port[PORT_APP2].ul_addr[CH_A] = + (offset += dc->config_table.ul_app1_len); + dc->port[PORT_APP2].ul_size[CH_A] = + dc->config_table.ul_app2_len - buff_offset; + + /* Ctrl ul configuration */ + dc->port[PORT_CTRL].ul_addr[CH_A] = + (offset += dc->config_table.ul_app2_len); + dc->port[PORT_CTRL].ul_size[CH_A] = + dc->config_table.ul_ctrl_len - buff_offset; +} + +/* Dump config table under initalization phase */ +#ifdef DEBUG +static void dump_table(const struct nozomi *dc) +{ + DBG3("signature: 0x%08X", dc->config_table.signature); + DBG3("version: 0x%04X", dc->config_table.version); + DBG3("product_information: 0x%04X", \ + dc->config_table.product_information); + DBG3("toggle enabled: %d", dc->config_table.toggle.enabled); + DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul); + DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl); + DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl); + + DBG3("dl_start: 0x%04X", dc->config_table.dl_start); + DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1, + dc->config_table.dl_mdm_len1); + DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2, + dc->config_table.dl_mdm_len2); + DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1, + dc->config_table.dl_diag_len1); + DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2, + dc->config_table.dl_diag_len2); + DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len, + dc->config_table.dl_app1_len); + DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len, + dc->config_table.dl_app2_len); + DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len, + dc->config_table.dl_ctrl_len); + DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start, + dc->config_table.ul_start); + DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1, + dc->config_table.ul_mdm_len1); + DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2, + dc->config_table.ul_mdm_len2); + DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len, + dc->config_table.ul_diag_len); + DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len, + dc->config_table.ul_app1_len); + DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len, + dc->config_table.ul_app2_len); + DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len, + dc->config_table.ul_ctrl_len); +} +#else +static inline void dump_table(const struct nozomi *dc) { } +#endif + +/* + * Read configuration table from card under intalization phase + * Returns 1 if ok, else 0 + */ +static int nozomi_read_config_table(struct nozomi *dc) +{ + read_mem32((u32 *) &dc->config_table, dc->base_addr + 0, + sizeof(struct config_table)); + + if (dc->config_table.signature != CONFIG_MAGIC) { + dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n", + dc->config_table.signature, CONFIG_MAGIC); + return 0; + } + + if ((dc->config_table.version == 0) + || (dc->config_table.toggle.enabled == TOGGLE_VALID)) { + int i; + DBG1("Second phase, configuring card"); + + setup_memory(dc); + + dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul; + dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl; + dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl; + DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d", + dc->port[PORT_MDM].toggle_ul, + dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl); + + dump_table(dc); + + for (i = PORT_MDM; i < MAX_PORT; i++) { + memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); + memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); + } + + /* Enable control channel */ + dc->last_ier = dc->last_ier | CTRL_DL; + writew(dc->last_ier, dc->reg_ier); + + dc->state = NOZOMI_STATE_ALLOCATED; + dev_info(&dc->pdev->dev, "Initialization OK!\n"); + return 1; + } + + if ((dc->config_table.version > 0) + && (dc->config_table.toggle.enabled != TOGGLE_VALID)) { + u32 offset = 0; + DBG1("First phase: pushing upload buffers, clearing download"); + + dev_info(&dc->pdev->dev, "Version of card: %d\n", + dc->config_table.version); + + /* Here we should disable all I/O over F32. */ + setup_memory(dc); + + /* + * We should send ALL channel pair tokens back along + * with reset token + */ + + /* push upload modem buffers */ + write_mem32(dc->port[PORT_MDM].ul_addr[CH_A], + (u32 *) &offset, 4); + write_mem32(dc->port[PORT_MDM].ul_addr[CH_B], + (u32 *) &offset, 4); + + writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr); + + DBG1("First phase done"); + } + + return 1; +} + +/* Enable uplink interrupts */ +static void enable_transmit_ul(enum port_type port, struct nozomi *dc) +{ + static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL}; + + if (port < NOZOMI_MAX_PORTS) { + dc->last_ier |= mask[port]; + writew(dc->last_ier, dc->reg_ier); + } else { + dev_err(&dc->pdev->dev, "Called with wrong port?\n"); + } +} + +/* Disable uplink interrupts */ +static void disable_transmit_ul(enum port_type port, struct nozomi *dc) +{ + static const u16 mask[] = + {~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL}; + + if (port < NOZOMI_MAX_PORTS) { + dc->last_ier &= mask[port]; + writew(dc->last_ier, dc->reg_ier); + } else { + dev_err(&dc->pdev->dev, "Called with wrong port?\n"); + } +} + +/* Enable downlink interrupts */ +static void enable_transmit_dl(enum port_type port, struct nozomi *dc) +{ + static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL}; + + if (port < NOZOMI_MAX_PORTS) { + dc->last_ier |= mask[port]; + writew(dc->last_ier, dc->reg_ier); + } else { + dev_err(&dc->pdev->dev, "Called with wrong port?\n"); + } +} + +/* Disable downlink interrupts */ +static void disable_transmit_dl(enum port_type port, struct nozomi *dc) +{ + static const u16 mask[] = + {~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL}; + + if (port < NOZOMI_MAX_PORTS) { + dc->last_ier &= mask[port]; + writew(dc->last_ier, dc->reg_ier); + } else { + dev_err(&dc->pdev->dev, "Called with wrong port?\n"); + } +} + +/* + * Return 1 - send buffer to card and ack. + * Return 0 - don't ack, don't send buffer to card. + */ +static int send_data(enum port_type index, struct nozomi *dc) +{ + u32 size = 0; + struct port *port = &dc->port[index]; + const u8 toggle = port->toggle_ul; + void __iomem *addr = port->ul_addr[toggle]; + const u32 ul_size = port->ul_size[toggle]; + struct tty_struct *tty = tty_port_tty_get(&port->port); + + /* Get data from tty and place in buf for now */ + size = kfifo_out(&port->fifo_ul, dc->send_buf, + ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); + + if (size == 0) { + DBG4("No more data to send, disable link:"); + tty_kref_put(tty); + return 0; + } + + /* DUMP(buf, size); */ + + /* Write length + data */ + write_mem32(addr, (u32 *) &size, 4); + write_mem32(addr + 4, (u32 *) dc->send_buf, size); + + if (tty) + tty_wakeup(tty); + + tty_kref_put(tty); + return 1; +} + +/* If all data has been read, return 1, else 0 */ +static int receive_data(enum port_type index, struct nozomi *dc) +{ + u8 buf[RECEIVE_BUF_MAX] = { 0 }; + int size; + u32 offset = 4; + struct port *port = &dc->port[index]; + void __iomem *addr = port->dl_addr[port->toggle_dl]; + struct tty_struct *tty = tty_port_tty_get(&port->port); + int i, ret; + + if (unlikely(!tty)) { + DBG1("tty not open for port: %d?", index); + return 1; + } + + read_mem32((u32 *) &size, addr, 4); + /* DBG1( "%d bytes port: %d", size, index); */ + + if (test_bit(TTY_THROTTLED, &tty->flags)) { + DBG1("No room in tty, don't read data, don't ack interrupt, " + "disable interrupt"); + + /* disable interrupt in downlink... */ + disable_transmit_dl(index, dc); + ret = 0; + goto put; + } + + if (unlikely(size == 0)) { + dev_err(&dc->pdev->dev, "size == 0?\n"); + ret = 1; + goto put; + } + + while (size > 0) { + read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); + + if (size == 1) { + tty_insert_flip_char(tty, buf[0], TTY_NORMAL); + size = 0; + } else if (size < RECEIVE_BUF_MAX) { + size -= tty_insert_flip_string(tty, (char *) buf, size); + } else { + i = tty_insert_flip_string(tty, \ + (char *) buf, RECEIVE_BUF_MAX); + size -= i; + offset += i; + } + } + + set_bit(index, &dc->flip); + ret = 1; +put: + tty_kref_put(tty); + return ret; +} + +/* Debug for interrupts */ +#ifdef DEBUG +static char *interrupt2str(u16 interrupt) +{ + static char buf[TMP_BUF_MAX]; + char *p = buf; + + interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL; + interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "MDM_DL2 ") : NULL; + + interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "MDM_UL1 ") : NULL; + interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "MDM_UL2 ") : NULL; + + interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "DIAG_DL1 ") : NULL; + interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "DIAG_DL2 ") : NULL; + + interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "DIAG_UL ") : NULL; + + interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "APP1_DL ") : NULL; + interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "APP2_DL ") : NULL; + + interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "APP1_UL ") : NULL; + interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "APP2_UL ") : NULL; + + interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "CTRL_DL ") : NULL; + interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "CTRL_UL ") : NULL; + + interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf), + "RESET ") : NULL; + + return buf; +} +#endif + +/* + * Receive flow control + * Return 1 - If ok, else 0 + */ +static int receive_flow_control(struct nozomi *dc) +{ + enum port_type port = PORT_MDM; + struct ctrl_dl ctrl_dl; + struct ctrl_dl old_ctrl; + u16 enable_ier = 0; + + read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2); + + switch (ctrl_dl.port) { + case CTRL_CMD: + DBG1("The Base Band sends this value as a response to a " + "request for IMSI detach sent over the control " + "channel uplink (see section 7.6.1)."); + break; + case CTRL_MDM: + port = PORT_MDM; + enable_ier = MDM_DL; + break; + case CTRL_DIAG: + port = PORT_DIAG; + enable_ier = DIAG_DL; + break; + case CTRL_APP1: + port = PORT_APP1; + enable_ier = APP1_DL; + break; + case CTRL_APP2: + port = PORT_APP2; + enable_ier = APP2_DL; + if (dc->state == NOZOMI_STATE_ALLOCATED) { + /* + * After card initialization the flow control + * received for APP2 is always the last + */ + dc->state = NOZOMI_STATE_READY; + dev_info(&dc->pdev->dev, "Device READY!\n"); + } + break; + default: + dev_err(&dc->pdev->dev, + "ERROR: flow control received for non-existing port\n"); + return 0; + }; + + DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl), + *((u16 *)&ctrl_dl)); + + old_ctrl = dc->port[port].ctrl_dl; + dc->port[port].ctrl_dl = ctrl_dl; + + if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) { + DBG1("Disable interrupt (0x%04X) on port: %d", + enable_ier, port); + disable_transmit_ul(port, dc); + + } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { + + if (kfifo_len(&dc->port[port].fifo_ul)) { + DBG1("Enable interrupt (0x%04X) on port: %d", + enable_ier, port); + DBG1("Data in buffer [%d], enable transmit! ", + kfifo_len(&dc->port[port].fifo_ul)); + enable_transmit_ul(port, dc); + } else { + DBG1("No data in buffer..."); + } + } + + if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) { + DBG1(" No change in mctrl"); + return 1; + } + /* Update statistics */ + if (old_ctrl.CTS != ctrl_dl.CTS) + dc->port[port].tty_icount.cts++; + if (old_ctrl.DSR != ctrl_dl.DSR) + dc->port[port].tty_icount.dsr++; + if (old_ctrl.RI != ctrl_dl.RI) + dc->port[port].tty_icount.rng++; + if (old_ctrl.DCD != ctrl_dl.DCD) + dc->port[port].tty_icount.dcd++; + + wake_up_interruptible(&dc->port[port].tty_wait); + + DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)", + port, + dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts, + dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr); + + return 1; +} + +static enum ctrl_port_type port2ctrl(enum port_type port, + const struct nozomi *dc) +{ + switch (port) { + case PORT_MDM: + return CTRL_MDM; + case PORT_DIAG: + return CTRL_DIAG; + case PORT_APP1: + return CTRL_APP1; + case PORT_APP2: + return CTRL_APP2; + default: + dev_err(&dc->pdev->dev, + "ERROR: send flow control " \ + "received for non-existing port\n"); + }; + return CTRL_ERROR; +} + +/* + * Send flow control, can only update one channel at a time + * Return 0 - If we have updated all flow control + * Return 1 - If we need to update more flow control, ack current enable more + */ +static int send_flow_control(struct nozomi *dc) +{ + u32 i, more_flow_control_to_be_updated = 0; + u16 *ctrl; + + for (i = PORT_MDM; i < MAX_PORT; i++) { + if (dc->port[i].update_flow_control) { + if (more_flow_control_to_be_updated) { + /* We have more flow control to be updated */ + return 1; + } + dc->port[i].ctrl_ul.port = port2ctrl(i, dc); + ctrl = (u16 *)&dc->port[i].ctrl_ul; + write_mem32(dc->port[PORT_CTRL].ul_addr[0], \ + (u32 *) ctrl, 2); + dc->port[i].update_flow_control = 0; + more_flow_control_to_be_updated = 1; + } + } + return 0; +} + +/* + * Handle downlink data, ports that are handled are modem and diagnostics + * Return 1 - ok + * Return 0 - toggle fields are out of sync + */ +static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle, + u16 read_iir, u16 mask1, u16 mask2) +{ + if (*toggle == 0 && read_iir & mask1) { + if (receive_data(port, dc)) { + writew(mask1, dc->reg_fcr); + *toggle = !(*toggle); + } + + if (read_iir & mask2) { + if (receive_data(port, dc)) { + writew(mask2, dc->reg_fcr); + *toggle = !(*toggle); + } + } + } else if (*toggle == 1 && read_iir & mask2) { + if (receive_data(port, dc)) { + writew(mask2, dc->reg_fcr); + *toggle = !(*toggle); + } + + if (read_iir & mask1) { + if (receive_data(port, dc)) { + writew(mask1, dc->reg_fcr); + *toggle = !(*toggle); + } + } + } else { + dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n", + *toggle); + return 0; + } + return 1; +} + +/* + * Handle uplink data, this is currently for the modem port + * Return 1 - ok + * Return 0 - toggle field are out of sync + */ +static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir) +{ + u8 *toggle = &(dc->port[port].toggle_ul); + + if (*toggle == 0 && read_iir & MDM_UL1) { + dc->last_ier &= ~MDM_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(port, dc)) { + writew(MDM_UL1, dc->reg_fcr); + dc->last_ier = dc->last_ier | MDM_UL; + writew(dc->last_ier, dc->reg_ier); + *toggle = !*toggle; + } + + if (read_iir & MDM_UL2) { + dc->last_ier &= ~MDM_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(port, dc)) { + writew(MDM_UL2, dc->reg_fcr); + dc->last_ier = dc->last_ier | MDM_UL; + writew(dc->last_ier, dc->reg_ier); + *toggle = !*toggle; + } + } + + } else if (*toggle == 1 && read_iir & MDM_UL2) { + dc->last_ier &= ~MDM_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(port, dc)) { + writew(MDM_UL2, dc->reg_fcr); + dc->last_ier = dc->last_ier | MDM_UL; + writew(dc->last_ier, dc->reg_ier); + *toggle = !*toggle; + } + + if (read_iir & MDM_UL1) { + dc->last_ier &= ~MDM_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(port, dc)) { + writew(MDM_UL1, dc->reg_fcr); + dc->last_ier = dc->last_ier | MDM_UL; + writew(dc->last_ier, dc->reg_ier); + *toggle = !*toggle; + } + } + } else { + writew(read_iir & MDM_UL, dc->reg_fcr); + dev_err(&dc->pdev->dev, "port out of sync!\n"); + return 0; + } + return 1; +} + +static irqreturn_t interrupt_handler(int irq, void *dev_id) +{ + struct nozomi *dc = dev_id; + unsigned int a; + u16 read_iir; + + if (!dc) + return IRQ_NONE; + + spin_lock(&dc->spin_mutex); + read_iir = readw(dc->reg_iir); + + /* Card removed */ + if (read_iir == (u16)-1) + goto none; + /* + * Just handle interrupt enabled in IER + * (by masking with dc->last_ier) + */ + read_iir &= dc->last_ier; + + if (read_iir == 0) + goto none; + + + DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir, + dc->last_ier); + + if (read_iir & RESET) { + if (unlikely(!nozomi_read_config_table(dc))) { + dc->last_ier = 0x0; + writew(dc->last_ier, dc->reg_ier); + dev_err(&dc->pdev->dev, "Could not read status from " + "card, we should disable interface\n"); + } else { + writew(RESET, dc->reg_fcr); + } + /* No more useful info if this was the reset interrupt. */ + goto exit_handler; + } + if (read_iir & CTRL_UL) { + DBG1("CTRL_UL"); + dc->last_ier &= ~CTRL_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_flow_control(dc)) { + writew(CTRL_UL, dc->reg_fcr); + dc->last_ier = dc->last_ier | CTRL_UL; + writew(dc->last_ier, dc->reg_ier); + } + } + if (read_iir & CTRL_DL) { + receive_flow_control(dc); + writew(CTRL_DL, dc->reg_fcr); + } + if (read_iir & MDM_DL) { + if (!handle_data_dl(dc, PORT_MDM, + &(dc->port[PORT_MDM].toggle_dl), read_iir, + MDM_DL1, MDM_DL2)) { + dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n"); + goto exit_handler; + } + } + if (read_iir & MDM_UL) { + if (!handle_data_ul(dc, PORT_MDM, read_iir)) { + dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n"); + goto exit_handler; + } + } + if (read_iir & DIAG_DL) { + if (!handle_data_dl(dc, PORT_DIAG, + &(dc->port[PORT_DIAG].toggle_dl), read_iir, + DIAG_DL1, DIAG_DL2)) { + dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n"); + goto exit_handler; + } + } + if (read_iir & DIAG_UL) { + dc->last_ier &= ~DIAG_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(PORT_DIAG, dc)) { + writew(DIAG_UL, dc->reg_fcr); + dc->last_ier = dc->last_ier | DIAG_UL; + writew(dc->last_ier, dc->reg_ier); + } + } + if (read_iir & APP1_DL) { + if (receive_data(PORT_APP1, dc)) + writew(APP1_DL, dc->reg_fcr); + } + if (read_iir & APP1_UL) { + dc->last_ier &= ~APP1_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(PORT_APP1, dc)) { + writew(APP1_UL, dc->reg_fcr); + dc->last_ier = dc->last_ier | APP1_UL; + writew(dc->last_ier, dc->reg_ier); + } + } + if (read_iir & APP2_DL) { + if (receive_data(PORT_APP2, dc)) + writew(APP2_DL, dc->reg_fcr); + } + if (read_iir & APP2_UL) { + dc->last_ier &= ~APP2_UL; + writew(dc->last_ier, dc->reg_ier); + if (send_data(PORT_APP2, dc)) { + writew(APP2_UL, dc->reg_fcr); + dc->last_ier = dc->last_ier | APP2_UL; + writew(dc->last_ier, dc->reg_ier); + } + } + +exit_handler: + spin_unlock(&dc->spin_mutex); + for (a = 0; a < NOZOMI_MAX_PORTS; a++) { + struct tty_struct *tty; + if (test_and_clear_bit(a, &dc->flip)) { + tty = tty_port_tty_get(&dc->port[a].port); + if (tty) + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } + } + return IRQ_HANDLED; +none: + spin_unlock(&dc->spin_mutex); + return IRQ_NONE; +} + +static void nozomi_get_card_type(struct nozomi *dc) +{ + int i; + u32 size = 0; + + for (i = 0; i < 6; i++) + size += pci_resource_len(dc->pdev, i); + + /* Assume card type F32_8 if no match */ + dc->card_type = size == 2048 ? F32_2 : F32_8; + + dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type); +} + +static void nozomi_setup_private_data(struct nozomi *dc) +{ + void __iomem *offset = dc->base_addr + dc->card_type / 2; + unsigned int i; + + dc->reg_fcr = (void __iomem *)(offset + R_FCR); + dc->reg_iir = (void __iomem *)(offset + R_IIR); + dc->reg_ier = (void __iomem *)(offset + R_IER); + dc->last_ier = 0; + dc->flip = 0; + + dc->port[PORT_MDM].token_dl = MDM_DL; + dc->port[PORT_DIAG].token_dl = DIAG_DL; + dc->port[PORT_APP1].token_dl = APP1_DL; + dc->port[PORT_APP2].token_dl = APP2_DL; + + for (i = 0; i < MAX_PORT; i++) + init_waitqueue_head(&dc->port[i].tty_wait); +} + +static ssize_t card_type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev)); + + return sprintf(buf, "%d\n", dc->card_type); +} +static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL); + +static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev)); + + return sprintf(buf, "%u\n", dc->open_ttys); +} +static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL); + +static void make_sysfs_files(struct nozomi *dc) +{ + if (device_create_file(&dc->pdev->dev, &dev_attr_card_type)) + dev_err(&dc->pdev->dev, + "Could not create sysfs file for card_type\n"); + if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys)) + dev_err(&dc->pdev->dev, + "Could not create sysfs file for open_ttys\n"); +} + +static void remove_sysfs_files(struct nozomi *dc) +{ + device_remove_file(&dc->pdev->dev, &dev_attr_card_type); + device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys); +} + +/* Allocate memory for one device */ +static int __devinit nozomi_card_init(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + resource_size_t start; + int ret; + struct nozomi *dc = NULL; + int ndev_idx; + int i; + + dev_dbg(&pdev->dev, "Init, new card found\n"); + + for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++) + if (!ndevs[ndev_idx]) + break; + + if (ndev_idx >= ARRAY_SIZE(ndevs)) { + dev_err(&pdev->dev, "no free tty range for this card left\n"); + ret = -EIO; + goto err; + } + + dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL); + if (unlikely(!dc)) { + dev_err(&pdev->dev, "Could not allocate memory\n"); + ret = -ENOMEM; + goto err_free; + } + + dc->pdev = pdev; + + ret = pci_enable_device(dc->pdev); + if (ret) { + dev_err(&pdev->dev, "Failed to enable PCI Device\n"); + goto err_free; + } + + ret = pci_request_regions(dc->pdev, NOZOMI_NAME); + if (ret) { + dev_err(&pdev->dev, "I/O address 0x%04x already in use\n", + (int) /* nozomi_private.io_addr */ 0); + goto err_disable_device; + } + + start = pci_resource_start(dc->pdev, 0); + if (start == 0) { + dev_err(&pdev->dev, "No I/O address for card detected\n"); + ret = -ENODEV; + goto err_rel_regs; + } + + /* Find out what card type it is */ + nozomi_get_card_type(dc); + + dc->base_addr = ioremap_nocache(start, dc->card_type); + if (!dc->base_addr) { + dev_err(&pdev->dev, "Unable to map card MMIO\n"); + ret = -ENODEV; + goto err_rel_regs; + } + + dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL); + if (!dc->send_buf) { + dev_err(&pdev->dev, "Could not allocate send buffer?\n"); + ret = -ENOMEM; + goto err_free_sbuf; + } + + for (i = PORT_MDM; i < MAX_PORT; i++) { + if (kfifo_alloc(&dc->port[i].fifo_ul, + FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { + dev_err(&pdev->dev, + "Could not allocate kfifo buffer\n"); + ret = -ENOMEM; + goto err_free_kfifo; + } + } + + spin_lock_init(&dc->spin_mutex); + + nozomi_setup_private_data(dc); + + /* Disable all interrupts */ + dc->last_ier = 0; + writew(dc->last_ier, dc->reg_ier); + + ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED, + NOZOMI_NAME, dc); + if (unlikely(ret)) { + dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); + goto err_free_kfifo; + } + + DBG1("base_addr: %p", dc->base_addr); + + make_sysfs_files(dc); + + dc->index_start = ndev_idx * MAX_PORT; + ndevs[ndev_idx] = dc; + + pci_set_drvdata(pdev, dc); + + /* Enable RESET interrupt */ + dc->last_ier = RESET; + iowrite16(dc->last_ier, dc->reg_ier); + + dc->state = NOZOMI_STATE_ENABLED; + + for (i = 0; i < MAX_PORT; i++) { + struct device *tty_dev; + struct port *port = &dc->port[i]; + port->dc = dc; + mutex_init(&port->tty_sem); + tty_port_init(&port->port); + port->port.ops = &noz_tty_port_ops; + tty_dev = tty_register_device(ntty_driver, dc->index_start + i, + &pdev->dev); + + if (IS_ERR(tty_dev)) { + ret = PTR_ERR(tty_dev); + dev_err(&pdev->dev, "Could not allocate tty?\n"); + goto err_free_tty; + } + } + + return 0; + +err_free_tty: + for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) + tty_unregister_device(ntty_driver, i); +err_free_kfifo: + for (i = 0; i < MAX_PORT; i++) + kfifo_free(&dc->port[i].fifo_ul); +err_free_sbuf: + kfree(dc->send_buf); + iounmap(dc->base_addr); +err_rel_regs: + pci_release_regions(pdev); +err_disable_device: + pci_disable_device(pdev); +err_free: + kfree(dc); +err: + return ret; +} + +static void __devexit tty_exit(struct nozomi *dc) +{ + unsigned int i; + + DBG1(" "); + + flush_scheduled_work(); + + for (i = 0; i < MAX_PORT; ++i) { + struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port); + if (tty && list_empty(&tty->hangup_work.entry)) + tty_hangup(tty); + tty_kref_put(tty); + } + /* Racy below - surely should wait for scheduled work to be done or + complete off a hangup method ? */ + while (dc->open_ttys) + msleep(1); + for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) + tty_unregister_device(ntty_driver, i); +} + +/* Deallocate memory for one device */ +static void __devexit nozomi_card_exit(struct pci_dev *pdev) +{ + int i; + struct ctrl_ul ctrl; + struct nozomi *dc = pci_get_drvdata(pdev); + + /* Disable all interrupts */ + dc->last_ier = 0; + writew(dc->last_ier, dc->reg_ier); + + tty_exit(dc); + + /* Send 0x0001, command card to resend the reset token. */ + /* This is to get the reset when the module is reloaded. */ + ctrl.port = 0x00; + ctrl.reserved = 0; + ctrl.RTS = 0; + ctrl.DTR = 1; + DBG1("sending flow control 0x%04X", *((u16 *)&ctrl)); + + /* Setup dc->reg addresses to we can use defines here */ + write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2); + writew(CTRL_UL, dc->reg_fcr); /* push the token to the card. */ + + remove_sysfs_files(dc); + + free_irq(pdev->irq, dc); + + for (i = 0; i < MAX_PORT; i++) + kfifo_free(&dc->port[i].fifo_ul); + + kfree(dc->send_buf); + + iounmap(dc->base_addr); + + pci_release_regions(pdev); + + pci_disable_device(pdev); + + ndevs[dc->index_start / MAX_PORT] = NULL; + + kfree(dc); +} + +static void set_rts(const struct tty_struct *tty, int rts) +{ + struct port *port = get_port_by_tty(tty); + + port->ctrl_ul.RTS = rts; + port->update_flow_control = 1; + enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty)); +} + +static void set_dtr(const struct tty_struct *tty, int dtr) +{ + struct port *port = get_port_by_tty(tty); + + DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr); + + port->ctrl_ul.DTR = dtr; + port->update_flow_control = 1; + enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty)); +} + +/* + * ---------------------------------------------------------------------------- + * TTY code + * ---------------------------------------------------------------------------- + */ + +static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) +{ + struct port *port = get_port_by_tty(tty); + struct nozomi *dc = get_dc_by_tty(tty); + int ret; + if (!port || !dc || dc->state != NOZOMI_STATE_READY) + return -ENODEV; + ret = tty_init_termios(tty); + if (ret == 0) { + tty_driver_kref_get(driver); + tty->count++; + tty->driver_data = port; + driver->ttys[tty->index] = tty; + } + return ret; +} + +static void ntty_cleanup(struct tty_struct *tty) +{ + tty->driver_data = NULL; +} + +static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) +{ + struct port *port = container_of(tport, struct port, port); + struct nozomi *dc = port->dc; + unsigned long flags; + + DBG1("open: %d", port->token_dl); + spin_lock_irqsave(&dc->spin_mutex, flags); + dc->last_ier = dc->last_ier | port->token_dl; + writew(dc->last_ier, dc->reg_ier); + dc->open_ttys++; + spin_unlock_irqrestore(&dc->spin_mutex, flags); + printk("noz: activated %d: %p\n", tty->index, tport); + return 0; +} + +static int ntty_open(struct tty_struct *tty, struct file *filp) +{ + struct port *port = tty->driver_data; + return tty_port_open(&port->port, tty, filp); +} + +static void ntty_shutdown(struct tty_port *tport) +{ + struct port *port = container_of(tport, struct port, port); + struct nozomi *dc = port->dc; + unsigned long flags; + + DBG1("close: %d", port->token_dl); + spin_lock_irqsave(&dc->spin_mutex, flags); + dc->last_ier &= ~(port->token_dl); + writew(dc->last_ier, dc->reg_ier); + dc->open_ttys--; + spin_unlock_irqrestore(&dc->spin_mutex, flags); + printk("noz: shutdown %p\n", tport); +} + +static void ntty_close(struct tty_struct *tty, struct file *filp) +{ + struct port *port = tty->driver_data; + if (port) + tty_port_close(&port->port, tty, filp); +} + +static void ntty_hangup(struct tty_struct *tty) +{ + struct port *port = tty->driver_data; + tty_port_hangup(&port->port); +} + +/* + * called when the userspace process writes to the tty (/dev/noz*). + * Data is inserted into a fifo, which is then read and transfered to the modem. + */ +static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, + int count) +{ + int rval = -EINVAL; + struct nozomi *dc = get_dc_by_tty(tty); + struct port *port = tty->driver_data; + unsigned long flags; + + /* DBG1( "WRITEx: %d, index = %d", count, index); */ + + if (!dc || !port) + return -ENODEV; + + mutex_lock(&port->tty_sem); + + if (unlikely(!port->port.count)) { + DBG1(" "); + goto exit; + } + + rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); + + /* notify card */ + if (unlikely(dc == NULL)) { + DBG1("No device context?"); + goto exit; + } + + spin_lock_irqsave(&dc->spin_mutex, flags); + /* CTS is only valid on the modem channel */ + if (port == &(dc->port[PORT_MDM])) { + if (port->ctrl_dl.CTS) { + DBG4("Enable interrupt"); + enable_transmit_ul(tty->index % MAX_PORT, dc); + } else { + dev_err(&dc->pdev->dev, + "CTS not active on modem port?\n"); + } + } else { + enable_transmit_ul(tty->index % MAX_PORT, dc); + } + spin_unlock_irqrestore(&dc->spin_mutex, flags); + +exit: + mutex_unlock(&port->tty_sem); + return rval; +} + +/* + * Calculate how much is left in device + * This method is called by the upper tty layer. + * #according to sources N_TTY.c it expects a value >= 0 and + * does not check for negative values. + * + * If the port is unplugged report lots of room and let the bits + * dribble away so we don't block anything. + */ +static int ntty_write_room(struct tty_struct *tty) +{ + struct port *port = tty->driver_data; + int room = 4096; + const struct nozomi *dc = get_dc_by_tty(tty); + + if (dc) { + mutex_lock(&port->tty_sem); + if (port->port.count) + room = kfifo_avail(&port->fifo_ul); + mutex_unlock(&port->tty_sem); + } + return room; +} + +/* Gets io control parameters */ +static int ntty_tiocmget(struct tty_struct *tty) +{ + const struct port *port = tty->driver_data; + const struct ctrl_dl *ctrl_dl = &port->ctrl_dl; + const struct ctrl_ul *ctrl_ul = &port->ctrl_ul; + + /* Note: these could change under us but it is not clear this + matters if so */ + return (ctrl_ul->RTS ? TIOCM_RTS : 0) | + (ctrl_ul->DTR ? TIOCM_DTR : 0) | + (ctrl_dl->DCD ? TIOCM_CAR : 0) | + (ctrl_dl->RI ? TIOCM_RNG : 0) | + (ctrl_dl->DSR ? TIOCM_DSR : 0) | + (ctrl_dl->CTS ? TIOCM_CTS : 0); +} + +/* Sets io controls parameters */ +static int ntty_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct nozomi *dc = get_dc_by_tty(tty); + unsigned long flags; + + spin_lock_irqsave(&dc->spin_mutex, flags); + if (set & TIOCM_RTS) + set_rts(tty, 1); + else if (clear & TIOCM_RTS) + set_rts(tty, 0); + + if (set & TIOCM_DTR) + set_dtr(tty, 1); + else if (clear & TIOCM_DTR) + set_dtr(tty, 0); + spin_unlock_irqrestore(&dc->spin_mutex, flags); + + return 0; +} + +static int ntty_cflags_changed(struct port *port, unsigned long flags, + struct async_icount *cprev) +{ + const struct async_icount cnow = port->tty_icount; + int ret; + + ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) || + ((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || + ((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || + ((flags & TIOCM_CTS) && (cnow.cts != cprev->cts)); + + *cprev = cnow; + + return ret; +} + +static int ntty_tiocgicount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + struct port *port = tty->driver_data; + const struct async_icount cnow = port->tty_icount; + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->frame = cnow.frame; + icount->overrun = cnow.overrun; + icount->parity = cnow.parity; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + return 0; +} + +static int ntty_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct port *port = tty->driver_data; + int rval = -ENOIOCTLCMD; + + DBG1("******** IOCTL, cmd: %d", cmd); + + switch (cmd) { + case TIOCMIWAIT: { + struct async_icount cprev = port->tty_icount; + + rval = wait_event_interruptible(port->tty_wait, + ntty_cflags_changed(port, arg, &cprev)); + break; + } + default: + DBG1("ERR: 0x%08X, %d", cmd, cmd); + break; + }; + + return rval; +} + +/* + * Called by the upper tty layer when tty buffers are ready + * to receive data again after a call to throttle. + */ +static void ntty_unthrottle(struct tty_struct *tty) +{ + struct nozomi *dc = get_dc_by_tty(tty); + unsigned long flags; + + DBG1("UNTHROTTLE"); + spin_lock_irqsave(&dc->spin_mutex, flags); + enable_transmit_dl(tty->index % MAX_PORT, dc); + set_rts(tty, 1); + + spin_unlock_irqrestore(&dc->spin_mutex, flags); +} + +/* + * Called by the upper tty layer when the tty buffers are almost full. + * The driver should stop send more data. + */ +static void ntty_throttle(struct tty_struct *tty) +{ + struct nozomi *dc = get_dc_by_tty(tty); + unsigned long flags; + + DBG1("THROTTLE"); + spin_lock_irqsave(&dc->spin_mutex, flags); + set_rts(tty, 0); + spin_unlock_irqrestore(&dc->spin_mutex, flags); +} + +/* Returns number of chars in buffer, called by tty layer */ +static s32 ntty_chars_in_buffer(struct tty_struct *tty) +{ + struct port *port = tty->driver_data; + struct nozomi *dc = get_dc_by_tty(tty); + s32 rval = 0; + + if (unlikely(!dc || !port)) { + goto exit_in_buffer; + } + + if (unlikely(!port->port.count)) { + dev_err(&dc->pdev->dev, "No tty open?\n"); + goto exit_in_buffer; + } + + rval = kfifo_len(&port->fifo_ul); + +exit_in_buffer: + return rval; +} + +static const struct tty_port_operations noz_tty_port_ops = { + .activate = ntty_activate, + .shutdown = ntty_shutdown, +}; + +static const struct tty_operations tty_ops = { + .ioctl = ntty_ioctl, + .open = ntty_open, + .close = ntty_close, + .hangup = ntty_hangup, + .write = ntty_write, + .write_room = ntty_write_room, + .unthrottle = ntty_unthrottle, + .throttle = ntty_throttle, + .chars_in_buffer = ntty_chars_in_buffer, + .tiocmget = ntty_tiocmget, + .tiocmset = ntty_tiocmset, + .get_icount = ntty_tiocgicount, + .install = ntty_install, + .cleanup = ntty_cleanup, +}; + +/* Module initialization */ +static struct pci_driver nozomi_driver = { + .name = NOZOMI_NAME, + .id_table = nozomi_pci_tbl, + .probe = nozomi_card_init, + .remove = __devexit_p(nozomi_card_exit), +}; + +static __init int nozomi_init(void) +{ + int ret; + + printk(KERN_INFO "Initializing %s\n", VERSION_STRING); + + ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS); + if (!ntty_driver) + return -ENOMEM; + + ntty_driver->owner = THIS_MODULE; + ntty_driver->driver_name = NOZOMI_NAME_TTY; + ntty_driver->name = "noz"; + ntty_driver->major = 0; + ntty_driver->type = TTY_DRIVER_TYPE_SERIAL; + ntty_driver->subtype = SERIAL_TYPE_NORMAL; + ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + ntty_driver->init_termios = tty_std_termios; + ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \ + HUPCL | CLOCAL; + ntty_driver->init_termios.c_ispeed = 115200; + ntty_driver->init_termios.c_ospeed = 115200; + tty_set_operations(ntty_driver, &tty_ops); + + ret = tty_register_driver(ntty_driver); + if (ret) { + printk(KERN_ERR "Nozomi: failed to register ntty driver\n"); + goto free_tty; + } + + ret = pci_register_driver(&nozomi_driver); + if (ret) { + printk(KERN_ERR "Nozomi: can't register pci driver\n"); + goto unr_tty; + } + + return 0; +unr_tty: + tty_unregister_driver(ntty_driver); +free_tty: + put_tty_driver(ntty_driver); + return ret; +} + +static __exit void nozomi_exit(void) +{ + printk(KERN_INFO "Unloading %s\n", DRIVER_DESC); + pci_unregister_driver(&nozomi_driver); + tty_unregister_driver(ntty_driver); + put_tty_driver(ntty_driver); +} + +module_init(nozomi_init); +module_exit(nozomi_exit); + +module_param(debug, int, S_IRUGO | S_IWUSR); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c new file mode 100644 index 000000000000..3780da8ad12d --- /dev/null +++ b/drivers/tty/rocket.c @@ -0,0 +1,3199 @@ +/* + * RocketPort device driver for Linux + * + * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Kernel Synchronization: + * + * This driver has 2 kernel control paths - exception handlers (calls into the driver + * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts + * are not used. + * + * Critical data: + * - rp_table[], accessed through passed "info" pointers, is a global (static) array of + * serial port state information and the xmit_buf circular buffer. Protected by + * a per port spinlock. + * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there + * is data to be transmitted. Protected by atomic bit operations. + * - rp_num_ports, int indicating number of open ports, protected by atomic operations. + * + * rp_write() and rp_write_char() functions use a per port semaphore to protect against + * simultaneous access to the same port by more than one process. + */ + +/****** Defines ******/ +#define ROCKET_PARANOIA_CHECK +#define ROCKET_DISABLE_SIMUSAGE + +#undef ROCKET_SOFT_FLOW +#undef ROCKET_DEBUG_OPEN +#undef ROCKET_DEBUG_INTR +#undef ROCKET_DEBUG_WRITE +#undef ROCKET_DEBUG_FLOW +#undef ROCKET_DEBUG_THROTTLE +#undef ROCKET_DEBUG_WAIT_UNTIL_SENT +#undef ROCKET_DEBUG_RECEIVE +#undef ROCKET_DEBUG_HANGUP +#undef REV_PCI_ORDER +#undef ROCKET_DEBUG_IO + +#define POLL_PERIOD HZ/100 /* Polling period .01 seconds (10ms) */ + +/****** Kernel includes ******/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****** RocketPort includes ******/ + +#include "rocket_int.h" +#include "rocket.h" + +#define ROCKET_VERSION "2.09" +#define ROCKET_DATE "12-June-2003" + +/****** RocketPort Local Variables ******/ + +static void rp_do_poll(unsigned long dummy); + +static struct tty_driver *rocket_driver; + +static struct rocket_version driver_version = { + ROCKET_VERSION, ROCKET_DATE +}; + +static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of serial port state information. */ +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 DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0); + +static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */ +static unsigned long board2; +static unsigned long board3; +static unsigned long board4; +static unsigned long controller; +static int support_low_speed; +static unsigned long modem1; +static unsigned long modem2; +static unsigned long modem3; +static unsigned long modem4; +static unsigned long pc104_1[8]; +static unsigned long pc104_2[8]; +static unsigned long pc104_3[8]; +static unsigned long pc104_4[8]; +static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 }; + +static int rp_baud_base[NUM_BOARDS]; /* Board config info (Someday make a per-board structure) */ +static unsigned long rcktpt_io_addr[NUM_BOARDS]; +static int rcktpt_type[NUM_BOARDS]; +static int is_PCI[NUM_BOARDS]; +static rocketModel_t rocketModel[NUM_BOARDS]; +static int max_board; +static const struct tty_port_operations rocket_port_ops; + +/* + * The following arrays define the interrupt bits corresponding to each AIOP. + * These bits are different between the ISA and regular PCI boards and the + * Universal PCI boards. + */ + +static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = { + AIOP_INTR_BIT_0, + AIOP_INTR_BIT_1, + AIOP_INTR_BIT_2, + AIOP_INTR_BIT_3 +}; + +static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = { + UPCI_AIOP_INTR_BIT_0, + UPCI_AIOP_INTR_BIT_1, + UPCI_AIOP_INTR_BIT_2, + UPCI_AIOP_INTR_BIT_3 +}; + +static Byte_t RData[RDATASIZE] = { + 0x00, 0x09, 0xf6, 0x82, + 0x02, 0x09, 0x86, 0xfb, + 0x04, 0x09, 0x00, 0x0a, + 0x06, 0x09, 0x01, 0x0a, + 0x08, 0x09, 0x8a, 0x13, + 0x0a, 0x09, 0xc5, 0x11, + 0x0c, 0x09, 0x86, 0x85, + 0x0e, 0x09, 0x20, 0x0a, + 0x10, 0x09, 0x21, 0x0a, + 0x12, 0x09, 0x41, 0xff, + 0x14, 0x09, 0x82, 0x00, + 0x16, 0x09, 0x82, 0x7b, + 0x18, 0x09, 0x8a, 0x7d, + 0x1a, 0x09, 0x88, 0x81, + 0x1c, 0x09, 0x86, 0x7a, + 0x1e, 0x09, 0x84, 0x81, + 0x20, 0x09, 0x82, 0x7c, + 0x22, 0x09, 0x0a, 0x0a +}; + +static Byte_t RRegData[RREGDATASIZE] = { + 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ + 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ + 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ + 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ + 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ + 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ + 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ + 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ + 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ + 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ + 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ + 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ + 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ +}; + +static CONTROLLER_T sController[CTL_SIZE] = { + {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, + {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}, + {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, + {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}, + {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, + {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}, + {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, + {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}} +}; + +static Byte_t sBitMapClrTbl[8] = { + 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f +}; + +static Byte_t sBitMapSetTbl[8] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 +}; + +static int sClockPrescale = 0x14; + +/* + * Line number is the ttySIx number (x), the Minor number. We + * assign them sequentially, starting at zero. The following + * array keeps track of the line number assigned to a given board/aiop/channel. + */ +static unsigned char lineNumbers[MAX_RP_PORTS]; +static unsigned long nextLineNumber; + +/***** RocketPort Static Prototypes *********/ +static int __init init_ISA(int i); +static void rp_wait_until_sent(struct tty_struct *tty, int timeout); +static void rp_flush_buffer(struct tty_struct *tty); +static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model); +static unsigned char GetLineNumber(int ctrl, int aiop, int ch); +static unsigned char SetLineNumber(int ctrl, int aiop, int ch); +static void rp_start(struct tty_struct *tty); +static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, + int ChanNum); +static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode); +static void sFlushRxFIFO(CHANNEL_T * ChP); +static void sFlushTxFIFO(CHANNEL_T * ChP); +static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags); +static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags); +static void sModemReset(CONTROLLER_T * CtlP, int chan, int on); +static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on); +static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data); +static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, + ByteIO_t * AiopIOList, int AiopIOListSize, + WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, + int PeriodicOnly, int altChanRingIndicator, + int UPCIRingInd); +static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, + ByteIO_t * AiopIOList, int AiopIOListSize, + int IRQNum, Byte_t Frequency, int PeriodicOnly); +static int sReadAiopID(ByteIO_t io); +static int sReadAiopNumChan(WordIO_t io); + +MODULE_AUTHOR("Theodore Ts'o"); +MODULE_DESCRIPTION("Comtrol RocketPort driver"); +module_param(board1, ulong, 0); +MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1"); +module_param(board2, ulong, 0); +MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2"); +module_param(board3, ulong, 0); +MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3"); +module_param(board4, ulong, 0); +MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4"); +module_param(controller, ulong, 0); +MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller"); +module_param(support_low_speed, bool, 0); +MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud"); +module_param(modem1, ulong, 0); +MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem"); +module_param(modem2, ulong, 0); +MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem"); +module_param(modem3, ulong, 0); +MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem"); +module_param(modem4, ulong, 0); +MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem"); +module_param_array(pc104_1, ulong, NULL, 0); +MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,..."); +module_param_array(pc104_2, ulong, NULL, 0); +MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,..."); +module_param_array(pc104_3, ulong, NULL, 0); +MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,..."); +module_param_array(pc104_4, ulong, NULL, 0); +MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,..."); + +static int rp_init(void); +static void rp_cleanup_module(void); + +module_init(rp_init); +module_exit(rp_cleanup_module); + + +MODULE_LICENSE("Dual BSD/GPL"); + +/*************************************************************************/ +/* Module code starts here */ + +static inline int rocket_paranoia_check(struct r_port *info, + const char *routine) +{ +#ifdef ROCKET_PARANOIA_CHECK + if (!info) + return 1; + if (info->magic != RPORT_MAGIC) { + printk(KERN_WARNING "Warning: bad magic number for rocketport " + "struct in %s\n", routine); + return 1; + } +#endif + return 0; +} + + +/* Serial port receive data function. Called (from timer poll) when an AIOPIC signals + * that receive data is present on a serial port. Pulls data from FIFO, moves it into the + * tty layer. + */ +static void rp_do_receive(struct r_port *info, + struct tty_struct *tty, + CHANNEL_t * cp, unsigned int ChanStatus) +{ + unsigned int CharNStat; + int ToRecv, wRecv, space; + unsigned char *cbuf; + + ToRecv = sGetRxCnt(cp); +#ifdef ROCKET_DEBUG_INTR + printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv); +#endif + if (ToRecv == 0) + return; + + /* + * if status indicates there are errored characters in the + * FIFO, then enter status mode (a word in FIFO holds + * character and status). + */ + if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { + if (!(ChanStatus & STATMODE)) { +#ifdef ROCKET_DEBUG_RECEIVE + printk(KERN_INFO "Entering STATMODE...\n"); +#endif + ChanStatus |= STATMODE; + sEnRxStatusMode(cp); + } + } + + /* + * if we previously entered status mode, then read down the + * FIFO one word at a time, pulling apart the character and + * the status. Update error counters depending on status + */ + if (ChanStatus & STATMODE) { +#ifdef ROCKET_DEBUG_RECEIVE + printk(KERN_INFO "Ignore %x, read %x...\n", + info->ignore_status_mask, info->read_status_mask); +#endif + while (ToRecv) { + char flag; + + CharNStat = sInW(sGetTxRxDataIO(cp)); +#ifdef ROCKET_DEBUG_RECEIVE + printk(KERN_INFO "%x...\n", CharNStat); +#endif + if (CharNStat & STMBREAKH) + CharNStat &= ~(STMFRAMEH | STMPARITYH); + if (CharNStat & info->ignore_status_mask) { + ToRecv--; + continue; + } + CharNStat &= info->read_status_mask; + if (CharNStat & STMBREAKH) + flag = TTY_BREAK; + else if (CharNStat & STMPARITYH) + flag = TTY_PARITY; + else if (CharNStat & STMFRAMEH) + flag = TTY_FRAME; + else if (CharNStat & STMRCVROVRH) + flag = TTY_OVERRUN; + else + flag = TTY_NORMAL; + tty_insert_flip_char(tty, CharNStat & 0xff, flag); + ToRecv--; + } + + /* + * after we've emptied the FIFO in status mode, turn + * status mode back off + */ + if (sGetRxCnt(cp) == 0) { +#ifdef ROCKET_DEBUG_RECEIVE + printk(KERN_INFO "Status mode off.\n"); +#endif + sDisRxStatusMode(cp); + } + } else { + /* + * we aren't in status mode, so read down the FIFO two + * characters at time by doing repeated word IO + * transfer. + */ + space = tty_prepare_flip_string(tty, &cbuf, ToRecv); + if (space < ToRecv) { +#ifdef ROCKET_DEBUG_RECEIVE + printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space); +#endif + if (space <= 0) + return; + ToRecv = space; + } + wRecv = ToRecv >> 1; + if (wRecv) + sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv); + if (ToRecv & 1) + cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp)); + } + /* Push the data up to the tty layer */ + tty_flip_buffer_push(tty); +} + +/* + * Serial port transmit data function. Called from the timer polling loop as a + * result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready + * to be sent out the serial port. Data is buffered in rp_table[line].xmit_buf, it is + * moved to the port's xmit FIFO. *info is critical data, protected by spinlocks. + */ +static void rp_do_transmit(struct r_port *info) +{ + int c; + CHANNEL_t *cp = &info->channel; + struct tty_struct *tty; + unsigned long flags; + +#ifdef ROCKET_DEBUG_INTR + printk(KERN_DEBUG "%s\n", __func__); +#endif + if (!info) + return; + tty = tty_port_tty_get(&info->port); + + if (tty == NULL) { + printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__); + clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + return; + } + + spin_lock_irqsave(&info->slock, flags); + info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); + + /* Loop sending data to FIFO until done or FIFO full */ + while (1) { + if (tty->stopped || tty->hw_stopped) + break; + c = min(info->xmit_fifo_room, info->xmit_cnt); + c = min(c, XMIT_BUF_SIZE - info->xmit_tail); + if (c <= 0 || info->xmit_fifo_room <= 0) + break; + sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2); + if (c & 1) + sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]); + info->xmit_tail += c; + info->xmit_tail &= XMIT_BUF_SIZE - 1; + info->xmit_cnt -= c; + info->xmit_fifo_room -= c; +#ifdef ROCKET_DEBUG_INTR + printk(KERN_INFO "tx %d chars...\n", c); +#endif + } + + if (info->xmit_cnt == 0) + clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + + if (info->xmit_cnt < WAKEUP_CHARS) { + tty_wakeup(tty); +#ifdef ROCKETPORT_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif + } + + spin_unlock_irqrestore(&info->slock, flags); + tty_kref_put(tty); + +#ifdef ROCKET_DEBUG_INTR + printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, + info->xmit_tail, info->xmit_fifo_room); +#endif +} + +/* + * Called when a serial port signals it has read data in it's RX FIFO. + * It checks what interrupts are pending and services them, including + * receiving serial data. + */ +static void rp_handle_port(struct r_port *info) +{ + CHANNEL_t *cp; + struct tty_struct *tty; + unsigned int IntMask, ChanStatus; + + if (!info) + return; + + if ((info->port.flags & ASYNC_INITIALIZED) == 0) { + printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " + "info->flags & NOT_INIT\n"); + return; + } + tty = tty_port_tty_get(&info->port); + if (!tty) { + printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " + "tty==NULL\n"); + return; + } + cp = &info->channel; + + IntMask = sGetChanIntID(cp) & info->intmask; +#ifdef ROCKET_DEBUG_INTR + printk(KERN_INFO "rp_interrupt %02x...\n", IntMask); +#endif + ChanStatus = sGetChanStatus(cp); + if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */ + rp_do_receive(info, tty, cp, ChanStatus); + } + if (IntMask & DELTA_CD) { /* CD change */ +#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP)) + printk(KERN_INFO "ttyR%d CD now %s...\n", info->line, + (ChanStatus & CD_ACT) ? "on" : "off"); +#endif + if (!(ChanStatus & CD_ACT) && info->cd_status) { +#ifdef ROCKET_DEBUG_HANGUP + printk(KERN_INFO "CD drop, calling hangup.\n"); +#endif + tty_hangup(tty); + } + info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0; + wake_up_interruptible(&info->port.open_wait); + } +#ifdef ROCKET_DEBUG_INTR + if (IntMask & DELTA_CTS) { /* CTS change */ + printk(KERN_INFO "CTS change...\n"); + } + if (IntMask & DELTA_DSR) { /* DSR change */ + printk(KERN_INFO "DSR change...\n"); + } +#endif + tty_kref_put(tty); +} + +/* + * The top level polling routine. Repeats every 1/100 HZ (10ms). + */ +static void rp_do_poll(unsigned long dummy) +{ + CONTROLLER_t *ctlp; + int ctrl, aiop, ch, line; + unsigned int xmitmask, i; + unsigned int CtlMask; + unsigned char AiopMask; + Word_t bit; + + /* Walk through all the boards (ctrl's) */ + for (ctrl = 0; ctrl < max_board; ctrl++) { + if (rcktpt_io_addr[ctrl] <= 0) + continue; + + /* Get a ptr to the board's control struct */ + ctlp = sCtlNumToCtlPtr(ctrl); + + /* Get the interrupt status from the board */ +#ifdef CONFIG_PCI + if (ctlp->BusType == isPCI) + CtlMask = sPCIGetControllerIntStatus(ctlp); + else +#endif + CtlMask = sGetControllerIntStatus(ctlp); + + /* Check if any AIOP read bits are set */ + for (aiop = 0; CtlMask; aiop++) { + bit = ctlp->AiopIntrBits[aiop]; + if (CtlMask & bit) { + CtlMask &= ~bit; + AiopMask = sGetAiopIntStatus(ctlp, aiop); + + /* Check if any port read bits are set */ + for (ch = 0; AiopMask; AiopMask >>= 1, ch++) { + if (AiopMask & 1) { + + /* Get the line number (/dev/ttyRx number). */ + /* Read the data from the port. */ + line = GetLineNumber(ctrl, aiop, ch); + rp_handle_port(rp_table[line]); + } + } + } + } + + xmitmask = xmit_flags[ctrl]; + + /* + * xmit_flags contains bit-significant flags, indicating there is data + * to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port + * 1, ... (32 total possible). The variable i has the aiop and ch + * numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc). + */ + if (xmitmask) { + for (i = 0; i < rocketModel[ctrl].numPorts; i++) { + if (xmitmask & (1 << i)) { + aiop = (i & 0x18) >> 3; + ch = i & 0x07; + line = GetLineNumber(ctrl, aiop, ch); + rp_do_transmit(rp_table[line]); + } + } + } + } + + /* + * Reset the timer so we get called at the next clock tick (10ms). + */ + if (atomic_read(&rp_num_ports_open)) + mod_timer(&rocket_timer, jiffies + POLL_PERIOD); +} + +/* + * Initializes the r_port structure for a port, as well as enabling the port on + * the board. + * Inputs: board, aiop, chan numbers + */ +static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) +{ + unsigned rocketMode; + struct r_port *info; + int line; + CONTROLLER_T *ctlp; + + /* Get the next available line number */ + line = SetLineNumber(board, aiop, chan); + + ctlp = sCtlNumToCtlPtr(board); + + /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */ + info = kzalloc(sizeof (struct r_port), GFP_KERNEL); + if (!info) { + printk(KERN_ERR "Couldn't allocate info struct for line #%d\n", + line); + return; + } + + info->magic = RPORT_MAGIC; + info->line = line; + info->ctlp = ctlp; + info->board = board; + info->aiop = aiop; + info->chan = chan; + tty_port_init(&info->port); + info->port.ops = &rocket_port_ops; + init_completion(&info->close_wait); + info->flags &= ~ROCKET_MODE_MASK; + switch (pc104[board][line]) { + case 422: + info->flags |= ROCKET_MODE_RS422; + break; + case 485: + info->flags |= ROCKET_MODE_RS485; + break; + case 232: + default: + info->flags |= ROCKET_MODE_RS232; + break; + } + + info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR; + if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { + printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n", + board, aiop, chan); + kfree(info); + return; + } + + rocketMode = info->flags & ROCKET_MODE_MASK; + + if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485)) + sEnRTSToggle(&info->channel); + else + sDisRTSToggle(&info->channel); + + if (ctlp->boardType == ROCKET_TYPE_PC104) { + switch (rocketMode) { + case ROCKET_MODE_RS485: + sSetInterfaceMode(&info->channel, InterfaceModeRS485); + break; + case ROCKET_MODE_RS422: + sSetInterfaceMode(&info->channel, InterfaceModeRS422); + break; + case ROCKET_MODE_RS232: + default: + if (info->flags & ROCKET_RTS_TOGGLE) + sSetInterfaceMode(&info->channel, InterfaceModeRS232T); + else + sSetInterfaceMode(&info->channel, InterfaceModeRS232); + break; + } + } + spin_lock_init(&info->slock); + mutex_init(&info->write_mtx); + rp_table[line] = info; + tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev : + NULL); +} + +/* + * Configures a rocketport port according to its termio settings. Called from + * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. + */ +static void configure_r_port(struct tty_struct *tty, struct r_port *info, + struct ktermios *old_termios) +{ + unsigned cflag; + unsigned long flags; + unsigned rocketMode; + int bits, baud, divisor; + CHANNEL_t *cp; + struct ktermios *t = tty->termios; + + cp = &info->channel; + cflag = t->c_cflag; + + /* Byte size and parity */ + if ((cflag & CSIZE) == CS8) { + sSetData8(cp); + bits = 10; + } else { + sSetData7(cp); + bits = 9; + } + if (cflag & CSTOPB) { + sSetStop2(cp); + bits++; + } else { + sSetStop1(cp); + } + + if (cflag & PARENB) { + sEnParity(cp); + bits++; + if (cflag & PARODD) { + sSetOddParity(cp); + } else { + sSetEvenParity(cp); + } + } else { + sDisParity(cp); + } + + /* baud rate */ + baud = tty_get_baud_rate(tty); + if (!baud) + baud = 9600; + divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1; + if ((divisor >= 8192 || divisor < 0) && old_termios) { + baud = tty_termios_baud_rate(old_termios); + if (!baud) + baud = 9600; + divisor = (rp_baud_base[info->board] / baud) - 1; + } + if (divisor >= 8192 || divisor < 0) { + baud = 9600; + divisor = (rp_baud_base[info->board] / baud) - 1; + } + info->cps = baud / bits; + sSetBaud(cp, divisor); + + /* FIXME: Should really back compute a baud rate from the divisor */ + tty_encode_baud_rate(tty, baud, baud); + + if (cflag & CRTSCTS) { + info->intmask |= DELTA_CTS; + sEnCTSFlowCtl(cp); + } else { + info->intmask &= ~DELTA_CTS; + sDisCTSFlowCtl(cp); + } + if (cflag & CLOCAL) { + info->intmask &= ~DELTA_CD; + } else { + spin_lock_irqsave(&info->slock, flags); + if (sGetChanStatus(cp) & CD_ACT) + info->cd_status = 1; + else + info->cd_status = 0; + info->intmask |= DELTA_CD; + spin_unlock_irqrestore(&info->slock, flags); + } + + /* + * Handle software flow control in the board + */ +#ifdef ROCKET_SOFT_FLOW + if (I_IXON(tty)) { + sEnTxSoftFlowCtl(cp); + if (I_IXANY(tty)) { + sEnIXANY(cp); + } else { + sDisIXANY(cp); + } + sSetTxXONChar(cp, START_CHAR(tty)); + sSetTxXOFFChar(cp, STOP_CHAR(tty)); + } else { + sDisTxSoftFlowCtl(cp); + sDisIXANY(cp); + sClrTxXOFF(cp); + } +#endif + + /* + * Set up ignore/read mask words + */ + info->read_status_mask = STMRCVROVRH | 0xFF; + if (I_INPCK(tty)) + info->read_status_mask |= STMFRAMEH | STMPARITYH; + if (I_BRKINT(tty) || I_PARMRK(tty)) + info->read_status_mask |= STMBREAKH; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(tty)) + info->ignore_status_mask |= STMFRAMEH | STMPARITYH; + if (I_IGNBRK(tty)) { + info->ignore_status_mask |= STMBREAKH; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too. (For real raw support). + */ + if (I_IGNPAR(tty)) + info->ignore_status_mask |= STMRCVROVRH; + } + + rocketMode = info->flags & ROCKET_MODE_MASK; + + if ((info->flags & ROCKET_RTS_TOGGLE) + || (rocketMode == ROCKET_MODE_RS485)) + sEnRTSToggle(cp); + else + sDisRTSToggle(cp); + + sSetRTS(&info->channel); + + if (cp->CtlP->boardType == ROCKET_TYPE_PC104) { + switch (rocketMode) { + case ROCKET_MODE_RS485: + sSetInterfaceMode(cp, InterfaceModeRS485); + break; + case ROCKET_MODE_RS422: + sSetInterfaceMode(cp, InterfaceModeRS422); + break; + case ROCKET_MODE_RS232: + default: + if (info->flags & ROCKET_RTS_TOGGLE) + sSetInterfaceMode(cp, InterfaceModeRS232T); + else + sSetInterfaceMode(cp, InterfaceModeRS232); + break; + } + } +} + +static int carrier_raised(struct tty_port *port) +{ + struct r_port *info = container_of(port, struct r_port, port); + return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; +} + +static void dtr_rts(struct tty_port *port, int on) +{ + struct r_port *info = container_of(port, struct r_port, port); + if (on) { + sSetDTR(&info->channel); + sSetRTS(&info->channel); + } else { + sClrDTR(&info->channel); + sClrRTS(&info->channel); + } +} + +/* + * Exception handler that opens a serial port. Creates xmit_buf storage, fills in + * port's r_port struct. Initializes the port hardware. + */ +static int rp_open(struct tty_struct *tty, struct file *filp) +{ + struct r_port *info; + struct tty_port *port; + int line = 0, retval; + CHANNEL_t *cp; + unsigned long page; + + line = tty->index; + if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL)) + return -ENXIO; + port = &info->port; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + if (port->flags & ASYNC_CLOSING) { + retval = wait_for_completion_interruptible(&info->close_wait); + free_page(page); + if (retval) + return retval; + return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); + } + + /* + * We must not sleep from here until the port is marked fully in use. + */ + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + + tty->driver_data = info; + tty_port_tty_set(port, tty); + + if (port->count++ == 0) { + atomic_inc(&rp_num_ports_open); + +#ifdef ROCKET_DEBUG_OPEN + printk(KERN_INFO "rocket mod++ = %d...\n", + atomic_read(&rp_num_ports_open)); +#endif + } +#ifdef ROCKET_DEBUG_OPEN + printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count); +#endif + + /* + * Info->count is now 1; so it's safe to sleep now. + */ + if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { + cp = &info->channel; + sSetRxTrigger(cp, TRIG_1); + if (sGetChanStatus(cp) & CD_ACT) + info->cd_status = 1; + else + info->cd_status = 0; + sDisRxStatusMode(cp); + sFlushRxFIFO(cp); + sFlushTxFIFO(cp); + + sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN)); + sSetRxTrigger(cp, TRIG_1); + + sGetChanStatus(cp); + sDisRxStatusMode(cp); + sClrTxXOFF(cp); + + sDisCTSFlowCtl(cp); + sDisTxSoftFlowCtl(cp); + + sEnRxFIFO(cp); + sEnTransmit(cp); + + set_bit(ASYNCB_INITIALIZED, &info->port.flags); + + /* + * Set up the tty->alt_speed kludge + */ + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) + tty->alt_speed = 57600; + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) + tty->alt_speed = 115200; + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) + tty->alt_speed = 230400; + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) + tty->alt_speed = 460800; + + configure_r_port(tty, info, NULL); + if (tty->termios->c_cflag & CBAUD) { + sSetDTR(cp); + sSetRTS(cp); + } + } + /* Starts (or resets) the maint polling loop */ + mod_timer(&rocket_timer, jiffies + POLL_PERIOD); + + retval = tty_port_block_til_ready(port, tty, filp); + if (retval) { +#ifdef ROCKET_DEBUG_OPEN + printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval); +#endif + return retval; + } + return 0; +} + +/* + * Exception handler that closes a serial port. info->port.count is considered critical. + */ +static void rp_close(struct tty_struct *tty, struct file *filp) +{ + struct r_port *info = tty->driver_data; + struct tty_port *port = &info->port; + int timeout; + CHANNEL_t *cp; + + if (rocket_paranoia_check(info, "rp_close")) + return; + +#ifdef ROCKET_DEBUG_OPEN + printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count); +#endif + + if (tty_port_close_start(port, tty, filp) == 0) + return; + + mutex_lock(&port->mutex); + cp = &info->channel; + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps; + if (timeout == 0) + timeout = 1; + rp_wait_until_sent(tty, timeout); + clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + + sDisTransmit(cp); + sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN)); + sDisCTSFlowCtl(cp); + sDisTxSoftFlowCtl(cp); + sClrTxXOFF(cp); + sFlushRxFIFO(cp); + sFlushTxFIFO(cp); + sClrRTS(cp); + if (C_HUPCL(tty)) + sClrDTR(cp); + + rp_flush_buffer(tty); + + tty_ldisc_flush(tty); + + clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + + /* We can't yet use tty_port_close_end as the buffer handling in this + driver is a bit different to the usual */ + + if (port->blocked_open) { + if (port->close_delay) { + msleep_interruptible(jiffies_to_msecs(port->close_delay)); + } + wake_up_interruptible(&port->open_wait); + } else { + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = NULL; + } + } + spin_lock_irq(&port->lock); + info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); + tty->closing = 0; + spin_unlock_irq(&port->lock); + mutex_unlock(&port->mutex); + tty_port_tty_set(port, NULL); + + wake_up_interruptible(&port->close_wait); + complete_all(&info->close_wait); + atomic_dec(&rp_num_ports_open); + +#ifdef ROCKET_DEBUG_OPEN + printk(KERN_INFO "rocket mod-- = %d...\n", + atomic_read(&rp_num_ports_open)); + printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line); +#endif + +} + +static void rp_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + unsigned cflag; + + if (rocket_paranoia_check(info, "rp_set_termios")) + return; + + cflag = tty->termios->c_cflag; + + /* + * This driver doesn't support CS5 or CS6 + */ + if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6)) + tty->termios->c_cflag = + ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE)); + /* Or CMSPAR */ + tty->termios->c_cflag &= ~CMSPAR; + + configure_r_port(tty, info, old_termios); + + cp = &info->channel; + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) { + sClrDTR(cp); + sClrRTS(cp); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) { + if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS)) + sSetRTS(cp); + sSetDTR(cp); + } + + if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rp_start(tty); + } +} + +static int rp_break(struct tty_struct *tty, int break_state) +{ + struct r_port *info = tty->driver_data; + unsigned long flags; + + if (rocket_paranoia_check(info, "rp_break")) + return -EINVAL; + + spin_lock_irqsave(&info->slock, flags); + if (break_state == -1) + sSendBreak(&info->channel); + else + sClrBreak(&info->channel); + spin_unlock_irqrestore(&info->slock, flags); + return 0; +} + +/* + * sGetChanRI used to be a macro in rocket_int.h. When the functionality for + * the UPCI boards was added, it was decided to make this a function because + * the macro was getting too complicated. All cases except the first one + * (UPCIRingInd) are taken directly from the original macro. + */ +static int sGetChanRI(CHANNEL_T * ChP) +{ + CONTROLLER_t *CtlP = ChP->CtlP; + int ChanNum = ChP->ChanNum; + int RingInd = 0; + + if (CtlP->UPCIRingInd) + RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]); + else if (CtlP->AltChanRingIndicator) + RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT; + else if (CtlP->boardType == ROCKET_TYPE_PC104) + RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]); + + return RingInd; +} + +/********************************************************************************************/ +/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */ + +/* + * Returns the state of the serial modem control lines. These next 2 functions + * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs. + */ +static int rp_tiocmget(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + unsigned int control, result, ChanStatus; + + ChanStatus = sGetChanStatusLo(&info->channel); + control = info->channel.TxControl[3]; + result = ((control & SET_RTS) ? TIOCM_RTS : 0) | + ((control & SET_DTR) ? TIOCM_DTR : 0) | + ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) | + (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) | + ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) | + ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0); + + return result; +} + +/* + * Sets the modem control lines + */ +static int rp_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct r_port *info = tty->driver_data; + + if (set & TIOCM_RTS) + info->channel.TxControl[3] |= SET_RTS; + if (set & TIOCM_DTR) + info->channel.TxControl[3] |= SET_DTR; + if (clear & TIOCM_RTS) + info->channel.TxControl[3] &= ~SET_RTS; + if (clear & TIOCM_DTR) + info->channel.TxControl[3] &= ~SET_DTR; + + out32(info->channel.IndexAddr, info->channel.TxControl); + return 0; +} + +static int get_config(struct r_port *info, struct rocket_config __user *retinfo) +{ + struct rocket_config tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof (tmp)); + mutex_lock(&info->port.mutex); + tmp.line = info->line; + tmp.flags = info->flags; + tmp.close_delay = info->port.close_delay; + tmp.closing_wait = info->port.closing_wait; + tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; + mutex_unlock(&info->port.mutex); + + if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) + return -EFAULT; + return 0; +} + +static int set_config(struct tty_struct *tty, struct r_port *info, + struct rocket_config __user *new_info) +{ + struct rocket_config new_serial; + + if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) + return -EFAULT; + + mutex_lock(&info->port.mutex); + if (!capable(CAP_SYS_ADMIN)) + { + if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) { + mutex_unlock(&info->port.mutex); + return -EPERM; + } + info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); + configure_r_port(tty, info, NULL); + mutex_unlock(&info->port.mutex); + return 0; + } + + info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS)); + info->port.close_delay = new_serial.close_delay; + info->port.closing_wait = new_serial.closing_wait; + + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) + tty->alt_speed = 57600; + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) + tty->alt_speed = 115200; + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) + tty->alt_speed = 230400; + if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) + tty->alt_speed = 460800; + mutex_unlock(&info->port.mutex); + + configure_r_port(tty, info, NULL); + return 0; +} + +/* + * This function fills in a rocket_ports struct with information + * about what boards/ports are in the system. This info is passed + * to user space. See setrocket.c where the info is used to create + * the /dev/ttyRx ports. + */ +static int get_ports(struct r_port *info, struct rocket_ports __user *retports) +{ + struct rocket_ports tmp; + int board; + + if (!retports) + return -EFAULT; + memset(&tmp, 0, sizeof (tmp)); + tmp.tty_major = rocket_driver->major; + + for (board = 0; board < 4; board++) { + tmp.rocketModel[board].model = rocketModel[board].model; + strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString); + tmp.rocketModel[board].numPorts = rocketModel[board].numPorts; + tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2; + tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber; + } + if (copy_to_user(retports, &tmp, sizeof (*retports))) + return -EFAULT; + return 0; +} + +static int reset_rm2(struct r_port *info, void __user *arg) +{ + int reset; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&reset, arg, sizeof (int))) + return -EFAULT; + if (reset) + reset = 1; + + if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII && + rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII) + return -EINVAL; + + if (info->ctlp->BusType == isISA) + sModemReset(info->ctlp, info->chan, reset); + else + sPCIModemReset(info->ctlp, info->chan, reset); + + return 0; +} + +static int get_version(struct r_port *info, struct rocket_version __user *retvers) +{ + if (copy_to_user(retvers, &driver_version, sizeof (*retvers))) + return -EFAULT; + return 0; +} + +/* IOCTL call handler into the driver */ +static int rp_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct r_port *info = tty->driver_data; + void __user *argp = (void __user *)arg; + int ret = 0; + + if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) + return -ENXIO; + + switch (cmd) { + case RCKP_GET_STRUCT: + if (copy_to_user(argp, info, sizeof (struct r_port))) + ret = -EFAULT; + break; + case RCKP_GET_CONFIG: + ret = get_config(info, argp); + break; + case RCKP_SET_CONFIG: + ret = set_config(tty, info, argp); + break; + case RCKP_GET_PORTS: + ret = get_ports(info, argp); + break; + case RCKP_RESET_RM2: + ret = reset_rm2(info, argp); + break; + case RCKP_GET_VERSION: + ret = get_version(info, argp); + break; + default: + ret = -ENOIOCTLCMD; + } + return ret; +} + +static void rp_send_xchar(struct tty_struct *tty, char ch) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + + if (rocket_paranoia_check(info, "rp_send_xchar")) + return; + + cp = &info->channel; + if (sGetTxCnt(cp)) + sWriteTxPrioByte(cp, ch); + else + sWriteTxByte(sGetTxRxDataIO(cp), ch); +} + +static void rp_throttle(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + +#ifdef ROCKET_DEBUG_THROTTLE + printk(KERN_INFO "throttle %s: %d....\n", tty->name, + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (rocket_paranoia_check(info, "rp_throttle")) + return; + + cp = &info->channel; + if (I_IXOFF(tty)) + rp_send_xchar(tty, STOP_CHAR(tty)); + + sClrRTS(&info->channel); +} + +static void rp_unthrottle(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; +#ifdef ROCKET_DEBUG_THROTTLE + printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (rocket_paranoia_check(info, "rp_throttle")) + return; + + cp = &info->channel; + if (I_IXOFF(tty)) + rp_send_xchar(tty, START_CHAR(tty)); + + sSetRTS(&info->channel); +} + +/* + * ------------------------------------------------------------ + * rp_stop() and rp_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rp_stop(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + +#ifdef ROCKET_DEBUG_FLOW + printk(KERN_INFO "stop %s: %d %d....\n", tty->name, + info->xmit_cnt, info->xmit_fifo_room); +#endif + + if (rocket_paranoia_check(info, "rp_stop")) + return; + + if (sGetTxCnt(&info->channel)) + sDisTransmit(&info->channel); +} + +static void rp_start(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + +#ifdef ROCKET_DEBUG_FLOW + printk(KERN_INFO "start %s: %d %d....\n", tty->name, + info->xmit_cnt, info->xmit_fifo_room); +#endif + + if (rocket_paranoia_check(info, "rp_stop")) + return; + + sEnTransmit(&info->channel); + set_bit((info->aiop * 8) + info->chan, + (void *) &xmit_flags[info->board]); +} + +/* + * rp_wait_until_sent() --- wait until the transmitter is empty + */ +static void rp_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + unsigned long orig_jiffies; + int check_time, exit_time; + int txcnt; + + if (rocket_paranoia_check(info, "rp_wait_until_sent")) + return; + + cp = &info->channel; + + orig_jiffies = jiffies; +#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT + printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout, + jiffies); + printk(KERN_INFO "cps=%d...\n", info->cps); +#endif + while (1) { + txcnt = sGetTxCnt(cp); + if (!txcnt) { + if (sGetChanStatusLo(cp) & TXSHRMT) + break; + check_time = (HZ / info->cps) / 5; + } else { + check_time = HZ * txcnt / info->cps; + } + if (timeout) { + exit_time = orig_jiffies + timeout - jiffies; + if (exit_time <= 0) + break; + if (exit_time < check_time) + check_time = exit_time; + } + if (check_time == 0) + check_time = 1; +#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT + printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt, + jiffies, check_time); +#endif + msleep_interruptible(jiffies_to_msecs(check_time)); + if (signal_pending(current)) + break; + } + __set_current_state(TASK_RUNNING); +#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT + printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); +#endif +} + +/* + * rp_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rp_hangup(struct tty_struct *tty) +{ + CHANNEL_t *cp; + struct r_port *info = tty->driver_data; + unsigned long flags; + + if (rocket_paranoia_check(info, "rp_hangup")) + return; + +#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP)) + printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); +#endif + rp_flush_buffer(tty); + spin_lock_irqsave(&info->port.lock, flags); + if (info->port.flags & ASYNC_CLOSING) { + spin_unlock_irqrestore(&info->port.lock, flags); + return; + } + if (info->port.count) + atomic_dec(&rp_num_ports_open); + clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + spin_unlock_irqrestore(&info->port.lock, flags); + + tty_port_hangup(&info->port); + + cp = &info->channel; + sDisRxFIFO(cp); + sDisTransmit(cp); + sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN)); + sDisCTSFlowCtl(cp); + sDisTxSoftFlowCtl(cp); + sClrTxXOFF(cp); + clear_bit(ASYNCB_INITIALIZED, &info->port.flags); + + wake_up_interruptible(&info->port.open_wait); +} + +/* + * Exception handler - write char routine. The RocketPort driver uses a + * double-buffering strategy, with the twist that if the in-memory CPU + * buffer is empty, and there's space in the transmit FIFO, the + * writing routines will write directly to transmit FIFO. + * Write buffer and counters protected by spinlocks + */ +static int rp_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + unsigned long flags; + + if (rocket_paranoia_check(info, "rp_put_char")) + return 0; + + /* + * Grab the port write mutex, locking out other processes that try to + * write to this port + */ + mutex_lock(&info->write_mtx); + +#ifdef ROCKET_DEBUG_WRITE + printk(KERN_INFO "rp_put_char %c...\n", ch); +#endif + + spin_lock_irqsave(&info->slock, flags); + cp = &info->channel; + + if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0) + info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); + + if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) { + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= XMIT_BUF_SIZE - 1; + info->xmit_cnt++; + set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + } else { + sOutB(sGetTxRxDataIO(cp), ch); + info->xmit_fifo_room--; + } + spin_unlock_irqrestore(&info->slock, flags); + mutex_unlock(&info->write_mtx); + return 1; +} + +/* + * Exception handler - write routine, called when user app writes to the device. + * A per port write mutex is used to protect from another process writing to + * this port at the same time. This other process could be running on the other CPU + * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). + * Spinlocks protect the info xmit members. + */ +static int rp_write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + const unsigned char *b; + int c, retval = 0; + unsigned long flags; + + if (count <= 0 || rocket_paranoia_check(info, "rp_write")) + return 0; + + if (mutex_lock_interruptible(&info->write_mtx)) + return -ERESTARTSYS; + +#ifdef ROCKET_DEBUG_WRITE + printk(KERN_INFO "rp_write %d chars...\n", count); +#endif + cp = &info->channel; + + if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count) + info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); + + /* + * If the write queue for the port is empty, and there is FIFO space, stuff bytes + * into FIFO. Use the write queue for temp storage. + */ + if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) { + c = min(count, info->xmit_fifo_room); + b = buf; + + /* Push data into FIFO, 2 bytes at a time */ + sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2); + + /* If there is a byte remaining, write it */ + if (c & 1) + sOutB(sGetTxRxDataIO(cp), b[c - 1]); + + retval += c; + buf += c; + count -= c; + + spin_lock_irqsave(&info->slock, flags); + info->xmit_fifo_room -= c; + spin_unlock_irqrestore(&info->slock, flags); + } + + /* If count is zero, we wrote it all and are done */ + if (!count) + goto end; + + /* Write remaining data into the port's xmit_buf */ + while (1) { + /* Hung up ? */ + if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags)) + goto end; + c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); + c = min(c, XMIT_BUF_SIZE - info->xmit_head); + if (c <= 0) + break; + + b = buf; + memcpy(info->xmit_buf + info->xmit_head, b, c); + + spin_lock_irqsave(&info->slock, flags); + info->xmit_head = + (info->xmit_head + c) & (XMIT_BUF_SIZE - 1); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->slock, flags); + + buf += c; + count -= c; + retval += c; + } + + if ((retval > 0) && !tty->stopped && !tty->hw_stopped) + set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); + +end: + if (info->xmit_cnt < WAKEUP_CHARS) { + tty_wakeup(tty); +#ifdef ROCKETPORT_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif + } + mutex_unlock(&info->write_mtx); + return retval; +} + +/* + * Return the number of characters that can be sent. We estimate + * only using the in-memory transmit buffer only, and ignore the + * potential space in the transmit FIFO. + */ +static int rp_write_room(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + int ret; + + if (rocket_paranoia_check(info, "rp_write_room")) + return 0; + + ret = XMIT_BUF_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; +#ifdef ROCKET_DEBUG_WRITE + printk(KERN_INFO "rp_write_room returns %d...\n", ret); +#endif + return ret; +} + +/* + * Return the number of characters in the buffer. Again, this only + * counts those characters in the in-memory transmit buffer. + */ +static int rp_chars_in_buffer(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + + if (rocket_paranoia_check(info, "rp_chars_in_buffer")) + return 0; + + cp = &info->channel; + +#ifdef ROCKET_DEBUG_WRITE + printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt); +#endif + return info->xmit_cnt; +} + +/* + * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the + * r_port struct for the port. Note that spinlock are used to protect info members, + * do not call this function if the spinlock is already held. + */ +static void rp_flush_buffer(struct tty_struct *tty) +{ + struct r_port *info = tty->driver_data; + CHANNEL_t *cp; + unsigned long flags; + + if (rocket_paranoia_check(info, "rp_flush_buffer")) + return; + + spin_lock_irqsave(&info->slock, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + spin_unlock_irqrestore(&info->slock, flags); + +#ifdef ROCKETPORT_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif + tty_wakeup(tty); + + cp = &info->channel; + sFlushTxFIFO(cp); +} + +#ifdef CONFIG_PCI + +static struct pci_device_id __devinitdata __used rocket_pci_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(pci, rocket_pci_ids); + +/* + * Called when a PCI card is found. Retrieves and stores model information, + * init's aiopic and serial port hardware. + * Inputs: i is the board number (0-n) + */ +static __init int register_PCI(int i, struct pci_dev *dev) +{ + int num_aiops, aiop, max_num_aiops, num_chan, chan; + unsigned int aiopio[MAX_AIOPS_PER_BOARD]; + char *str, *board_type; + CONTROLLER_t *ctlp; + + int fast_clock = 0; + int altChanRingIndicator = 0; + int ports_per_aiop = 8; + WordIO_t ConfigIO = 0; + ByteIO_t UPCIRingInd = 0; + + if (!dev || pci_enable_device(dev)) + return 0; + + rcktpt_io_addr[i] = pci_resource_start(dev, 0); + + rcktpt_type[i] = ROCKET_TYPE_NORMAL; + rocketModel[i].loadrm2 = 0; + rocketModel[i].startingPortNumber = nextLineNumber; + + /* Depending on the model, set up some config variables */ + switch (dev->device) { + case PCI_DEVICE_ID_RP4QUAD: + str = "Quadcable"; + max_num_aiops = 1; + ports_per_aiop = 4; + rocketModel[i].model = MODEL_RP4QUAD; + strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable"); + rocketModel[i].numPorts = 4; + break; + case PCI_DEVICE_ID_RP8OCTA: + str = "Octacable"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_RP8OCTA; + strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_URP8OCTA: + str = "Octacable"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_UPCI_RP8OCTA; + strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_RP8INTF: + str = "8"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_RP8INTF; + strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_URP8INTF: + str = "8"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_UPCI_RP8INTF; + strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_RP8J: + str = "8J"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_RP8J; + strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_RP4J: + str = "4J"; + max_num_aiops = 1; + ports_per_aiop = 4; + rocketModel[i].model = MODEL_RP4J; + strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors"); + rocketModel[i].numPorts = 4; + break; + case PCI_DEVICE_ID_RP8SNI: + str = "8 (DB78 Custom)"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_RP8SNI; + strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_RP16SNI: + str = "16 (DB78 Custom)"; + max_num_aiops = 2; + rocketModel[i].model = MODEL_RP16SNI; + strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78"); + rocketModel[i].numPorts = 16; + break; + case PCI_DEVICE_ID_RP16INTF: + str = "16"; + max_num_aiops = 2; + rocketModel[i].model = MODEL_RP16INTF; + strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F"); + rocketModel[i].numPorts = 16; + break; + case PCI_DEVICE_ID_URP16INTF: + str = "16"; + max_num_aiops = 2; + rocketModel[i].model = MODEL_UPCI_RP16INTF; + strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F"); + rocketModel[i].numPorts = 16; + break; + case PCI_DEVICE_ID_CRP16INTF: + str = "16"; + max_num_aiops = 2; + rocketModel[i].model = MODEL_CPCI_RP16INTF; + strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F"); + rocketModel[i].numPorts = 16; + break; + case PCI_DEVICE_ID_RP32INTF: + str = "32"; + max_num_aiops = 4; + rocketModel[i].model = MODEL_RP32INTF; + strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F"); + rocketModel[i].numPorts = 32; + break; + case PCI_DEVICE_ID_URP32INTF: + str = "32"; + max_num_aiops = 4; + rocketModel[i].model = MODEL_UPCI_RP32INTF; + strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F"); + rocketModel[i].numPorts = 32; + break; + case PCI_DEVICE_ID_RPP4: + str = "Plus Quadcable"; + max_num_aiops = 1; + ports_per_aiop = 4; + altChanRingIndicator++; + fast_clock++; + rocketModel[i].model = MODEL_RPP4; + strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port"); + rocketModel[i].numPorts = 4; + break; + case PCI_DEVICE_ID_RPP8: + str = "Plus Octacable"; + max_num_aiops = 2; + ports_per_aiop = 4; + altChanRingIndicator++; + fast_clock++; + rocketModel[i].model = MODEL_RPP8; + strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port"); + rocketModel[i].numPorts = 8; + break; + case PCI_DEVICE_ID_RP2_232: + str = "Plus 2 (RS-232)"; + max_num_aiops = 1; + ports_per_aiop = 2; + altChanRingIndicator++; + fast_clock++; + rocketModel[i].model = MODEL_RP2_232; + strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232"); + rocketModel[i].numPorts = 2; + break; + case PCI_DEVICE_ID_RP2_422: + str = "Plus 2 (RS-422)"; + max_num_aiops = 1; + ports_per_aiop = 2; + altChanRingIndicator++; + fast_clock++; + rocketModel[i].model = MODEL_RP2_422; + strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422"); + rocketModel[i].numPorts = 2; + break; + case PCI_DEVICE_ID_RP6M: + + max_num_aiops = 1; + ports_per_aiop = 6; + str = "6-port"; + + /* If revision is 1, the rocketmodem flash must be loaded. + * If it is 2 it is a "socketed" version. */ + if (dev->revision == 1) { + rcktpt_type[i] = ROCKET_TYPE_MODEMII; + rocketModel[i].loadrm2 = 1; + } else { + rcktpt_type[i] = ROCKET_TYPE_MODEM; + } + + rocketModel[i].model = MODEL_RP6M; + strcpy(rocketModel[i].modelString, "RocketModem 6 port"); + rocketModel[i].numPorts = 6; + break; + case PCI_DEVICE_ID_RP4M: + max_num_aiops = 1; + ports_per_aiop = 4; + str = "4-port"; + if (dev->revision == 1) { + rcktpt_type[i] = ROCKET_TYPE_MODEMII; + rocketModel[i].loadrm2 = 1; + } else { + rcktpt_type[i] = ROCKET_TYPE_MODEM; + } + + rocketModel[i].model = MODEL_RP4M; + strcpy(rocketModel[i].modelString, "RocketModem 4 port"); + rocketModel[i].numPorts = 4; + break; + default: + str = "(unknown/unsupported)"; + max_num_aiops = 0; + break; + } + + /* + * Check for UPCI boards. + */ + + switch (dev->device) { + case PCI_DEVICE_ID_URP32INTF: + case PCI_DEVICE_ID_URP8INTF: + case PCI_DEVICE_ID_URP16INTF: + case PCI_DEVICE_ID_CRP16INTF: + case PCI_DEVICE_ID_URP8OCTA: + rcktpt_io_addr[i] = pci_resource_start(dev, 2); + ConfigIO = pci_resource_start(dev, 1); + if (dev->device == PCI_DEVICE_ID_URP8OCTA) { + UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND; + + /* + * Check for octa or quad cable. + */ + if (! + (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) & + PCI_GPIO_CTRL_8PORT)) { + str = "Quadcable"; + ports_per_aiop = 4; + rocketModel[i].numPorts = 4; + } + } + break; + case PCI_DEVICE_ID_UPCI_RM3_8PORT: + str = "8 ports"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_UPCI_RM3_8PORT; + strcpy(rocketModel[i].modelString, "RocketModem III 8 port"); + rocketModel[i].numPorts = 8; + rcktpt_io_addr[i] = pci_resource_start(dev, 2); + UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND; + ConfigIO = pci_resource_start(dev, 1); + rcktpt_type[i] = ROCKET_TYPE_MODEMIII; + break; + case PCI_DEVICE_ID_UPCI_RM3_4PORT: + str = "4 ports"; + max_num_aiops = 1; + rocketModel[i].model = MODEL_UPCI_RM3_4PORT; + strcpy(rocketModel[i].modelString, "RocketModem III 4 port"); + rocketModel[i].numPorts = 4; + rcktpt_io_addr[i] = pci_resource_start(dev, 2); + UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND; + ConfigIO = pci_resource_start(dev, 1); + rcktpt_type[i] = ROCKET_TYPE_MODEMIII; + break; + default: + break; + } + + switch (rcktpt_type[i]) { + case ROCKET_TYPE_MODEM: + board_type = "RocketModem"; + break; + case ROCKET_TYPE_MODEMII: + board_type = "RocketModem II"; + break; + case ROCKET_TYPE_MODEMIII: + board_type = "RocketModem III"; + break; + default: + board_type = "RocketPort"; + break; + } + + if (fast_clock) { + sClockPrescale = 0x12; /* mod 2 (divide by 3) */ + rp_baud_base[i] = 921600; + } else { + /* + * If support_low_speed is set, use the slow clock + * prescale, which supports 50 bps + */ + if (support_low_speed) { + /* mod 9 (divide by 10) prescale */ + sClockPrescale = 0x19; + rp_baud_base[i] = 230400; + } else { + /* mod 4 (devide by 5) prescale */ + sClockPrescale = 0x14; + rp_baud_base[i] = 460800; + } + } + + for (aiop = 0; aiop < max_num_aiops; aiop++) + aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40); + ctlp = sCtlNumToCtlPtr(i); + num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd); + for (aiop = 0; aiop < max_num_aiops; aiop++) + ctlp->AiopNumChan[aiop] = ports_per_aiop; + + dev_info(&dev->dev, "comtrol PCI controller #%d found at " + "address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n", + i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString, + rocketModel[i].startingPortNumber, + rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1); + + if (num_aiops <= 0) { + rcktpt_io_addr[i] = 0; + return (0); + } + is_PCI[i] = 1; + + /* Reset the AIOPIC, init the serial ports */ + for (aiop = 0; aiop < num_aiops; aiop++) { + sResetAiopByNum(ctlp, aiop); + num_chan = ports_per_aiop; + for (chan = 0; chan < num_chan; chan++) + init_r_port(i, aiop, chan, dev); + } + + /* Rocket modems must be reset */ + if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || + (rcktpt_type[i] == ROCKET_TYPE_MODEMII) || + (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) { + num_chan = ports_per_aiop; + for (chan = 0; chan < num_chan; chan++) + sPCIModemReset(ctlp, chan, 1); + msleep(500); + for (chan = 0; chan < num_chan; chan++) + sPCIModemReset(ctlp, chan, 0); + msleep(500); + rmSpeakerReset(ctlp, rocketModel[i].model); + } + return (1); +} + +/* + * Probes for PCI cards, inits them if found + * Input: board_found = number of ISA boards already found, or the + * starting board number + * Returns: Number of PCI boards found + */ +static int __init init_PCI(int boards_found) +{ + struct pci_dev *dev = NULL; + int count = 0; + + /* Work through the PCI device list, pulling out ours */ + while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { + if (register_PCI(count + boards_found, dev)) + count++; + } + return (count); +} + +#endif /* CONFIG_PCI */ + +/* + * Probes for ISA cards + * Input: i = the board number to look for + * Returns: 1 if board found, 0 else + */ +static int __init init_ISA(int i) +{ + int num_aiops, num_chan = 0, total_num_chan = 0; + int aiop, chan; + unsigned int aiopio[MAX_AIOPS_PER_BOARD]; + CONTROLLER_t *ctlp; + char *type_string; + + /* If io_addr is zero, no board configured */ + if (rcktpt_io_addr[i] == 0) + return (0); + + /* Reserve the IO region */ + if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) { + printk(KERN_ERR "Unable to reserve IO region for configured " + "ISA RocketPort at address 0x%lx, board not " + "installed...\n", rcktpt_io_addr[i]); + rcktpt_io_addr[i] = 0; + return (0); + } + + ctlp = sCtlNumToCtlPtr(i); + + ctlp->boardType = rcktpt_type[i]; + + switch (rcktpt_type[i]) { + case ROCKET_TYPE_PC104: + type_string = "(PC104)"; + break; + case ROCKET_TYPE_MODEM: + type_string = "(RocketModem)"; + break; + case ROCKET_TYPE_MODEMII: + type_string = "(RocketModem II)"; + break; + default: + type_string = ""; + break; + } + + /* + * If support_low_speed is set, use the slow clock prescale, + * which supports 50 bps + */ + if (support_low_speed) { + sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */ + rp_baud_base[i] = 230400; + } else { + sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */ + rp_baud_base[i] = 460800; + } + + for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++) + aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400); + + num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0); + + if (ctlp->boardType == ROCKET_TYPE_PC104) { + sEnAiop(ctlp, 2); /* only one AIOPIC, but these */ + sEnAiop(ctlp, 3); /* CSels used for other stuff */ + } + + /* If something went wrong initing the AIOP's release the ISA IO memory */ + if (num_aiops <= 0) { + release_region(rcktpt_io_addr[i], 64); + rcktpt_io_addr[i] = 0; + return (0); + } + + rocketModel[i].startingPortNumber = nextLineNumber; + + for (aiop = 0; aiop < num_aiops; aiop++) { + sResetAiopByNum(ctlp, aiop); + sEnAiop(ctlp, aiop); + num_chan = sGetAiopNumChan(ctlp, aiop); + total_num_chan += num_chan; + for (chan = 0; chan < num_chan; chan++) + init_r_port(i, aiop, chan, NULL); + } + is_PCI[i] = 0; + if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) { + num_chan = sGetAiopNumChan(ctlp, 0); + total_num_chan = num_chan; + for (chan = 0; chan < num_chan; chan++) + sModemReset(ctlp, chan, 1); + msleep(500); + for (chan = 0; chan < num_chan; chan++) + sModemReset(ctlp, chan, 0); + msleep(500); + strcpy(rocketModel[i].modelString, "RocketModem ISA"); + } else { + strcpy(rocketModel[i].modelString, "RocketPort ISA"); + } + rocketModel[i].numPorts = total_num_chan; + rocketModel[i].model = MODEL_ISA; + + printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n", + i, rcktpt_io_addr[i], num_aiops, type_string); + + printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n", + rocketModel[i].modelString, + rocketModel[i].startingPortNumber, + rocketModel[i].startingPortNumber + + rocketModel[i].numPorts - 1); + + return (1); +} + +static const struct tty_operations rocket_ops = { + .open = rp_open, + .close = rp_close, + .write = rp_write, + .put_char = rp_put_char, + .write_room = rp_write_room, + .chars_in_buffer = rp_chars_in_buffer, + .flush_buffer = rp_flush_buffer, + .ioctl = rp_ioctl, + .throttle = rp_throttle, + .unthrottle = rp_unthrottle, + .set_termios = rp_set_termios, + .stop = rp_stop, + .start = rp_start, + .hangup = rp_hangup, + .break_ctl = rp_break, + .send_xchar = rp_send_xchar, + .wait_until_sent = rp_wait_until_sent, + .tiocmget = rp_tiocmget, + .tiocmset = rp_tiocmset, +}; + +static const struct tty_port_operations rocket_port_ops = { + .carrier_raised = carrier_raised, + .dtr_rts = dtr_rts, +}; + +/* + * The module "startup" routine; it's run when the module is loaded. + */ +static int __init rp_init(void) +{ + int ret = -ENOMEM, pci_boards_found, isa_boards_found, i; + + printk(KERN_INFO "RocketPort device driver module, version %s, %s\n", + ROCKET_VERSION, ROCKET_DATE); + + rocket_driver = alloc_tty_driver(MAX_RP_PORTS); + if (!rocket_driver) + goto err; + + /* + * If board 1 is non-zero, there is at least one ISA configured. If controller is + * zero, use the default controller IO address of board1 + 0x40. + */ + if (board1) { + if (controller == 0) + controller = board1 + 0x40; + } else { + controller = 0; /* Used as a flag, meaning no ISA boards */ + } + + /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */ + if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) { + printk(KERN_ERR "Unable to reserve IO region for first " + "configured ISA RocketPort controller 0x%lx. " + "Driver exiting\n", controller); + ret = -EBUSY; + goto err_tty; + } + + /* Store ISA variable retrieved from command line or .conf file. */ + rcktpt_io_addr[0] = board1; + rcktpt_io_addr[1] = board2; + rcktpt_io_addr[2] = board3; + rcktpt_io_addr[3] = board4; + + rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; + rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0]; + rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; + rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1]; + rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; + rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2]; + rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL; + rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3]; + + /* + * Set up the tty driver structure and then register this + * driver with the tty layer. + */ + + rocket_driver->owner = THIS_MODULE; + rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV; + rocket_driver->name = "ttyR"; + rocket_driver->driver_name = "Comtrol RocketPort"; + rocket_driver->major = TTY_ROCKET_MAJOR; + rocket_driver->minor_start = 0; + rocket_driver->type = TTY_DRIVER_TYPE_SERIAL; + rocket_driver->subtype = SERIAL_TYPE_NORMAL; + rocket_driver->init_termios = tty_std_termios; + rocket_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + rocket_driver->init_termios.c_ispeed = 9600; + rocket_driver->init_termios.c_ospeed = 9600; +#ifdef ROCKET_SOFT_FLOW + rocket_driver->flags |= TTY_DRIVER_REAL_RAW; +#endif + tty_set_operations(rocket_driver, &rocket_ops); + + ret = tty_register_driver(rocket_driver); + if (ret < 0) { + printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); + goto err_controller; + } + +#ifdef ROCKET_DEBUG_OPEN + printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major); +#endif + + /* + * OK, let's probe each of the controllers looking for boards. Any boards found + * will be initialized here. + */ + isa_boards_found = 0; + pci_boards_found = 0; + + for (i = 0; i < NUM_BOARDS; i++) { + if (init_ISA(i)) + isa_boards_found++; + } + +#ifdef CONFIG_PCI + if (isa_boards_found < NUM_BOARDS) + pci_boards_found = init_PCI(isa_boards_found); +#endif + + max_board = pci_boards_found + isa_boards_found; + + if (max_board == 0) { + printk(KERN_ERR "No rocketport ports found; unloading driver\n"); + ret = -ENXIO; + goto err_ttyu; + } + + return 0; +err_ttyu: + tty_unregister_driver(rocket_driver); +err_controller: + if (controller) + release_region(controller, 4); +err_tty: + put_tty_driver(rocket_driver); +err: + return ret; +} + + +static void rp_cleanup_module(void) +{ + int retval; + int i; + + del_timer_sync(&rocket_timer); + + retval = tty_unregister_driver(rocket_driver); + if (retval) + printk(KERN_ERR "Error %d while trying to unregister " + "rocketport driver\n", -retval); + + for (i = 0; i < MAX_RP_PORTS; i++) + if (rp_table[i]) { + tty_unregister_device(rocket_driver, i); + kfree(rp_table[i]); + } + + put_tty_driver(rocket_driver); + + for (i = 0; i < NUM_BOARDS; i++) { + if (rcktpt_io_addr[i] <= 0 || is_PCI[i]) + continue; + release_region(rcktpt_io_addr[i], 64); + } + if (controller) + release_region(controller, 4); +} + +/*************************************************************************** +Function: sInitController +Purpose: Initialization of controller global registers and controller + structure. +Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize, + IRQNum,Frequency,PeriodicOnly) + CONTROLLER_T *CtlP; Ptr to controller structure + int CtlNum; Controller number + ByteIO_t MudbacIO; Mudbac base I/O address. + ByteIO_t *AiopIOList; List of I/O addresses for each AIOP. + This list must be in the order the AIOPs will be found on the + controller. Once an AIOP in the list is not found, it is + assumed that there are no more AIOPs on the controller. + int AiopIOListSize; Number of addresses in AiopIOList + int IRQNum; Interrupt Request number. Can be any of the following: + 0: Disable global interrupts + 3: IRQ 3 + 4: IRQ 4 + 5: IRQ 5 + 9: IRQ 9 + 10: IRQ 10 + 11: IRQ 11 + 12: IRQ 12 + 15: IRQ 15 + Byte_t Frequency: A flag identifying the frequency + of the periodic interrupt, can be any one of the following: + FREQ_DIS - periodic interrupt disabled + FREQ_137HZ - 137 Hertz + FREQ_69HZ - 69 Hertz + FREQ_34HZ - 34 Hertz + FREQ_17HZ - 17 Hertz + FREQ_9HZ - 9 Hertz + FREQ_4HZ - 4 Hertz + If IRQNum is set to 0 the Frequency parameter is + overidden, it is forced to a value of FREQ_DIS. + int PeriodicOnly: 1 if all interrupts except the periodic + interrupt are to be blocked. + 0 is both the periodic interrupt and + other channel interrupts are allowed. + If IRQNum is set to 0 the PeriodicOnly parameter is + overidden, it is forced to a value of 0. +Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller + initialization failed. + +Comments: + If periodic interrupts are to be disabled but AIOP interrupts + are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0. + + If interrupts are to be completely disabled set IRQNum to 0. + + Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an + invalid combination. + + This function performs initialization of global interrupt modes, + but it does not actually enable global interrupts. To enable + and disable global interrupts use functions sEnGlobalInt() and + sDisGlobalInt(). Enabling of global interrupts is normally not + done until all other initializations are complete. + + Even if interrupts are globally enabled, they must also be + individually enabled for each channel that is to generate + interrupts. + +Warnings: No range checking on any of the parameters is done. + + No context switches are allowed while executing this function. + + After this function all AIOPs on the controller are disabled, + they can be enabled with sEnAiop(). +*/ +static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, + ByteIO_t * AiopIOList, int AiopIOListSize, + int IRQNum, Byte_t Frequency, int PeriodicOnly) +{ + int i; + ByteIO_t io; + int done; + + CtlP->AiopIntrBits = aiop_intr_bits; + CtlP->AltChanRingIndicator = 0; + CtlP->CtlNum = CtlNum; + CtlP->CtlID = CTLID_0001; /* controller release 1 */ + CtlP->BusType = isISA; + CtlP->MBaseIO = MudbacIO; + CtlP->MReg1IO = MudbacIO + 1; + CtlP->MReg2IO = MudbacIO + 2; + CtlP->MReg3IO = MudbacIO + 3; +#if 1 + CtlP->MReg2 = 0; /* interrupt disable */ + CtlP->MReg3 = 0; /* no periodic interrupts */ +#else + if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */ + CtlP->MReg2 = 0; /* interrupt disable */ + CtlP->MReg3 = 0; /* no periodic interrupts */ + } else { + CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ + CtlP->MReg3 = Frequency; /* set frequency */ + if (PeriodicOnly) { /* periodic interrupt only */ + CtlP->MReg3 |= PERIODIC_ONLY; + } + } +#endif + sOutB(CtlP->MReg2IO, CtlP->MReg2); + sOutB(CtlP->MReg3IO, CtlP->MReg3); + sControllerEOI(CtlP); /* clear EOI if warm init */ + /* Init AIOPs */ + CtlP->NumAiop = 0; + for (i = done = 0; i < AiopIOListSize; i++) { + io = AiopIOList[i]; + CtlP->AiopIO[i] = (WordIO_t) io; + CtlP->AiopIntChanIO[i] = io + _INT_CHAN; + sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */ + sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */ + if (done) + continue; + sEnAiop(CtlP, i); /* enable the AIOP */ + CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ + if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ + done = 1; /* done looking for AIOPs */ + else { + CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */ + sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */ + sOutB(io + _INDX_DATA, sClockPrescale); + CtlP->NumAiop++; /* bump count of AIOPs */ + } + sDisAiop(CtlP, i); /* disable AIOP */ + } + + if (CtlP->NumAiop == 0) + return (-1); + else + return (CtlP->NumAiop); +} + +/*************************************************************************** +Function: sPCIInitController +Purpose: Initialization of controller global registers and controller + structure. +Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize, + IRQNum,Frequency,PeriodicOnly) + CONTROLLER_T *CtlP; Ptr to controller structure + int CtlNum; Controller number + ByteIO_t *AiopIOList; List of I/O addresses for each AIOP. + This list must be in the order the AIOPs will be found on the + controller. Once an AIOP in the list is not found, it is + assumed that there are no more AIOPs on the controller. + int AiopIOListSize; Number of addresses in AiopIOList + int IRQNum; Interrupt Request number. Can be any of the following: + 0: Disable global interrupts + 3: IRQ 3 + 4: IRQ 4 + 5: IRQ 5 + 9: IRQ 9 + 10: IRQ 10 + 11: IRQ 11 + 12: IRQ 12 + 15: IRQ 15 + Byte_t Frequency: A flag identifying the frequency + of the periodic interrupt, can be any one of the following: + FREQ_DIS - periodic interrupt disabled + FREQ_137HZ - 137 Hertz + FREQ_69HZ - 69 Hertz + FREQ_34HZ - 34 Hertz + FREQ_17HZ - 17 Hertz + FREQ_9HZ - 9 Hertz + FREQ_4HZ - 4 Hertz + If IRQNum is set to 0 the Frequency parameter is + overidden, it is forced to a value of FREQ_DIS. + int PeriodicOnly: 1 if all interrupts except the periodic + interrupt are to be blocked. + 0 is both the periodic interrupt and + other channel interrupts are allowed. + If IRQNum is set to 0 the PeriodicOnly parameter is + overidden, it is forced to a value of 0. +Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller + initialization failed. + +Comments: + If periodic interrupts are to be disabled but AIOP interrupts + are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0. + + If interrupts are to be completely disabled set IRQNum to 0. + + Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an + invalid combination. + + This function performs initialization of global interrupt modes, + but it does not actually enable global interrupts. To enable + and disable global interrupts use functions sEnGlobalInt() and + sDisGlobalInt(). Enabling of global interrupts is normally not + done until all other initializations are complete. + + Even if interrupts are globally enabled, they must also be + individually enabled for each channel that is to generate + interrupts. + +Warnings: No range checking on any of the parameters is done. + + No context switches are allowed while executing this function. + + After this function all AIOPs on the controller are disabled, + they can be enabled with sEnAiop(). +*/ +static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, + ByteIO_t * AiopIOList, int AiopIOListSize, + WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, + int PeriodicOnly, int altChanRingIndicator, + int UPCIRingInd) +{ + int i; + ByteIO_t io; + + CtlP->AltChanRingIndicator = altChanRingIndicator; + CtlP->UPCIRingInd = UPCIRingInd; + CtlP->CtlNum = CtlNum; + CtlP->CtlID = CTLID_0001; /* controller release 1 */ + CtlP->BusType = isPCI; /* controller release 1 */ + + if (ConfigIO) { + CtlP->isUPCI = 1; + CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL; + CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL; + CtlP->AiopIntrBits = upci_aiop_intr_bits; + } else { + CtlP->isUPCI = 0; + CtlP->PCIIO = + (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC); + CtlP->AiopIntrBits = aiop_intr_bits; + } + + sPCIControllerEOI(CtlP); /* clear EOI if warm init */ + /* Init AIOPs */ + CtlP->NumAiop = 0; + for (i = 0; i < AiopIOListSize; i++) { + io = AiopIOList[i]; + CtlP->AiopIO[i] = (WordIO_t) io; + CtlP->AiopIntChanIO[i] = io + _INT_CHAN; + + CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ + if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ + break; /* done looking for AIOPs */ + + CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */ + sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */ + sOutB(io + _INDX_DATA, sClockPrescale); + CtlP->NumAiop++; /* bump count of AIOPs */ + } + + if (CtlP->NumAiop == 0) + return (-1); + else + return (CtlP->NumAiop); +} + +/*************************************************************************** +Function: sReadAiopID +Purpose: Read the AIOP idenfication number directly from an AIOP. +Call: sReadAiopID(io) + ByteIO_t io: AIOP base I/O address +Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X + is replace by an identifying number. + Flag AIOPID_NULL if no valid AIOP is found +Warnings: No context switches are allowed while executing this function. + +*/ +static int sReadAiopID(ByteIO_t io) +{ + Byte_t AiopID; /* ID byte from AIOP */ + + sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */ + sOutB(io + _CMD_REG, 0x0); + AiopID = sInW(io + _CHN_STAT0) & 0x07; + if (AiopID == 0x06) + return (1); + else /* AIOP does not exist */ + return (-1); +} + +/*************************************************************************** +Function: sReadAiopNumChan +Purpose: Read the number of channels available in an AIOP directly from + an AIOP. +Call: sReadAiopNumChan(io) + WordIO_t io: AIOP base I/O address +Return: int: The number of channels available +Comments: The number of channels is determined by write/reads from identical + offsets within the SRAM address spaces for channels 0 and 4. + If the channel 4 space is mirrored to channel 0 it is a 4 channel + AIOP, otherwise it is an 8 channel. +Warnings: No context switches are allowed while executing this function. +*/ +static int sReadAiopNumChan(WordIO_t io) +{ + Word_t x; + static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; + + /* write to chan 0 SRAM */ + out32((DWordIO_t) io + _INDX_ADDR, R); + sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */ + x = sInW(io + _INDX_DATA); + sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */ + if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */ + return (8); + else + return (4); +} + +/*************************************************************************** +Function: sInitChan +Purpose: Initialization of a channel and channel structure +Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) + CONTROLLER_T *CtlP; Ptr to controller structure + CHANNEL_T *ChP; Ptr to channel structure + int AiopNum; AIOP number within controller + int ChanNum; Channel number within AIOP +Return: int: 1 if initialization succeeded, 0 if it fails because channel + number exceeds number of channels available in AIOP. +Comments: This function must be called before a channel can be used. +Warnings: No range checking on any of the parameters is done. + + No context switches are allowed while executing this function. +*/ +static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, + int ChanNum) +{ + int i; + WordIO_t AiopIO; + WordIO_t ChIOOff; + Byte_t *ChR; + Word_t ChOff; + static Byte_t R[4]; + int brd9600; + + if (ChanNum >= CtlP->AiopNumChan[AiopNum]) + return 0; /* exceeds num chans in AIOP */ + + /* Channel, AIOP, and controller identifiers */ + ChP->CtlP = CtlP; + ChP->ChanID = CtlP->AiopID[AiopNum]; + ChP->AiopNum = AiopNum; + ChP->ChanNum = ChanNum; + + /* Global direct addresses */ + AiopIO = CtlP->AiopIO[AiopNum]; + ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG; + ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN; + ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK; + ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR; + ChP->IndexData = AiopIO + _INDX_DATA; + + /* Channel direct addresses */ + ChIOOff = AiopIO + ChP->ChanNum * 2; + ChP->TxRxData = ChIOOff + _TD0; + ChP->ChanStat = ChIOOff + _CHN_STAT0; + ChP->TxRxCount = ChIOOff + _FIFO_CNT0; + ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0; + + /* Initialize the channel from the RData array */ + for (i = 0; i < RDATASIZE; i += 4) { + R[0] = RData[i]; + R[1] = RData[i + 1] + 0x10 * ChanNum; + R[2] = RData[i + 2]; + R[3] = RData[i + 3]; + out32(ChP->IndexAddr, R); + } + + ChR = ChP->R; + for (i = 0; i < RREGDATASIZE; i += 4) { + ChR[i] = RRegData[i]; + ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum; + ChR[i + 2] = RRegData[i + 2]; + ChR[i + 3] = RRegData[i + 3]; + } + + /* Indexed registers */ + ChOff = (Word_t) ChanNum *0x1000; + + if (sClockPrescale == 0x14) + brd9600 = 47; + else + brd9600 = 23; + + ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD); + ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8); + ChP->BaudDiv[2] = (Byte_t) brd9600; + ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8); + out32(ChP->IndexAddr, ChP->BaudDiv); + + ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL); + ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8); + ChP->TxControl[2] = 0; + ChP->TxControl[3] = 0; + out32(ChP->IndexAddr, ChP->TxControl); + + ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL); + ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8); + ChP->RxControl[2] = 0; + ChP->RxControl[3] = 0; + out32(ChP->IndexAddr, ChP->RxControl); + + ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS); + ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8); + ChP->TxEnables[2] = 0; + ChP->TxEnables[3] = 0; + out32(ChP->IndexAddr, ChP->TxEnables); + + ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1); + ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8); + ChP->TxCompare[2] = 0; + ChP->TxCompare[3] = 0; + out32(ChP->IndexAddr, ChP->TxCompare); + + ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1); + ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8); + ChP->TxReplace1[2] = 0; + ChP->TxReplace1[3] = 0; + out32(ChP->IndexAddr, ChP->TxReplace1); + + ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2); + ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8); + ChP->TxReplace2[2] = 0; + ChP->TxReplace2[3] = 0; + out32(ChP->IndexAddr, ChP->TxReplace2); + + ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; + ChP->TxFIFO = ChOff + _TX_FIFO; + + sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ + sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */ + sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ + sOutW(ChP->IndexData, 0); + ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; + ChP->RxFIFO = ChOff + _RX_FIFO; + + sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ + sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */ + sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */ + sOutW(ChP->IndexData, 0); + sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ + sOutW(ChP->IndexData, 0); + ChP->TxPrioCnt = ChOff + _TXP_CNT; + sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt); + sOutB(ChP->IndexData, 0); + ChP->TxPrioPtr = ChOff + _TXP_PNTR; + sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr); + sOutB(ChP->IndexData, 0); + ChP->TxPrioBuf = ChOff + _TXP_BUF; + sEnRxProcessor(ChP); /* start the Rx processor */ + + return 1; +} + +/*************************************************************************** +Function: sStopRxProcessor +Purpose: Stop the receive processor from processing a channel. +Call: sStopRxProcessor(ChP) + CHANNEL_T *ChP; Ptr to channel structure + +Comments: The receive processor can be started again with sStartRxProcessor(). + This function causes the receive processor to skip over the + stopped channel. It does not stop it from processing other channels. + +Warnings: No context switches are allowed while executing this function. + + Do not leave the receive processor stopped for more than one + character time. + + After calling this function a delay of 4 uS is required to ensure + that the receive processor is no longer processing this channel. +*/ +static void sStopRxProcessor(CHANNEL_T * ChP) +{ + Byte_t R[4]; + + R[0] = ChP->R[0]; + R[1] = ChP->R[1]; + R[2] = 0x0a; + R[3] = ChP->R[3]; + out32(ChP->IndexAddr, R); +} + +/*************************************************************************** +Function: sFlushRxFIFO +Purpose: Flush the Rx FIFO +Call: sFlushRxFIFO(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: void +Comments: To prevent data from being enqueued or dequeued in the Tx FIFO + while it is being flushed the receive processor is stopped + and the transmitter is disabled. After these operations a + 4 uS delay is done before clearing the pointers to allow + the receive processor to stop. These items are handled inside + this function. +Warnings: No context switches are allowed while executing this function. +*/ +static void sFlushRxFIFO(CHANNEL_T * ChP) +{ + int i; + Byte_t Ch; /* channel number within AIOP */ + int RxFIFOEnabled; /* 1 if Rx FIFO enabled */ + + if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ + return; /* don't need to flush */ + + RxFIFOEnabled = 0; + if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */ + RxFIFOEnabled = 1; + sDisRxFIFO(ChP); /* disable it */ + for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */ + sInB(ChP->IntChan); /* depends on bus i/o timing */ + } + sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ + Ch = (Byte_t) sGetChanNum(ChP); + sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */ + sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */ + sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */ + sOutW(ChP->IndexData, 0); + sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ + sOutW(ChP->IndexData, 0); + if (RxFIFOEnabled) + sEnRxFIFO(ChP); /* enable Rx FIFO */ +} + +/*************************************************************************** +Function: sFlushTxFIFO +Purpose: Flush the Tx FIFO +Call: sFlushTxFIFO(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: void +Comments: To prevent data from being enqueued or dequeued in the Tx FIFO + while it is being flushed the receive processor is stopped + and the transmitter is disabled. After these operations a + 4 uS delay is done before clearing the pointers to allow + the receive processor to stop. These items are handled inside + this function. +Warnings: No context switches are allowed while executing this function. +*/ +static void sFlushTxFIFO(CHANNEL_T * ChP) +{ + int i; + Byte_t Ch; /* channel number within AIOP */ + int TxEnabled; /* 1 if transmitter enabled */ + + if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ + return; /* don't need to flush */ + + TxEnabled = 0; + if (ChP->TxControl[3] & TX_ENABLE) { + TxEnabled = 1; + sDisTransmit(ChP); /* disable transmitter */ + } + sStopRxProcessor(ChP); /* stop Rx processor */ + for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */ + sInB(ChP->IntChan); /* depends on bus i/o timing */ + Ch = (Byte_t) sGetChanNum(ChP); + sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */ + sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */ + sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ + sOutW(ChP->IndexData, 0); + if (TxEnabled) + sEnTransmit(ChP); /* enable transmitter */ + sStartRxProcessor(ChP); /* restart Rx processor */ +} + +/*************************************************************************** +Function: sWriteTxPrioByte +Purpose: Write a byte of priority transmit data to a channel +Call: sWriteTxPrioByte(ChP,Data) + CHANNEL_T *ChP; Ptr to channel structure + Byte_t Data; The transmit data byte + +Return: int: 1 if the bytes is successfully written, otherwise 0. + +Comments: The priority byte is transmitted before any data in the Tx FIFO. + +Warnings: No context switches are allowed while executing this function. +*/ +static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) +{ + Byte_t DWBuf[4]; /* buffer for double word writes */ + Word_t *WordPtr; /* must be far because Win SS != DS */ + register DWordIO_t IndexAddr; + + if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */ + IndexAddr = ChP->IndexAddr; + sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */ + if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */ + return (0); /* nothing sent */ + + WordPtr = (Word_t *) (&DWBuf[0]); + *WordPtr = ChP->TxPrioBuf; /* data byte address */ + + DWBuf[2] = Data; /* data byte value */ + out32(IndexAddr, DWBuf); /* write it out */ + + *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ + + DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ + DWBuf[3] = 0; /* priority buffer pointer */ + out32(IndexAddr, DWBuf); /* write it out */ + } else { /* write it to Tx FIFO */ + + sWriteTxByte(sGetTxRxDataIO(ChP), Data); + } + return (1); /* 1 byte sent */ +} + +/*************************************************************************** +Function: sEnInterrupts +Purpose: Enable one or more interrupts for a channel +Call: sEnInterrupts(ChP,Flags) + CHANNEL_T *ChP; Ptr to channel structure + Word_t Flags: Interrupt enable flags, can be any combination + of the following flags: + TXINT_EN: Interrupt on Tx FIFO empty + RXINT_EN: Interrupt on Rx FIFO at trigger level (see + sSetRxTrigger()) + SRCINT_EN: Interrupt on SRC (Special Rx Condition) + MCINT_EN: Interrupt on modem input change + CHANINT_EN: Allow channel interrupt signal to the AIOP's + Interrupt Channel Register. +Return: void +Comments: If an interrupt enable flag is set in Flags, that interrupt will be + enabled. If an interrupt enable flag is not set in Flags, that + interrupt will not be changed. Interrupts can be disabled with + function sDisInterrupts(). + + This function sets the appropriate bit for the channel in the AIOP's + Interrupt Mask Register if the CHANINT_EN flag is set. This allows + this channel's bit to be set in the AIOP's Interrupt Channel Register. + + Interrupts must also be globally enabled before channel interrupts + will be passed on to the host. This is done with function + sEnGlobalInt(). + + In some cases it may be desirable to disable interrupts globally but + enable channel interrupts. This would allow the global interrupt + status register to be used to determine which AIOPs need service. +*/ +static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) +{ + Byte_t Mask; /* Interrupt Mask Register */ + + ChP->RxControl[2] |= + ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); + + out32(ChP->IndexAddr, ChP->RxControl); + + ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN); + + out32(ChP->IndexAddr, ChP->TxControl); + + if (Flags & CHANINT_EN) { + Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum]; + sOutB(ChP->IntMask, Mask); + } +} + +/*************************************************************************** +Function: sDisInterrupts +Purpose: Disable one or more interrupts for a channel +Call: sDisInterrupts(ChP,Flags) + CHANNEL_T *ChP; Ptr to channel structure + Word_t Flags: Interrupt flags, can be any combination + of the following flags: + TXINT_EN: Interrupt on Tx FIFO empty + RXINT_EN: Interrupt on Rx FIFO at trigger level (see + sSetRxTrigger()) + SRCINT_EN: Interrupt on SRC (Special Rx Condition) + MCINT_EN: Interrupt on modem input change + CHANINT_EN: Disable channel interrupt signal to the + AIOP's Interrupt Channel Register. +Return: void +Comments: If an interrupt flag is set in Flags, that interrupt will be + disabled. If an interrupt flag is not set in Flags, that + interrupt will not be changed. Interrupts can be enabled with + function sEnInterrupts(). + + This function clears the appropriate bit for the channel in the AIOP's + Interrupt Mask Register if the CHANINT_EN flag is set. This blocks + this channel's bit from being set in the AIOP's Interrupt Channel + Register. +*/ +static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) +{ + Byte_t Mask; /* Interrupt Mask Register */ + + ChP->RxControl[2] &= + ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); + out32(ChP->IndexAddr, ChP->RxControl); + ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN); + out32(ChP->IndexAddr, ChP->TxControl); + + if (Flags & CHANINT_EN) { + Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum]; + sOutB(ChP->IntMask, Mask); + } +} + +static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) +{ + sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum); +} + +/* + * Not an official SSCI function, but how to reset RocketModems. + * ISA bus version + */ +static void sModemReset(CONTROLLER_T * CtlP, int chan, int on) +{ + ByteIO_t addr; + Byte_t val; + + addr = CtlP->AiopIO[0] + 0x400; + val = sInB(CtlP->MReg3IO); + /* if AIOP[1] is not enabled, enable it */ + if ((val & 2) == 0) { + val = sInB(CtlP->MReg2IO); + sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03)); + sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6)); + } + + sEnAiop(CtlP, 1); + if (!on) + addr += 8; + sOutB(addr + chan, 0); /* apply or remove reset */ + sDisAiop(CtlP, 1); +} + +/* + * Not an official SSCI function, but how to reset RocketModems. + * PCI bus version + */ +static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on) +{ + ByteIO_t addr; + + addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */ + if (!on) + addr += 8; + sOutB(addr + chan, 0); /* apply or remove reset */ +} + +/* Resets the speaker controller on RocketModem II and III devices */ +static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model) +{ + ByteIO_t addr; + + /* RocketModem II speaker control is at the 8th port location of offset 0x40 */ + if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) { + addr = CtlP->AiopIO[0] + 0x4F; + sOutB(addr, 0); + } + + /* RocketModem III speaker control is at the 1st port location of offset 0x80 */ + if ((model == MODEL_UPCI_RM3_8PORT) + || (model == MODEL_UPCI_RM3_4PORT)) { + addr = CtlP->AiopIO[0] + 0x88; + sOutB(addr, 0); + } +} + +/* Returns the line number given the controller (board), aiop and channel number */ +static unsigned char GetLineNumber(int ctrl, int aiop, int ch) +{ + return lineNumbers[(ctrl << 5) | (aiop << 3) | ch]; +} + +/* + * Stores the line number associated with a given controller (board), aiop + * and channel number. + * Returns: The line number assigned + */ +static unsigned char SetLineNumber(int ctrl, int aiop, int ch) +{ + lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++; + return (nextLineNumber - 1); +} diff --git a/drivers/tty/rocket.h b/drivers/tty/rocket.h new file mode 100644 index 000000000000..ec863f35f1a9 --- /dev/null +++ b/drivers/tty/rocket.h @@ -0,0 +1,111 @@ +/* + * rocket.h --- the exported interface of the rocket driver to its configuration program. + * + * Written by Theodore Ts'o, Copyright 1997. + * Copyright 1997 Comtrol Corporation. + * + */ + +/* Model Information Struct */ +typedef struct { + unsigned long model; + char modelString[80]; + unsigned long numPorts; + int loadrm2; + int startingPortNumber; +} rocketModel_t; + +struct rocket_config { + int line; + int flags; + int closing_wait; + int close_delay; + int port; + int reserved[32]; +}; + +struct rocket_ports { + int tty_major; + int callout_major; + rocketModel_t rocketModel[8]; +}; + +struct rocket_version { + char rocket_version[32]; + char rocket_date[32]; + char reserved[64]; +}; + +/* + * Rocketport flags + */ +/*#define ROCKET_CALLOUT_NOHUP 0x00000001 */ +#define ROCKET_FORCE_CD 0x00000002 +#define ROCKET_HUP_NOTIFY 0x00000004 +#define ROCKET_SPLIT_TERMIOS 0x00000008 +#define ROCKET_SPD_MASK 0x00000070 +#define ROCKET_SPD_HI 0x00000010 /* Use 56000 instead of 38400 bps */ +#define ROCKET_SPD_VHI 0x00000020 /* Use 115200 instead of 38400 bps */ +#define ROCKET_SPD_SHI 0x00000030 /* Use 230400 instead of 38400 bps */ +#define ROCKET_SPD_WARP 0x00000040 /* Use 460800 instead of 38400 bps */ +#define ROCKET_SAK 0x00000080 +#define ROCKET_SESSION_LOCKOUT 0x00000100 +#define ROCKET_PGRP_LOCKOUT 0x00000200 +#define ROCKET_RTS_TOGGLE 0x00000400 +#define ROCKET_MODE_MASK 0x00003000 +#define ROCKET_MODE_RS232 0x00000000 +#define ROCKET_MODE_RS485 0x00001000 +#define ROCKET_MODE_RS422 0x00002000 +#define ROCKET_FLAGS 0x00003FFF + +#define ROCKET_USR_MASK 0x0071 /* Legal flags that non-privileged + * users can set or reset */ + +/* + * For closing_wait and closing_wait2 + */ +#define ROCKET_CLOSING_WAIT_NONE ASYNC_CLOSING_WAIT_NONE +#define ROCKET_CLOSING_WAIT_INF ASYNC_CLOSING_WAIT_INF + +/* + * Rocketport ioctls -- "RP" + */ +#define RCKP_GET_STRUCT 0x00525001 +#define RCKP_GET_CONFIG 0x00525002 +#define RCKP_SET_CONFIG 0x00525003 +#define RCKP_GET_PORTS 0x00525004 +#define RCKP_RESET_RM2 0x00525005 +#define RCKP_GET_VERSION 0x00525006 + +/* Rocketport Models */ +#define MODEL_RP32INTF 0x0001 /* RP 32 port w/external I/F */ +#define MODEL_RP8INTF 0x0002 /* RP 8 port w/external I/F */ +#define MODEL_RP16INTF 0x0003 /* RP 16 port w/external I/F */ +#define MODEL_RP8OCTA 0x0005 /* RP 8 port w/octa cable */ +#define MODEL_RP4QUAD 0x0004 /* RP 4 port w/quad cable */ +#define MODEL_RP8J 0x0006 /* RP 8 port w/RJ11 connectors */ +#define MODEL_RP4J 0x0007 /* RP 4 port w/RJ45 connectors */ +#define MODEL_RP8SNI 0x0008 /* RP 8 port w/ DB78 SNI connector */ +#define MODEL_RP16SNI 0x0009 /* RP 16 port w/ DB78 SNI connector */ +#define MODEL_RPP4 0x000A /* RP Plus 4 port */ +#define MODEL_RPP8 0x000B /* RP Plus 8 port */ +#define MODEL_RP2_232 0x000E /* RP Plus 2 port RS232 */ +#define MODEL_RP2_422 0x000F /* RP Plus 2 port RS232 */ + +/* Rocketmodem II Models */ +#define MODEL_RP6M 0x000C /* RM 6 port */ +#define MODEL_RP4M 0x000D /* RM 4 port */ + +/* Universal PCI boards */ +#define MODEL_UPCI_RP32INTF 0x0801 /* RP UPCI 32 port w/external I/F */ +#define MODEL_UPCI_RP8INTF 0x0802 /* RP UPCI 8 port w/external I/F */ +#define MODEL_UPCI_RP16INTF 0x0803 /* RP UPCI 16 port w/external I/F */ +#define MODEL_UPCI_RP8OCTA 0x0805 /* RP UPCI 8 port w/octa cable */ +#define MODEL_UPCI_RM3_8PORT 0x080C /* RP UPCI Rocketmodem III 8 port */ +#define MODEL_UPCI_RM3_4PORT 0x080C /* RP UPCI Rocketmodem III 4 port */ + +/* Compact PCI 16 port */ +#define MODEL_CPCI_RP16INTF 0x0903 /* RP Compact PCI 16 port w/external I/F */ + +/* All ISA boards */ +#define MODEL_ISA 0x1000 diff --git a/drivers/tty/rocket_int.h b/drivers/tty/rocket_int.h new file mode 100644 index 000000000000..67e0f1e778a2 --- /dev/null +++ b/drivers/tty/rocket_int.h @@ -0,0 +1,1214 @@ +/* + * rocket_int.h --- internal header file for rocket.c + * + * Written by Theodore Ts'o, Copyright 1997. + * Copyright 1997 Comtrol Corporation. + * + */ + +/* + * Definition of the types in rcktpt_type + */ +#define ROCKET_TYPE_NORMAL 0 +#define ROCKET_TYPE_MODEM 1 +#define ROCKET_TYPE_MODEMII 2 +#define ROCKET_TYPE_MODEMIII 3 +#define ROCKET_TYPE_PC104 4 + +#include + +#include +#include + +typedef unsigned char Byte_t; +typedef unsigned int ByteIO_t; + +typedef unsigned int Word_t; +typedef unsigned int WordIO_t; + +typedef unsigned int DWordIO_t; + +/* + * Note! Normally the Linux I/O macros already take care of + * byte-swapping the I/O instructions. However, all accesses using + * sOutDW aren't really 32-bit accesses, but should be handled in byte + * order. Hence the use of the cpu_to_le32() macro to byte-swap + * things to no-op the byte swapping done by the big-endian outl() + * instruction. + */ + +static inline void sOutB(unsigned short port, unsigned char value) +{ +#ifdef ROCKET_DEBUG_IO + printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value); +#endif + outb_p(value, port); +} + +static inline void sOutW(unsigned short port, unsigned short value) +{ +#ifdef ROCKET_DEBUG_IO + printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value); +#endif + outw_p(value, port); +} + +static inline void out32(unsigned short port, Byte_t *p) +{ + u32 value = get_unaligned_le32(p); +#ifdef ROCKET_DEBUG_IO + printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value); +#endif + outl_p(value, port); +} + +static inline unsigned char sInB(unsigned short port) +{ + return inb_p(port); +} + +static inline unsigned short sInW(unsigned short port) +{ + return inw_p(port); +} + +/* This is used to move arrays of bytes so byte swapping isn't appropriate. */ +#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count) +#define sInStrW(port, addr, count) if (count) insw(port, addr, count) + +#define CTL_SIZE 8 +#define AIOP_CTL_SIZE 4 +#define CHAN_AIOP_SIZE 8 +#define MAX_PORTS_PER_AIOP 8 +#define MAX_AIOPS_PER_BOARD 4 +#define MAX_PORTS_PER_BOARD 32 + +/* Bus type ID */ +#define isISA 0 +#define isPCI 1 +#define isMC 2 + +/* Controller ID numbers */ +#define CTLID_NULL -1 /* no controller exists */ +#define CTLID_0001 0x0001 /* controller release 1 */ + +/* AIOP ID numbers, identifies AIOP type implementing channel */ +#define AIOPID_NULL -1 /* no AIOP or channel exists */ +#define AIOPID_0001 0x0001 /* AIOP release 1 */ + +/************************************************************************ + Global Register Offsets - Direct Access - Fixed values +************************************************************************/ + +#define _CMD_REG 0x38 /* Command Register 8 Write */ +#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */ +#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */ +#define _UNUSED 0x3B /* Unused 8 */ +#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */ +#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */ + +/************************************************************************ + Channel Register Offsets for 1st channel in AIOP - Direct Access +************************************************************************/ +#define _TD0 0x00 /* Transmit Data 16 Write */ +#define _RD0 0x00 /* Receive Data 16 Read */ +#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */ +#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */ +#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */ + +/************************************************************************ + Tx Control Register Offsets - Indexed - External - Fixed +************************************************************************/ +#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */ +#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */ +#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */ +#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */ +#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */ +#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */ + +/************************************************************************ +Memory Controller Register Offsets - Indexed - External - Fixed +************************************************************************/ +#define _RX_FIFO 0x000 /* Rx FIFO */ +#define _TX_FIFO 0x800 /* Tx FIFO */ +#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */ +#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */ +#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */ +#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */ +#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */ +#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */ + +#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */ +#define TXFIFO_SIZE 255 /* size of Tx FIFO */ +#define RXFIFO_SIZE 1023 /* size of Rx FIFO */ + +/************************************************************************ +Tx Priority Buffer - Indexed - External - Fixed +************************************************************************/ +#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */ +#define TXP_SIZE 0x20 /* 32 bytes */ + +/************************************************************************ +Channel Register Offsets - Indexed - Internal - Fixed +************************************************************************/ + +#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */ +#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */ +#define _BAUD 0xFF4 /* Baud Rate 16 Write */ +#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */ + +#define STMBREAK 0x08 /* BREAK */ +#define STMFRAME 0x04 /* framing error */ +#define STMRCVROVR 0x02 /* receiver over run error */ +#define STMPARITY 0x01 /* parity error */ +#define STMERROR (STMBREAK | STMFRAME | STMPARITY) +#define STMBREAKH 0x800 /* BREAK */ +#define STMFRAMEH 0x400 /* framing error */ +#define STMRCVROVRH 0x200 /* receiver over run error */ +#define STMPARITYH 0x100 /* parity error */ +#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH) + +#define CTS_ACT 0x20 /* CTS input asserted */ +#define DSR_ACT 0x10 /* DSR input asserted */ +#define CD_ACT 0x08 /* CD input asserted */ +#define TXFIFOMT 0x04 /* Tx FIFO is empty */ +#define TXSHRMT 0x02 /* Tx shift register is empty */ +#define RDA 0x01 /* Rx data available */ +#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */ + +#define STATMODE 0x8000 /* status mode enable bit */ +#define RXFOVERFL 0x2000 /* receive FIFO overflow */ +#define RX2MATCH 0x1000 /* receive compare byte 2 match */ +#define RX1MATCH 0x0800 /* receive compare byte 1 match */ +#define RXBREAK 0x0400 /* received BREAK */ +#define RXFRAME 0x0200 /* received framing error */ +#define RXPARITY 0x0100 /* received parity error */ +#define STATERROR (RXBREAK | RXFRAME | RXPARITY) + +#define CTSFC_EN 0x80 /* CTS flow control enable bit */ +#define RTSTOG_EN 0x40 /* RTS toggle enable bit */ +#define TXINT_EN 0x10 /* transmit interrupt enable */ +#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */ +#define PARITY_EN 0x04 /* enable parity (0 = no parity) */ +#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */ +#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */ + +#define SETBREAK 0x10 /* send break condition (must clear) */ +#define LOCALLOOP 0x08 /* local loopback set for test */ +#define SET_DTR 0x04 /* assert DTR */ +#define SET_RTS 0x02 /* assert RTS */ +#define TX_ENABLE 0x01 /* enable transmitter */ + +#define RTSFC_EN 0x40 /* RTS flow control enable */ +#define RXPROC_EN 0x20 /* receive processor enable */ +#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */ +#define TRIG_1 0x08 /* trigger level 1 char */ +#define TRIG_1_2 0x10 /* trigger level 1/2 */ +#define TRIG_7_8 0x18 /* trigger level 7/8 */ +#define TRIG_MASK 0x18 /* trigger level mask */ +#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */ +#define RXINT_EN 0x02 /* Rx interrupt enable */ +#define MCINT_EN 0x01 /* modem change interrupt enable */ + +#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */ +#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */ +#define SRC_INT 0x08 /* special receive condition interrupt */ +#define DELTA_CD 0x04 /* CD change interrupt */ +#define DELTA_CTS 0x02 /* CTS change interrupt */ +#define DELTA_DSR 0x01 /* DSR change interrupt */ + +#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */ +#define IGN2_EN 0x08 /* ignore byte 2 enable */ +#define IGN1_EN 0x04 /* ignore byte 1 enable */ +#define COMP2_EN 0x02 /* compare byte 2 enable */ +#define COMP1_EN 0x01 /* compare byte 1 enable */ + +#define RESET_ALL 0x80 /* reset AIOP (all channels) */ +#define TXOVERIDE 0x40 /* Transmit software off override */ +#define RESETUART 0x20 /* reset channel's UART */ +#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */ +#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */ + +#define INTSTAT0 0x01 /* AIOP 0 interrupt status */ +#define INTSTAT1 0x02 /* AIOP 1 interrupt status */ +#define INTSTAT2 0x04 /* AIOP 2 interrupt status */ +#define INTSTAT3 0x08 /* AIOP 3 interrupt status */ + +#define INTR_EN 0x08 /* allow interrupts to host */ +#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */ + +/************************************************************************** + MUDBAC remapped for PCI +**************************************************************************/ + +#define _CFG_INT_PCI 0x40 +#define _PCI_INT_FUNC 0x3A + +#define PCI_STROB 0x2000 /* bit 13 of int aiop register */ +#define INTR_EN_PCI 0x0010 /* allow interrupts to host */ + +/* + * Definitions for Universal PCI board registers + */ +#define _PCI_9030_INT_CTRL 0x4c /* Offsets from BAR1 */ +#define _PCI_9030_GPIO_CTRL 0x54 +#define PCI_INT_CTRL_AIOP 0x0001 +#define PCI_GPIO_CTRL_8PORT 0x4000 +#define _PCI_9030_RING_IND 0xc0 /* Offsets from BAR1 */ + +#define CHAN3_EN 0x08 /* enable AIOP 3 */ +#define CHAN2_EN 0x04 /* enable AIOP 2 */ +#define CHAN1_EN 0x02 /* enable AIOP 1 */ +#define CHAN0_EN 0x01 /* enable AIOP 0 */ +#define FREQ_DIS 0x00 +#define FREQ_274HZ 0x60 +#define FREQ_137HZ 0x50 +#define FREQ_69HZ 0x40 +#define FREQ_34HZ 0x30 +#define FREQ_17HZ 0x20 +#define FREQ_9HZ 0x10 +#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */ + +#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */ + +#define RDATASIZE 72 +#define RREGDATASIZE 52 + +/* + * AIOP interrupt bits for ISA/PCI boards and UPCI boards. + */ +#define AIOP_INTR_BIT_0 0x0001 +#define AIOP_INTR_BIT_1 0x0002 +#define AIOP_INTR_BIT_2 0x0004 +#define AIOP_INTR_BIT_3 0x0008 + +#define AIOP_INTR_BITS ( \ + AIOP_INTR_BIT_0 \ + | AIOP_INTR_BIT_1 \ + | AIOP_INTR_BIT_2 \ + | AIOP_INTR_BIT_3) + +#define UPCI_AIOP_INTR_BIT_0 0x0004 +#define UPCI_AIOP_INTR_BIT_1 0x0020 +#define UPCI_AIOP_INTR_BIT_2 0x0100 +#define UPCI_AIOP_INTR_BIT_3 0x0800 + +#define UPCI_AIOP_INTR_BITS ( \ + UPCI_AIOP_INTR_BIT_0 \ + | UPCI_AIOP_INTR_BIT_1 \ + | UPCI_AIOP_INTR_BIT_2 \ + | UPCI_AIOP_INTR_BIT_3) + +/* Controller level information structure */ +typedef struct { + int CtlID; + int CtlNum; + int BusType; + int boardType; + int isUPCI; + WordIO_t PCIIO; + WordIO_t PCIIO2; + ByteIO_t MBaseIO; + ByteIO_t MReg1IO; + ByteIO_t MReg2IO; + ByteIO_t MReg3IO; + Byte_t MReg2; + Byte_t MReg3; + int NumAiop; + int AltChanRingIndicator; + ByteIO_t UPCIRingInd; + WordIO_t AiopIO[AIOP_CTL_SIZE]; + ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE]; + int AiopID[AIOP_CTL_SIZE]; + int AiopNumChan[AIOP_CTL_SIZE]; + Word_t *AiopIntrBits; +} CONTROLLER_T; + +typedef CONTROLLER_T CONTROLLER_t; + +/* Channel level information structure */ +typedef struct { + CONTROLLER_T *CtlP; + int AiopNum; + int ChanID; + int ChanNum; + int rtsToggle; + + ByteIO_t Cmd; + ByteIO_t IntChan; + ByteIO_t IntMask; + DWordIO_t IndexAddr; + WordIO_t IndexData; + + WordIO_t TxRxData; + WordIO_t ChanStat; + WordIO_t TxRxCount; + ByteIO_t IntID; + + Word_t TxFIFO; + Word_t TxFIFOPtrs; + Word_t RxFIFO; + Word_t RxFIFOPtrs; + Word_t TxPrioCnt; + Word_t TxPrioPtr; + Word_t TxPrioBuf; + + Byte_t R[RREGDATASIZE]; + + Byte_t BaudDiv[4]; + Byte_t TxControl[4]; + Byte_t RxControl[4]; + Byte_t TxEnables[4]; + Byte_t TxCompare[4]; + Byte_t TxReplace1[4]; + Byte_t TxReplace2[4]; +} CHANNEL_T; + +typedef CHANNEL_T CHANNEL_t; +typedef CHANNEL_T *CHANPTR_T; + +#define InterfaceModeRS232 0x00 +#define InterfaceModeRS422 0x08 +#define InterfaceModeRS485 0x10 +#define InterfaceModeRS232T 0x18 + +/*************************************************************************** +Function: sClrBreak +Purpose: Stop sending a transmit BREAK signal +Call: sClrBreak(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sClrBreak(ChP) \ +do { \ + (ChP)->TxControl[3] &= ~SETBREAK; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sClrDTR +Purpose: Clr the DTR output +Call: sClrDTR(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sClrDTR(ChP) \ +do { \ + (ChP)->TxControl[3] &= ~SET_DTR; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sClrRTS +Purpose: Clr the RTS output +Call: sClrRTS(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sClrRTS(ChP) \ +do { \ + if ((ChP)->rtsToggle) break; \ + (ChP)->TxControl[3] &= ~SET_RTS; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sClrTxXOFF +Purpose: Clear any existing transmit software flow control off condition +Call: sClrTxXOFF(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sClrTxXOFF(ChP) \ +do { \ + sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \ + sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \ +} while (0) + +/*************************************************************************** +Function: sCtlNumToCtlPtr +Purpose: Convert a controller number to controller structure pointer +Call: sCtlNumToCtlPtr(CtlNum) + int CtlNum; Controller number +Return: CONTROLLER_T *: Ptr to controller structure +*/ +#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM] + +/*************************************************************************** +Function: sControllerEOI +Purpose: Strobe the MUDBAC's End Of Interrupt bit. +Call: sControllerEOI(CtlP) + CONTROLLER_T *CtlP; Ptr to controller structure +*/ +#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB) + +/*************************************************************************** +Function: sPCIControllerEOI +Purpose: Strobe the PCI End Of Interrupt bit. + For the UPCI boards, toggle the AIOP interrupt enable bit + (this was taken from the Windows driver). +Call: sPCIControllerEOI(CtlP) + CONTROLLER_T *CtlP; Ptr to controller structure +*/ +#define sPCIControllerEOI(CTLP) \ +do { \ + if ((CTLP)->isUPCI) { \ + Word_t w = sInW((CTLP)->PCIIO); \ + sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \ + sOutW((CTLP)->PCIIO, w); \ + } \ + else { \ + sOutW((CTLP)->PCIIO, PCI_STROB); \ + } \ +} while (0) + +/*************************************************************************** +Function: sDisAiop +Purpose: Disable I/O access to an AIOP +Call: sDisAiop(CltP) + CONTROLLER_T *CtlP; Ptr to controller structure + int AiopNum; Number of AIOP on controller +*/ +#define sDisAiop(CTLP,AIOPNUM) \ +do { \ + (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \ + sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \ +} while (0) + +/*************************************************************************** +Function: sDisCTSFlowCtl +Purpose: Disable output flow control using CTS +Call: sDisCTSFlowCtl(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sDisCTSFlowCtl(ChP) \ +do { \ + (ChP)->TxControl[2] &= ~CTSFC_EN; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sDisIXANY +Purpose: Disable IXANY Software Flow Control +Call: sDisIXANY(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sDisIXANY(ChP) \ +do { \ + (ChP)->R[0x0e] = 0x86; \ + out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ +} while (0) + +/*************************************************************************** +Function: DisParity +Purpose: Disable parity +Call: sDisParity(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: Function sSetParity() can be used in place of functions sEnParity(), + sDisParity(), sSetOddParity(), and sSetEvenParity(). +*/ +#define sDisParity(ChP) \ +do { \ + (ChP)->TxControl[2] &= ~PARITY_EN; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sDisRTSToggle +Purpose: Disable RTS toggle +Call: sDisRTSToggle(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sDisRTSToggle(ChP) \ +do { \ + (ChP)->TxControl[2] &= ~RTSTOG_EN; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ + (ChP)->rtsToggle = 0; \ +} while (0) + +/*************************************************************************** +Function: sDisRxFIFO +Purpose: Disable Rx FIFO +Call: sDisRxFIFO(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sDisRxFIFO(ChP) \ +do { \ + (ChP)->R[0x32] = 0x0a; \ + out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ +} while (0) + +/*************************************************************************** +Function: sDisRxStatusMode +Purpose: Disable the Rx status mode +Call: sDisRxStatusMode(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: This takes the channel out of the receive status mode. All + subsequent reads of receive data using sReadRxWord() will return + two data bytes. +*/ +#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0) + +/*************************************************************************** +Function: sDisTransmit +Purpose: Disable transmit +Call: sDisTransmit(ChP) + CHANNEL_T *ChP; Ptr to channel structure + This disables movement of Tx data from the Tx FIFO into the 1 byte + Tx buffer. Therefore there could be up to a 2 byte latency + between the time sDisTransmit() is called and the transmit buffer + and transmit shift register going completely empty. +*/ +#define sDisTransmit(ChP) \ +do { \ + (ChP)->TxControl[3] &= ~TX_ENABLE; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sDisTxSoftFlowCtl +Purpose: Disable Tx Software Flow Control +Call: sDisTxSoftFlowCtl(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sDisTxSoftFlowCtl(ChP) \ +do { \ + (ChP)->R[0x06] = 0x8a; \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ +} while (0) + +/*************************************************************************** +Function: sEnAiop +Purpose: Enable I/O access to an AIOP +Call: sEnAiop(CltP) + CONTROLLER_T *CtlP; Ptr to controller structure + int AiopNum; Number of AIOP on controller +*/ +#define sEnAiop(CTLP,AIOPNUM) \ +do { \ + (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \ + sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \ +} while (0) + +/*************************************************************************** +Function: sEnCTSFlowCtl +Purpose: Enable output flow control using CTS +Call: sEnCTSFlowCtl(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sEnCTSFlowCtl(ChP) \ +do { \ + (ChP)->TxControl[2] |= CTSFC_EN; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sEnIXANY +Purpose: Enable IXANY Software Flow Control +Call: sEnIXANY(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sEnIXANY(ChP) \ +do { \ + (ChP)->R[0x0e] = 0x21; \ + out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ +} while (0) + +/*************************************************************************** +Function: EnParity +Purpose: Enable parity +Call: sEnParity(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: Function sSetParity() can be used in place of functions sEnParity(), + sDisParity(), sSetOddParity(), and sSetEvenParity(). + +Warnings: Before enabling parity odd or even parity should be chosen using + functions sSetOddParity() or sSetEvenParity(). +*/ +#define sEnParity(ChP) \ +do { \ + (ChP)->TxControl[2] |= PARITY_EN; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sEnRTSToggle +Purpose: Enable RTS toggle +Call: sEnRTSToggle(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: This function will disable RTS flow control and clear the RTS + line to allow operation of RTS toggle. +*/ +#define sEnRTSToggle(ChP) \ +do { \ + (ChP)->RxControl[2] &= ~RTSFC_EN; \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ + (ChP)->TxControl[2] |= RTSTOG_EN; \ + (ChP)->TxControl[3] &= ~SET_RTS; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ + (ChP)->rtsToggle = 1; \ +} while (0) + +/*************************************************************************** +Function: sEnRxFIFO +Purpose: Enable Rx FIFO +Call: sEnRxFIFO(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sEnRxFIFO(ChP) \ +do { \ + (ChP)->R[0x32] = 0x08; \ + out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ +} while (0) + +/*************************************************************************** +Function: sEnRxProcessor +Purpose: Enable the receive processor +Call: sEnRxProcessor(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: This function is used to start the receive processor. When + the channel is in the reset state the receive processor is not + running. This is done to prevent the receive processor from + executing invalid microcode instructions prior to the + downloading of the microcode. + +Warnings: This function must be called after valid microcode has been + downloaded to the AIOP, and it must not be called before the + microcode has been downloaded. +*/ +#define sEnRxProcessor(ChP) \ +do { \ + (ChP)->RxControl[2] |= RXPROC_EN; \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ +} while (0) + +/*************************************************************************** +Function: sEnRxStatusMode +Purpose: Enable the Rx status mode +Call: sEnRxStatusMode(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: This places the channel in the receive status mode. All subsequent + reads of receive data using sReadRxWord() will return a data byte + in the low word and a status byte in the high word. + +*/ +#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE) + +/*************************************************************************** +Function: sEnTransmit +Purpose: Enable transmit +Call: sEnTransmit(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sEnTransmit(ChP) \ +do { \ + (ChP)->TxControl[3] |= TX_ENABLE; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sEnTxSoftFlowCtl +Purpose: Enable Tx Software Flow Control +Call: sEnTxSoftFlowCtl(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sEnTxSoftFlowCtl(ChP) \ +do { \ + (ChP)->R[0x06] = 0xc5; \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ +} while (0) + +/*************************************************************************** +Function: sGetAiopIntStatus +Purpose: Get the AIOP interrupt status +Call: sGetAiopIntStatus(CtlP,AiopNum) + CONTROLLER_T *CtlP; Ptr to controller structure + int AiopNum; AIOP number +Return: Byte_t: The AIOP interrupt status. Bits 0 through 7 + represent channels 0 through 7 respectively. If a + bit is set that channel is interrupting. +*/ +#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM]) + +/*************************************************************************** +Function: sGetAiopNumChan +Purpose: Get the number of channels supported by an AIOP +Call: sGetAiopNumChan(CtlP,AiopNum) + CONTROLLER_T *CtlP; Ptr to controller structure + int AiopNum; AIOP number +Return: int: The number of channels supported by the AIOP +*/ +#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM] + +/*************************************************************************** +Function: sGetChanIntID +Purpose: Get a channel's interrupt identification byte +Call: sGetChanIntID(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: Byte_t: The channel interrupt ID. Can be any + combination of the following flags: + RXF_TRIG: Rx FIFO trigger level interrupt + TXFIFO_MT: Tx FIFO empty interrupt + SRC_INT: Special receive condition interrupt + DELTA_CD: CD change interrupt + DELTA_CTS: CTS change interrupt + DELTA_DSR: DSR change interrupt +*/ +#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR)) + +/*************************************************************************** +Function: sGetChanNum +Purpose: Get the number of a channel within an AIOP +Call: sGetChanNum(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: int: Channel number within AIOP, or NULLCHAN if channel does + not exist. +*/ +#define sGetChanNum(ChP) (ChP)->ChanNum + +/*************************************************************************** +Function: sGetChanStatus +Purpose: Get the channel status +Call: sGetChanStatus(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: Word_t: The channel status. Can be any combination of + the following flags: + LOW BYTE FLAGS + CTS_ACT: CTS input asserted + DSR_ACT: DSR input asserted + CD_ACT: CD input asserted + TXFIFOMT: Tx FIFO is empty + TXSHRMT: Tx shift register is empty + RDA: Rx data available + + HIGH BYTE FLAGS + STATMODE: status mode enable bit + RXFOVERFL: receive FIFO overflow + RX2MATCH: receive compare byte 2 match + RX1MATCH: receive compare byte 1 match + RXBREAK: received BREAK + RXFRAME: received framing error + RXPARITY: received parity error +Warnings: This function will clear the high byte flags in the Channel + Status Register. +*/ +#define sGetChanStatus(ChP) sInW((ChP)->ChanStat) + +/*************************************************************************** +Function: sGetChanStatusLo +Purpose: Get the low byte only of the channel status +Call: sGetChanStatusLo(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: Byte_t: The channel status low byte. Can be any combination + of the following flags: + CTS_ACT: CTS input asserted + DSR_ACT: DSR input asserted + CD_ACT: CD input asserted + TXFIFOMT: Tx FIFO is empty + TXSHRMT: Tx shift register is empty + RDA: Rx data available +*/ +#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat) + +/********************************************************************** + * Get RI status of channel + * Defined as a function in rocket.c -aes + */ +#if 0 +#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \ + (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \ + (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \ + (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \ + 0)) +#endif + +/*************************************************************************** +Function: sGetControllerIntStatus +Purpose: Get the controller interrupt status +Call: sGetControllerIntStatus(CtlP) + CONTROLLER_T *CtlP; Ptr to controller structure +Return: Byte_t: The controller interrupt status in the lower 4 + bits. Bits 0 through 3 represent AIOP's 0 + through 3 respectively. If a bit is set that + AIOP is interrupting. Bits 4 through 7 will + always be cleared. +*/ +#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f) + +/*************************************************************************** +Function: sPCIGetControllerIntStatus +Purpose: Get the controller interrupt status +Call: sPCIGetControllerIntStatus(CtlP) + CONTROLLER_T *CtlP; Ptr to controller structure +Return: unsigned char: The controller interrupt status in the lower 4 + bits and bit 4. Bits 0 through 3 represent AIOP's 0 + through 3 respectively. Bit 4 is set if the int + was generated from periodic. If a bit is set the + AIOP is interrupting. +*/ +#define sPCIGetControllerIntStatus(CTLP) \ + ((CTLP)->isUPCI ? \ + (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \ + ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS)) + +/*************************************************************************** + +Function: sGetRxCnt +Purpose: Get the number of data bytes in the Rx FIFO +Call: sGetRxCnt(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: int: The number of data bytes in the Rx FIFO. +Comments: Byte read of count register is required to obtain Rx count. + +*/ +#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount) + +/*************************************************************************** +Function: sGetTxCnt +Purpose: Get the number of data bytes in the Tx FIFO +Call: sGetTxCnt(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: Byte_t: The number of data bytes in the Tx FIFO. +Comments: Byte read of count register is required to obtain Tx count. + +*/ +#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount) + +/***************************************************************************** +Function: sGetTxRxDataIO +Purpose: Get the I/O address of a channel's TxRx Data register +Call: sGetTxRxDataIO(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Return: WordIO_t: I/O address of a channel's TxRx Data register +*/ +#define sGetTxRxDataIO(ChP) (ChP)->TxRxData + +/*************************************************************************** +Function: sInitChanDefaults +Purpose: Initialize a channel structure to it's default state. +Call: sInitChanDefaults(ChP) + CHANNEL_T *ChP; Ptr to the channel structure +Comments: This function must be called once for every channel structure + that exists before any other SSCI calls can be made. + +*/ +#define sInitChanDefaults(ChP) \ +do { \ + (ChP)->CtlP = NULLCTLPTR; \ + (ChP)->AiopNum = NULLAIOP; \ + (ChP)->ChanID = AIOPID_NULL; \ + (ChP)->ChanNum = NULLCHAN; \ +} while (0) + +/*************************************************************************** +Function: sResetAiopByNum +Purpose: Reset the AIOP by number +Call: sResetAiopByNum(CTLP,AIOPNUM) + CONTROLLER_T CTLP; Ptr to controller structure + AIOPNUM; AIOP index +*/ +#define sResetAiopByNum(CTLP,AIOPNUM) \ +do { \ + sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \ + sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \ +} while (0) + +/*************************************************************************** +Function: sSendBreak +Purpose: Send a transmit BREAK signal +Call: sSendBreak(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSendBreak(ChP) \ +do { \ + (ChP)->TxControl[3] |= SETBREAK; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetBaud +Purpose: Set baud rate +Call: sSetBaud(ChP,Divisor) + CHANNEL_T *ChP; Ptr to channel structure + Word_t Divisor; 16 bit baud rate divisor for channel +*/ +#define sSetBaud(ChP,DIVISOR) \ +do { \ + (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ + (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ + out32((ChP)->IndexAddr,(ChP)->BaudDiv); \ +} while (0) + +/*************************************************************************** +Function: sSetData7 +Purpose: Set data bits to 7 +Call: sSetData7(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSetData7(ChP) \ +do { \ + (ChP)->TxControl[2] &= ~DATA8BIT; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetData8 +Purpose: Set data bits to 8 +Call: sSetData8(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSetData8(ChP) \ +do { \ + (ChP)->TxControl[2] |= DATA8BIT; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetDTR +Purpose: Set the DTR output +Call: sSetDTR(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSetDTR(ChP) \ +do { \ + (ChP)->TxControl[3] |= SET_DTR; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetEvenParity +Purpose: Set even parity +Call: sSetEvenParity(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: Function sSetParity() can be used in place of functions sEnParity(), + sDisParity(), sSetOddParity(), and sSetEvenParity(). + +Warnings: This function has no effect unless parity is enabled with function + sEnParity(). +*/ +#define sSetEvenParity(ChP) \ +do { \ + (ChP)->TxControl[2] |= EVEN_PAR; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetOddParity +Purpose: Set odd parity +Call: sSetOddParity(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: Function sSetParity() can be used in place of functions sEnParity(), + sDisParity(), sSetOddParity(), and sSetEvenParity(). + +Warnings: This function has no effect unless parity is enabled with function + sEnParity(). +*/ +#define sSetOddParity(ChP) \ +do { \ + (ChP)->TxControl[2] &= ~EVEN_PAR; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetRTS +Purpose: Set the RTS output +Call: sSetRTS(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSetRTS(ChP) \ +do { \ + if ((ChP)->rtsToggle) break; \ + (ChP)->TxControl[3] |= SET_RTS; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetRxTrigger +Purpose: Set the Rx FIFO trigger level +Call: sSetRxProcessor(ChP,Level) + CHANNEL_T *ChP; Ptr to channel structure + Byte_t Level; Number of characters in Rx FIFO at which the + interrupt will be generated. Can be any of the following flags: + + TRIG_NO: no trigger + TRIG_1: 1 character in FIFO + TRIG_1_2: FIFO 1/2 full + TRIG_7_8: FIFO 7/8 full +Comments: An interrupt will be generated when the trigger level is reached + only if function sEnInterrupt() has been called with flag + RXINT_EN set. The RXF_TRIG flag in the Interrupt Idenfification + register will be set whenever the trigger level is reached + regardless of the setting of RXINT_EN. + +*/ +#define sSetRxTrigger(ChP,LEVEL) \ +do { \ + (ChP)->RxControl[2] &= ~TRIG_MASK; \ + (ChP)->RxControl[2] |= LEVEL; \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetStop1 +Purpose: Set stop bits to 1 +Call: sSetStop1(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSetStop1(ChP) \ +do { \ + (ChP)->TxControl[2] &= ~STOP2; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetStop2 +Purpose: Set stop bits to 2 +Call: sSetStop2(ChP) + CHANNEL_T *ChP; Ptr to channel structure +*/ +#define sSetStop2(ChP) \ +do { \ + (ChP)->TxControl[2] |= STOP2; \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ +} while (0) + +/*************************************************************************** +Function: sSetTxXOFFChar +Purpose: Set the Tx XOFF flow control character +Call: sSetTxXOFFChar(ChP,Ch) + CHANNEL_T *ChP; Ptr to channel structure + Byte_t Ch; The value to set the Tx XOFF character to +*/ +#define sSetTxXOFFChar(ChP,CH) \ +do { \ + (ChP)->R[0x07] = (CH); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ +} while (0) + +/*************************************************************************** +Function: sSetTxXONChar +Purpose: Set the Tx XON flow control character +Call: sSetTxXONChar(ChP,Ch) + CHANNEL_T *ChP; Ptr to channel structure + Byte_t Ch; The value to set the Tx XON character to +*/ +#define sSetTxXONChar(ChP,CH) \ +do { \ + (ChP)->R[0x0b] = (CH); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \ +} while (0) + +/*************************************************************************** +Function: sStartRxProcessor +Purpose: Start a channel's receive processor +Call: sStartRxProcessor(ChP) + CHANNEL_T *ChP; Ptr to channel structure +Comments: This function is used to start a Rx processor after it was + stopped with sStopRxProcessor() or sStopSWInFlowCtl(). It + will restart both the Rx processor and software input flow control. + +*/ +#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0]) + +/*************************************************************************** +Function: sWriteTxByte +Purpose: Write a transmit data byte to a channel. + ByteIO_t io: Channel transmit register I/O address. This can + be obtained with sGetTxRxDataIO(). + Byte_t Data; The transmit data byte. +Warnings: This function writes the data byte without checking to see if + sMaxTxSize is exceeded in the Tx FIFO. +*/ +#define sWriteTxByte(IO,DATA) sOutB(IO,DATA) + +/* + * Begin Linux specific definitions for the Rocketport driver + * + * This code is Copyright Theodore Ts'o, 1995-1997 + */ + +struct r_port { + int magic; + struct tty_port port; + int line; + int flags; /* Don't yet match the ASY_ flags!! */ + unsigned int board:3; + unsigned int aiop:2; + unsigned int chan:3; + CONTROLLER_t *ctlp; + CHANNEL_t channel; + int intmask; + int xmit_fifo_room; /* room in xmit fifo */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + int cd_status; + int ignore_status_mask; + int read_status_mask; + int cps; + + struct completion close_wait; /* Not yet matching the core */ + spinlock_t slock; + struct mutex write_mtx; +}; + +#define RPORT_MAGIC 0x525001 + +#define NUM_BOARDS 8 +#define MAX_RP_PORTS (32*NUM_BOARDS) + +/* + * The size of the xmit buffer is 1 page, or 4096 bytes + */ +#define XMIT_BUF_SIZE 4096 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * Assigned major numbers for the Comtrol Rocketport + */ +#define TTY_ROCKET_MAJOR 46 +#define CUA_ROCKET_MAJOR 47 + +#ifdef PCI_VENDOR_ID_RP +#undef PCI_VENDOR_ID_RP +#undef PCI_DEVICE_ID_RP8OCTA +#undef PCI_DEVICE_ID_RP8INTF +#undef PCI_DEVICE_ID_RP16INTF +#undef PCI_DEVICE_ID_RP32INTF +#undef PCI_DEVICE_ID_URP8OCTA +#undef PCI_DEVICE_ID_URP8INTF +#undef PCI_DEVICE_ID_URP16INTF +#undef PCI_DEVICE_ID_CRP16INTF +#undef PCI_DEVICE_ID_URP32INTF +#endif + +/* Comtrol PCI Vendor ID */ +#define PCI_VENDOR_ID_RP 0x11fe + +/* Comtrol Device ID's */ +#define PCI_DEVICE_ID_RP32INTF 0x0001 /* Rocketport 32 port w/external I/F */ +#define PCI_DEVICE_ID_RP8INTF 0x0002 /* Rocketport 8 port w/external I/F */ +#define PCI_DEVICE_ID_RP16INTF 0x0003 /* Rocketport 16 port w/external I/F */ +#define PCI_DEVICE_ID_RP4QUAD 0x0004 /* Rocketport 4 port w/quad cable */ +#define PCI_DEVICE_ID_RP8OCTA 0x0005 /* Rocketport 8 port w/octa cable */ +#define PCI_DEVICE_ID_RP8J 0x0006 /* Rocketport 8 port w/RJ11 connectors */ +#define PCI_DEVICE_ID_RP4J 0x0007 /* Rocketport 4 port w/RJ11 connectors */ +#define PCI_DEVICE_ID_RP8SNI 0x0008 /* Rocketport 8 port w/ DB78 SNI (Siemens) connector */ +#define PCI_DEVICE_ID_RP16SNI 0x0009 /* Rocketport 16 port w/ DB78 SNI (Siemens) connector */ +#define PCI_DEVICE_ID_RPP4 0x000A /* Rocketport Plus 4 port */ +#define PCI_DEVICE_ID_RPP8 0x000B /* Rocketport Plus 8 port */ +#define PCI_DEVICE_ID_RP6M 0x000C /* RocketModem 6 port */ +#define PCI_DEVICE_ID_RP4M 0x000D /* RocketModem 4 port */ +#define PCI_DEVICE_ID_RP2_232 0x000E /* Rocketport Plus 2 port RS232 */ +#define PCI_DEVICE_ID_RP2_422 0x000F /* Rocketport Plus 2 port RS422 */ + +/* Universal PCI boards */ +#define PCI_DEVICE_ID_URP32INTF 0x0801 /* Rocketport UPCI 32 port w/external I/F */ +#define PCI_DEVICE_ID_URP8INTF 0x0802 /* Rocketport UPCI 8 port w/external I/F */ +#define PCI_DEVICE_ID_URP16INTF 0x0803 /* Rocketport UPCI 16 port w/external I/F */ +#define PCI_DEVICE_ID_URP8OCTA 0x0805 /* Rocketport UPCI 8 port w/octa cable */ +#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C /* Rocketmodem III 8 port */ +#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D /* Rocketmodem III 4 port */ + +/* Compact PCI device */ +#define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */ + diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c new file mode 100644 index 000000000000..18888d005a0a --- /dev/null +++ b/drivers/tty/synclink.c @@ -0,0 +1,8119 @@ +/* + * linux/drivers/char/synclink.c + * + * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ + * + * Device driver for Microgate SyncLink ISA and PCI + * high speed multiprotocol serial adapters. + * + * written by Paul Fulghum for Microgate Corporation + * paulkf@microgate.com + * + * Microgate and SyncLink are trademarks of Microgate Corporation + * + * Derived from serial.c written by Theodore Ts'o and Linus Torvalds + * + * Original release 01/11/99 + * + * This code is released under the GNU General Public License (GPL) + * + * This driver is primarily intended for use in synchronous + * HDLC mode. Asynchronous mode is also provided. + * + * When operating in synchronous mode, each call to mgsl_write() + * contains exactly one complete HDLC frame. Calling mgsl_put_char + * will start assembling an HDLC frame that will not be sent until + * mgsl_flush_chars or mgsl_write is called. + * + * Synchronous receive data is reported as complete frames. To accomplish + * this, the TTY flip buffer is bypassed (too small to hold largest + * frame and may fragment frames) and the line discipline + * receive entry point is called directly. + * + * This driver has been tested with a slightly modified ppp.c driver + * for synchronous PPP. + * + * 2000/02/16 + * Added interface for syncppp.c driver (an alternate synchronous PPP + * implementation that also supports Cisco HDLC). Each device instance + * registers as a tty device AND a network device (if dosyncppp option + * is set for the device). The functionality is determined by which + * device interface is opened. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__i386__) +# define BREAKPOINT() asm(" int $3"); +#else +# define BREAKPOINT() { } +#endif + +#define MAX_ISA_DEVICES 10 +#define MAX_PCI_DEVICES 10 +#define MAX_TOTAL_DEVICES 20 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 +#endif + +#define GET_USER(error,value,addr) error = get_user(value,addr) +#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 +#define PUT_USER(error,value,addr) error = put_user(value,addr) +#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 + +#include + +#define RCLRVALUE 0xffff + +static MGSL_PARAMS default_params = { + MGSL_MODE_HDLC, /* unsigned long mode */ + 0, /* unsigned char loopback; */ + HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */ + HDLC_ENCODING_NRZI_SPACE, /* unsigned char encoding; */ + 0, /* unsigned long clock_speed; */ + 0xff, /* unsigned char addr_filter; */ + HDLC_CRC_16_CCITT, /* unsigned short crc_type; */ + HDLC_PREAMBLE_LENGTH_8BITS, /* unsigned char preamble_length; */ + HDLC_PREAMBLE_PATTERN_NONE, /* unsigned char preamble; */ + 9600, /* unsigned long data_rate; */ + 8, /* unsigned char data_bits; */ + 1, /* unsigned char stop_bits; */ + ASYNC_PARITY_NONE /* unsigned char parity; */ +}; + +#define SHARED_MEM_ADDRESS_SIZE 0x40000 +#define BUFFERLISTSIZE 4096 +#define DMABUFFERSIZE 4096 +#define MAXRXFRAMES 7 + +typedef struct _DMABUFFERENTRY +{ + u32 phys_addr; /* 32-bit flat physical address of data buffer */ + volatile u16 count; /* buffer size/data count */ + volatile u16 status; /* Control/status field */ + volatile u16 rcc; /* character count field */ + u16 reserved; /* padding required by 16C32 */ + u32 link; /* 32-bit flat link to next buffer entry */ + char *virt_addr; /* virtual address of data buffer */ + u32 phys_entry; /* physical address of this buffer entry */ + dma_addr_t dma_addr; +} DMABUFFERENTRY, *DMAPBUFFERENTRY; + +/* The queue of BH actions to be performed */ + +#define BH_RECEIVE 1 +#define BH_TRANSMIT 2 +#define BH_STATUS 4 + +#define IO_PIN_SHUTDOWN_LIMIT 100 + +struct _input_signal_events { + int ri_up; + int ri_down; + int dsr_up; + int dsr_down; + int dcd_up; + int dcd_down; + int cts_up; + int cts_down; +}; + +/* transmit holding buffer definitions*/ +#define MAX_TX_HOLDING_BUFFERS 5 +struct tx_holding_buffer { + int buffer_size; + unsigned char * buffer; +}; + + +/* + * Device instance data structure + */ + +struct mgsl_struct { + int magic; + struct tty_port port; + int line; + int hw_version; + + struct mgsl_icount icount; + + int timeout; + int x_char; /* xon/xoff character */ + u16 read_status_mask; + u16 ignore_status_mask; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + + wait_queue_head_t status_event_wait_q; + wait_queue_head_t event_wait_q; + struct timer_list tx_timer; /* HDLC transmit timeout timer */ + struct mgsl_struct *next_device; /* device list link */ + + spinlock_t irq_spinlock; /* spinlock for synchronizing with ISR */ + struct work_struct task; /* task structure for scheduling bh */ + + u32 EventMask; /* event trigger mask */ + u32 RecordedEvents; /* pending events */ + + u32 max_frame_size; /* as set by device config */ + + u32 pending_bh; + + bool bh_running; /* Protection from multiple */ + int isr_overflow; + bool bh_requested; + + int dcd_chkcount; /* check counts to prevent */ + int cts_chkcount; /* too many IRQs if a signal */ + int dsr_chkcount; /* is floating */ + int ri_chkcount; + + char *buffer_list; /* virtual address of Rx & Tx buffer lists */ + u32 buffer_list_phys; + dma_addr_t buffer_list_dma_addr; + + unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ + DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ + unsigned int current_rx_buffer; + + int num_tx_dma_buffers; /* number of tx dma frames required */ + int tx_dma_buffers_used; + unsigned int tx_buffer_count; /* count of total allocated Tx buffers */ + DMABUFFERENTRY *tx_buffer_list; /* list of transmit buffer entries */ + int start_tx_dma_buffer; /* tx dma buffer to start tx dma operation */ + int current_tx_buffer; /* next tx dma buffer to be loaded */ + + unsigned char *intermediate_rxbuffer; + + int num_tx_holding_buffers; /* number of tx holding buffer allocated */ + int get_tx_holding_index; /* next tx holding buffer for adapter to load */ + int put_tx_holding_index; /* next tx holding buffer to store user request */ + int tx_holding_count; /* number of tx holding buffers waiting */ + struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS]; + + bool rx_enabled; + bool rx_overflow; + bool rx_rcc_underrun; + + bool tx_enabled; + bool tx_active; + u32 idle_mode; + + u16 cmr_value; + u16 tcsr_value; + + char device_name[25]; /* device instance name */ + + unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */ + unsigned char bus; /* expansion bus number (zero based) */ + unsigned char function; /* PCI device number */ + + unsigned int io_base; /* base I/O address of adapter */ + unsigned int io_addr_size; /* size of the I/O address range */ + bool io_addr_requested; /* true if I/O address requested */ + + unsigned int irq_level; /* interrupt level */ + unsigned long irq_flags; + bool irq_requested; /* true if IRQ requested */ + + unsigned int dma_level; /* DMA channel */ + bool dma_requested; /* true if dma channel requested */ + + u16 mbre_bit; + u16 loopback_bits; + u16 usc_idle_mode; + + MGSL_PARAMS params; /* communications parameters */ + + unsigned char serial_signals; /* current serial signal states */ + + bool irq_occurred; /* for diagnostics use */ + unsigned int init_error; /* Initialization startup error (DIAGS) */ + int fDiagnosticsmode; /* Driver in Diagnostic mode? (DIAGS) */ + + u32 last_mem_alloc; + unsigned char* memory_base; /* shared memory address (PCI only) */ + u32 phys_memory_base; + bool shared_mem_requested; + + unsigned char* lcr_base; /* local config registers (PCI only) */ + u32 phys_lcr_base; + u32 lcr_offset; + bool lcr_mem_requested; + + u32 misc_ctrl_value; + char flag_buf[MAX_ASYNC_BUFFER_SIZE]; + char char_buf[MAX_ASYNC_BUFFER_SIZE]; + bool drop_rts_on_tx_done; + + bool loopmode_insert_requested; + bool loopmode_send_done_requested; + + struct _input_signal_events input_signal_events; + + /* generic HDLC device parts */ + int netcount; + spinlock_t netlock; + +#if SYNCLINK_GENERIC_HDLC + struct net_device *netdev; +#endif +}; + +#define MGSL_MAGIC 0x5401 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#ifndef SERIAL_XMIT_SIZE +#define SERIAL_XMIT_SIZE 4096 +#endif + +/* + * These macros define the offsets used in calculating the + * I/O address of the specified USC registers. + */ + + +#define DCPIN 2 /* Bit 1 of I/O address */ +#define SDPIN 4 /* Bit 2 of I/O address */ + +#define DCAR 0 /* DMA command/address register */ +#define CCAR SDPIN /* channel command/address register */ +#define DATAREG DCPIN + SDPIN /* serial data register */ +#define MSBONLY 0x41 +#define LSBONLY 0x40 + +/* + * These macros define the register address (ordinal number) + * used for writing address/value pairs to the USC. + */ + +#define CMR 0x02 /* Channel mode Register */ +#define CCSR 0x04 /* Channel Command/status Register */ +#define CCR 0x06 /* Channel Control Register */ +#define PSR 0x08 /* Port status Register */ +#define PCR 0x0a /* Port Control Register */ +#define TMDR 0x0c /* Test mode Data Register */ +#define TMCR 0x0e /* Test mode Control Register */ +#define CMCR 0x10 /* Clock mode Control Register */ +#define HCR 0x12 /* Hardware Configuration Register */ +#define IVR 0x14 /* Interrupt Vector Register */ +#define IOCR 0x16 /* Input/Output Control Register */ +#define ICR 0x18 /* Interrupt Control Register */ +#define DCCR 0x1a /* Daisy Chain Control Register */ +#define MISR 0x1c /* Misc Interrupt status Register */ +#define SICR 0x1e /* status Interrupt Control Register */ +#define RDR 0x20 /* Receive Data Register */ +#define RMR 0x22 /* Receive mode Register */ +#define RCSR 0x24 /* Receive Command/status Register */ +#define RICR 0x26 /* Receive Interrupt Control Register */ +#define RSR 0x28 /* Receive Sync Register */ +#define RCLR 0x2a /* Receive count Limit Register */ +#define RCCR 0x2c /* Receive Character count Register */ +#define TC0R 0x2e /* Time Constant 0 Register */ +#define TDR 0x30 /* Transmit Data Register */ +#define TMR 0x32 /* Transmit mode Register */ +#define TCSR 0x34 /* Transmit Command/status Register */ +#define TICR 0x36 /* Transmit Interrupt Control Register */ +#define TSR 0x38 /* Transmit Sync Register */ +#define TCLR 0x3a /* Transmit count Limit Register */ +#define TCCR 0x3c /* Transmit Character count Register */ +#define TC1R 0x3e /* Time Constant 1 Register */ + + +/* + * MACRO DEFINITIONS FOR DMA REGISTERS + */ + +#define DCR 0x06 /* DMA Control Register (shared) */ +#define DACR 0x08 /* DMA Array count Register (shared) */ +#define BDCR 0x12 /* Burst/Dwell Control Register (shared) */ +#define DIVR 0x14 /* DMA Interrupt Vector Register (shared) */ +#define DICR 0x18 /* DMA Interrupt Control Register (shared) */ +#define CDIR 0x1a /* Clear DMA Interrupt Register (shared) */ +#define SDIR 0x1c /* Set DMA Interrupt Register (shared) */ + +#define TDMR 0x02 /* Transmit DMA mode Register */ +#define TDIAR 0x1e /* Transmit DMA Interrupt Arm Register */ +#define TBCR 0x2a /* Transmit Byte count Register */ +#define TARL 0x2c /* Transmit Address Register (low) */ +#define TARU 0x2e /* Transmit Address Register (high) */ +#define NTBCR 0x3a /* Next Transmit Byte count Register */ +#define NTARL 0x3c /* Next Transmit Address Register (low) */ +#define NTARU 0x3e /* Next Transmit Address Register (high) */ + +#define RDMR 0x82 /* Receive DMA mode Register (non-shared) */ +#define RDIAR 0x9e /* Receive DMA Interrupt Arm Register */ +#define RBCR 0xaa /* Receive Byte count Register */ +#define RARL 0xac /* Receive Address Register (low) */ +#define RARU 0xae /* Receive Address Register (high) */ +#define NRBCR 0xba /* Next Receive Byte count Register */ +#define NRARL 0xbc /* Next Receive Address Register (low) */ +#define NRARU 0xbe /* Next Receive Address Register (high) */ + + +/* + * MACRO DEFINITIONS FOR MODEM STATUS BITS + */ + +#define MODEMSTATUS_DTR 0x80 +#define MODEMSTATUS_DSR 0x40 +#define MODEMSTATUS_RTS 0x20 +#define MODEMSTATUS_CTS 0x10 +#define MODEMSTATUS_RI 0x04 +#define MODEMSTATUS_DCD 0x01 + + +/* + * Channel Command/Address Register (CCAR) Command Codes + */ + +#define RTCmd_Null 0x0000 +#define RTCmd_ResetHighestIus 0x1000 +#define RTCmd_TriggerChannelLoadDma 0x2000 +#define RTCmd_TriggerRxDma 0x2800 +#define RTCmd_TriggerTxDma 0x3000 +#define RTCmd_TriggerRxAndTxDma 0x3800 +#define RTCmd_PurgeRxFifo 0x4800 +#define RTCmd_PurgeTxFifo 0x5000 +#define RTCmd_PurgeRxAndTxFifo 0x5800 +#define RTCmd_LoadRcc 0x6800 +#define RTCmd_LoadTcc 0x7000 +#define RTCmd_LoadRccAndTcc 0x7800 +#define RTCmd_LoadTC0 0x8800 +#define RTCmd_LoadTC1 0x9000 +#define RTCmd_LoadTC0AndTC1 0x9800 +#define RTCmd_SerialDataLSBFirst 0xa000 +#define RTCmd_SerialDataMSBFirst 0xa800 +#define RTCmd_SelectBigEndian 0xb000 +#define RTCmd_SelectLittleEndian 0xb800 + + +/* + * DMA Command/Address Register (DCAR) Command Codes + */ + +#define DmaCmd_Null 0x0000 +#define DmaCmd_ResetTxChannel 0x1000 +#define DmaCmd_ResetRxChannel 0x1200 +#define DmaCmd_StartTxChannel 0x2000 +#define DmaCmd_StartRxChannel 0x2200 +#define DmaCmd_ContinueTxChannel 0x3000 +#define DmaCmd_ContinueRxChannel 0x3200 +#define DmaCmd_PauseTxChannel 0x4000 +#define DmaCmd_PauseRxChannel 0x4200 +#define DmaCmd_AbortTxChannel 0x5000 +#define DmaCmd_AbortRxChannel 0x5200 +#define DmaCmd_InitTxChannel 0x7000 +#define DmaCmd_InitRxChannel 0x7200 +#define DmaCmd_ResetHighestDmaIus 0x8000 +#define DmaCmd_ResetAllChannels 0x9000 +#define DmaCmd_StartAllChannels 0xa000 +#define DmaCmd_ContinueAllChannels 0xb000 +#define DmaCmd_PauseAllChannels 0xc000 +#define DmaCmd_AbortAllChannels 0xd000 +#define DmaCmd_InitAllChannels 0xf000 + +#define TCmd_Null 0x0000 +#define TCmd_ClearTxCRC 0x2000 +#define TCmd_SelectTicrTtsaData 0x4000 +#define TCmd_SelectTicrTxFifostatus 0x5000 +#define TCmd_SelectTicrIntLevel 0x6000 +#define TCmd_SelectTicrdma_level 0x7000 +#define TCmd_SendFrame 0x8000 +#define TCmd_SendAbort 0x9000 +#define TCmd_EnableDleInsertion 0xc000 +#define TCmd_DisableDleInsertion 0xd000 +#define TCmd_ClearEofEom 0xe000 +#define TCmd_SetEofEom 0xf000 + +#define RCmd_Null 0x0000 +#define RCmd_ClearRxCRC 0x2000 +#define RCmd_EnterHuntmode 0x3000 +#define RCmd_SelectRicrRtsaData 0x4000 +#define RCmd_SelectRicrRxFifostatus 0x5000 +#define RCmd_SelectRicrIntLevel 0x6000 +#define RCmd_SelectRicrdma_level 0x7000 + +/* + * Bits for enabling and disabling IRQs in Interrupt Control Register (ICR) + */ + +#define RECEIVE_STATUS BIT5 +#define RECEIVE_DATA BIT4 +#define TRANSMIT_STATUS BIT3 +#define TRANSMIT_DATA BIT2 +#define IO_PIN BIT1 +#define MISC BIT0 + + +/* + * Receive status Bits in Receive Command/status Register RCSR + */ + +#define RXSTATUS_SHORT_FRAME BIT8 +#define RXSTATUS_CODE_VIOLATION BIT8 +#define RXSTATUS_EXITED_HUNT BIT7 +#define RXSTATUS_IDLE_RECEIVED BIT6 +#define RXSTATUS_BREAK_RECEIVED BIT5 +#define RXSTATUS_ABORT_RECEIVED BIT5 +#define RXSTATUS_RXBOUND BIT4 +#define RXSTATUS_CRC_ERROR BIT3 +#define RXSTATUS_FRAMING_ERROR BIT3 +#define RXSTATUS_ABORT BIT2 +#define RXSTATUS_PARITY_ERROR BIT2 +#define RXSTATUS_OVERRUN BIT1 +#define RXSTATUS_DATA_AVAILABLE BIT0 +#define RXSTATUS_ALL 0x01f6 +#define usc_UnlatchRxstatusBits(a,b) usc_OutReg( (a), RCSR, (u16)((b) & RXSTATUS_ALL) ) + +/* + * Values for setting transmit idle mode in + * Transmit Control/status Register (TCSR) + */ +#define IDLEMODE_FLAGS 0x0000 +#define IDLEMODE_ALT_ONE_ZERO 0x0100 +#define IDLEMODE_ZERO 0x0200 +#define IDLEMODE_ONE 0x0300 +#define IDLEMODE_ALT_MARK_SPACE 0x0500 +#define IDLEMODE_SPACE 0x0600 +#define IDLEMODE_MARK 0x0700 +#define IDLEMODE_MASK 0x0700 + +/* + * IUSC revision identifiers + */ +#define IUSC_SL1660 0x4d44 +#define IUSC_PRE_SL1660 0x4553 + +/* + * Transmit status Bits in Transmit Command/status Register (TCSR) + */ + +#define TCSR_PRESERVE 0x0F00 + +#define TCSR_UNDERWAIT BIT11 +#define TXSTATUS_PREAMBLE_SENT BIT7 +#define TXSTATUS_IDLE_SENT BIT6 +#define TXSTATUS_ABORT_SENT BIT5 +#define TXSTATUS_EOF_SENT BIT4 +#define TXSTATUS_EOM_SENT BIT4 +#define TXSTATUS_CRC_SENT BIT3 +#define TXSTATUS_ALL_SENT BIT2 +#define TXSTATUS_UNDERRUN BIT1 +#define TXSTATUS_FIFO_EMPTY BIT0 +#define TXSTATUS_ALL 0x00fa +#define usc_UnlatchTxstatusBits(a,b) usc_OutReg( (a), TCSR, (u16)((a)->tcsr_value + ((b) & 0x00FF)) ) + + +#define MISCSTATUS_RXC_LATCHED BIT15 +#define MISCSTATUS_RXC BIT14 +#define MISCSTATUS_TXC_LATCHED BIT13 +#define MISCSTATUS_TXC BIT12 +#define MISCSTATUS_RI_LATCHED BIT11 +#define MISCSTATUS_RI BIT10 +#define MISCSTATUS_DSR_LATCHED BIT9 +#define MISCSTATUS_DSR BIT8 +#define MISCSTATUS_DCD_LATCHED BIT7 +#define MISCSTATUS_DCD BIT6 +#define MISCSTATUS_CTS_LATCHED BIT5 +#define MISCSTATUS_CTS BIT4 +#define MISCSTATUS_RCC_UNDERRUN BIT3 +#define MISCSTATUS_DPLL_NO_SYNC BIT2 +#define MISCSTATUS_BRG1_ZERO BIT1 +#define MISCSTATUS_BRG0_ZERO BIT0 + +#define usc_UnlatchIostatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0xaaa0)) +#define usc_UnlatchMiscstatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0x000f)) + +#define SICR_RXC_ACTIVE BIT15 +#define SICR_RXC_INACTIVE BIT14 +#define SICR_RXC (BIT15+BIT14) +#define SICR_TXC_ACTIVE BIT13 +#define SICR_TXC_INACTIVE BIT12 +#define SICR_TXC (BIT13+BIT12) +#define SICR_RI_ACTIVE BIT11 +#define SICR_RI_INACTIVE BIT10 +#define SICR_RI (BIT11+BIT10) +#define SICR_DSR_ACTIVE BIT9 +#define SICR_DSR_INACTIVE BIT8 +#define SICR_DSR (BIT9+BIT8) +#define SICR_DCD_ACTIVE BIT7 +#define SICR_DCD_INACTIVE BIT6 +#define SICR_DCD (BIT7+BIT6) +#define SICR_CTS_ACTIVE BIT5 +#define SICR_CTS_INACTIVE BIT4 +#define SICR_CTS (BIT5+BIT4) +#define SICR_RCC_UNDERFLOW BIT3 +#define SICR_DPLL_NO_SYNC BIT2 +#define SICR_BRG1_ZERO BIT1 +#define SICR_BRG0_ZERO BIT0 + +void usc_DisableMasterIrqBit( struct mgsl_struct *info ); +void usc_EnableMasterIrqBit( struct mgsl_struct *info ); +void usc_EnableInterrupts( struct mgsl_struct *info, u16 IrqMask ); +void usc_DisableInterrupts( struct mgsl_struct *info, u16 IrqMask ); +void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask ); + +#define usc_EnableInterrupts( a, b ) \ + usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0xc0 + (b)) ) + +#define usc_DisableInterrupts( a, b ) \ + usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0x80 + (b)) ) + +#define usc_EnableMasterIrqBit(a) \ + usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0x0f00) + 0xb000) ) + +#define usc_DisableMasterIrqBit(a) \ + usc_OutReg( (a), ICR, (u16)(usc_InReg((a),ICR) & 0x7f00) ) + +#define usc_ClearIrqPendingBits( a, b ) usc_OutReg( (a), DCCR, 0x40 + (b) ) + +/* + * Transmit status Bits in Transmit Control status Register (TCSR) + * and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) + */ + +#define TXSTATUS_PREAMBLE_SENT BIT7 +#define TXSTATUS_IDLE_SENT BIT6 +#define TXSTATUS_ABORT_SENT BIT5 +#define TXSTATUS_EOF BIT4 +#define TXSTATUS_CRC_SENT BIT3 +#define TXSTATUS_ALL_SENT BIT2 +#define TXSTATUS_UNDERRUN BIT1 +#define TXSTATUS_FIFO_EMPTY BIT0 + +#define DICR_MASTER BIT15 +#define DICR_TRANSMIT BIT0 +#define DICR_RECEIVE BIT1 + +#define usc_EnableDmaInterrupts(a,b) \ + usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) | (b)) ) + +#define usc_DisableDmaInterrupts(a,b) \ + usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) & ~(b)) ) + +#define usc_EnableStatusIrqs(a,b) \ + usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) | (b)) ) + +#define usc_DisablestatusIrqs(a,b) \ + usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) & ~(b)) ) + +/* Transmit status Bits in Transmit Control status Register (TCSR) */ +/* and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) */ + + +#define DISABLE_UNCONDITIONAL 0 +#define DISABLE_END_OF_FRAME 1 +#define ENABLE_UNCONDITIONAL 2 +#define ENABLE_AUTO_CTS 3 +#define ENABLE_AUTO_DCD 3 +#define usc_EnableTransmitter(a,b) \ + usc_OutReg( (a), TMR, (u16)((usc_InReg((a),TMR) & 0xfffc) | (b)) ) +#define usc_EnableReceiver(a,b) \ + usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) ) + +static u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port ); +static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value ); +static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ); + +static u16 usc_InReg( struct mgsl_struct *info, u16 Port ); +static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value ); +static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ); +void usc_RCmd( struct mgsl_struct *info, u16 Cmd ); +void usc_TCmd( struct mgsl_struct *info, u16 Cmd ); + +#define usc_TCmd(a,b) usc_OutReg((a), TCSR, (u16)((a)->tcsr_value + (b))) +#define usc_RCmd(a,b) usc_OutReg((a), RCSR, (b)) + +#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1)) + +static void usc_process_rxoverrun_sync( struct mgsl_struct *info ); +static void usc_start_receiver( struct mgsl_struct *info ); +static void usc_stop_receiver( struct mgsl_struct *info ); + +static void usc_start_transmitter( struct mgsl_struct *info ); +static void usc_stop_transmitter( struct mgsl_struct *info ); +static void usc_set_txidle( struct mgsl_struct *info ); +static void usc_load_txfifo( struct mgsl_struct *info ); + +static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate ); +static void usc_enable_loopback( struct mgsl_struct *info, int enable ); + +static void usc_get_serial_signals( struct mgsl_struct *info ); +static void usc_set_serial_signals( struct mgsl_struct *info ); + +static void usc_reset( struct mgsl_struct *info ); + +static void usc_set_sync_mode( struct mgsl_struct *info ); +static void usc_set_sdlc_mode( struct mgsl_struct *info ); +static void usc_set_async_mode( struct mgsl_struct *info ); +static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate ); + +static void usc_loopback_frame( struct mgsl_struct *info ); + +static void mgsl_tx_timeout(unsigned long context); + + +static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ); +static void usc_loopmode_insert_request( struct mgsl_struct * info ); +static int usc_loopmode_active( struct mgsl_struct * info); +static void usc_loopmode_send_done( struct mgsl_struct * info ); + +static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); + +#if SYNCLINK_GENERIC_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(struct mgsl_struct *info); +static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size); +static int hdlcdev_init(struct mgsl_struct *info); +static void hdlcdev_exit(struct mgsl_struct *info); +#endif + +/* + * Defines a BUS descriptor value for the PCI adapter + * local bus address ranges. + */ + +#define BUS_DESCRIPTOR( WrHold, WrDly, RdDly, Nwdd, Nwad, Nxda, Nrdd, Nrad ) \ +(0x00400020 + \ +((WrHold) << 30) + \ +((WrDly) << 28) + \ +((RdDly) << 26) + \ +((Nwdd) << 20) + \ +((Nwad) << 15) + \ +((Nxda) << 13) + \ +((Nrdd) << 11) + \ +((Nrad) << 6) ) + +static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit); + +/* + * Adapter diagnostic routines + */ +static bool mgsl_register_test( struct mgsl_struct *info ); +static bool mgsl_irq_test( struct mgsl_struct *info ); +static bool mgsl_dma_test( struct mgsl_struct *info ); +static bool mgsl_memory_test( struct mgsl_struct *info ); +static int mgsl_adapter_test( struct mgsl_struct *info ); + +/* + * device and resource management routines + */ +static int mgsl_claim_resources(struct mgsl_struct *info); +static void mgsl_release_resources(struct mgsl_struct *info); +static void mgsl_add_device(struct mgsl_struct *info); +static struct mgsl_struct* mgsl_allocate_device(void); + +/* + * DMA buffer manupulation functions. + */ +static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ); +static bool mgsl_get_rx_frame( struct mgsl_struct *info ); +static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info ); +static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ); +static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ); +static int num_free_tx_dma_buffers(struct mgsl_struct *info); +static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize); +static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count); + +/* + * DMA and Shared Memory buffer allocation and formatting + */ +static int mgsl_allocate_dma_buffers(struct mgsl_struct *info); +static void mgsl_free_dma_buffers(struct mgsl_struct *info); +static int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); +static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); +static int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info); +static void mgsl_free_buffer_list_memory(struct mgsl_struct *info); +static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info); +static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info); +static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info); +static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info); +static bool load_next_tx_holding_buffer(struct mgsl_struct *info); +static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize); + +/* + * Bottom half interrupt handlers + */ +static void mgsl_bh_handler(struct work_struct *work); +static void mgsl_bh_receive(struct mgsl_struct *info); +static void mgsl_bh_transmit(struct mgsl_struct *info); +static void mgsl_bh_status(struct mgsl_struct *info); + +/* + * Interrupt handler routines and dispatch table. + */ +static void mgsl_isr_null( struct mgsl_struct *info ); +static void mgsl_isr_transmit_data( struct mgsl_struct *info ); +static void mgsl_isr_receive_data( struct mgsl_struct *info ); +static void mgsl_isr_receive_status( struct mgsl_struct *info ); +static void mgsl_isr_transmit_status( struct mgsl_struct *info ); +static void mgsl_isr_io_pin( struct mgsl_struct *info ); +static void mgsl_isr_misc( struct mgsl_struct *info ); +static void mgsl_isr_receive_dma( struct mgsl_struct *info ); +static void mgsl_isr_transmit_dma( struct mgsl_struct *info ); + +typedef void (*isr_dispatch_func)(struct mgsl_struct *); + +static isr_dispatch_func UscIsrTable[7] = +{ + mgsl_isr_null, + mgsl_isr_misc, + mgsl_isr_io_pin, + mgsl_isr_transmit_data, + mgsl_isr_transmit_status, + mgsl_isr_receive_data, + mgsl_isr_receive_status +}; + +/* + * ioctl call handlers + */ +static int tiocmget(struct tty_struct *tty); +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); +static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount + __user *user_icount); +static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params); +static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params); +static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode); +static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode); +static int mgsl_txenable(struct mgsl_struct * info, int enable); +static int mgsl_txabort(struct mgsl_struct * info); +static int mgsl_rxenable(struct mgsl_struct * info, int enable); +static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask); +static int mgsl_loopmode_send_done( struct mgsl_struct * info ); + +/* set non-zero on successful registration with PCI subsystem */ +static bool pci_registered; + +/* + * Global linked list of SyncLink devices + */ +static struct mgsl_struct *mgsl_device_list; +static int mgsl_device_count; + +/* + * Set this param to non-zero to load eax with the + * .text section address and breakpoint on module load. + * This is useful for use with gdb and add-symbol-file command. + */ +static int break_on_load; + +/* + * Driver major number, defaults to zero to get auto + * assigned major number. May be forced as module parameter. + */ +static int ttymajor; + +/* + * Array of user specified options for ISA adapters. + */ +static int io[MAX_ISA_DEVICES]; +static int irq[MAX_ISA_DEVICES]; +static int dma[MAX_ISA_DEVICES]; +static int debug_level; +static int maxframe[MAX_TOTAL_DEVICES]; +static int txdmabufs[MAX_TOTAL_DEVICES]; +static int txholdbufs[MAX_TOTAL_DEVICES]; + +module_param(break_on_load, bool, 0); +module_param(ttymajor, int, 0); +module_param_array(io, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param_array(dma, int, NULL, 0); +module_param(debug_level, int, 0); +module_param_array(maxframe, int, NULL, 0); +module_param_array(txdmabufs, int, NULL, 0); +module_param_array(txholdbufs, int, NULL, 0); + +static char *driver_name = "SyncLink serial driver"; +static char *driver_version = "$Revision: 4.38 $"; + +static int synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent); +static void synclink_remove_one (struct pci_dev *dev); + +static struct pci_device_id synclink_pci_tbl[] = { + { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); + +MODULE_LICENSE("GPL"); + +static struct pci_driver synclink_pci_driver = { + .name = "synclink", + .id_table = synclink_pci_tbl, + .probe = synclink_init_one, + .remove = __devexit_p(synclink_remove_one), +}; + +static struct tty_driver *serial_driver; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + + +static void mgsl_change_params(struct mgsl_struct *info); +static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout); + +/* + * 1st function defined in .text section. Calling this function in + * init_module() followed by a breakpoint allows a remote debugger + * (gdb) to get the .text address for the add-symbol-file command. + * This allows remote debugging of dynamically loadable modules. + */ +static void* mgsl_get_text_ptr(void) +{ + return mgsl_get_text_ptr; +} + +static inline int mgsl_paranoia_check(struct mgsl_struct *info, + char *name, const char *routine) +{ +#ifdef MGSL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for mgsl struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null mgsl_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, name, routine); + return 1; + } + if (info->magic != MGSL_MAGIC) { + printk(badmagic, name, routine); + return 1; + } +#else + if (!info) + return 1; +#endif + return 0; +} + +/** + * line discipline callback wrappers + * + * The wrappers maintain line discipline references + * while calling into the line discipline. + * + * ldisc_receive_buf - pass receive data to line discipline + */ + +static void ldisc_receive_buf(struct tty_struct *tty, + const __u8 *data, char *flags, int count) +{ + struct tty_ldisc *ld; + if (!tty) + return; + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->ops->receive_buf) + ld->ops->receive_buf(tty, data, flags, count); + tty_ldisc_deref(ld); + } +} + +/* mgsl_stop() throttle (stop) transmitter + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static void mgsl_stop(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (mgsl_paranoia_check(info, tty->name, "mgsl_stop")) + return; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("mgsl_stop(%s)\n",info->device_name); + + spin_lock_irqsave(&info->irq_spinlock,flags); + if (info->tx_enabled) + usc_stop_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + +} /* end of mgsl_stop() */ + +/* mgsl_start() release (start) transmitter + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static void mgsl_start(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (mgsl_paranoia_check(info, tty->name, "mgsl_start")) + return; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("mgsl_start(%s)\n",info->device_name); + + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!info->tx_enabled) + usc_start_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + +} /* end of mgsl_start() */ + +/* + * Bottom half work queue access functions + */ + +/* mgsl_bh_action() Return next bottom half action to perform. + * Return Value: BH action code or 0 if nothing to do. + */ +static int mgsl_bh_action(struct mgsl_struct *info) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&info->irq_spinlock,flags); + + if (info->pending_bh & BH_RECEIVE) { + info->pending_bh &= ~BH_RECEIVE; + rc = BH_RECEIVE; + } else if (info->pending_bh & BH_TRANSMIT) { + info->pending_bh &= ~BH_TRANSMIT; + rc = BH_TRANSMIT; + } else if (info->pending_bh & BH_STATUS) { + info->pending_bh &= ~BH_STATUS; + rc = BH_STATUS; + } + + if (!rc) { + /* Mark BH routine as complete */ + info->bh_running = false; + info->bh_requested = false; + } + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return rc; +} + +/* + * Perform bottom half processing of work items queued by ISR. + */ +static void mgsl_bh_handler(struct work_struct *work) +{ + struct mgsl_struct *info = + container_of(work, struct mgsl_struct, task); + int action; + + if (!info) + return; + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):mgsl_bh_handler(%s) entry\n", + __FILE__,__LINE__,info->device_name); + + info->bh_running = true; + + while((action = mgsl_bh_action(info)) != 0) { + + /* Process work item */ + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):mgsl_bh_handler() work item action=%d\n", + __FILE__,__LINE__,action); + + switch (action) { + + case BH_RECEIVE: + mgsl_bh_receive(info); + break; + case BH_TRANSMIT: + mgsl_bh_transmit(info); + break; + case BH_STATUS: + mgsl_bh_status(info); + break; + default: + /* unknown work item ID */ + printk("Unknown work item ID=%08X!\n", action); + break; + } + } + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):mgsl_bh_handler(%s) exit\n", + __FILE__,__LINE__,info->device_name); +} + +static void mgsl_bh_receive(struct mgsl_struct *info) +{ + bool (*get_rx_frame)(struct mgsl_struct *info) = + (info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame); + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):mgsl_bh_receive(%s)\n", + __FILE__,__LINE__,info->device_name); + + do + { + if (info->rx_rcc_underrun) { + unsigned long flags; + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return; + } + } while(get_rx_frame(info)); +} + +static void mgsl_bh_transmit(struct mgsl_struct *info) +{ + struct tty_struct *tty = info->port.tty; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):mgsl_bh_transmit() entry on %s\n", + __FILE__,__LINE__,info->device_name); + + if (tty) + tty_wakeup(tty); + + /* if transmitter idle and loopmode_send_done_requested + * then start echoing RxD to TxD + */ + spin_lock_irqsave(&info->irq_spinlock,flags); + if ( !info->tx_active && info->loopmode_send_done_requested ) + usc_loopmode_send_done( info ); + spin_unlock_irqrestore(&info->irq_spinlock,flags); +} + +static void mgsl_bh_status(struct mgsl_struct *info) +{ + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):mgsl_bh_status() entry on %s\n", + __FILE__,__LINE__,info->device_name); + + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + info->dcd_chkcount = 0; + info->cts_chkcount = 0; +} + +/* mgsl_isr_receive_status() + * + * Service a receive status interrupt. The type of status + * interrupt is indicated by the state of the RCSR. + * This is only used for HDLC mode. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_receive_status( struct mgsl_struct *info ) +{ + u16 status = usc_InReg( info, RCSR ); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_receive_status status=%04X\n", + __FILE__,__LINE__,status); + + if ( (status & RXSTATUS_ABORT_RECEIVED) && + info->loopmode_insert_requested && + usc_loopmode_active(info) ) + { + ++info->icount.rxabort; + info->loopmode_insert_requested = false; + + /* clear CMR:13 to start echoing RxD to TxD */ + info->cmr_value &= ~BIT13; + usc_OutReg(info, CMR, info->cmr_value); + + /* disable received abort irq (no longer required) */ + usc_OutReg(info, RICR, + (usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED)); + } + + if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) { + if (status & RXSTATUS_EXITED_HUNT) + info->icount.exithunt++; + if (status & RXSTATUS_IDLE_RECEIVED) + info->icount.rxidle++; + wake_up_interruptible(&info->event_wait_q); + } + + if (status & RXSTATUS_OVERRUN){ + info->icount.rxover++; + usc_process_rxoverrun_sync( info ); + } + + usc_ClearIrqPendingBits( info, RECEIVE_STATUS ); + usc_UnlatchRxstatusBits( info, status ); + +} /* end of mgsl_isr_receive_status() */ + +/* mgsl_isr_transmit_status() + * + * Service a transmit status interrupt + * HDLC mode :end of transmit frame + * Async mode:all data is sent + * transmit status is indicated by bits in the TCSR. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_transmit_status( struct mgsl_struct *info ) +{ + u16 status = usc_InReg( info, TCSR ); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_transmit_status status=%04X\n", + __FILE__,__LINE__,status); + + usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); + usc_UnlatchTxstatusBits( info, status ); + + if ( status & (TXSTATUS_UNDERRUN | TXSTATUS_ABORT_SENT) ) + { + /* finished sending HDLC abort. This may leave */ + /* the TxFifo with data from the aborted frame */ + /* so purge the TxFifo. Also shutdown the DMA */ + /* channel in case there is data remaining in */ + /* the DMA buffer */ + usc_DmaCmd( info, DmaCmd_ResetTxChannel ); + usc_RTCmd( info, RTCmd_PurgeTxFifo ); + } + + if ( status & TXSTATUS_EOF_SENT ) + info->icount.txok++; + else if ( status & TXSTATUS_UNDERRUN ) + info->icount.txunder++; + else if ( status & TXSTATUS_ABORT_SENT ) + info->icount.txabort++; + else + info->icount.txunder++; + + info->tx_active = false; + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + del_timer(&info->tx_timer); + + if ( info->drop_rts_on_tx_done ) { + usc_get_serial_signals( info ); + if ( info->serial_signals & SerialSignal_RTS ) { + info->serial_signals &= ~SerialSignal_RTS; + usc_set_serial_signals( info ); + } + info->drop_rts_on_tx_done = false; + } + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_tx_done(info); + else +#endif + { + if (info->port.tty->stopped || info->port.tty->hw_stopped) { + usc_stop_transmitter(info); + return; + } + info->pending_bh |= BH_TRANSMIT; + } + +} /* end of mgsl_isr_transmit_status() */ + +/* mgsl_isr_io_pin() + * + * Service an Input/Output pin interrupt. The type of + * interrupt is indicated by bits in the MISR + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_io_pin( struct mgsl_struct *info ) +{ + struct mgsl_icount *icount; + u16 status = usc_InReg( info, MISR ); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_io_pin status=%04X\n", + __FILE__,__LINE__,status); + + usc_ClearIrqPendingBits( info, IO_PIN ); + usc_UnlatchIostatusBits( info, status ); + + if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED | + MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) { + icount = &info->icount; + /* update input line counters */ + if (status & MISCSTATUS_RI_LATCHED) { + if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + usc_DisablestatusIrqs(info,SICR_RI); + icount->rng++; + if ( status & MISCSTATUS_RI ) + info->input_signal_events.ri_up++; + else + info->input_signal_events.ri_down++; + } + if (status & MISCSTATUS_DSR_LATCHED) { + if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + usc_DisablestatusIrqs(info,SICR_DSR); + icount->dsr++; + if ( status & MISCSTATUS_DSR ) + info->input_signal_events.dsr_up++; + else + info->input_signal_events.dsr_down++; + } + if (status & MISCSTATUS_DCD_LATCHED) { + if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + usc_DisablestatusIrqs(info,SICR_DCD); + icount->dcd++; + if (status & MISCSTATUS_DCD) { + info->input_signal_events.dcd_up++; + } else + info->input_signal_events.dcd_down++; +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) { + if (status & MISCSTATUS_DCD) + netif_carrier_on(info->netdev); + else + netif_carrier_off(info->netdev); + } +#endif + } + if (status & MISCSTATUS_CTS_LATCHED) + { + if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + usc_DisablestatusIrqs(info,SICR_CTS); + icount->cts++; + if ( status & MISCSTATUS_CTS ) + info->input_signal_events.cts_up++; + else + info->input_signal_events.cts_down++; + } + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + if ( (info->port.flags & ASYNC_CHECK_CD) && + (status & MISCSTATUS_DCD_LATCHED) ) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s CD now %s...", info->device_name, + (status & MISCSTATUS_DCD) ? "on" : "off"); + if (status & MISCSTATUS_DCD) + wake_up_interruptible(&info->port.open_wait); + else { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("doing serial hangup..."); + if (info->port.tty) + tty_hangup(info->port.tty); + } + } + + if ( (info->port.flags & ASYNC_CTS_FLOW) && + (status & MISCSTATUS_CTS_LATCHED) ) { + if (info->port.tty->hw_stopped) { + if (status & MISCSTATUS_CTS) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("CTS tx start..."); + if (info->port.tty) + info->port.tty->hw_stopped = 0; + usc_start_transmitter(info); + info->pending_bh |= BH_TRANSMIT; + return; + } + } else { + if (!(status & MISCSTATUS_CTS)) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("CTS tx stop..."); + if (info->port.tty) + info->port.tty->hw_stopped = 1; + usc_stop_transmitter(info); + } + } + } + } + + info->pending_bh |= BH_STATUS; + + /* for diagnostics set IRQ flag */ + if ( status & MISCSTATUS_TXC_LATCHED ){ + usc_OutReg( info, SICR, + (unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) ); + usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED ); + info->irq_occurred = true; + } + +} /* end of mgsl_isr_io_pin() */ + +/* mgsl_isr_transmit_data() + * + * Service a transmit data interrupt (async mode only). + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_transmit_data( struct mgsl_struct *info ) +{ + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n", + __FILE__,__LINE__,info->xmit_cnt); + + usc_ClearIrqPendingBits( info, TRANSMIT_DATA ); + + if (info->port.tty->stopped || info->port.tty->hw_stopped) { + usc_stop_transmitter(info); + return; + } + + if ( info->xmit_cnt ) + usc_load_txfifo( info ); + else + info->tx_active = false; + + if (info->xmit_cnt < WAKEUP_CHARS) + info->pending_bh |= BH_TRANSMIT; + +} /* end of mgsl_isr_transmit_data() */ + +/* mgsl_isr_receive_data() + * + * Service a receive data interrupt. This occurs + * when operating in asynchronous interrupt transfer mode. + * The receive data FIFO is flushed to the receive data buffers. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_receive_data( struct mgsl_struct *info ) +{ + int Fifocount; + u16 status; + int work = 0; + unsigned char DataByte; + struct tty_struct *tty = info->port.tty; + struct mgsl_icount *icount = &info->icount; + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_receive_data\n", + __FILE__,__LINE__); + + usc_ClearIrqPendingBits( info, RECEIVE_DATA ); + + /* select FIFO status for RICR readback */ + usc_RCmd( info, RCmd_SelectRicrRxFifostatus ); + + /* clear the Wordstatus bit so that status readback */ + /* only reflects the status of this byte */ + usc_OutReg( info, RICR+LSBONLY, (u16)(usc_InReg(info, RICR+LSBONLY) & ~BIT3 )); + + /* flush the receive FIFO */ + + while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) { + int flag; + + /* read one byte from RxFIFO */ + outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY), + info->io_base + CCAR ); + DataByte = inb( info->io_base + CCAR ); + + /* get the status of the received byte */ + status = usc_InReg(info, RCSR); + if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + + RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) + usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); + + icount->rx++; + + flag = 0; + if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + + RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) { + printk("rxerr=%04X\n",status); + /* update error statistics */ + if ( status & RXSTATUS_BREAK_RECEIVED ) { + status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR); + icount->brk++; + } else if (status & RXSTATUS_PARITY_ERROR) + icount->parity++; + else if (status & RXSTATUS_FRAMING_ERROR) + icount->frame++; + else if (status & RXSTATUS_OVERRUN) { + /* must issue purge fifo cmd before */ + /* 16C32 accepts more receive chars */ + usc_RTCmd(info,RTCmd_PurgeRxFifo); + icount->overrun++; + } + + /* discard char if tty control flags say so */ + if (status & info->ignore_status_mask) + continue; + + status &= info->read_status_mask; + + if (status & RXSTATUS_BREAK_RECEIVED) { + flag = TTY_BREAK; + if (info->port.flags & ASYNC_SAK) + do_SAK(tty); + } else if (status & RXSTATUS_PARITY_ERROR) + flag = TTY_PARITY; + else if (status & RXSTATUS_FRAMING_ERROR) + flag = TTY_FRAME; + } /* end of if (error) */ + tty_insert_flip_char(tty, DataByte, flag); + if (status & RXSTATUS_OVERRUN) { + /* Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + work += tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + } + + if ( debug_level >= DEBUG_LEVEL_ISR ) { + printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n", + __FILE__,__LINE__,icount->rx,icount->brk, + icount->parity,icount->frame,icount->overrun); + } + + if(work) + tty_flip_buffer_push(tty); +} + +/* mgsl_isr_misc() + * + * Service a miscellaneous interrupt source. + * + * Arguments: info pointer to device extension (instance data) + * Return Value: None + */ +static void mgsl_isr_misc( struct mgsl_struct *info ) +{ + u16 status = usc_InReg( info, MISR ); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_misc status=%04X\n", + __FILE__,__LINE__,status); + + if ((status & MISCSTATUS_RCC_UNDERRUN) && + (info->params.mode == MGSL_MODE_HDLC)) { + + /* turn off receiver and rx DMA */ + usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); + usc_DmaCmd(info, DmaCmd_ResetRxChannel); + usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); + usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS); + + /* schedule BH handler to restart receiver */ + info->pending_bh |= BH_RECEIVE; + info->rx_rcc_underrun = true; + } + + usc_ClearIrqPendingBits( info, MISC ); + usc_UnlatchMiscstatusBits( info, status ); + +} /* end of mgsl_isr_misc() */ + +/* mgsl_isr_null() + * + * Services undefined interrupt vectors from the + * USC. (hence this function SHOULD never be called) + * + * Arguments: info pointer to device extension (instance data) + * Return Value: None + */ +static void mgsl_isr_null( struct mgsl_struct *info ) +{ + +} /* end of mgsl_isr_null() */ + +/* mgsl_isr_receive_dma() + * + * Service a receive DMA channel interrupt. + * For this driver there are two sources of receive DMA interrupts + * as identified in the Receive DMA mode Register (RDMR): + * + * BIT3 EOA/EOL End of List, all receive buffers in receive + * buffer list have been filled (no more free buffers + * available). The DMA controller has shut down. + * + * BIT2 EOB End of Buffer. This interrupt occurs when a receive + * DMA buffer is terminated in response to completion + * of a good frame or a frame with errors. The status + * of the frame is stored in the buffer entry in the + * list of receive buffer entries. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_receive_dma( struct mgsl_struct *info ) +{ + u16 status; + + /* clear interrupt pending and IUS bit for Rx DMA IRQ */ + usc_OutDmaReg( info, CDIR, BIT9+BIT1 ); + + /* Read the receive DMA status to identify interrupt type. */ + /* This also clears the status bits. */ + status = usc_InDmaReg( info, RDMR ); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_receive_dma(%s) status=%04X\n", + __FILE__,__LINE__,info->device_name,status); + + info->pending_bh |= BH_RECEIVE; + + if ( status & BIT3 ) { + info->rx_overflow = true; + info->icount.buf_overrun++; + } + +} /* end of mgsl_isr_receive_dma() */ + +/* mgsl_isr_transmit_dma() + * + * This function services a transmit DMA channel interrupt. + * + * For this driver there is one source of transmit DMA interrupts + * as identified in the Transmit DMA Mode Register (TDMR): + * + * BIT2 EOB End of Buffer. This interrupt occurs when a + * transmit DMA buffer has been emptied. + * + * The driver maintains enough transmit DMA buffers to hold at least + * one max frame size transmit frame. When operating in a buffered + * transmit mode, there may be enough transmit DMA buffers to hold at + * least two or more max frame size frames. On an EOB condition, + * determine if there are any queued transmit buffers and copy into + * transmit DMA buffers if we have room. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_isr_transmit_dma( struct mgsl_struct *info ) +{ + u16 status; + + /* clear interrupt pending and IUS bit for Tx DMA IRQ */ + usc_OutDmaReg(info, CDIR, BIT8+BIT0 ); + + /* Read the transmit DMA status to identify interrupt type. */ + /* This also clears the status bits. */ + + status = usc_InDmaReg( info, TDMR ); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n", + __FILE__,__LINE__,info->device_name,status); + + if ( status & BIT2 ) { + --info->tx_dma_buffers_used; + + /* if there are transmit frames queued, + * try to load the next one + */ + if ( load_next_tx_holding_buffer(info) ) { + /* if call returns non-zero value, we have + * at least one free tx holding buffer + */ + info->pending_bh |= BH_TRANSMIT; + } + } + +} /* end of mgsl_isr_transmit_dma() */ + +/* mgsl_interrupt() + * + * Interrupt service routine entry point. + * + * Arguments: + * + * irq interrupt number that caused interrupt + * dev_id device ID supplied during interrupt registration + * + * Return Value: None + */ +static irqreturn_t mgsl_interrupt(int dummy, void *dev_id) +{ + struct mgsl_struct *info = dev_id; + u16 UscVector; + u16 DmaVector; + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n", + __FILE__, __LINE__, info->irq_level); + + spin_lock(&info->irq_spinlock); + + for(;;) { + /* Read the interrupt vectors from hardware. */ + UscVector = usc_InReg(info, IVR) >> 9; + DmaVector = usc_InDmaReg(info, DIVR); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s UscVector=%08X DmaVector=%08X\n", + __FILE__,__LINE__,info->device_name,UscVector,DmaVector); + + if ( !UscVector && !DmaVector ) + break; + + /* Dispatch interrupt vector */ + if ( UscVector ) + (*UscIsrTable[UscVector])(info); + else if ( (DmaVector&(BIT10|BIT9)) == BIT10) + mgsl_isr_transmit_dma(info); + else + mgsl_isr_receive_dma(info); + + if ( info->isr_overflow ) { + printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n", + __FILE__, __LINE__, info->device_name, info->irq_level); + usc_DisableMasterIrqBit(info); + usc_DisableDmaInterrupts(info,DICR_MASTER); + break; + } + } + + /* Request bottom half processing if there's something + * for it to do and the bh is not already running + */ + + if ( info->pending_bh && !info->bh_running && !info->bh_requested ) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s queueing bh task.\n", + __FILE__,__LINE__,info->device_name); + schedule_work(&info->task); + info->bh_requested = true; + } + + spin_unlock(&info->irq_spinlock); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n", + __FILE__, __LINE__, info->irq_level); + + return IRQ_HANDLED; +} /* end of mgsl_interrupt() */ + +/* startup() + * + * Initialize and start device. + * + * Arguments: info pointer to device instance data + * Return Value: 0 if success, otherwise error code + */ +static int startup(struct mgsl_struct * info) +{ + int retval = 0; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name); + + if (info->port.flags & ASYNC_INITIALIZED) + return 0; + + if (!info->xmit_buf) { + /* allocate a page of memory for a transmit buffer */ + info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); + if (!info->xmit_buf) { + printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", + __FILE__,__LINE__,info->device_name); + return -ENOMEM; + } + } + + info->pending_bh = 0; + + memset(&info->icount, 0, sizeof(info->icount)); + + setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info); + + /* Allocate and claim adapter resources */ + retval = mgsl_claim_resources(info); + + /* perform existence check and diagnostics */ + if ( !retval ) + retval = mgsl_adapter_test(info); + + if ( retval ) { + if (capable(CAP_SYS_ADMIN) && info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); + mgsl_release_resources(info); + return retval; + } + + /* program hardware for current parameters */ + mgsl_change_params(info); + + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); + + info->port.flags |= ASYNC_INITIALIZED; + + return 0; + +} /* end of startup() */ + +/* shutdown() + * + * Called by mgsl_close() and mgsl_hangup() to shutdown hardware + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void shutdown(struct mgsl_struct * info) +{ + unsigned long flags; + + if (!(info->port.flags & ASYNC_INITIALIZED)) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_shutdown(%s)\n", + __FILE__,__LINE__, info->device_name ); + + /* clear status wait queue because status changes */ + /* can't happen after shutting down the hardware */ + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + del_timer_sync(&info->tx_timer); + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = NULL; + } + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_DisableMasterIrqBit(info); + usc_stop_receiver(info); + usc_stop_transmitter(info); + usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS + + TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC ); + usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE); + + /* Disable DMAEN (Port 7, Bit 14) */ + /* This disconnects the DMA request signal from the ISA bus */ + /* on the ISA adapter. This has no effect for the PCI adapter */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14)); + + /* Disable INTEN (Port 6, Bit12) */ + /* This disconnects the IRQ request signal to the ISA bus */ + /* on the ISA adapter. This has no effect for the PCI adapter */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12)); + + if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { + info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + usc_set_serial_signals(info); + } + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + mgsl_release_resources(info); + + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); + + info->port.flags &= ~ASYNC_INITIALIZED; + +} /* end of shutdown() */ + +static void mgsl_program_hw(struct mgsl_struct *info) +{ + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + + usc_stop_receiver(info); + usc_stop_transmitter(info); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + if (info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW || + info->netcount) + usc_set_sync_mode(info); + else + usc_set_async_mode(info); + + usc_set_serial_signals(info); + + info->dcd_chkcount = 0; + info->cts_chkcount = 0; + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + + usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI); + usc_EnableInterrupts(info, IO_PIN); + usc_get_serial_signals(info); + + if (info->netcount || info->port.tty->termios->c_cflag & CREAD) + usc_start_receiver(info); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); +} + +/* Reconfigure adapter based on new parameters + */ +static void mgsl_change_params(struct mgsl_struct *info) +{ + unsigned cflag; + int bits_per_char; + + if (!info->port.tty || !info->port.tty->termios) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_change_params(%s)\n", + __FILE__,__LINE__, info->device_name ); + + cflag = info->port.tty->termios->c_cflag; + + /* if B0 rate (hangup) specified then negate DTR and RTS */ + /* otherwise assert DTR and RTS */ + if (cflag & CBAUD) + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + + /* byte size and parity */ + + switch (cflag & CSIZE) { + case CS5: info->params.data_bits = 5; break; + case CS6: info->params.data_bits = 6; break; + case CS7: info->params.data_bits = 7; break; + case CS8: info->params.data_bits = 8; break; + /* Never happens, but GCC is too dumb to figure it out */ + default: info->params.data_bits = 7; break; + } + + if (cflag & CSTOPB) + info->params.stop_bits = 2; + else + info->params.stop_bits = 1; + + info->params.parity = ASYNC_PARITY_NONE; + if (cflag & PARENB) { + if (cflag & PARODD) + info->params.parity = ASYNC_PARITY_ODD; + else + info->params.parity = ASYNC_PARITY_EVEN; +#ifdef CMSPAR + if (cflag & CMSPAR) + info->params.parity = ASYNC_PARITY_SPACE; +#endif + } + + /* calculate number of jiffies to transmit a full + * FIFO (32 bytes) at specified data rate + */ + bits_per_char = info->params.data_bits + + info->params.stop_bits + 1; + + /* if port data rate is set to 460800 or less then + * allow tty settings to override, otherwise keep the + * current data rate. + */ + if (info->params.data_rate <= 460800) + info->params.data_rate = tty_get_baud_rate(info->port.tty); + + if ( info->params.data_rate ) { + info->timeout = (32*HZ*bits_per_char) / + info->params.data_rate; + } + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + if (cflag & CRTSCTS) + info->port.flags |= ASYNC_CTS_FLOW; + else + info->port.flags &= ~ASYNC_CTS_FLOW; + + if (cflag & CLOCAL) + info->port.flags &= ~ASYNC_CHECK_CD; + else + info->port.flags |= ASYNC_CHECK_CD; + + /* process tty input control flags */ + + info->read_status_mask = RXSTATUS_OVERRUN; + if (I_INPCK(info->port.tty)) + info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; + if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) + info->read_status_mask |= RXSTATUS_BREAK_RECEIVED; + + if (I_IGNPAR(info->port.tty)) + info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; + if (I_IGNBRK(info->port.tty)) { + info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED; + /* If ignoring parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->port.tty)) + info->ignore_status_mask |= RXSTATUS_OVERRUN; + } + + mgsl_program_hw(info); + +} /* end of mgsl_change_params() */ + +/* mgsl_put_char() + * + * Add a character to the transmit buffer. + * + * Arguments: tty pointer to tty information structure + * ch character to add to transmit buffer + * + * Return Value: None + */ +static int mgsl_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + int ret = 0; + + if (debug_level >= DEBUG_LEVEL_INFO) { + printk(KERN_DEBUG "%s(%d):mgsl_put_char(%d) on %s\n", + __FILE__, __LINE__, ch, info->device_name); + } + + if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) + return 0; + + if (!info->xmit_buf) + return 0; + + spin_lock_irqsave(&info->irq_spinlock, flags); + + if ((info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active) { + if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) { + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE-1; + info->xmit_cnt++; + ret = 1; + } + } + spin_unlock_irqrestore(&info->irq_spinlock, flags); + return ret; + +} /* end of mgsl_put_char() */ + +/* mgsl_flush_chars() + * + * Enable transmitter so remaining characters in the + * transmit buffer are sent. + * + * Arguments: tty pointer to tty information structure + * Return Value: None + */ +static void mgsl_flush_chars(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n", + __FILE__,__LINE__,info->device_name,info->xmit_cnt); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n", + __FILE__,__LINE__,info->device_name ); + + spin_lock_irqsave(&info->irq_spinlock,flags); + + if (!info->tx_active) { + if ( (info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) { + /* operating in synchronous (frame oriented) mode */ + /* copy data from circular xmit_buf to */ + /* transmit DMA buffer. */ + mgsl_load_tx_dma_buffer(info, + info->xmit_buf,info->xmit_cnt); + } + usc_start_transmitter(info); + } + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + +} /* end of mgsl_flush_chars() */ + +/* mgsl_write() + * + * Send a block of data + * + * Arguments: + * + * tty pointer to tty information structure + * buf pointer to buffer containing send data + * count size of send data in bytes + * + * Return Value: number of characters written + */ +static int mgsl_write(struct tty_struct * tty, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_write(%s) count=%d\n", + __FILE__,__LINE__,info->device_name,count); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) + goto cleanup; + + if (!info->xmit_buf) + goto cleanup; + + if ( info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW ) { + /* operating in synchronous (frame oriented) mode */ + /* operating in synchronous (frame oriented) mode */ + if (info->tx_active) { + + if ( info->params.mode == MGSL_MODE_HDLC ) { + ret = 0; + goto cleanup; + } + /* transmitter is actively sending data - + * if we have multiple transmit dma and + * holding buffers, attempt to queue this + * frame for transmission at a later time. + */ + if (info->tx_holding_count >= info->num_tx_holding_buffers ) { + /* no tx holding buffers available */ + ret = 0; + goto cleanup; + } + + /* queue transmit frame request */ + ret = count; + save_tx_buffer_request(info,buf,count); + + /* if we have sufficient tx dma buffers, + * load the next buffered tx request + */ + spin_lock_irqsave(&info->irq_spinlock,flags); + load_next_tx_holding_buffer(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + goto cleanup; + } + + /* if operating in HDLC LoopMode and the adapter */ + /* has yet to be inserted into the loop, we can't */ + /* transmit */ + + if ( (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) && + !usc_loopmode_active(info) ) + { + ret = 0; + goto cleanup; + } + + if ( info->xmit_cnt ) { + /* Send accumulated from send_char() calls */ + /* as frame and wait before accepting more data. */ + ret = 0; + + /* copy data from circular xmit_buf to */ + /* transmit DMA buffer. */ + mgsl_load_tx_dma_buffer(info, + info->xmit_buf,info->xmit_cnt); + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_write(%s) sync xmit_cnt flushing\n", + __FILE__,__LINE__,info->device_name); + } else { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_write(%s) sync transmit accepted\n", + __FILE__,__LINE__,info->device_name); + ret = count; + info->xmit_cnt = count; + mgsl_load_tx_dma_buffer(info,buf,count); + } + } else { + while (1) { + spin_lock_irqsave(&info->irq_spinlock,flags); + c = min_t(int, count, + min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + spin_unlock_irqrestore(&info->irq_spinlock,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; + spin_unlock_irqrestore(&info->irq_spinlock,flags); + buf += c; + count -= c; + ret += c; + } + } + + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!info->tx_active) + usc_start_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } +cleanup: + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_write(%s) returning=%d\n", + __FILE__,__LINE__,info->device_name,ret); + + return ret; + +} /* end of mgsl_write() */ + +/* mgsl_write_room() + * + * Return the count of free bytes in transmit buffer + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static int mgsl_write_room(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + int ret; + + if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_write_room(%s)=%d\n", + __FILE__,__LINE__, info->device_name,ret ); + + if ( info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW ) { + /* operating in synchronous (frame oriented) mode */ + if ( info->tx_active ) + return 0; + else + return HDLC_MAX_FRAME_SIZE; + } + + return ret; + +} /* end of mgsl_write_room() */ + +/* mgsl_chars_in_buffer() + * + * Return the count of bytes in transmit buffer + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static int mgsl_chars_in_buffer(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_chars_in_buffer(%s)\n", + __FILE__,__LINE__, info->device_name ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_chars_in_buffer")) + return 0; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_chars_in_buffer(%s)=%d\n", + __FILE__,__LINE__, info->device_name,info->xmit_cnt ); + + if ( info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW ) { + /* operating in synchronous (frame oriented) mode */ + if ( info->tx_active ) + return info->max_frame_size; + else + return 0; + } + + return info->xmit_cnt; +} /* end of mgsl_chars_in_buffer() */ + +/* mgsl_flush_buffer() + * + * Discard all data in the send buffer + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static void mgsl_flush_buffer(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_flush_buffer(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_buffer")) + return; + + spin_lock_irqsave(&info->irq_spinlock,flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + del_timer(&info->tx_timer); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + tty_wakeup(tty); +} + +/* mgsl_send_xchar() + * + * Send a high-priority XON/XOFF character + * + * Arguments: tty pointer to tty info structure + * ch character to send + * Return Value: None + */ +static void mgsl_send_xchar(struct tty_struct *tty, char ch) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_send_xchar(%s,%d)\n", + __FILE__,__LINE__, info->device_name, ch ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_send_xchar")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!info->tx_enabled) + usc_start_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } +} /* end of mgsl_send_xchar() */ + +/* mgsl_throttle() + * + * Signal remote device to throttle send data (our receive data) + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static void mgsl_throttle(struct tty_struct * tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_throttle(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_throttle")) + return; + + if (I_IXOFF(tty)) + mgsl_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->irq_spinlock,flags); + info->serial_signals &= ~SerialSignal_RTS; + usc_set_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } +} /* end of mgsl_throttle() */ + +/* mgsl_unthrottle() + * + * Signal remote device to stop throttling send data (our receive data) + * + * Arguments: tty pointer to tty info structure + * Return Value: None + */ +static void mgsl_unthrottle(struct tty_struct * tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_unthrottle(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + mgsl_send_xchar(tty, START_CHAR(tty)); + } + + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->irq_spinlock,flags); + info->serial_signals |= SerialSignal_RTS; + usc_set_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + +} /* end of mgsl_unthrottle() */ + +/* mgsl_get_stats() + * + * get the current serial parameters information + * + * Arguments: info pointer to device instance data + * user_icount pointer to buffer to hold returned stats + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount) +{ + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_get_params(%s)\n", + __FILE__,__LINE__, info->device_name); + + if (!user_icount) { + memset(&info->icount, 0, sizeof(info->icount)); + } else { + mutex_lock(&info->port.mutex); + COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); + mutex_unlock(&info->port.mutex); + if (err) + return -EFAULT; + } + + return 0; + +} /* end of mgsl_get_stats() */ + +/* mgsl_get_params() + * + * get the current serial parameters information + * + * Arguments: info pointer to device instance data + * user_params pointer to buffer to hold returned params + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params) +{ + int err; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_get_params(%s)\n", + __FILE__,__LINE__, info->device_name); + + mutex_lock(&info->port.mutex); + COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); + mutex_unlock(&info->port.mutex); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + return 0; + +} /* end of mgsl_get_params() */ + +/* mgsl_set_params() + * + * set the serial parameters + * + * Arguments: + * + * info pointer to device instance data + * new_params user buffer containing new serial params + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params) +{ + unsigned long flags; + MGSL_PARAMS tmp_params; + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_set_params %s\n", __FILE__,__LINE__, + info->device_name ); + COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_set_params(%s) user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + mutex_lock(&info->port.mutex); + spin_lock_irqsave(&info->irq_spinlock,flags); + memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + mgsl_change_params(info); + mutex_unlock(&info->port.mutex); + + return 0; + +} /* end of mgsl_set_params() */ + +/* mgsl_get_txidle() + * + * get the current transmit idle mode + * + * Arguments: info pointer to device instance data + * idle_mode pointer to buffer to hold returned idle mode + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode) +{ + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_get_txidle(%s)=%d\n", + __FILE__,__LINE__, info->device_name, info->idle_mode); + + COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int)); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_get_txidle(%s) user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + return 0; + +} /* end of mgsl_get_txidle() */ + +/* mgsl_set_txidle() service ioctl to set transmit idle mode + * + * Arguments: info pointer to device instance data + * idle_mode new idle mode + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_set_txidle(%s,%d)\n", __FILE__,__LINE__, + info->device_name, idle_mode ); + + spin_lock_irqsave(&info->irq_spinlock,flags); + info->idle_mode = idle_mode; + usc_set_txidle( info ); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return 0; + +} /* end of mgsl_set_txidle() */ + +/* mgsl_txenable() + * + * enable or disable the transmitter + * + * Arguments: + * + * info pointer to device instance data + * enable 1 = enable, 0 = disable + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_txenable(struct mgsl_struct * info, int enable) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_txenable(%s,%d)\n", __FILE__,__LINE__, + info->device_name, enable); + + spin_lock_irqsave(&info->irq_spinlock,flags); + if ( enable ) { + if ( !info->tx_enabled ) { + + usc_start_transmitter(info); + /*-------------------------------------------------- + * if HDLC/SDLC Loop mode, attempt to insert the + * station in the 'loop' by setting CMR:13. Upon + * receipt of the next GoAhead (RxAbort) sequence, + * the OnLoop indicator (CCSR:7) should go active + * to indicate that we are on the loop + *--------------------------------------------------*/ + if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) + usc_loopmode_insert_request( info ); + } + } else { + if ( info->tx_enabled ) + usc_stop_transmitter(info); + } + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return 0; + +} /* end of mgsl_txenable() */ + +/* mgsl_txabort() abort send HDLC frame + * + * Arguments: info pointer to device instance data + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_txabort(struct mgsl_struct * info) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_txabort(%s)\n", __FILE__,__LINE__, + info->device_name); + + spin_lock_irqsave(&info->irq_spinlock,flags); + if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) + { + if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) + usc_loopmode_cancel_transmit( info ); + else + usc_TCmd(info,TCmd_SendAbort); + } + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return 0; + +} /* end of mgsl_txabort() */ + +/* mgsl_rxenable() enable or disable the receiver + * + * Arguments: info pointer to device instance data + * enable 1 = enable, 0 = disable + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_rxenable(struct mgsl_struct * info, int enable) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_rxenable(%s,%d)\n", __FILE__,__LINE__, + info->device_name, enable); + + spin_lock_irqsave(&info->irq_spinlock,flags); + if ( enable ) { + if ( !info->rx_enabled ) + usc_start_receiver(info); + } else { + if ( info->rx_enabled ) + usc_stop_receiver(info); + } + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return 0; + +} /* end of mgsl_rxenable() */ + +/* mgsl_wait_event() wait for specified event to occur + * + * Arguments: info pointer to device instance data + * mask pointer to bitmask of events to wait for + * Return Value: 0 if successful and bit mask updated with + * of events triggerred, + * otherwise error code + */ +static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr) +{ + unsigned long flags; + int s; + int rc=0; + struct mgsl_icount cprev, cnow; + int events; + int mask; + struct _input_signal_events oldsigs, newsigs; + DECLARE_WAITQUEUE(wait, current); + + COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int)); + if (rc) { + return -EFAULT; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_wait_event(%s,%d)\n", __FILE__,__LINE__, + info->device_name, mask); + + spin_lock_irqsave(&info->irq_spinlock,flags); + + /* return immediately if state matches requested events */ + usc_get_serial_signals(info); + s = info->serial_signals; + events = mask & + ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + + ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + + ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + + ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); + if (events) { + spin_unlock_irqrestore(&info->irq_spinlock,flags); + goto exit; + } + + /* save current irq counts */ + cprev = info->icount; + oldsigs = info->input_signal_events; + + /* enable hunt and idle irqs if needed */ + if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { + u16 oldreg = usc_InReg(info,RICR); + u16 newreg = oldreg + + (mask & MgslEvent_ExitHuntMode ? RXSTATUS_EXITED_HUNT:0) + + (mask & MgslEvent_IdleReceived ? RXSTATUS_IDLE_RECEIVED:0); + if (oldreg != newreg) + usc_OutReg(info, RICR, newreg); + } + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&info->event_wait_q, &wait); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get current irq counts */ + spin_lock_irqsave(&info->irq_spinlock,flags); + cnow = info->icount; + newsigs = info->input_signal_events; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + /* if no change, wait aborted for some reason */ + if (newsigs.dsr_up == oldsigs.dsr_up && + newsigs.dsr_down == oldsigs.dsr_down && + newsigs.dcd_up == oldsigs.dcd_up && + newsigs.dcd_down == oldsigs.dcd_down && + newsigs.cts_up == oldsigs.cts_up && + newsigs.cts_down == oldsigs.cts_down && + newsigs.ri_up == oldsigs.ri_up && + newsigs.ri_down == oldsigs.ri_down && + cnow.exithunt == cprev.exithunt && + cnow.rxidle == cprev.rxidle) { + rc = -EIO; + break; + } + + events = mask & + ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + + (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + + (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + + (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + + (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + + (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + + (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + + (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + + (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + + (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); + if (events) + break; + + cprev = cnow; + oldsigs = newsigs; + } + + remove_wait_queue(&info->event_wait_q, &wait); + set_current_state(TASK_RUNNING); + + if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!waitqueue_active(&info->event_wait_q)) { + /* disable enable exit hunt mode/idle rcvd IRQs */ + usc_OutReg(info, RICR, usc_InReg(info,RICR) & + ~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)); + } + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } +exit: + if ( rc == 0 ) + PUT_USER(rc, events, mask_ptr); + + return rc; + +} /* end of mgsl_wait_event() */ + +static int modem_input_wait(struct mgsl_struct *info,int arg) +{ + unsigned long flags; + int rc; + struct mgsl_icount cprev, cnow; + DECLARE_WAITQUEUE(wait, current); + + /* save current irq counts */ + spin_lock_irqsave(&info->irq_spinlock,flags); + cprev = info->icount; + add_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get new irq counts */ + spin_lock_irqsave(&info->irq_spinlock,flags); + cnow = info->icount; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + /* if no change, wait aborted for some reason */ + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + rc = -EIO; + break; + } + + /* check for change in caller specified modem input */ + if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || + (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || + (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || + (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { + rc = 0; + break; + } + + cprev = cnow; + } + remove_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_RUNNING); + return rc; +} + +/* return the state of the serial control and status signals + */ +static int tiocmget(struct tty_struct *tty) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned int result; + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_get_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) + + ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) + + ((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) + + ((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) + + ((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) + + ((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0); + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s tiocmget() value=%08X\n", + __FILE__,__LINE__, info->device_name, result ); + return result; +} + +/* set modem control signals (DTR/RTS) + */ +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s tiocmset(%x,%x)\n", + __FILE__,__LINE__,info->device_name, set, clear); + + if (set & TIOCM_RTS) + info->serial_signals |= SerialSignal_RTS; + if (set & TIOCM_DTR) + info->serial_signals |= SerialSignal_DTR; + if (clear & TIOCM_RTS) + info->serial_signals &= ~SerialSignal_RTS; + if (clear & TIOCM_DTR) + info->serial_signals &= ~SerialSignal_DTR; + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_set_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return 0; +} + +/* mgsl_break() Set or clear transmit break condition + * + * Arguments: tty pointer to tty instance data + * break_state -1=set break condition, 0=clear + * Return Value: error code + */ +static int mgsl_break(struct tty_struct *tty, int break_state) +{ + struct mgsl_struct * info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_break(%s,%d)\n", + __FILE__,__LINE__, info->device_name, break_state); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) + return -EINVAL; + + spin_lock_irqsave(&info->irq_spinlock,flags); + if (break_state == -1) + usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) | BIT7)); + else + usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return 0; + +} /* end of mgsl_break() */ + +/* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +static int msgl_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) + +{ + struct mgsl_struct * info = tty->driver_data; + struct mgsl_icount cnow; /* kernel counter temps */ + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->frame = cnow.frame; + icount->overrun = cnow.overrun; + icount->parity = cnow.parity; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + return 0; +} + +/* mgsl_ioctl() Service an IOCTL request + * + * Arguments: + * + * tty pointer to tty instance data + * cmd IOCTL command code + * arg command argument/context + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct mgsl_struct * info = tty->driver_data; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, + info->device_name, cmd ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + return mgsl_ioctl_common(info, cmd, arg); +} + +static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + + switch (cmd) { + case MGSL_IOCGPARAMS: + return mgsl_get_params(info, argp); + case MGSL_IOCSPARAMS: + return mgsl_set_params(info, argp); + case MGSL_IOCGTXIDLE: + return mgsl_get_txidle(info, argp); + case MGSL_IOCSTXIDLE: + return mgsl_set_txidle(info,(int)arg); + case MGSL_IOCTXENABLE: + return mgsl_txenable(info,(int)arg); + case MGSL_IOCRXENABLE: + return mgsl_rxenable(info,(int)arg); + case MGSL_IOCTXABORT: + return mgsl_txabort(info); + case MGSL_IOCGSTATS: + return mgsl_get_stats(info, argp); + case MGSL_IOCWAITEVENT: + return mgsl_wait_event(info, argp); + case MGSL_IOCLOOPTXDONE: + return mgsl_loopmode_send_done(info); + /* Wait for modem input (DCD,RI,DSR,CTS) change + * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS) + */ + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* mgsl_set_termios() + * + * Set new termios settings + * + * Arguments: + * + * tty pointer to tty structure + * termios pointer to buffer to hold returned old termios + * + * Return Value: None + */ +static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct mgsl_struct *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__, + tty->driver->name ); + + mgsl_change_params(info); + + /* Handle transition to B0 status */ + if (old_termios->c_cflag & CBAUD && + !(tty->termios->c_cflag & CBAUD)) { + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_set_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + tty->termios->c_cflag & CBAUD) { + info->serial_signals |= SerialSignal_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->serial_signals |= SerialSignal_RTS; + } + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_set_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + + /* Handle turning off CRTSCTS */ + if (old_termios->c_cflag & CRTSCTS && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mgsl_start(tty); + } + +} /* end of mgsl_set_termios() */ + +/* mgsl_close() + * + * Called when port is closed. Wait for remaining data to be + * sent. Disable port and free resources. + * + * Arguments: + * + * tty pointer to open tty structure + * filp pointer to open file object + * + * Return Value: None + */ +static void mgsl_close(struct tty_struct *tty, struct file * filp) +{ + struct mgsl_struct * info = tty->driver_data; + + if (mgsl_paranoia_check(info, tty->name, "mgsl_close")) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_close(%s) entry, count=%d\n", + __FILE__,__LINE__, info->device_name, info->port.count); + + if (tty_port_close_start(&info->port, tty, filp) == 0) + goto cleanup; + + mutex_lock(&info->port.mutex); + if (info->port.flags & ASYNC_INITIALIZED) + mgsl_wait_until_sent(tty, info->timeout); + mgsl_flush_buffer(tty); + tty_ldisc_flush(tty); + shutdown(info); + mutex_unlock(&info->port.mutex); + + tty_port_close_end(&info->port, tty); + info->port.tty = NULL; +cleanup: + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, + tty->driver->name, info->port.count); + +} /* end of mgsl_close() */ + +/* mgsl_wait_until_sent() + * + * Wait until the transmitter is empty. + * + * Arguments: + * + * tty pointer to tty info structure + * timeout time to wait for send completion + * + * Return Value: None + */ +static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct mgsl_struct * info = tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (!info ) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_wait_until_sent(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_wait_until_sent")) + return; + + if (!(info->port.flags & ASYNC_INITIALIZED)) + goto exit; + + orig_jiffies = jiffies; + + /* Set check interval to 1/5 of estimated time to + * send a character, and make it at least 1. The check + * interval should also be less than the timeout. + * Note: use tight timings here to satisfy the NIST-PCTS. + */ + + if ( info->params.data_rate ) { + char_time = info->timeout/(32 * 5); + if (!char_time) + char_time++; + } else + char_time = 1; + + if (timeout) + char_time = min_t(unsigned long, char_time, timeout); + + if ( info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW ) { + while (info->tx_active) { + msleep_interruptible(jiffies_to_msecs(char_time)); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + } else { + while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) && + info->tx_enabled) { + msleep_interruptible(jiffies_to_msecs(char_time)); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + } + +exit: + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_wait_until_sent(%s) exit\n", + __FILE__,__LINE__, info->device_name ); + +} /* end of mgsl_wait_until_sent() */ + +/* mgsl_hangup() + * + * Called by tty_hangup() when a hangup is signaled. + * This is the same as to closing all open files for the port. + * + * Arguments: tty pointer to associated tty object + * Return Value: None + */ +static void mgsl_hangup(struct tty_struct *tty) +{ + struct mgsl_struct * info = tty->driver_data; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_hangup(%s)\n", + __FILE__,__LINE__, info->device_name ); + + if (mgsl_paranoia_check(info, tty->name, "mgsl_hangup")) + return; + + mgsl_flush_buffer(tty); + shutdown(info); + + info->port.count = 0; + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; + info->port.tty = NULL; + + wake_up_interruptible(&info->port.open_wait); + +} /* end of mgsl_hangup() */ + +/* + * carrier_raised() + * + * Return true if carrier is raised + */ + +static int carrier_raised(struct tty_port *port) +{ + unsigned long flags; + struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); + + spin_lock_irqsave(&info->irq_spinlock, flags); + usc_get_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock, flags); + return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; +} + +static void dtr_rts(struct tty_port *port, int on) +{ + struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + if (on) + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + usc_set_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); +} + + +/* block_til_ready() + * + * Block the current process until the specified port + * is ready to be opened. + * + * Arguments: + * + * tty pointer to tty info structure + * filp pointer to open file object + * info pointer to device instance data + * + * Return Value: 0 if success, otherwise error code + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct mgsl_struct *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + bool do_clocal = false; + bool extra_count = false; + unsigned long flags; + int dcd; + struct tty_port *port = &info->port; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready on %s\n", + __FILE__,__LINE__, tty->driver->name ); + + if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ + /* nonblock mode is set or port is not enabled */ + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = true; + + /* Wait for carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, port->count is dropped by one, so that + * mgsl_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + + retval = 0; + add_wait_queue(&port->open_wait, &wait); + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready before block on %s count=%d\n", + __FILE__,__LINE__, tty->driver->name, port->count ); + + spin_lock_irqsave(&info->irq_spinlock, flags); + if (!tty_hung_up_p(filp)) { + extra_count = true; + port->count--; + } + spin_unlock_irqrestore(&info->irq_spinlock, flags); + port->blocked_open++; + + while (1) { + if (tty->termios->c_cflag & CBAUD) + tty_port_raise_dtr_rts(port); + + set_current_state(TASK_INTERRUPTIBLE); + + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ + retval = (port->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS; + break; + } + + dcd = tty_port_carrier_raised(&info->port); + + if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd)) + break; + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready blocking on %s count=%d\n", + __FILE__,__LINE__, tty->driver->name, port->count ); + + tty_unlock(); + schedule(); + tty_lock(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + + /* FIXME: Racy on hangup during close wait */ + if (extra_count) + port->count++; + port->blocked_open--; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready after blocking on %s count=%d\n", + __FILE__,__LINE__, tty->driver->name, port->count ); + + if (!retval) + port->flags |= ASYNC_NORMAL_ACTIVE; + + return retval; + +} /* end of block_til_ready() */ + +/* mgsl_open() + * + * Called when a port is opened. Init and enable port. + * Perform serial-specific initialization for the tty structure. + * + * Arguments: tty pointer to tty info structure + * filp associated file pointer + * + * Return Value: 0 if success, otherwise error code + */ +static int mgsl_open(struct tty_struct *tty, struct file * filp) +{ + struct mgsl_struct *info; + int retval, line; + unsigned long flags; + + /* verify range of specified line number */ + line = tty->index; + if ((line < 0) || (line >= mgsl_device_count)) { + printk("%s(%d):mgsl_open with invalid line #%d.\n", + __FILE__,__LINE__,line); + return -ENODEV; + } + + /* find the info structure for the specified line */ + info = mgsl_device_list; + while(info && info->line != line) + info = info->next_device; + if (mgsl_paranoia_check(info, tty->name, "mgsl_open")) + return -ENODEV; + + tty->driver_data = info; + info->port.tty = tty; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_open(%s), old ref count = %d\n", + __FILE__,__LINE__,tty->driver->name, info->port.count); + + /* If port is closing, signal caller to try again */ + if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ + if (info->port.flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->port.close_wait); + retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + goto cleanup; + } + + info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + spin_lock_irqsave(&info->netlock, flags); + if (info->netcount) { + retval = -EBUSY; + spin_unlock_irqrestore(&info->netlock, flags); + goto cleanup; + } + info->port.count++; + spin_unlock_irqrestore(&info->netlock, flags); + + if (info->port.count == 1) { + /* 1st open on this device, init hardware */ + retval = startup(info); + if (retval < 0) + goto cleanup; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready(%s) returned %d\n", + __FILE__,__LINE__, info->device_name, retval); + goto cleanup; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgsl_open(%s) success\n", + __FILE__,__LINE__, info->device_name); + retval = 0; + +cleanup: + if (retval) { + if (tty->count == 1) + info->port.tty = NULL; /* tty layer will release tty struct */ + if(info->port.count) + info->port.count--; + } + + return retval; + +} /* end of mgsl_open() */ + +/* + * /proc fs routines.... + */ + +static inline void line_info(struct seq_file *m, struct mgsl_struct *info) +{ + char stat_buf[30]; + unsigned long flags; + + if (info->bus_type == MGSL_BUS_TYPE_PCI) { + seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", + info->device_name, info->io_base, info->irq_level, + info->phys_memory_base, info->phys_lcr_base); + } else { + seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", + info->device_name, info->io_base, + info->irq_level, info->dma_level); + } + + /* output current serial signal states */ + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_get_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (info->serial_signals & SerialSignal_RTS) + strcat(stat_buf, "|RTS"); + if (info->serial_signals & SerialSignal_CTS) + strcat(stat_buf, "|CTS"); + if (info->serial_signals & SerialSignal_DTR) + strcat(stat_buf, "|DTR"); + if (info->serial_signals & SerialSignal_DSR) + strcat(stat_buf, "|DSR"); + if (info->serial_signals & SerialSignal_DCD) + strcat(stat_buf, "|CD"); + if (info->serial_signals & SerialSignal_RI) + strcat(stat_buf, "|RI"); + + if (info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW ) { + seq_printf(m, " HDLC txok:%d rxok:%d", + info->icount.txok, info->icount.rxok); + if (info->icount.txunder) + seq_printf(m, " txunder:%d", info->icount.txunder); + if (info->icount.txabort) + seq_printf(m, " txabort:%d", info->icount.txabort); + if (info->icount.rxshort) + seq_printf(m, " rxshort:%d", info->icount.rxshort); + if (info->icount.rxlong) + seq_printf(m, " rxlong:%d", info->icount.rxlong); + if (info->icount.rxover) + seq_printf(m, " rxover:%d", info->icount.rxover); + if (info->icount.rxcrc) + seq_printf(m, " rxcrc:%d", info->icount.rxcrc); + } else { + seq_printf(m, " ASYNC tx:%d rx:%d", + info->icount.tx, info->icount.rx); + if (info->icount.frame) + seq_printf(m, " fe:%d", info->icount.frame); + if (info->icount.parity) + seq_printf(m, " pe:%d", info->icount.parity); + if (info->icount.brk) + seq_printf(m, " brk:%d", info->icount.brk); + if (info->icount.overrun) + seq_printf(m, " oe:%d", info->icount.overrun); + } + + /* Append serial signal status to end */ + seq_printf(m, " %s\n", stat_buf+1); + + seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", + info->tx_active,info->bh_requested,info->bh_running, + info->pending_bh); + + spin_lock_irqsave(&info->irq_spinlock,flags); + { + u16 Tcsr = usc_InReg( info, TCSR ); + u16 Tdmr = usc_InDmaReg( info, TDMR ); + u16 Ticr = usc_InReg( info, TICR ); + u16 Rscr = usc_InReg( info, RCSR ); + u16 Rdmr = usc_InDmaReg( info, RDMR ); + u16 Ricr = usc_InReg( info, RICR ); + u16 Icr = usc_InReg( info, ICR ); + u16 Dccr = usc_InReg( info, DCCR ); + u16 Tmr = usc_InReg( info, TMR ); + u16 Tccr = usc_InReg( info, TCCR ); + u16 Ccar = inw( info->io_base + CCAR ); + seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" + "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", + Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); + } + spin_unlock_irqrestore(&info->irq_spinlock,flags); +} + +/* Called to print information about devices */ +static int mgsl_proc_show(struct seq_file *m, void *v) +{ + struct mgsl_struct *info; + + seq_printf(m, "synclink driver:%s\n", driver_version); + + info = mgsl_device_list; + while( info ) { + line_info(m, info); + info = info->next_device; + } + return 0; +} + +static int mgsl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mgsl_proc_show, NULL); +} + +static const struct file_operations mgsl_proc_fops = { + .owner = THIS_MODULE, + .open = mgsl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* mgsl_allocate_dma_buffers() + * + * Allocate and format DMA buffers (ISA adapter) + * or format shared memory buffers (PCI adapter). + * + * Arguments: info pointer to device instance data + * Return Value: 0 if success, otherwise error + */ +static int mgsl_allocate_dma_buffers(struct mgsl_struct *info) +{ + unsigned short BuffersPerFrame; + + info->last_mem_alloc = 0; + + /* Calculate the number of DMA buffers necessary to hold the */ + /* largest allowable frame size. Note: If the max frame size is */ + /* not an even multiple of the DMA buffer size then we need to */ + /* round the buffer count per frame up one. */ + + BuffersPerFrame = (unsigned short)(info->max_frame_size/DMABUFFERSIZE); + if ( info->max_frame_size % DMABUFFERSIZE ) + BuffersPerFrame++; + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + /* + * The PCI adapter has 256KBytes of shared memory to use. + * This is 64 PAGE_SIZE buffers. + * + * The first page is used for padding at this time so the + * buffer list does not begin at offset 0 of the PCI + * adapter's shared memory. + * + * The 2nd page is used for the buffer list. A 4K buffer + * list can hold 128 DMA_BUFFER structures at 32 bytes + * each. + * + * This leaves 62 4K pages. + * + * The next N pages are used for transmit frame(s). We + * reserve enough 4K page blocks to hold the required + * number of transmit dma buffers (num_tx_dma_buffers), + * each of MaxFrameSize size. + * + * Of the remaining pages (62-N), determine how many can + * be used to receive full MaxFrameSize inbound frames + */ + info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; + info->rx_buffer_count = 62 - info->tx_buffer_count; + } else { + /* Calculate the number of PAGE_SIZE buffers needed for */ + /* receive and transmit DMA buffers. */ + + + /* Calculate the number of DMA buffers necessary to */ + /* hold 7 max size receive frames and one max size transmit frame. */ + /* The receive buffer count is bumped by one so we avoid an */ + /* End of List condition if all receive buffers are used when */ + /* using linked list DMA buffers. */ + + info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; + info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6; + + /* + * limit total TxBuffers & RxBuffers to 62 4K total + * (ala PCI Allocation) + */ + + if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 ) + info->rx_buffer_count = 62 - info->tx_buffer_count; + + } + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n", + __FILE__,__LINE__, info->tx_buffer_count,info->rx_buffer_count); + + if ( mgsl_alloc_buffer_list_memory( info ) < 0 || + mgsl_alloc_frame_memory(info, info->rx_buffer_list, info->rx_buffer_count) < 0 || + mgsl_alloc_frame_memory(info, info->tx_buffer_list, info->tx_buffer_count) < 0 || + mgsl_alloc_intermediate_rxbuffer_memory(info) < 0 || + mgsl_alloc_intermediate_txbuffer_memory(info) < 0 ) { + printk("%s(%d):Can't allocate DMA buffer memory\n",__FILE__,__LINE__); + return -ENOMEM; + } + + mgsl_reset_rx_dma_buffers( info ); + mgsl_reset_tx_dma_buffers( info ); + + return 0; + +} /* end of mgsl_allocate_dma_buffers() */ + +/* + * mgsl_alloc_buffer_list_memory() + * + * Allocate a common DMA buffer for use as the + * receive and transmit buffer lists. + * + * A buffer list is a set of buffer entries where each entry contains + * a pointer to an actual buffer and a pointer to the next buffer entry + * (plus some other info about the buffer). + * + * The buffer entries for a list are built to form a circular list so + * that when the entire list has been traversed you start back at the + * beginning. + * + * This function allocates memory for just the buffer entries. + * The links (pointer to next entry) are filled in with the physical + * address of the next entry so the adapter can navigate the list + * using bus master DMA. The pointers to the actual buffers are filled + * out later when the actual buffers are allocated. + * + * Arguments: info pointer to device instance data + * Return Value: 0 if success, otherwise error + */ +static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) +{ + unsigned int i; + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + /* PCI adapter uses shared memory. */ + info->buffer_list = info->memory_base + info->last_mem_alloc; + info->buffer_list_phys = info->last_mem_alloc; + info->last_mem_alloc += BUFFERLISTSIZE; + } else { + /* ISA adapter uses system memory. */ + /* The buffer lists are allocated as a common buffer that both */ + /* the processor and adapter can access. This allows the driver to */ + /* inspect portions of the buffer while other portions are being */ + /* updated by the adapter using Bus Master DMA. */ + + info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); + if (info->buffer_list == NULL) + return -ENOMEM; + info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); + } + + /* We got the memory for the buffer entry lists. */ + /* Initialize the memory block to all zeros. */ + memset( info->buffer_list, 0, BUFFERLISTSIZE ); + + /* Save virtual address pointers to the receive and */ + /* transmit buffer lists. (Receive 1st). These pointers will */ + /* be used by the processor to access the lists. */ + info->rx_buffer_list = (DMABUFFERENTRY *)info->buffer_list; + info->tx_buffer_list = (DMABUFFERENTRY *)info->buffer_list; + info->tx_buffer_list += info->rx_buffer_count; + + /* + * Build the links for the buffer entry lists such that + * two circular lists are built. (Transmit and Receive). + * + * Note: the links are physical addresses + * which are read by the adapter to determine the next + * buffer entry to use. + */ + + for ( i = 0; i < info->rx_buffer_count; i++ ) { + /* calculate and store physical address of this buffer entry */ + info->rx_buffer_list[i].phys_entry = + info->buffer_list_phys + (i * sizeof(DMABUFFERENTRY)); + + /* calculate and store physical address of */ + /* next entry in cirular list of entries */ + + info->rx_buffer_list[i].link = info->buffer_list_phys; + + if ( i < info->rx_buffer_count - 1 ) + info->rx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY); + } + + for ( i = 0; i < info->tx_buffer_count; i++ ) { + /* calculate and store physical address of this buffer entry */ + info->tx_buffer_list[i].phys_entry = info->buffer_list_phys + + ((info->rx_buffer_count + i) * sizeof(DMABUFFERENTRY)); + + /* calculate and store physical address of */ + /* next entry in cirular list of entries */ + + info->tx_buffer_list[i].link = info->buffer_list_phys + + info->rx_buffer_count * sizeof(DMABUFFERENTRY); + + if ( i < info->tx_buffer_count - 1 ) + info->tx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY); + } + + return 0; + +} /* end of mgsl_alloc_buffer_list_memory() */ + +/* Free DMA buffers allocated for use as the + * receive and transmit buffer lists. + * Warning: + * + * The data transfer buffers associated with the buffer list + * MUST be freed before freeing the buffer list itself because + * the buffer list contains the information necessary to free + * the individual buffers! + */ +static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) +{ + if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) + dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); + + info->buffer_list = NULL; + info->rx_buffer_list = NULL; + info->tx_buffer_list = NULL; + +} /* end of mgsl_free_buffer_list_memory() */ + +/* + * mgsl_alloc_frame_memory() + * + * Allocate the frame DMA buffers used by the specified buffer list. + * Each DMA buffer will be one memory page in size. This is necessary + * because memory can fragment enough that it may be impossible + * contiguous pages. + * + * Arguments: + * + * info pointer to device instance data + * BufferList pointer to list of buffer entries + * Buffercount count of buffer entries in buffer list + * + * Return Value: 0 if success, otherwise -ENOMEM + */ +static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) +{ + int i; + u32 phys_addr; + + /* Allocate page sized buffers for the receive buffer list */ + + for ( i = 0; i < Buffercount; i++ ) { + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + /* PCI adapter uses shared memory buffers. */ + BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; + phys_addr = info->last_mem_alloc; + info->last_mem_alloc += DMABUFFERSIZE; + } else { + /* ISA adapter uses system memory. */ + BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); + if (BufferList[i].virt_addr == NULL) + return -ENOMEM; + phys_addr = (u32)(BufferList[i].dma_addr); + } + BufferList[i].phys_addr = phys_addr; + } + + return 0; + +} /* end of mgsl_alloc_frame_memory() */ + +/* + * mgsl_free_frame_memory() + * + * Free the buffers associated with + * each buffer entry of a buffer list. + * + * Arguments: + * + * info pointer to device instance data + * BufferList pointer to list of buffer entries + * Buffercount count of buffer entries in buffer list + * + * Return Value: None + */ +static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount) +{ + int i; + + if ( BufferList ) { + for ( i = 0 ; i < Buffercount ; i++ ) { + if ( BufferList[i].virt_addr ) { + if ( info->bus_type != MGSL_BUS_TYPE_PCI ) + dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); + BufferList[i].virt_addr = NULL; + } + } + } + +} /* end of mgsl_free_frame_memory() */ + +/* mgsl_free_dma_buffers() + * + * Free DMA buffers + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_free_dma_buffers( struct mgsl_struct *info ) +{ + mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count ); + mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count ); + mgsl_free_buffer_list_memory( info ); + +} /* end of mgsl_free_dma_buffers() */ + + +/* + * mgsl_alloc_intermediate_rxbuffer_memory() + * + * Allocate a buffer large enough to hold max_frame_size. This buffer + * is used to pass an assembled frame to the line discipline. + * + * Arguments: + * + * info pointer to device instance data + * + * Return Value: 0 if success, otherwise -ENOMEM + */ +static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) +{ + info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA); + if ( info->intermediate_rxbuffer == NULL ) + return -ENOMEM; + + return 0; + +} /* end of mgsl_alloc_intermediate_rxbuffer_memory() */ + +/* + * mgsl_free_intermediate_rxbuffer_memory() + * + * + * Arguments: + * + * info pointer to device instance data + * + * Return Value: None + */ +static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) +{ + kfree(info->intermediate_rxbuffer); + info->intermediate_rxbuffer = NULL; + +} /* end of mgsl_free_intermediate_rxbuffer_memory() */ + +/* + * mgsl_alloc_intermediate_txbuffer_memory() + * + * Allocate intermdiate transmit buffer(s) large enough to hold max_frame_size. + * This buffer is used to load transmit frames into the adapter's dma transfer + * buffers when there is sufficient space. + * + * Arguments: + * + * info pointer to device instance data + * + * Return Value: 0 if success, otherwise -ENOMEM + */ +static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) +{ + int i; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s %s(%d) allocating %d tx holding buffers\n", + info->device_name, __FILE__,__LINE__,info->num_tx_holding_buffers); + + memset(info->tx_holding_buffers,0,sizeof(info->tx_holding_buffers)); + + for ( i=0; inum_tx_holding_buffers; ++i) { + info->tx_holding_buffers[i].buffer = + kmalloc(info->max_frame_size, GFP_KERNEL); + if (info->tx_holding_buffers[i].buffer == NULL) { + for (--i; i >= 0; i--) { + kfree(info->tx_holding_buffers[i].buffer); + info->tx_holding_buffers[i].buffer = NULL; + } + return -ENOMEM; + } + } + + return 0; + +} /* end of mgsl_alloc_intermediate_txbuffer_memory() */ + +/* + * mgsl_free_intermediate_txbuffer_memory() + * + * + * Arguments: + * + * info pointer to device instance data + * + * Return Value: None + */ +static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) +{ + int i; + + for ( i=0; inum_tx_holding_buffers; ++i ) { + kfree(info->tx_holding_buffers[i].buffer); + info->tx_holding_buffers[i].buffer = NULL; + } + + info->get_tx_holding_index = 0; + info->put_tx_holding_index = 0; + info->tx_holding_count = 0; + +} /* end of mgsl_free_intermediate_txbuffer_memory() */ + + +/* + * load_next_tx_holding_buffer() + * + * attempts to load the next buffered tx request into the + * tx dma buffers + * + * Arguments: + * + * info pointer to device instance data + * + * Return Value: true if next buffered tx request loaded + * into adapter's tx dma buffer, + * false otherwise + */ +static bool load_next_tx_holding_buffer(struct mgsl_struct *info) +{ + bool ret = false; + + if ( info->tx_holding_count ) { + /* determine if we have enough tx dma buffers + * to accommodate the next tx frame + */ + struct tx_holding_buffer *ptx = + &info->tx_holding_buffers[info->get_tx_holding_index]; + int num_free = num_free_tx_dma_buffers(info); + int num_needed = ptx->buffer_size / DMABUFFERSIZE; + if ( ptx->buffer_size % DMABUFFERSIZE ) + ++num_needed; + + if (num_needed <= num_free) { + info->xmit_cnt = ptx->buffer_size; + mgsl_load_tx_dma_buffer(info,ptx->buffer,ptx->buffer_size); + + --info->tx_holding_count; + if ( ++info->get_tx_holding_index >= info->num_tx_holding_buffers) + info->get_tx_holding_index=0; + + /* restart transmit timer */ + mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); + + ret = true; + } + } + + return ret; +} + +/* + * save_tx_buffer_request() + * + * attempt to store transmit frame request for later transmission + * + * Arguments: + * + * info pointer to device instance data + * Buffer pointer to buffer containing frame to load + * BufferSize size in bytes of frame in Buffer + * + * Return Value: 1 if able to store, 0 otherwise + */ +static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize) +{ + struct tx_holding_buffer *ptx; + + if ( info->tx_holding_count >= info->num_tx_holding_buffers ) { + return 0; /* all buffers in use */ + } + + ptx = &info->tx_holding_buffers[info->put_tx_holding_index]; + ptx->buffer_size = BufferSize; + memcpy( ptx->buffer, Buffer, BufferSize); + + ++info->tx_holding_count; + if ( ++info->put_tx_holding_index >= info->num_tx_holding_buffers) + info->put_tx_holding_index=0; + + return 1; +} + +static int mgsl_claim_resources(struct mgsl_struct *info) +{ + if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) { + printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->io_base); + return -ENODEV; + } + info->io_addr_requested = true; + + if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags, + info->device_name, info ) < 0 ) { + printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n", + __FILE__,__LINE__,info->device_name, info->irq_level ); + goto errout; + } + info->irq_requested = true; + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { + printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base); + goto errout; + } + info->shared_mem_requested = true; + if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { + printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); + goto errout; + } + info->lcr_mem_requested = true; + + info->memory_base = ioremap_nocache(info->phys_memory_base, + 0x40000); + if (!info->memory_base) { + printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + goto errout; + } + + if ( !mgsl_memory_test(info) ) { + printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + goto errout; + } + + info->lcr_base = ioremap_nocache(info->phys_lcr_base, + PAGE_SIZE); + if (!info->lcr_base) { + printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); + goto errout; + } + info->lcr_base += info->lcr_offset; + + } else { + /* claim DMA channel */ + + if (request_dma(info->dma_level,info->device_name) < 0){ + printk( "%s(%d):Cant request DMA channel on device %s DMA=%d\n", + __FILE__,__LINE__,info->device_name, info->dma_level ); + mgsl_release_resources( info ); + return -ENODEV; + } + info->dma_requested = true; + + /* ISA adapter uses bus master DMA */ + set_dma_mode(info->dma_level,DMA_MODE_CASCADE); + enable_dma(info->dma_level); + } + + if ( mgsl_allocate_dma_buffers(info) < 0 ) { + printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n", + __FILE__,__LINE__,info->device_name, info->dma_level ); + goto errout; + } + + return 0; +errout: + mgsl_release_resources(info); + return -ENODEV; + +} /* end of mgsl_claim_resources() */ + +static void mgsl_release_resources(struct mgsl_struct *info) +{ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_release_resources(%s) entry\n", + __FILE__,__LINE__,info->device_name ); + + if ( info->irq_requested ) { + free_irq(info->irq_level, info); + info->irq_requested = false; + } + if ( info->dma_requested ) { + disable_dma(info->dma_level); + free_dma(info->dma_level); + info->dma_requested = false; + } + mgsl_free_dma_buffers(info); + mgsl_free_intermediate_rxbuffer_memory(info); + mgsl_free_intermediate_txbuffer_memory(info); + + if ( info->io_addr_requested ) { + release_region(info->io_base,info->io_addr_size); + info->io_addr_requested = false; + } + if ( info->shared_mem_requested ) { + release_mem_region(info->phys_memory_base,0x40000); + info->shared_mem_requested = false; + } + if ( info->lcr_mem_requested ) { + release_mem_region(info->phys_lcr_base + info->lcr_offset,128); + info->lcr_mem_requested = false; + } + if (info->memory_base){ + iounmap(info->memory_base); + info->memory_base = NULL; + } + if (info->lcr_base){ + iounmap(info->lcr_base - info->lcr_offset); + info->lcr_base = NULL; + } + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_release_resources(%s) exit\n", + __FILE__,__LINE__,info->device_name ); + +} /* end of mgsl_release_resources() */ + +/* mgsl_add_device() + * + * Add the specified device instance data structure to the + * global linked list of devices and increment the device count. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_add_device( struct mgsl_struct *info ) +{ + info->next_device = NULL; + info->line = mgsl_device_count; + sprintf(info->device_name,"ttySL%d",info->line); + + if (info->line < MAX_TOTAL_DEVICES) { + if (maxframe[info->line]) + info->max_frame_size = maxframe[info->line]; + + if (txdmabufs[info->line]) { + info->num_tx_dma_buffers = txdmabufs[info->line]; + if (info->num_tx_dma_buffers < 1) + info->num_tx_dma_buffers = 1; + } + + if (txholdbufs[info->line]) { + info->num_tx_holding_buffers = txholdbufs[info->line]; + if (info->num_tx_holding_buffers < 1) + info->num_tx_holding_buffers = 1; + else if (info->num_tx_holding_buffers > MAX_TX_HOLDING_BUFFERS) + info->num_tx_holding_buffers = MAX_TX_HOLDING_BUFFERS; + } + } + + mgsl_device_count++; + + if ( !mgsl_device_list ) + mgsl_device_list = info; + else { + struct mgsl_struct *current_dev = mgsl_device_list; + while( current_dev->next_device ) + current_dev = current_dev->next_device; + current_dev->next_device = info; + } + + if ( info->max_frame_size < 4096 ) + info->max_frame_size = 4096; + else if ( info->max_frame_size > 65535 ) + info->max_frame_size = 65535; + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", + info->hw_version + 1, info->device_name, info->io_base, info->irq_level, + info->phys_memory_base, info->phys_lcr_base, + info->max_frame_size ); + } else { + printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", + info->device_name, info->io_base, info->irq_level, info->dma_level, + info->max_frame_size ); + } + +#if SYNCLINK_GENERIC_HDLC + hdlcdev_init(info); +#endif + +} /* end of mgsl_add_device() */ + +static const struct tty_port_operations mgsl_port_ops = { + .carrier_raised = carrier_raised, + .dtr_rts = dtr_rts, +}; + + +/* mgsl_allocate_device() + * + * Allocate and initialize a device instance structure + * + * Arguments: none + * Return Value: pointer to mgsl_struct if success, otherwise NULL + */ +static struct mgsl_struct* mgsl_allocate_device(void) +{ + struct mgsl_struct *info; + + info = kzalloc(sizeof(struct mgsl_struct), + GFP_KERNEL); + + if (!info) { + printk("Error can't allocate device instance data\n"); + } else { + tty_port_init(&info->port); + info->port.ops = &mgsl_port_ops; + info->magic = MGSL_MAGIC; + INIT_WORK(&info->task, mgsl_bh_handler); + info->max_frame_size = 4096; + info->port.close_delay = 5*HZ/10; + info->port.closing_wait = 30*HZ; + init_waitqueue_head(&info->status_event_wait_q); + init_waitqueue_head(&info->event_wait_q); + spin_lock_init(&info->irq_spinlock); + spin_lock_init(&info->netlock); + memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); + info->idle_mode = HDLC_TXIDLE_FLAGS; + info->num_tx_dma_buffers = 1; + info->num_tx_holding_buffers = 0; + } + + return info; + +} /* end of mgsl_allocate_device()*/ + +static const struct tty_operations mgsl_ops = { + .open = mgsl_open, + .close = mgsl_close, + .write = mgsl_write, + .put_char = mgsl_put_char, + .flush_chars = mgsl_flush_chars, + .write_room = mgsl_write_room, + .chars_in_buffer = mgsl_chars_in_buffer, + .flush_buffer = mgsl_flush_buffer, + .ioctl = mgsl_ioctl, + .throttle = mgsl_throttle, + .unthrottle = mgsl_unthrottle, + .send_xchar = mgsl_send_xchar, + .break_ctl = mgsl_break, + .wait_until_sent = mgsl_wait_until_sent, + .set_termios = mgsl_set_termios, + .stop = mgsl_stop, + .start = mgsl_start, + .hangup = mgsl_hangup, + .tiocmget = tiocmget, + .tiocmset = tiocmset, + .get_icount = msgl_get_icount, + .proc_fops = &mgsl_proc_fops, +}; + +/* + * perform tty device initialization + */ +static int mgsl_init_tty(void) +{ + int rc; + + serial_driver = alloc_tty_driver(128); + if (!serial_driver) + return -ENOMEM; + + serial_driver->owner = THIS_MODULE; + serial_driver->driver_name = "synclink"; + serial_driver->name = "ttySL"; + serial_driver->major = ttymajor; + serial_driver->minor_start = 64; + serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_driver->subtype = SERIAL_TYPE_NORMAL; + serial_driver->init_termios = tty_std_termios; + serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; + serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(serial_driver, &mgsl_ops); + if ((rc = tty_register_driver(serial_driver)) < 0) { + printk("%s(%d):Couldn't register serial driver\n", + __FILE__,__LINE__); + put_tty_driver(serial_driver); + serial_driver = NULL; + return rc; + } + + printk("%s %s, tty major#%d\n", + driver_name, driver_version, + serial_driver->major); + return 0; +} + +/* enumerate user specified ISA adapters + */ +static void mgsl_enum_isa_devices(void) +{ + struct mgsl_struct *info; + int i; + + /* Check for user specified ISA devices */ + + for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("ISA device specified io=%04X,irq=%d,dma=%d\n", + io[i], irq[i], dma[i] ); + + info = mgsl_allocate_device(); + if ( !info ) { + /* error allocating device instance data */ + if ( debug_level >= DEBUG_LEVEL_ERROR ) + printk( "can't allocate device instance data.\n"); + continue; + } + + /* Copy user configuration info to device instance data */ + info->io_base = (unsigned int)io[i]; + info->irq_level = (unsigned int)irq[i]; + info->irq_level = irq_canonicalize(info->irq_level); + info->dma_level = (unsigned int)dma[i]; + info->bus_type = MGSL_BUS_TYPE_ISA; + info->io_addr_size = 16; + info->irq_flags = 0; + + mgsl_add_device( info ); + } +} + +static void synclink_cleanup(void) +{ + int rc; + struct mgsl_struct *info; + struct mgsl_struct *tmp; + + printk("Unloading %s: %s\n", driver_name, driver_version); + + if (serial_driver) { + if ((rc = tty_unregister_driver(serial_driver))) + printk("%s(%d) failed to unregister tty driver err=%d\n", + __FILE__,__LINE__,rc); + put_tty_driver(serial_driver); + } + + info = mgsl_device_list; + while(info) { +#if SYNCLINK_GENERIC_HDLC + hdlcdev_exit(info); +#endif + mgsl_release_resources(info); + tmp = info; + info = info->next_device; + kfree(tmp); + } + + if (pci_registered) + pci_unregister_driver(&synclink_pci_driver); +} + +static int __init synclink_init(void) +{ + int rc; + + if (break_on_load) { + mgsl_get_text_ptr(); + BREAKPOINT(); + } + + printk("%s %s\n", driver_name, driver_version); + + mgsl_enum_isa_devices(); + if ((rc = pci_register_driver(&synclink_pci_driver)) < 0) + printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc); + else + pci_registered = true; + + if ((rc = mgsl_init_tty()) < 0) + goto error; + + return 0; + +error: + synclink_cleanup(); + return rc; +} + +static void __exit synclink_exit(void) +{ + synclink_cleanup(); +} + +module_init(synclink_init); +module_exit(synclink_exit); + +/* + * usc_RTCmd() + * + * Issue a USC Receive/Transmit command to the + * Channel Command/Address Register (CCAR). + * + * Notes: + * + * The command is encoded in the most significant 5 bits <15..11> + * of the CCAR value. Bits <10..7> of the CCAR must be preserved + * and Bits <6..0> must be written as zeros. + * + * Arguments: + * + * info pointer to device information structure + * Cmd command mask (use symbolic macros) + * + * Return Value: + * + * None + */ +static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) +{ + /* output command to CCAR in bits <15..11> */ + /* preserve bits <10..7>, bits <6..0> must be zero */ + + outw( Cmd + info->loopback_bits, info->io_base + CCAR ); + + /* Read to flush write to CCAR */ + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + inw( info->io_base + CCAR ); + +} /* end of usc_RTCmd() */ + +/* + * usc_DmaCmd() + * + * Issue a DMA command to the DMA Command/Address Register (DCAR). + * + * Arguments: + * + * info pointer to device information structure + * Cmd DMA command mask (usc_DmaCmd_XX Macros) + * + * Return Value: + * + * None + */ +static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) +{ + /* write command mask to DCAR */ + outw( Cmd + info->mbre_bit, info->io_base ); + + /* Read to flush write to DCAR */ + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + inw( info->io_base ); + +} /* end of usc_DmaCmd() */ + +/* + * usc_OutDmaReg() + * + * Write a 16-bit value to a USC DMA register + * + * Arguments: + * + * info pointer to device info structure + * RegAddr register address (number) for write + * RegValue 16-bit value to write to register + * + * Return Value: + * + * None + * + */ +static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) +{ + /* Note: The DCAR is located at the adapter base address */ + /* Note: must preserve state of BIT8 in DCAR */ + + outw( RegAddr + info->mbre_bit, info->io_base ); + outw( RegValue, info->io_base ); + + /* Read to flush write to DCAR */ + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + inw( info->io_base ); + +} /* end of usc_OutDmaReg() */ + +/* + * usc_InDmaReg() + * + * Read a 16-bit value from a DMA register + * + * Arguments: + * + * info pointer to device info structure + * RegAddr register address (number) to read from + * + * Return Value: + * + * The 16-bit value read from register + * + */ +static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr ) +{ + /* Note: The DCAR is located at the adapter base address */ + /* Note: must preserve state of BIT8 in DCAR */ + + outw( RegAddr + info->mbre_bit, info->io_base ); + return inw( info->io_base ); + +} /* end of usc_InDmaReg() */ + +/* + * + * usc_OutReg() + * + * Write a 16-bit value to a USC serial channel register + * + * Arguments: + * + * info pointer to device info structure + * RegAddr register address (number) to write to + * RegValue 16-bit value to write to register + * + * Return Value: + * + * None + * + */ +static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) +{ + outw( RegAddr + info->loopback_bits, info->io_base + CCAR ); + outw( RegValue, info->io_base + CCAR ); + + /* Read to flush write to CCAR */ + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + inw( info->io_base + CCAR ); + +} /* end of usc_OutReg() */ + +/* + * usc_InReg() + * + * Reads a 16-bit value from a USC serial channel register + * + * Arguments: + * + * info pointer to device extension + * RegAddr register address (number) to read from + * + * Return Value: + * + * 16-bit value read from register + */ +static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) +{ + outw( RegAddr + info->loopback_bits, info->io_base + CCAR ); + return inw( info->io_base + CCAR ); + +} /* end of usc_InReg() */ + +/* usc_set_sdlc_mode() + * + * Set up the adapter for SDLC DMA communications. + * + * Arguments: info pointer to device instance data + * Return Value: NONE + */ +static void usc_set_sdlc_mode( struct mgsl_struct *info ) +{ + u16 RegValue; + bool PreSL1660; + + /* + * determine if the IUSC on the adapter is pre-SL1660. If + * not, take advantage of the UnderWait feature of more + * modern chips. If an underrun occurs and this bit is set, + * the transmitter will idle the programmed idle pattern + * until the driver has time to service the underrun. Otherwise, + * the dma controller may get the cycles previously requested + * and begin transmitting queued tx data. + */ + usc_OutReg(info,TMCR,0x1f); + RegValue=usc_InReg(info,TMDR); + PreSL1660 = (RegValue == IUSC_PRE_SL1660); + + if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) + { + /* + ** Channel Mode Register (CMR) + ** + ** <15..14> 10 Tx Sub Modes, Send Flag on Underrun + ** <13> 0 0 = Transmit Disabled (initially) + ** <12> 0 1 = Consecutive Idles share common 0 + ** <11..8> 1110 Transmitter Mode = HDLC/SDLC Loop + ** <7..4> 0000 Rx Sub Modes, addr/ctrl field handling + ** <3..0> 0110 Receiver Mode = HDLC/SDLC + ** + ** 1000 1110 0000 0110 = 0x8e06 + */ + RegValue = 0x8e06; + + /*-------------------------------------------------- + * ignore user options for UnderRun Actions and + * preambles + *--------------------------------------------------*/ + } + else + { + /* Channel mode Register (CMR) + * + * <15..14> 00 Tx Sub modes, Underrun Action + * <13> 0 1 = Send Preamble before opening flag + * <12> 0 1 = Consecutive Idles share common 0 + * <11..8> 0110 Transmitter mode = HDLC/SDLC + * <7..4> 0000 Rx Sub modes, addr/ctrl field handling + * <3..0> 0110 Receiver mode = HDLC/SDLC + * + * 0000 0110 0000 0110 = 0x0606 + */ + if (info->params.mode == MGSL_MODE_RAW) { + RegValue = 0x0001; /* Set Receive mode = external sync */ + + usc_OutReg( info, IOCR, /* Set IOCR DCD is RxSync Detect Input */ + (unsigned short)((usc_InReg(info, IOCR) & ~(BIT13|BIT12)) | BIT12)); + + /* + * TxSubMode: + * CMR <15> 0 Don't send CRC on Tx Underrun + * CMR <14> x undefined + * CMR <13> 0 Send preamble before openning sync + * CMR <12> 0 Send 8-bit syncs, 1=send Syncs per TxLength + * + * TxMode: + * CMR <11-8) 0100 MonoSync + * + * 0x00 0100 xxxx xxxx 04xx + */ + RegValue |= 0x0400; + } + else { + + RegValue = 0x0606; + + if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 ) + RegValue |= BIT14; + else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG ) + RegValue |= BIT15; + else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC ) + RegValue |= BIT15 + BIT14; + } + + if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE ) + RegValue |= BIT13; + } + + if ( info->params.mode == MGSL_MODE_HDLC && + (info->params.flags & HDLC_FLAG_SHARE_ZERO) ) + RegValue |= BIT12; + + if ( info->params.addr_filter != 0xff ) + { + /* set up receive address filtering */ + usc_OutReg( info, RSR, info->params.addr_filter ); + RegValue |= BIT4; + } + + usc_OutReg( info, CMR, RegValue ); + info->cmr_value = RegValue; + + /* Receiver mode Register (RMR) + * + * <15..13> 000 encoding + * <12..11> 00 FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1) + * <10> 1 1 = Set CRC to all 1s (use for SDLC/HDLC) + * <9> 0 1 = Include Receive chars in CRC + * <8> 1 1 = Use Abort/PE bit as abort indicator + * <7..6> 00 Even parity + * <5> 0 parity disabled + * <4..2> 000 Receive Char Length = 8 bits + * <1..0> 00 Disable Receiver + * + * 0000 0101 0000 0000 = 0x0500 + */ + + RegValue = 0x0500; + + switch ( info->params.encoding ) { + case HDLC_ENCODING_NRZB: RegValue |= BIT13; break; + case HDLC_ENCODING_NRZI_MARK: RegValue |= BIT14; break; + case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 + BIT13; break; + case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT15; break; + case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 + BIT13; break; + case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break; + } + + if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT ) + RegValue |= BIT9; + else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT ) + RegValue |= ( BIT12 | BIT10 | BIT9 ); + + usc_OutReg( info, RMR, RegValue ); + + /* Set the Receive count Limit Register (RCLR) to 0xffff. */ + /* When an opening flag of an SDLC frame is recognized the */ + /* Receive Character count (RCC) is loaded with the value in */ + /* RCLR. The RCC is decremented for each received byte. The */ + /* value of RCC is stored after the closing flag of the frame */ + /* allowing the frame size to be computed. */ + + usc_OutReg( info, RCLR, RCLRVALUE ); + + usc_RCmd( info, RCmd_SelectRicrdma_level ); + + /* Receive Interrupt Control Register (RICR) + * + * <15..8> ? RxFIFO DMA Request Level + * <7> 0 Exited Hunt IA (Interrupt Arm) + * <6> 0 Idle Received IA + * <5> 0 Break/Abort IA + * <4> 0 Rx Bound IA + * <3> 1 Queued status reflects oldest 2 bytes in FIFO + * <2> 0 Abort/PE IA + * <1> 1 Rx Overrun IA + * <0> 0 Select TC0 value for readback + * + * 0000 0000 0000 1000 = 0x000a + */ + + /* Carry over the Exit Hunt and Idle Received bits */ + /* in case they have been armed by usc_ArmEvents. */ + + RegValue = usc_InReg( info, RICR ) & 0xc0; + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); + else + usc_OutReg( info, RICR, (u16)(0x140a | RegValue) ); + + /* Unlatch all Rx status bits and clear Rx status IRQ Pending */ + + usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, RECEIVE_STATUS ); + + /* Transmit mode Register (TMR) + * + * <15..13> 000 encoding + * <12..11> 00 FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1) + * <10> 1 1 = Start CRC as all 1s (use for SDLC/HDLC) + * <9> 0 1 = Tx CRC Enabled + * <8> 0 1 = Append CRC to end of transmit frame + * <7..6> 00 Transmit parity Even + * <5> 0 Transmit parity Disabled + * <4..2> 000 Tx Char Length = 8 bits + * <1..0> 00 Disable Transmitter + * + * 0000 0100 0000 0000 = 0x0400 + */ + + RegValue = 0x0400; + + switch ( info->params.encoding ) { + case HDLC_ENCODING_NRZB: RegValue |= BIT13; break; + case HDLC_ENCODING_NRZI_MARK: RegValue |= BIT14; break; + case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 + BIT13; break; + case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT15; break; + case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 + BIT13; break; + case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break; + } + + if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT ) + RegValue |= BIT9 + BIT8; + else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT ) + RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8); + + usc_OutReg( info, TMR, RegValue ); + + usc_set_txidle( info ); + + + usc_TCmd( info, TCmd_SelectTicrdma_level ); + + /* Transmit Interrupt Control Register (TICR) + * + * <15..8> ? Transmit FIFO DMA Level + * <7> 0 Present IA (Interrupt Arm) + * <6> 0 Idle Sent IA + * <5> 1 Abort Sent IA + * <4> 1 EOF/EOM Sent IA + * <3> 0 CRC Sent IA + * <2> 1 1 = Wait for SW Trigger to Start Frame + * <1> 1 Tx Underrun IA + * <0> 0 TC0 constant on read back + * + * 0000 0000 0011 0110 = 0x0036 + */ + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + usc_OutReg( info, TICR, 0x0736 ); + else + usc_OutReg( info, TICR, 0x1436 ); + + usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); + + /* + ** Transmit Command/Status Register (TCSR) + ** + ** <15..12> 0000 TCmd + ** <11> 0/1 UnderWait + ** <10..08> 000 TxIdle + ** <7> x PreSent + ** <6> x IdleSent + ** <5> x AbortSent + ** <4> x EOF/EOM Sent + ** <3> x CRC Sent + ** <2> x All Sent + ** <1> x TxUnder + ** <0> x TxEmpty + ** + ** 0000 0000 0000 0000 = 0x0000 + */ + info->tcsr_value = 0; + + if ( !PreSL1660 ) + info->tcsr_value |= TCSR_UNDERWAIT; + + usc_OutReg( info, TCSR, info->tcsr_value ); + + /* Clock mode Control Register (CMCR) + * + * <15..14> 00 counter 1 Source = Disabled + * <13..12> 00 counter 0 Source = Disabled + * <11..10> 11 BRG1 Input is TxC Pin + * <9..8> 11 BRG0 Input is TxC Pin + * <7..6> 01 DPLL Input is BRG1 Output + * <5..3> XXX TxCLK comes from Port 0 + * <2..0> XXX RxCLK comes from Port 1 + * + * 0000 1111 0111 0111 = 0x0f77 + */ + + RegValue = 0x0f40; + + if ( info->params.flags & HDLC_FLAG_RXC_DPLL ) + RegValue |= 0x0003; /* RxCLK from DPLL */ + else if ( info->params.flags & HDLC_FLAG_RXC_BRG ) + RegValue |= 0x0004; /* RxCLK from BRG0 */ + else if ( info->params.flags & HDLC_FLAG_RXC_TXCPIN) + RegValue |= 0x0006; /* RxCLK from TXC Input */ + else + RegValue |= 0x0007; /* RxCLK from Port1 */ + + if ( info->params.flags & HDLC_FLAG_TXC_DPLL ) + RegValue |= 0x0018; /* TxCLK from DPLL */ + else if ( info->params.flags & HDLC_FLAG_TXC_BRG ) + RegValue |= 0x0020; /* TxCLK from BRG0 */ + else if ( info->params.flags & HDLC_FLAG_TXC_RXCPIN) + RegValue |= 0x0038; /* RxCLK from TXC Input */ + else + RegValue |= 0x0030; /* TxCLK from Port0 */ + + usc_OutReg( info, CMCR, RegValue ); + + + /* Hardware Configuration Register (HCR) + * + * <15..14> 00 CTR0 Divisor:00=32,01=16,10=8,11=4 + * <13> 0 CTR1DSel:0=CTR0Div determines CTR0Div + * <12> 0 CVOK:0=report code violation in biphase + * <11..10> 00 DPLL Divisor:00=32,01=16,10=8,11=4 + * <9..8> XX DPLL mode:00=disable,01=NRZ,10=Biphase,11=Biphase Level + * <7..6> 00 reserved + * <5> 0 BRG1 mode:0=continuous,1=single cycle + * <4> X BRG1 Enable + * <3..2> 00 reserved + * <1> 0 BRG0 mode:0=continuous,1=single cycle + * <0> 0 BRG0 Enable + */ + + RegValue = 0x0000; + + if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) { + u32 XtalSpeed; + u32 DpllDivisor; + u16 Tc; + + /* DPLL is enabled. Use BRG1 to provide continuous reference clock */ + /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */ + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + XtalSpeed = 11059200; + else + XtalSpeed = 14745600; + + if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { + DpllDivisor = 16; + RegValue |= BIT10; + } + else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) { + DpllDivisor = 8; + RegValue |= BIT11; + } + else + DpllDivisor = 32; + + /* Tc = (Xtal/Speed) - 1 */ + /* If twice the remainder of (Xtal/Speed) is greater than Speed */ + /* then rounding up gives a more precise time constant. Instead */ + /* of rounding up and then subtracting 1 we just don't subtract */ + /* the one in this case. */ + + /*-------------------------------------------------- + * ejz: for DPLL mode, application should use the + * same clock speed as the partner system, even + * though clocking is derived from the input RxData. + * In case the user uses a 0 for the clock speed, + * default to 0xffffffff and don't try to divide by + * zero + *--------------------------------------------------*/ + if ( info->params.clock_speed ) + { + Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed); + if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2) + / info->params.clock_speed) ) + Tc--; + } + else + Tc = -1; + + + /* Write 16-bit Time Constant for BRG1 */ + usc_OutReg( info, TC1R, Tc ); + + RegValue |= BIT4; /* enable BRG1 */ + + switch ( info->params.encoding ) { + case HDLC_ENCODING_NRZ: + case HDLC_ENCODING_NRZB: + case HDLC_ENCODING_NRZI_MARK: + case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT8; break; + case HDLC_ENCODING_BIPHASE_MARK: + case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break; + case HDLC_ENCODING_BIPHASE_LEVEL: + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break; + } + } + + usc_OutReg( info, HCR, RegValue ); + + + /* Channel Control/status Register (CCSR) + * + * <15> X RCC FIFO Overflow status (RO) + * <14> X RCC FIFO Not Empty status (RO) + * <13> 0 1 = Clear RCC FIFO (WO) + * <12> X DPLL Sync (RW) + * <11> X DPLL 2 Missed Clocks status (RO) + * <10> X DPLL 1 Missed Clock status (RO) + * <9..8> 00 DPLL Resync on rising and falling edges (RW) + * <7> X SDLC Loop On status (RO) + * <6> X SDLC Loop Send status (RO) + * <5> 1 Bypass counters for TxClk and RxClk (RW) + * <4..2> 000 Last Char of SDLC frame has 8 bits (RW) + * <1..0> 00 reserved + * + * 0000 0000 0010 0000 = 0x0020 + */ + + usc_OutReg( info, CCSR, 0x1020 ); + + + if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) { + usc_OutReg( info, SICR, + (u16)(usc_InReg(info,SICR) | SICR_CTS_INACTIVE) ); + } + + + /* enable Master Interrupt Enable bit (MIE) */ + usc_EnableMasterIrqBit( info ); + + usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA + + TRANSMIT_STATUS + TRANSMIT_DATA + MISC); + + /* arm RCC underflow interrupt */ + usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3)); + usc_EnableInterrupts(info, MISC); + + info->mbre_bit = 0; + outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ + usc_DmaCmd( info, DmaCmd_ResetAllChannels ); /* disable both DMA channels */ + info->mbre_bit = BIT8; + outw( BIT8, info->io_base ); /* set Master Bus Enable (DCAR) */ + + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable DMAEN (Port 7, Bit 14) */ + /* This connects the DMA request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14)); + } + + /* DMA Control Register (DCR) + * + * <15..14> 10 Priority mode = Alternating Tx/Rx + * 01 Rx has priority + * 00 Tx has priority + * + * <13> 1 Enable Priority Preempt per DCR<15..14> + * (WARNING DCR<11..10> must be 00 when this is 1) + * 0 Choose activate channel per DCR<11..10> + * + * <12> 0 Little Endian for Array/List + * <11..10> 00 Both Channels can use each bus grant + * <9..6> 0000 reserved + * <5> 0 7 CLK - Minimum Bus Re-request Interval + * <4> 0 1 = drive D/C and S/D pins + * <3> 1 1 = Add one wait state to all DMA cycles. + * <2> 0 1 = Strobe /UAS on every transfer. + * <1..0> 11 Addr incrementing only affects LS24 bits + * + * 0110 0000 0000 1011 = 0x600b + */ + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + /* PCI adapter does not need DMA wait state */ + usc_OutDmaReg( info, DCR, 0xa00b ); + } + else + usc_OutDmaReg( info, DCR, 0x800b ); + + + /* Receive DMA mode Register (RDMR) + * + * <15..14> 11 DMA mode = Linked List Buffer mode + * <13> 1 RSBinA/L = store Rx status Block in Arrary/List entry + * <12> 1 Clear count of List Entry after fetching + * <11..10> 00 Address mode = Increment + * <9> 1 Terminate Buffer on RxBound + * <8> 0 Bus Width = 16bits + * <7..0> ? status Bits (write as 0s) + * + * 1111 0010 0000 0000 = 0xf200 + */ + + usc_OutDmaReg( info, RDMR, 0xf200 ); + + + /* Transmit DMA mode Register (TDMR) + * + * <15..14> 11 DMA mode = Linked List Buffer mode + * <13> 1 TCBinA/L = fetch Tx Control Block from List entry + * <12> 1 Clear count of List Entry after fetching + * <11..10> 00 Address mode = Increment + * <9> 1 Terminate Buffer on end of frame + * <8> 0 Bus Width = 16bits + * <7..0> ? status Bits (Read Only so write as 0) + * + * 1111 0010 0000 0000 = 0xf200 + */ + + usc_OutDmaReg( info, TDMR, 0xf200 ); + + + /* DMA Interrupt Control Register (DICR) + * + * <15> 1 DMA Interrupt Enable + * <14> 0 1 = Disable IEO from USC + * <13> 0 1 = Don't provide vector during IntAck + * <12> 1 1 = Include status in Vector + * <10..2> 0 reserved, Must be 0s + * <1> 0 1 = Rx DMA Interrupt Enabled + * <0> 0 1 = Tx DMA Interrupt Enabled + * + * 1001 0000 0000 0000 = 0x9000 + */ + + usc_OutDmaReg( info, DICR, 0x9000 ); + + usc_InDmaReg( info, RDMR ); /* clear pending receive DMA IRQ bits */ + usc_InDmaReg( info, TDMR ); /* clear pending transmit DMA IRQ bits */ + usc_OutDmaReg( info, CDIR, 0x0303 ); /* clear IUS and Pending for Tx and Rx */ + + /* Channel Control Register (CCR) + * + * <15..14> 10 Use 32-bit Tx Control Blocks (TCBs) + * <13> 0 Trigger Tx on SW Command Disabled + * <12> 0 Flag Preamble Disabled + * <11..10> 00 Preamble Length + * <9..8> 00 Preamble Pattern + * <7..6> 10 Use 32-bit Rx status Blocks (RSBs) + * <5> 0 Trigger Rx on SW Command Disabled + * <4..0> 0 reserved + * + * 1000 0000 1000 0000 = 0x8080 + */ + + RegValue = 0x8080; + + switch ( info->params.preamble_length ) { + case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break; + case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break; + case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break; + } + + switch ( info->params.preamble ) { + case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break; + case HDLC_PREAMBLE_PATTERN_ONES: RegValue |= BIT8; break; + case HDLC_PREAMBLE_PATTERN_10: RegValue |= BIT9; break; + case HDLC_PREAMBLE_PATTERN_01: RegValue |= BIT9 + BIT8; break; + } + + usc_OutReg( info, CCR, RegValue ); + + + /* + * Burst/Dwell Control Register + * + * <15..8> 0x20 Maximum number of transfers per bus grant + * <7..0> 0x00 Maximum number of clock cycles per bus grant + */ + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + /* don't limit bus occupancy on PCI adapter */ + usc_OutDmaReg( info, BDCR, 0x0000 ); + } + else + usc_OutDmaReg( info, BDCR, 0x2000 ); + + usc_stop_transmitter(info); + usc_stop_receiver(info); + +} /* end of usc_set_sdlc_mode() */ + +/* usc_enable_loopback() + * + * Set the 16C32 for internal loopback mode. + * The TxCLK and RxCLK signals are generated from the BRG0 and + * the TxD is looped back to the RxD internally. + * + * Arguments: info pointer to device instance data + * enable 1 = enable loopback, 0 = disable + * Return Value: None + */ +static void usc_enable_loopback(struct mgsl_struct *info, int enable) +{ + if (enable) { + /* blank external TXD output */ + usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6)); + + /* Clock mode Control Register (CMCR) + * + * <15..14> 00 counter 1 Disabled + * <13..12> 00 counter 0 Disabled + * <11..10> 11 BRG1 Input is TxC Pin + * <9..8> 11 BRG0 Input is TxC Pin + * <7..6> 01 DPLL Input is BRG1 Output + * <5..3> 100 TxCLK comes from BRG0 + * <2..0> 100 RxCLK comes from BRG0 + * + * 0000 1111 0110 0100 = 0x0f64 + */ + + usc_OutReg( info, CMCR, 0x0f64 ); + + /* Write 16-bit Time Constant for BRG0 */ + /* use clock speed if available, otherwise use 8 for diagnostics */ + if (info->params.clock_speed) { + if (info->bus_type == MGSL_BUS_TYPE_PCI) + usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); + else + usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1)); + } else + usc_OutReg(info, TC0R, (u16)8); + + /* Hardware Configuration Register (HCR) Clear Bit 1, BRG0 + mode = Continuous Set Bit 0 to enable BRG0. */ + usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) ); + + /* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */ + usc_OutReg(info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004)); + + /* set Internal Data loopback mode */ + info->loopback_bits = 0x300; + outw( 0x0300, info->io_base + CCAR ); + } else { + /* enable external TXD output */ + usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6)); + + /* clear Internal Data loopback mode */ + info->loopback_bits = 0; + outw( 0,info->io_base + CCAR ); + } + +} /* end of usc_enable_loopback() */ + +/* usc_enable_aux_clock() + * + * Enabled the AUX clock output at the specified frequency. + * + * Arguments: + * + * info pointer to device extension + * data_rate data rate of clock in bits per second + * A data rate of 0 disables the AUX clock. + * + * Return Value: None + */ +static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) +{ + u32 XtalSpeed; + u16 Tc; + + if ( data_rate ) { + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + XtalSpeed = 11059200; + else + XtalSpeed = 14745600; + + + /* Tc = (Xtal/Speed) - 1 */ + /* If twice the remainder of (Xtal/Speed) is greater than Speed */ + /* then rounding up gives a more precise time constant. Instead */ + /* of rounding up and then subtracting 1 we just don't subtract */ + /* the one in this case. */ + + + Tc = (u16)(XtalSpeed/data_rate); + if ( !(((XtalSpeed % data_rate) * 2) / data_rate) ) + Tc--; + + /* Write 16-bit Time Constant for BRG0 */ + usc_OutReg( info, TC0R, Tc ); + + /* + * Hardware Configuration Register (HCR) + * Clear Bit 1, BRG0 mode = Continuous + * Set Bit 0 to enable BRG0. + */ + + usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) ); + + /* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */ + usc_OutReg( info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) ); + } else { + /* data rate == 0 so turn off BRG0 */ + usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) ); + } + +} /* end of usc_enable_aux_clock() */ + +/* + * + * usc_process_rxoverrun_sync() + * + * This function processes a receive overrun by resetting the + * receive DMA buffers and issuing a Purge Rx FIFO command + * to allow the receiver to continue receiving. + * + * Arguments: + * + * info pointer to device extension + * + * Return Value: None + */ +static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) +{ + int start_index; + int end_index; + int frame_start_index; + bool start_of_frame_found = false; + bool end_of_frame_found = false; + bool reprogram_dma = false; + + DMABUFFERENTRY *buffer_list = info->rx_buffer_list; + u32 phys_addr; + + usc_DmaCmd( info, DmaCmd_PauseRxChannel ); + usc_RCmd( info, RCmd_EnterHuntmode ); + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + + /* CurrentRxBuffer points to the 1st buffer of the next */ + /* possibly available receive frame. */ + + frame_start_index = start_index = end_index = info->current_rx_buffer; + + /* Search for an unfinished string of buffers. This means */ + /* that a receive frame started (at least one buffer with */ + /* count set to zero) but there is no terminiting buffer */ + /* (status set to non-zero). */ + + while( !buffer_list[end_index].count ) + { + /* Count field has been reset to zero by 16C32. */ + /* This buffer is currently in use. */ + + if ( !start_of_frame_found ) + { + start_of_frame_found = true; + frame_start_index = end_index; + end_of_frame_found = false; + } + + if ( buffer_list[end_index].status ) + { + /* Status field has been set by 16C32. */ + /* This is the last buffer of a received frame. */ + + /* We want to leave the buffers for this frame intact. */ + /* Move on to next possible frame. */ + + start_of_frame_found = false; + end_of_frame_found = true; + } + + /* advance to next buffer entry in linked list */ + end_index++; + if ( end_index == info->rx_buffer_count ) + end_index = 0; + + if ( start_index == end_index ) + { + /* The entire list has been searched with all Counts == 0 and */ + /* all Status == 0. The receive buffers are */ + /* completely screwed, reset all receive buffers! */ + mgsl_reset_rx_dma_buffers( info ); + frame_start_index = 0; + start_of_frame_found = false; + reprogram_dma = true; + break; + } + } + + if ( start_of_frame_found && !end_of_frame_found ) + { + /* There is an unfinished string of receive DMA buffers */ + /* as a result of the receiver overrun. */ + + /* Reset the buffers for the unfinished frame */ + /* and reprogram the receive DMA controller to start */ + /* at the 1st buffer of unfinished frame. */ + + start_index = frame_start_index; + + do + { + *((unsigned long *)&(info->rx_buffer_list[start_index++].count)) = DMABUFFERSIZE; + + /* Adjust index for wrap around. */ + if ( start_index == info->rx_buffer_count ) + start_index = 0; + + } while( start_index != end_index ); + + reprogram_dma = true; + } + + if ( reprogram_dma ) + { + usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); + usc_ClearIrqPendingBits(info, RECEIVE_DATA|RECEIVE_STATUS); + usc_UnlatchRxstatusBits(info, RECEIVE_DATA|RECEIVE_STATUS); + + usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); + + /* This empties the receive FIFO and loads the RCC with RCLR */ + usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); + + /* program 16C32 with physical address of 1st DMA buffer entry */ + phys_addr = info->rx_buffer_list[frame_start_index].phys_entry; + usc_OutDmaReg( info, NRARL, (u16)phys_addr ); + usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) ); + + usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); + usc_EnableInterrupts( info, RECEIVE_STATUS ); + + /* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */ + /* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */ + + usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 ); + usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) ); + usc_DmaCmd( info, DmaCmd_InitRxChannel ); + if ( info->params.flags & HDLC_FLAG_AUTO_DCD ) + usc_EnableReceiver(info,ENABLE_AUTO_DCD); + else + usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); + } + else + { + /* This empties the receive FIFO and loads the RCC with RCLR */ + usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + } + +} /* end of usc_process_rxoverrun_sync() */ + +/* usc_stop_receiver() + * + * Disable USC receiver + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_stop_receiver( struct mgsl_struct *info ) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):usc_stop_receiver(%s)\n", + __FILE__,__LINE__, info->device_name ); + + /* Disable receive DMA channel. */ + /* This also disables receive DMA channel interrupts */ + usc_DmaCmd( info, DmaCmd_ResetRxChannel ); + + usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); + usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS ); + + usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); + + /* This empties the receive FIFO and loads the RCC with RCLR */ + usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + + info->rx_enabled = false; + info->rx_overflow = false; + info->rx_rcc_underrun = false; + +} /* end of stop_receiver() */ + +/* usc_start_receiver() + * + * Enable the USC receiver + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_start_receiver( struct mgsl_struct *info ) +{ + u32 phys_addr; + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):usc_start_receiver(%s)\n", + __FILE__,__LINE__, info->device_name ); + + mgsl_reset_rx_dma_buffers( info ); + usc_stop_receiver( info ); + + usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + + if ( info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW ) { + /* DMA mode Transfers */ + /* Program the DMA controller. */ + /* Enable the DMA controller end of buffer interrupt. */ + + /* program 16C32 with physical address of 1st DMA buffer entry */ + phys_addr = info->rx_buffer_list[0].phys_entry; + usc_OutDmaReg( info, NRARL, (u16)phys_addr ); + usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) ); + + usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); + usc_EnableInterrupts( info, RECEIVE_STATUS ); + + /* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */ + /* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */ + + usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 ); + usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) ); + usc_DmaCmd( info, DmaCmd_InitRxChannel ); + if ( info->params.flags & HDLC_FLAG_AUTO_DCD ) + usc_EnableReceiver(info,ENABLE_AUTO_DCD); + else + usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); + } else { + usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); + usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_EnableInterrupts(info, RECEIVE_DATA); + + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + usc_RCmd( info, RCmd_EnterHuntmode ); + + usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); + } + + usc_OutReg( info, CCSR, 0x1020 ); + + info->rx_enabled = true; + +} /* end of usc_start_receiver() */ + +/* usc_start_transmitter() + * + * Enable the USC transmitter and send a transmit frame if + * one is loaded in the DMA buffers. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_start_transmitter( struct mgsl_struct *info ) +{ + u32 phys_addr; + unsigned int FrameSize; + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):usc_start_transmitter(%s)\n", + __FILE__,__LINE__, info->device_name ); + + if ( info->xmit_cnt ) { + + /* If auto RTS enabled and RTS is inactive, then assert */ + /* RTS and set a flag indicating that the driver should */ + /* negate RTS when the transmission completes. */ + + info->drop_rts_on_tx_done = false; + + if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) { + usc_get_serial_signals( info ); + if ( !(info->serial_signals & SerialSignal_RTS) ) { + info->serial_signals |= SerialSignal_RTS; + usc_set_serial_signals( info ); + info->drop_rts_on_tx_done = true; + } + } + + + if ( info->params.mode == MGSL_MODE_ASYNC ) { + if ( !info->tx_active ) { + usc_UnlatchTxstatusBits(info, TXSTATUS_ALL); + usc_ClearIrqPendingBits(info, TRANSMIT_STATUS + TRANSMIT_DATA); + usc_EnableInterrupts(info, TRANSMIT_DATA); + usc_load_txfifo(info); + } + } else { + /* Disable transmit DMA controller while programming. */ + usc_DmaCmd( info, DmaCmd_ResetTxChannel ); + + /* Transmit DMA buffer is loaded, so program USC */ + /* to send the frame contained in the buffers. */ + + FrameSize = info->tx_buffer_list[info->start_tx_dma_buffer].rcc; + + /* if operating in Raw sync mode, reset the rcc component + * of the tx dma buffer entry, otherwise, the serial controller + * will send a closing sync char after this count. + */ + if ( info->params.mode == MGSL_MODE_RAW ) + info->tx_buffer_list[info->start_tx_dma_buffer].rcc = 0; + + /* Program the Transmit Character Length Register (TCLR) */ + /* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */ + usc_OutReg( info, TCLR, (u16)FrameSize ); + + usc_RTCmd( info, RTCmd_PurgeTxFifo ); + + /* Program the address of the 1st DMA Buffer Entry in linked list */ + phys_addr = info->tx_buffer_list[info->start_tx_dma_buffer].phys_entry; + usc_OutDmaReg( info, NTARL, (u16)phys_addr ); + usc_OutDmaReg( info, NTARU, (u16)(phys_addr >> 16) ); + + usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); + usc_EnableInterrupts( info, TRANSMIT_STATUS ); + + if ( info->params.mode == MGSL_MODE_RAW && + info->num_tx_dma_buffers > 1 ) { + /* When running external sync mode, attempt to 'stream' transmit */ + /* by filling tx dma buffers as they become available. To do this */ + /* we need to enable Tx DMA EOB Status interrupts : */ + /* */ + /* 1. Arm End of Buffer (EOB) Transmit DMA Interrupt (BIT2 of TDIAR) */ + /* 2. Enable Transmit DMA Interrupts (BIT0 of DICR) */ + + usc_OutDmaReg( info, TDIAR, BIT2|BIT3 ); + usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT0) ); + } + + /* Initialize Transmit DMA Channel */ + usc_DmaCmd( info, DmaCmd_InitTxChannel ); + + usc_TCmd( info, TCmd_SendFrame ); + + mod_timer(&info->tx_timer, jiffies + + msecs_to_jiffies(5000)); + } + info->tx_active = true; + } + + if ( !info->tx_enabled ) { + info->tx_enabled = true; + if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) + usc_EnableTransmitter(info,ENABLE_AUTO_CTS); + else + usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL); + } + +} /* end of usc_start_transmitter() */ + +/* usc_stop_transmitter() + * + * Stops the transmitter and DMA + * + * Arguments: info pointer to device isntance data + * Return Value: None + */ +static void usc_stop_transmitter( struct mgsl_struct *info ) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):usc_stop_transmitter(%s)\n", + __FILE__,__LINE__, info->device_name ); + + del_timer(&info->tx_timer); + + usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA ); + usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA ); + + usc_EnableTransmitter(info,DISABLE_UNCONDITIONAL); + usc_DmaCmd( info, DmaCmd_ResetTxChannel ); + usc_RTCmd( info, RTCmd_PurgeTxFifo ); + + info->tx_enabled = false; + info->tx_active = false; + +} /* end of usc_stop_transmitter() */ + +/* usc_load_txfifo() + * + * Fill the transmit FIFO until the FIFO is full or + * there is no more data to load. + * + * Arguments: info pointer to device extension (instance data) + * Return Value: None + */ +static void usc_load_txfifo( struct mgsl_struct *info ) +{ + int Fifocount; + u8 TwoBytes[2]; + + if ( !info->xmit_cnt && !info->x_char ) + return; + + /* Select transmit FIFO status readback in TICR */ + usc_TCmd( info, TCmd_SelectTicrTxFifostatus ); + + /* load the Transmit FIFO until FIFOs full or all data sent */ + + while( (Fifocount = usc_InReg(info, TICR) >> 8) && info->xmit_cnt ) { + /* there is more space in the transmit FIFO and */ + /* there is more data in transmit buffer */ + + if ( (info->xmit_cnt > 1) && (Fifocount > 1) && !info->x_char ) { + /* write a 16-bit word from transmit buffer to 16C32 */ + + TwoBytes[0] = info->xmit_buf[info->xmit_tail++]; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + TwoBytes[1] = info->xmit_buf[info->xmit_tail++]; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + + outw( *((u16 *)TwoBytes), info->io_base + DATAREG); + + info->xmit_cnt -= 2; + info->icount.tx += 2; + } else { + /* only 1 byte left to transmit or 1 FIFO slot left */ + + outw( (inw( info->io_base + CCAR) & 0x0780) | (TDR+LSBONLY), + info->io_base + CCAR ); + + if (info->x_char) { + /* transmit pending high priority char */ + outw( info->x_char,info->io_base + CCAR ); + info->x_char = 0; + } else { + outw( info->xmit_buf[info->xmit_tail++],info->io_base + CCAR ); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + } + info->icount.tx++; + } + } + +} /* end of usc_load_txfifo() */ + +/* usc_reset() + * + * Reset the adapter to a known state and prepare it for further use. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_reset( struct mgsl_struct *info ) +{ + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { + int i; + u32 readval; + + /* Set BIT30 of Misc Control Register */ + /* (Local Control Register 0x50) to force reset of USC. */ + + volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); + u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28); + + info->misc_ctrl_value |= BIT30; + *MiscCtrl = info->misc_ctrl_value; + + /* + * Force at least 170ns delay before clearing + * reset bit. Each read from LCR takes at least + * 30ns so 10 times for 300ns to be safe. + */ + for(i=0;i<10;i++) + readval = *MiscCtrl; + + info->misc_ctrl_value &= ~BIT30; + *MiscCtrl = info->misc_ctrl_value; + + *LCR0BRDR = BUS_DESCRIPTOR( + 1, // Write Strobe Hold (0-3) + 2, // Write Strobe Delay (0-3) + 2, // Read Strobe Delay (0-3) + 0, // NWDD (Write data-data) (0-3) + 4, // NWAD (Write Addr-data) (0-31) + 0, // NXDA (Read/Write Data-Addr) (0-3) + 0, // NRDD (Read Data-Data) (0-3) + 5 // NRAD (Read Addr-Data) (0-31) + ); + } else { + /* do HW reset */ + outb( 0,info->io_base + 8 ); + } + + info->mbre_bit = 0; + info->loopback_bits = 0; + info->usc_idle_mode = 0; + + /* + * Program the Bus Configuration Register (BCR) + * + * <15> 0 Don't use separate address + * <14..6> 0 reserved + * <5..4> 00 IAckmode = Default, don't care + * <3> 1 Bus Request Totem Pole output + * <2> 1 Use 16 Bit data bus + * <1> 0 IRQ Totem Pole output + * <0> 0 Don't Shift Right Addr + * + * 0000 0000 0000 1100 = 0x000c + * + * By writing to io_base + SDPIN the Wait/Ack pin is + * programmed to work as a Wait pin. + */ + + outw( 0x000c,info->io_base + SDPIN ); + + + outw( 0,info->io_base ); + outw( 0,info->io_base + CCAR ); + + /* select little endian byte ordering */ + usc_RTCmd( info, RTCmd_SelectLittleEndian ); + + + /* Port Control Register (PCR) + * + * <15..14> 11 Port 7 is Output (~DMAEN, Bit 14 : 0 = Enabled) + * <13..12> 11 Port 6 is Output (~INTEN, Bit 12 : 0 = Enabled) + * <11..10> 00 Port 5 is Input (No Connect, Don't Care) + * <9..8> 00 Port 4 is Input (No Connect, Don't Care) + * <7..6> 11 Port 3 is Output (~RTS, Bit 6 : 0 = Enabled ) + * <5..4> 11 Port 2 is Output (~DTR, Bit 4 : 0 = Enabled ) + * <3..2> 01 Port 1 is Input (Dedicated RxC) + * <1..0> 01 Port 0 is Input (Dedicated TxC) + * + * 1111 0000 1111 0101 = 0xf0f5 + */ + + usc_OutReg( info, PCR, 0xf0f5 ); + + + /* + * Input/Output Control Register + * + * <15..14> 00 CTS is active low input + * <13..12> 00 DCD is active low input + * <11..10> 00 TxREQ pin is input (DSR) + * <9..8> 00 RxREQ pin is input (RI) + * <7..6> 00 TxD is output (Transmit Data) + * <5..3> 000 TxC Pin in Input (14.7456MHz Clock) + * <2..0> 100 RxC is Output (drive with BRG0) + * + * 0000 0000 0000 0100 = 0x0004 + */ + + usc_OutReg( info, IOCR, 0x0004 ); + +} /* end of usc_reset() */ + +/* usc_set_async_mode() + * + * Program adapter for asynchronous communications. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_set_async_mode( struct mgsl_struct *info ) +{ + u16 RegValue; + + /* disable interrupts while programming USC */ + usc_DisableMasterIrqBit( info ); + + outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ + usc_DmaCmd( info, DmaCmd_ResetAllChannels ); /* disable both DMA channels */ + + usc_loopback_frame( info ); + + /* Channel mode Register (CMR) + * + * <15..14> 00 Tx Sub modes, 00 = 1 Stop Bit + * <13..12> 00 00 = 16X Clock + * <11..8> 0000 Transmitter mode = Asynchronous + * <7..6> 00 reserved? + * <5..4> 00 Rx Sub modes, 00 = 16X Clock + * <3..0> 0000 Receiver mode = Asynchronous + * + * 0000 0000 0000 0000 = 0x0 + */ + + RegValue = 0; + if ( info->params.stop_bits != 1 ) + RegValue |= BIT14; + usc_OutReg( info, CMR, RegValue ); + + + /* Receiver mode Register (RMR) + * + * <15..13> 000 encoding = None + * <12..08> 00000 reserved (Sync Only) + * <7..6> 00 Even parity + * <5> 0 parity disabled + * <4..2> 000 Receive Char Length = 8 bits + * <1..0> 00 Disable Receiver + * + * 0000 0000 0000 0000 = 0x0 + */ + + RegValue = 0; + + if ( info->params.data_bits != 8 ) + RegValue |= BIT4+BIT3+BIT2; + + if ( info->params.parity != ASYNC_PARITY_NONE ) { + RegValue |= BIT5; + if ( info->params.parity != ASYNC_PARITY_ODD ) + RegValue |= BIT6; + } + + usc_OutReg( info, RMR, RegValue ); + + + /* Set IRQ trigger level */ + + usc_RCmd( info, RCmd_SelectRicrIntLevel ); + + + /* Receive Interrupt Control Register (RICR) + * + * <15..8> ? RxFIFO IRQ Request Level + * + * Note: For async mode the receive FIFO level must be set + * to 0 to avoid the situation where the FIFO contains fewer bytes + * than the trigger level and no more data is expected. + * + * <7> 0 Exited Hunt IA (Interrupt Arm) + * <6> 0 Idle Received IA + * <5> 0 Break/Abort IA + * <4> 0 Rx Bound IA + * <3> 0 Queued status reflects oldest byte in FIFO + * <2> 0 Abort/PE IA + * <1> 0 Rx Overrun IA + * <0> 0 Select TC0 value for readback + * + * 0000 0000 0100 0000 = 0x0000 + (FIFOLEVEL in MSB) + */ + + usc_OutReg( info, RICR, 0x0000 ); + + usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, RECEIVE_STATUS ); + + + /* Transmit mode Register (TMR) + * + * <15..13> 000 encoding = None + * <12..08> 00000 reserved (Sync Only) + * <7..6> 00 Transmit parity Even + * <5> 0 Transmit parity Disabled + * <4..2> 000 Tx Char Length = 8 bits + * <1..0> 00 Disable Transmitter + * + * 0000 0000 0000 0000 = 0x0 + */ + + RegValue = 0; + + if ( info->params.data_bits != 8 ) + RegValue |= BIT4+BIT3+BIT2; + + if ( info->params.parity != ASYNC_PARITY_NONE ) { + RegValue |= BIT5; + if ( info->params.parity != ASYNC_PARITY_ODD ) + RegValue |= BIT6; + } + + usc_OutReg( info, TMR, RegValue ); + + usc_set_txidle( info ); + + + /* Set IRQ trigger level */ + + usc_TCmd( info, TCmd_SelectTicrIntLevel ); + + + /* Transmit Interrupt Control Register (TICR) + * + * <15..8> ? Transmit FIFO IRQ Level + * <7> 0 Present IA (Interrupt Arm) + * <6> 1 Idle Sent IA + * <5> 0 Abort Sent IA + * <4> 0 EOF/EOM Sent IA + * <3> 0 CRC Sent IA + * <2> 0 1 = Wait for SW Trigger to Start Frame + * <1> 0 Tx Underrun IA + * <0> 0 TC0 constant on read back + * + * 0000 0000 0100 0000 = 0x0040 + */ + + usc_OutReg( info, TICR, 0x1f40 ); + + usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); + usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); + + usc_enable_async_clock( info, info->params.data_rate ); + + + /* Channel Control/status Register (CCSR) + * + * <15> X RCC FIFO Overflow status (RO) + * <14> X RCC FIFO Not Empty status (RO) + * <13> 0 1 = Clear RCC FIFO (WO) + * <12> X DPLL in Sync status (RO) + * <11> X DPLL 2 Missed Clocks status (RO) + * <10> X DPLL 1 Missed Clock status (RO) + * <9..8> 00 DPLL Resync on rising and falling edges (RW) + * <7> X SDLC Loop On status (RO) + * <6> X SDLC Loop Send status (RO) + * <5> 1 Bypass counters for TxClk and RxClk (RW) + * <4..2> 000 Last Char of SDLC frame has 8 bits (RW) + * <1..0> 00 reserved + * + * 0000 0000 0010 0000 = 0x0020 + */ + + usc_OutReg( info, CCSR, 0x0020 ); + + usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA + + RECEIVE_DATA + RECEIVE_STATUS ); + + usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA + + RECEIVE_DATA + RECEIVE_STATUS ); + + usc_EnableMasterIrqBit( info ); + + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + } + + if (info->params.loopback) { + info->loopback_bits = 0x300; + outw(0x0300, info->io_base + CCAR); + } + +} /* end of usc_set_async_mode() */ + +/* usc_loopback_frame() + * + * Loop back a small (2 byte) dummy SDLC frame. + * Interrupts and DMA are NOT used. The purpose of this is to + * clear any 'stale' status info left over from running in async mode. + * + * The 16C32 shows the strange behaviour of marking the 1st + * received SDLC frame with a CRC error even when there is no + * CRC error. To get around this a small dummy from of 2 bytes + * is looped back when switching from async to sync mode. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_loopback_frame( struct mgsl_struct *info ) +{ + int i; + unsigned long oldmode = info->params.mode; + + info->params.mode = MGSL_MODE_HDLC; + + usc_DisableMasterIrqBit( info ); + + usc_set_sdlc_mode( info ); + usc_enable_loopback( info, 1 ); + + /* Write 16-bit Time Constant for BRG0 */ + usc_OutReg( info, TC0R, 0 ); + + /* Channel Control Register (CCR) + * + * <15..14> 00 Don't use 32-bit Tx Control Blocks (TCBs) + * <13> 0 Trigger Tx on SW Command Disabled + * <12> 0 Flag Preamble Disabled + * <11..10> 00 Preamble Length = 8-Bits + * <9..8> 01 Preamble Pattern = flags + * <7..6> 10 Don't use 32-bit Rx status Blocks (RSBs) + * <5> 0 Trigger Rx on SW Command Disabled + * <4..0> 0 reserved + * + * 0000 0001 0000 0000 = 0x0100 + */ + + usc_OutReg( info, CCR, 0x0100 ); + + /* SETUP RECEIVER */ + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); + + /* SETUP TRANSMITTER */ + /* Program the Transmit Character Length Register (TCLR) */ + /* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */ + usc_OutReg( info, TCLR, 2 ); + usc_RTCmd( info, RTCmd_PurgeTxFifo ); + + /* unlatch Tx status bits, and start transmit channel. */ + usc_UnlatchTxstatusBits(info,TXSTATUS_ALL); + outw(0,info->io_base + DATAREG); + + /* ENABLE TRANSMITTER */ + usc_TCmd( info, TCmd_SendFrame ); + usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL); + + /* WAIT FOR RECEIVE COMPLETE */ + for (i=0 ; i<1000 ; i++) + if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1)) + break; + + /* clear Internal Data loopback mode */ + usc_enable_loopback(info, 0); + + usc_EnableMasterIrqBit(info); + + info->params.mode = oldmode; + +} /* end of usc_loopback_frame() */ + +/* usc_set_sync_mode() Programs the USC for SDLC communications. + * + * Arguments: info pointer to adapter info structure + * Return Value: None + */ +static void usc_set_sync_mode( struct mgsl_struct *info ) +{ + usc_loopback_frame( info ); + usc_set_sdlc_mode( info ); + + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + } + + usc_enable_aux_clock(info, info->params.clock_speed); + + if (info->params.loopback) + usc_enable_loopback(info,1); + +} /* end of mgsl_set_sync_mode() */ + +/* usc_set_txidle() Set the HDLC idle mode for the transmitter. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_set_txidle( struct mgsl_struct *info ) +{ + u16 usc_idle_mode = IDLEMODE_FLAGS; + + /* Map API idle mode to USC register bits */ + + switch( info->idle_mode ){ + case HDLC_TXIDLE_FLAGS: usc_idle_mode = IDLEMODE_FLAGS; break; + case HDLC_TXIDLE_ALT_ZEROS_ONES: usc_idle_mode = IDLEMODE_ALT_ONE_ZERO; break; + case HDLC_TXIDLE_ZEROS: usc_idle_mode = IDLEMODE_ZERO; break; + case HDLC_TXIDLE_ONES: usc_idle_mode = IDLEMODE_ONE; break; + case HDLC_TXIDLE_ALT_MARK_SPACE: usc_idle_mode = IDLEMODE_ALT_MARK_SPACE; break; + case HDLC_TXIDLE_SPACE: usc_idle_mode = IDLEMODE_SPACE; break; + case HDLC_TXIDLE_MARK: usc_idle_mode = IDLEMODE_MARK; break; + } + + info->usc_idle_mode = usc_idle_mode; + //usc_OutReg(info, TCSR, usc_idle_mode); + info->tcsr_value &= ~IDLEMODE_MASK; /* clear idle mode bits */ + info->tcsr_value += usc_idle_mode; + usc_OutReg(info, TCSR, info->tcsr_value); + + /* + * if SyncLink WAN adapter is running in external sync mode, the + * transmitter has been set to Monosync in order to try to mimic + * a true raw outbound bit stream. Monosync still sends an open/close + * sync char at the start/end of a frame. Try to match those sync + * patterns to the idle mode set here + */ + if ( info->params.mode == MGSL_MODE_RAW ) { + unsigned char syncpat = 0; + switch( info->idle_mode ) { + case HDLC_TXIDLE_FLAGS: + syncpat = 0x7e; + break; + case HDLC_TXIDLE_ALT_ZEROS_ONES: + syncpat = 0x55; + break; + case HDLC_TXIDLE_ZEROS: + case HDLC_TXIDLE_SPACE: + syncpat = 0x00; + break; + case HDLC_TXIDLE_ONES: + case HDLC_TXIDLE_MARK: + syncpat = 0xff; + break; + case HDLC_TXIDLE_ALT_MARK_SPACE: + syncpat = 0xaa; + break; + } + + usc_SetTransmitSyncChars(info,syncpat,syncpat); + } + +} /* end of usc_set_txidle() */ + +/* usc_get_serial_signals() + * + * Query the adapter for the state of the V24 status (input) signals. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_get_serial_signals( struct mgsl_struct *info ) +{ + u16 status; + + /* clear all serial signals except DTR and RTS */ + info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS; + + /* Read the Misc Interrupt status Register (MISR) to get */ + /* the V24 status signals. */ + + status = usc_InReg( info, MISR ); + + /* set serial signal bits to reflect MISR */ + + if ( status & MISCSTATUS_CTS ) + info->serial_signals |= SerialSignal_CTS; + + if ( status & MISCSTATUS_DCD ) + info->serial_signals |= SerialSignal_DCD; + + if ( status & MISCSTATUS_RI ) + info->serial_signals |= SerialSignal_RI; + + if ( status & MISCSTATUS_DSR ) + info->serial_signals |= SerialSignal_DSR; + +} /* end of usc_get_serial_signals() */ + +/* usc_set_serial_signals() + * + * Set the state of DTR and RTS based on contents of + * serial_signals member of device extension. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void usc_set_serial_signals( struct mgsl_struct *info ) +{ + u16 Control; + unsigned char V24Out = info->serial_signals; + + /* get the current value of the Port Control Register (PCR) */ + + Control = usc_InReg( info, PCR ); + + if ( V24Out & SerialSignal_RTS ) + Control &= ~(BIT6); + else + Control |= BIT6; + + if ( V24Out & SerialSignal_DTR ) + Control &= ~(BIT4); + else + Control |= BIT4; + + usc_OutReg( info, PCR, Control ); + +} /* end of usc_set_serial_signals() */ + +/* usc_enable_async_clock() + * + * Enable the async clock at the specified frequency. + * + * Arguments: info pointer to device instance data + * data_rate data rate of clock in bps + * 0 disables the AUX clock. + * Return Value: None + */ +static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) +{ + if ( data_rate ) { + /* + * Clock mode Control Register (CMCR) + * + * <15..14> 00 counter 1 Disabled + * <13..12> 00 counter 0 Disabled + * <11..10> 11 BRG1 Input is TxC Pin + * <9..8> 11 BRG0 Input is TxC Pin + * <7..6> 01 DPLL Input is BRG1 Output + * <5..3> 100 TxCLK comes from BRG0 + * <2..0> 100 RxCLK comes from BRG0 + * + * 0000 1111 0110 0100 = 0x0f64 + */ + + usc_OutReg( info, CMCR, 0x0f64 ); + + + /* + * Write 16-bit Time Constant for BRG0 + * Time Constant = (ClkSpeed / data_rate) - 1 + * ClkSpeed = 921600 (ISA), 691200 (PCI) + */ + + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); + else + usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) ); + + + /* + * Hardware Configuration Register (HCR) + * Clear Bit 1, BRG0 mode = Continuous + * Set Bit 0 to enable BRG0. + */ + + usc_OutReg( info, HCR, + (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) ); + + + /* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */ + + usc_OutReg( info, IOCR, + (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) ); + } else { + /* data rate == 0 so turn off BRG0 */ + usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) ); + } + +} /* end of usc_enable_async_clock() */ + +/* + * Buffer Structures: + * + * Normal memory access uses virtual addresses that can make discontiguous + * physical memory pages appear to be contiguous in the virtual address + * space (the processors memory mapping handles the conversions). + * + * DMA transfers require physically contiguous memory. This is because + * the DMA system controller and DMA bus masters deal with memory using + * only physical addresses. + * + * This causes a problem under Windows NT when large DMA buffers are + * needed. Fragmentation of the nonpaged pool prevents allocations of + * physically contiguous buffers larger than the PAGE_SIZE. + * + * However the 16C32 supports Bus Master Scatter/Gather DMA which + * allows DMA transfers to physically discontiguous buffers. Information + * about each data transfer buffer is contained in a memory structure + * called a 'buffer entry'. A list of buffer entries is maintained + * to track and control the use of the data transfer buffers. + * + * To support this strategy we will allocate sufficient PAGE_SIZE + * contiguous memory buffers to allow for the total required buffer + * space. + * + * The 16C32 accesses the list of buffer entries using Bus Master + * DMA. Control information is read from the buffer entries by the + * 16C32 to control data transfers. status information is written to + * the buffer entries by the 16C32 to indicate the status of completed + * transfers. + * + * The CPU writes control information to the buffer entries to control + * the 16C32 and reads status information from the buffer entries to + * determine information about received and transmitted frames. + * + * Because the CPU and 16C32 (adapter) both need simultaneous access + * to the buffer entries, the buffer entry memory is allocated with + * HalAllocateCommonBuffer(). This restricts the size of the buffer + * entry list to PAGE_SIZE. + * + * The actual data buffers on the other hand will only be accessed + * by the CPU or the adapter but not by both simultaneously. This allows + * Scatter/Gather packet based DMA procedures for using physically + * discontiguous pages. + */ + +/* + * mgsl_reset_tx_dma_buffers() + * + * Set the count for all transmit buffers to 0 to indicate the + * buffer is available for use and set the current buffer to the + * first buffer. This effectively makes all buffers free and + * discards any data in buffers. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ) +{ + unsigned int i; + + for ( i = 0; i < info->tx_buffer_count; i++ ) { + *((unsigned long *)&(info->tx_buffer_list[i].count)) = 0; + } + + info->current_tx_buffer = 0; + info->start_tx_dma_buffer = 0; + info->tx_dma_buffers_used = 0; + + info->get_tx_holding_index = 0; + info->put_tx_holding_index = 0; + info->tx_holding_count = 0; + +} /* end of mgsl_reset_tx_dma_buffers() */ + +/* + * num_free_tx_dma_buffers() + * + * returns the number of free tx dma buffers available + * + * Arguments: info pointer to device instance data + * Return Value: number of free tx dma buffers + */ +static int num_free_tx_dma_buffers(struct mgsl_struct *info) +{ + return info->tx_buffer_count - info->tx_dma_buffers_used; +} + +/* + * mgsl_reset_rx_dma_buffers() + * + * Set the count for all receive buffers to DMABUFFERSIZE + * and set the current buffer to the first buffer. This effectively + * makes all buffers free and discards any data in buffers. + * + * Arguments: info pointer to device instance data + * Return Value: None + */ +static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) +{ + unsigned int i; + + for ( i = 0; i < info->rx_buffer_count; i++ ) { + *((unsigned long *)&(info->rx_buffer_list[i].count)) = DMABUFFERSIZE; +// info->rx_buffer_list[i].count = DMABUFFERSIZE; +// info->rx_buffer_list[i].status = 0; + } + + info->current_rx_buffer = 0; + +} /* end of mgsl_reset_rx_dma_buffers() */ + +/* + * mgsl_free_rx_frame_buffers() + * + * Free the receive buffers used by a received SDLC + * frame such that the buffers can be reused. + * + * Arguments: + * + * info pointer to device instance data + * StartIndex index of 1st receive buffer of frame + * EndIndex index of last receive buffer of frame + * + * Return Value: None + */ +static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ) +{ + bool Done = false; + DMABUFFERENTRY *pBufEntry; + unsigned int Index; + + /* Starting with 1st buffer entry of the frame clear the status */ + /* field and set the count field to DMA Buffer Size. */ + + Index = StartIndex; + + while( !Done ) { + pBufEntry = &(info->rx_buffer_list[Index]); + + if ( Index == EndIndex ) { + /* This is the last buffer of the frame! */ + Done = true; + } + + /* reset current buffer for reuse */ +// pBufEntry->status = 0; +// pBufEntry->count = DMABUFFERSIZE; + *((unsigned long *)&(pBufEntry->count)) = DMABUFFERSIZE; + + /* advance to next buffer entry in linked list */ + Index++; + if ( Index == info->rx_buffer_count ) + Index = 0; + } + + /* set current buffer to next buffer after last buffer of frame */ + info->current_rx_buffer = Index; + +} /* end of free_rx_frame_buffers() */ + +/* mgsl_get_rx_frame() + * + * This function attempts to return a received SDLC frame from the + * receive DMA buffers. Only frames received without errors are returned. + * + * Arguments: info pointer to device extension + * Return Value: true if frame returned, otherwise false + */ +static bool mgsl_get_rx_frame(struct mgsl_struct *info) +{ + unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ + unsigned short status; + DMABUFFERENTRY *pBufEntry; + unsigned int framesize = 0; + bool ReturnCode = false; + unsigned long flags; + struct tty_struct *tty = info->port.tty; + bool return_frame = false; + + /* + * current_rx_buffer points to the 1st buffer of the next available + * receive frame. To find the last buffer of the frame look for + * a non-zero status field in the buffer entries. (The status + * field is set by the 16C32 after completing a receive frame. + */ + + StartIndex = EndIndex = info->current_rx_buffer; + + while( !info->rx_buffer_list[EndIndex].status ) { + /* + * If the count field of the buffer entry is non-zero then + * this buffer has not been used. (The 16C32 clears the count + * field when it starts using the buffer.) If an unused buffer + * is encountered then there are no frames available. + */ + + if ( info->rx_buffer_list[EndIndex].count ) + goto Cleanup; + + /* advance to next buffer entry in linked list */ + EndIndex++; + if ( EndIndex == info->rx_buffer_count ) + EndIndex = 0; + + /* if entire list searched then no frame available */ + if ( EndIndex == StartIndex ) { + /* If this occurs then something bad happened, + * all buffers have been 'used' but none mark + * the end of a frame. Reset buffers and receiver. + */ + + if ( info->rx_enabled ){ + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + goto Cleanup; + } + } + + + /* check status of receive frame */ + + status = info->rx_buffer_list[EndIndex].status; + + if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN + + RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) { + if ( status & RXSTATUS_SHORT_FRAME ) + info->icount.rxshort++; + else if ( status & RXSTATUS_ABORT ) + info->icount.rxabort++; + else if ( status & RXSTATUS_OVERRUN ) + info->icount.rxover++; + else { + info->icount.rxcrc++; + if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) + return_frame = true; + } + framesize = 0; +#if SYNCLINK_GENERIC_HDLC + { + info->netdev->stats.rx_errors++; + info->netdev->stats.rx_frame_errors++; + } +#endif + } else + return_frame = true; + + if ( return_frame ) { + /* receive frame has no errors, get frame size. + * The frame size is the starting value of the RCC (which was + * set to 0xffff) minus the ending value of the RCC (decremented + * once for each receive character) minus 2 for the 16-bit CRC. + */ + + framesize = RCLRVALUE - info->rx_buffer_list[EndIndex].rcc; + + /* adjust frame size for CRC if any */ + if ( info->params.crc_type == HDLC_CRC_16_CCITT ) + framesize -= 2; + else if ( info->params.crc_type == HDLC_CRC_32_CCITT ) + framesize -= 4; + } + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk("%s(%d):mgsl_get_rx_frame(%s) status=%04X size=%d\n", + __FILE__,__LINE__,info->device_name,status,framesize); + + if ( debug_level >= DEBUG_LEVEL_DATA ) + mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr, + min_t(int, framesize, DMABUFFERSIZE),0); + + if (framesize) { + if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) && + ((framesize+1) > info->max_frame_size) ) || + (framesize > info->max_frame_size) ) + info->icount.rxlong++; + else { + /* copy dma buffer(s) to contiguous intermediate buffer */ + int copy_count = framesize; + int index = StartIndex; + unsigned char *ptmp = info->intermediate_rxbuffer; + + if ( !(status & RXSTATUS_CRC_ERROR)) + info->icount.rxok++; + + while(copy_count) { + int partial_count; + if ( copy_count > DMABUFFERSIZE ) + partial_count = DMABUFFERSIZE; + else + partial_count = copy_count; + + pBufEntry = &(info->rx_buffer_list[index]); + memcpy( ptmp, pBufEntry->virt_addr, partial_count ); + ptmp += partial_count; + copy_count -= partial_count; + + if ( ++index == info->rx_buffer_count ) + index = 0; + } + + if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) { + ++framesize; + *ptmp = (status & RXSTATUS_CRC_ERROR ? + RX_CRC_ERROR : + RX_OK); + + if ( debug_level >= DEBUG_LEVEL_DATA ) + printk("%s(%d):mgsl_get_rx_frame(%s) rx frame status=%d\n", + __FILE__,__LINE__,info->device_name, + *ptmp); + } + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_rx(info,info->intermediate_rxbuffer,framesize); + else +#endif + ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); + } + } + /* Free the buffers used by this frame. */ + mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex ); + + ReturnCode = true; + +Cleanup: + + if ( info->rx_enabled && info->rx_overflow ) { + /* The receiver needs to restarted because of + * a receive overflow (buffer or FIFO). If the + * receive buffers are now empty, then restart receiver. + */ + + if ( !info->rx_buffer_list[EndIndex].status && + info->rx_buffer_list[EndIndex].count ) { + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + } + + return ReturnCode; + +} /* end of mgsl_get_rx_frame() */ + +/* mgsl_get_raw_rx_frame() + * + * This function attempts to return a received frame from the + * receive DMA buffers when running in external loop mode. In this mode, + * we will return at most one DMABUFFERSIZE frame to the application. + * The USC receiver is triggering off of DCD going active to start a new + * frame, and DCD going inactive to terminate the frame (similar to + * processing a closing flag character). + * + * In this routine, we will return DMABUFFERSIZE "chunks" at a time. + * If DCD goes inactive, the last Rx DMA Buffer will have a non-zero + * status field and the RCC field will indicate the length of the + * entire received frame. We take this RCC field and get the modulus + * of RCC and DMABUFFERSIZE to determine if number of bytes in the + * last Rx DMA buffer and return that last portion of the frame. + * + * Arguments: info pointer to device extension + * Return Value: true if frame returned, otherwise false + */ +static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info) +{ + unsigned int CurrentIndex, NextIndex; + unsigned short status; + DMABUFFERENTRY *pBufEntry; + unsigned int framesize = 0; + bool ReturnCode = false; + unsigned long flags; + struct tty_struct *tty = info->port.tty; + + /* + * current_rx_buffer points to the 1st buffer of the next available + * receive frame. The status field is set by the 16C32 after + * completing a receive frame. If the status field of this buffer + * is zero, either the USC is still filling this buffer or this + * is one of a series of buffers making up a received frame. + * + * If the count field of this buffer is zero, the USC is either + * using this buffer or has used this buffer. Look at the count + * field of the next buffer. If that next buffer's count is + * non-zero, the USC is still actively using the current buffer. + * Otherwise, if the next buffer's count field is zero, the + * current buffer is complete and the USC is using the next + * buffer. + */ + CurrentIndex = NextIndex = info->current_rx_buffer; + ++NextIndex; + if ( NextIndex == info->rx_buffer_count ) + NextIndex = 0; + + if ( info->rx_buffer_list[CurrentIndex].status != 0 || + (info->rx_buffer_list[CurrentIndex].count == 0 && + info->rx_buffer_list[NextIndex].count == 0)) { + /* + * Either the status field of this dma buffer is non-zero + * (indicating the last buffer of a receive frame) or the next + * buffer is marked as in use -- implying this buffer is complete + * and an intermediate buffer for this received frame. + */ + + status = info->rx_buffer_list[CurrentIndex].status; + + if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN + + RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) { + if ( status & RXSTATUS_SHORT_FRAME ) + info->icount.rxshort++; + else if ( status & RXSTATUS_ABORT ) + info->icount.rxabort++; + else if ( status & RXSTATUS_OVERRUN ) + info->icount.rxover++; + else + info->icount.rxcrc++; + framesize = 0; + } else { + /* + * A receive frame is available, get frame size and status. + * + * The frame size is the starting value of the RCC (which was + * set to 0xffff) minus the ending value of the RCC (decremented + * once for each receive character) minus 2 or 4 for the 16-bit + * or 32-bit CRC. + * + * If the status field is zero, this is an intermediate buffer. + * It's size is 4K. + * + * If the DMA Buffer Entry's Status field is non-zero, the + * receive operation completed normally (ie: DCD dropped). The + * RCC field is valid and holds the received frame size. + * It is possible that the RCC field will be zero on a DMA buffer + * entry with a non-zero status. This can occur if the total + * frame size (number of bytes between the time DCD goes active + * to the time DCD goes inactive) exceeds 65535 bytes. In this + * case the 16C32 has underrun on the RCC count and appears to + * stop updating this counter to let us know the actual received + * frame size. If this happens (non-zero status and zero RCC), + * simply return the entire RxDMA Buffer + */ + if ( status ) { + /* + * In the event that the final RxDMA Buffer is + * terminated with a non-zero status and the RCC + * field is zero, we interpret this as the RCC + * having underflowed (received frame > 65535 bytes). + * + * Signal the event to the user by passing back + * a status of RxStatus_CrcError returning the full + * buffer and let the app figure out what data is + * actually valid + */ + if ( info->rx_buffer_list[CurrentIndex].rcc ) + framesize = RCLRVALUE - info->rx_buffer_list[CurrentIndex].rcc; + else + framesize = DMABUFFERSIZE; + } + else + framesize = DMABUFFERSIZE; + } + + if ( framesize > DMABUFFERSIZE ) { + /* + * if running in raw sync mode, ISR handler for + * End Of Buffer events terminates all buffers at 4K. + * If this frame size is said to be >4K, get the + * actual number of bytes of the frame in this buffer. + */ + framesize = framesize % DMABUFFERSIZE; + } + + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk("%s(%d):mgsl_get_raw_rx_frame(%s) status=%04X size=%d\n", + __FILE__,__LINE__,info->device_name,status,framesize); + + if ( debug_level >= DEBUG_LEVEL_DATA ) + mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr, + min_t(int, framesize, DMABUFFERSIZE),0); + + if (framesize) { + /* copy dma buffer(s) to contiguous intermediate buffer */ + /* NOTE: we never copy more than DMABUFFERSIZE bytes */ + + pBufEntry = &(info->rx_buffer_list[CurrentIndex]); + memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize); + info->icount.rxok++; + + ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); + } + + /* Free the buffers used by this frame. */ + mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex ); + + ReturnCode = true; + } + + + if ( info->rx_enabled && info->rx_overflow ) { + /* The receiver needs to restarted because of + * a receive overflow (buffer or FIFO). If the + * receive buffers are now empty, then restart receiver. + */ + + if ( !info->rx_buffer_list[CurrentIndex].status && + info->rx_buffer_list[CurrentIndex].count ) { + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + } + + return ReturnCode; + +} /* end of mgsl_get_raw_rx_frame() */ + +/* mgsl_load_tx_dma_buffer() + * + * Load the transmit DMA buffer with the specified data. + * + * Arguments: + * + * info pointer to device extension + * Buffer pointer to buffer containing frame to load + * BufferSize size in bytes of frame in Buffer + * + * Return Value: None + */ +static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, + const char *Buffer, unsigned int BufferSize) +{ + unsigned short Copycount; + unsigned int i = 0; + DMABUFFERENTRY *pBufEntry; + + if ( debug_level >= DEBUG_LEVEL_DATA ) + mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1); + + if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) { + /* set CMR:13 to start transmit when + * next GoAhead (abort) is received + */ + info->cmr_value |= BIT13; + } + + /* begin loading the frame in the next available tx dma + * buffer, remember it's starting location for setting + * up tx dma operation + */ + i = info->current_tx_buffer; + info->start_tx_dma_buffer = i; + + /* Setup the status and RCC (Frame Size) fields of the 1st */ + /* buffer entry in the transmit DMA buffer list. */ + + info->tx_buffer_list[i].status = info->cmr_value & 0xf000; + info->tx_buffer_list[i].rcc = BufferSize; + info->tx_buffer_list[i].count = BufferSize; + + /* Copy frame data from 1st source buffer to the DMA buffers. */ + /* The frame data may span multiple DMA buffers. */ + + while( BufferSize ){ + /* Get a pointer to next DMA buffer entry. */ + pBufEntry = &info->tx_buffer_list[i++]; + + if ( i == info->tx_buffer_count ) + i=0; + + /* Calculate the number of bytes that can be copied from */ + /* the source buffer to this DMA buffer. */ + if ( BufferSize > DMABUFFERSIZE ) + Copycount = DMABUFFERSIZE; + else + Copycount = BufferSize; + + /* Actually copy data from source buffer to DMA buffer. */ + /* Also set the data count for this individual DMA buffer. */ + if ( info->bus_type == MGSL_BUS_TYPE_PCI ) + mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); + else + memcpy(pBufEntry->virt_addr, Buffer, Copycount); + + pBufEntry->count = Copycount; + + /* Advance source pointer and reduce remaining data count. */ + Buffer += Copycount; + BufferSize -= Copycount; + + ++info->tx_dma_buffers_used; + } + + /* remember next available tx dma buffer */ + info->current_tx_buffer = i; + +} /* end of mgsl_load_tx_dma_buffer() */ + +/* + * mgsl_register_test() + * + * Performs a register test of the 16C32. + * + * Arguments: info pointer to device instance data + * Return Value: true if test passed, otherwise false + */ +static bool mgsl_register_test( struct mgsl_struct *info ) +{ + static unsigned short BitPatterns[] = + { 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f }; + static unsigned int Patterncount = ARRAY_SIZE(BitPatterns); + unsigned int i; + bool rc = true; + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_reset(info); + + /* Verify the reset state of some registers. */ + + if ( (usc_InReg( info, SICR ) != 0) || + (usc_InReg( info, IVR ) != 0) || + (usc_InDmaReg( info, DIVR ) != 0) ){ + rc = false; + } + + if ( rc ){ + /* Write bit patterns to various registers but do it out of */ + /* sync, then read back and verify values. */ + + for ( i = 0 ; i < Patterncount ; i++ ) { + usc_OutReg( info, TC0R, BitPatterns[i] ); + usc_OutReg( info, TC1R, BitPatterns[(i+1)%Patterncount] ); + usc_OutReg( info, TCLR, BitPatterns[(i+2)%Patterncount] ); + usc_OutReg( info, RCLR, BitPatterns[(i+3)%Patterncount] ); + usc_OutReg( info, RSR, BitPatterns[(i+4)%Patterncount] ); + usc_OutDmaReg( info, TBCR, BitPatterns[(i+5)%Patterncount] ); + + if ( (usc_InReg( info, TC0R ) != BitPatterns[i]) || + (usc_InReg( info, TC1R ) != BitPatterns[(i+1)%Patterncount]) || + (usc_InReg( info, TCLR ) != BitPatterns[(i+2)%Patterncount]) || + (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) || + (usc_InReg( info, RSR ) != BitPatterns[(i+4)%Patterncount]) || + (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){ + rc = false; + break; + } + } + } + + usc_reset(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return rc; + +} /* end of mgsl_register_test() */ + +/* mgsl_irq_test() Perform interrupt test of the 16C32. + * + * Arguments: info pointer to device instance data + * Return Value: true if test passed, otherwise false + */ +static bool mgsl_irq_test( struct mgsl_struct *info ) +{ + unsigned long EndTime; + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_reset(info); + + /* + * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition. + * The ISR sets irq_occurred to true. + */ + + info->irq_occurred = false; + + /* Enable INTEN gate for ISA adapter (Port 6, Bit12) */ + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + /* on the ISA adapter. This has no effect for the PCI adapter */ + usc_OutReg( info, PCR, (unsigned short)((usc_InReg(info, PCR) | BIT13) & ~BIT12) ); + + usc_EnableMasterIrqBit(info); + usc_EnableInterrupts(info, IO_PIN); + usc_ClearIrqPendingBits(info, IO_PIN); + + usc_UnlatchIostatusBits(info, MISCSTATUS_TXC_LATCHED); + usc_EnableStatusIrqs(info, SICR_TXC_ACTIVE + SICR_TXC_INACTIVE); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + EndTime=100; + while( EndTime-- && !info->irq_occurred ) { + msleep_interruptible(10); + } + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_reset(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return info->irq_occurred; + +} /* end of mgsl_irq_test() */ + +/* mgsl_dma_test() + * + * Perform a DMA test of the 16C32. A small frame is + * transmitted via DMA from a transmit buffer to a receive buffer + * using single buffer DMA mode. + * + * Arguments: info pointer to device instance data + * Return Value: true if test passed, otherwise false + */ +static bool mgsl_dma_test( struct mgsl_struct *info ) +{ + unsigned short FifoLevel; + unsigned long phys_addr; + unsigned int FrameSize; + unsigned int i; + char *TmpPtr; + bool rc = true; + unsigned short status=0; + unsigned long EndTime; + unsigned long flags; + MGSL_PARAMS tmp_params; + + /* save current port options */ + memcpy(&tmp_params,&info->params,sizeof(MGSL_PARAMS)); + /* load default port options */ + memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); + +#define TESTFRAMESIZE 40 + + spin_lock_irqsave(&info->irq_spinlock,flags); + + /* setup 16C32 for SDLC DMA transfer mode */ + + usc_reset(info); + usc_set_sdlc_mode(info); + usc_enable_loopback(info,1); + + /* Reprogram the RDMR so that the 16C32 does NOT clear the count + * field of the buffer entry after fetching buffer address. This + * way we can detect a DMA failure for a DMA read (which should be + * non-destructive to system memory) before we try and write to + * memory (where a failure could corrupt system memory). + */ + + /* Receive DMA mode Register (RDMR) + * + * <15..14> 11 DMA mode = Linked List Buffer mode + * <13> 1 RSBinA/L = store Rx status Block in List entry + * <12> 0 1 = Clear count of List Entry after fetching + * <11..10> 00 Address mode = Increment + * <9> 1 Terminate Buffer on RxBound + * <8> 0 Bus Width = 16bits + * <7..0> ? status Bits (write as 0s) + * + * 1110 0010 0000 0000 = 0xe200 + */ + + usc_OutDmaReg( info, RDMR, 0xe200 ); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + + /* SETUP TRANSMIT AND RECEIVE DMA BUFFERS */ + + FrameSize = TESTFRAMESIZE; + + /* setup 1st transmit buffer entry: */ + /* with frame size and transmit control word */ + + info->tx_buffer_list[0].count = FrameSize; + info->tx_buffer_list[0].rcc = FrameSize; + info->tx_buffer_list[0].status = 0x4000; + + /* build a transmit frame in 1st transmit DMA buffer */ + + TmpPtr = info->tx_buffer_list[0].virt_addr; + for (i = 0; i < FrameSize; i++ ) + *TmpPtr++ = i; + + /* setup 1st receive buffer entry: */ + /* clear status, set max receive buffer size */ + + info->rx_buffer_list[0].status = 0; + info->rx_buffer_list[0].count = FrameSize + 4; + + /* zero out the 1st receive buffer */ + + memset( info->rx_buffer_list[0].virt_addr, 0, FrameSize + 4 ); + + /* Set count field of next buffer entries to prevent */ + /* 16C32 from using buffers after the 1st one. */ + + info->tx_buffer_list[1].count = 0; + info->rx_buffer_list[1].count = 0; + + + /***************************/ + /* Program 16C32 receiver. */ + /***************************/ + + spin_lock_irqsave(&info->irq_spinlock,flags); + + /* setup DMA transfers */ + usc_RTCmd( info, RTCmd_PurgeRxFifo ); + + /* program 16C32 receiver with physical address of 1st DMA buffer entry */ + phys_addr = info->rx_buffer_list[0].phys_entry; + usc_OutDmaReg( info, NRARL, (unsigned short)phys_addr ); + usc_OutDmaReg( info, NRARU, (unsigned short)(phys_addr >> 16) ); + + /* Clear the Rx DMA status bits (read RDMR) and start channel */ + usc_InDmaReg( info, RDMR ); + usc_DmaCmd( info, DmaCmd_InitRxChannel ); + + /* Enable Receiver (RMR <1..0> = 10) */ + usc_OutReg( info, RMR, (unsigned short)((usc_InReg(info, RMR) & 0xfffc) | 0x0002) ); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + + /*************************************************************/ + /* WAIT FOR RECEIVER TO DMA ALL PARAMETERS FROM BUFFER ENTRY */ + /*************************************************************/ + + /* Wait 100ms for interrupt. */ + EndTime = jiffies + msecs_to_jiffies(100); + + for(;;) { + if (time_after(jiffies, EndTime)) { + rc = false; + break; + } + + spin_lock_irqsave(&info->irq_spinlock,flags); + status = usc_InDmaReg( info, RDMR ); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + if ( !(status & BIT4) && (status & BIT5) ) { + /* INITG (BIT 4) is inactive (no entry read in progress) AND */ + /* BUSY (BIT 5) is active (channel still active). */ + /* This means the buffer entry read has completed. */ + break; + } + } + + + /******************************/ + /* Program 16C32 transmitter. */ + /******************************/ + + spin_lock_irqsave(&info->irq_spinlock,flags); + + /* Program the Transmit Character Length Register (TCLR) */ + /* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */ + + usc_OutReg( info, TCLR, (unsigned short)info->tx_buffer_list[0].count ); + usc_RTCmd( info, RTCmd_PurgeTxFifo ); + + /* Program the address of the 1st DMA Buffer Entry in linked list */ + + phys_addr = info->tx_buffer_list[0].phys_entry; + usc_OutDmaReg( info, NTARL, (unsigned short)phys_addr ); + usc_OutDmaReg( info, NTARU, (unsigned short)(phys_addr >> 16) ); + + /* unlatch Tx status bits, and start transmit channel. */ + + usc_OutReg( info, TCSR, (unsigned short)(( usc_InReg(info, TCSR) & 0x0f00) | 0xfa) ); + usc_DmaCmd( info, DmaCmd_InitTxChannel ); + + /* wait for DMA controller to fill transmit FIFO */ + + usc_TCmd( info, TCmd_SelectTicrTxFifostatus ); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + + /**********************************/ + /* WAIT FOR TRANSMIT FIFO TO FILL */ + /**********************************/ + + /* Wait 100ms */ + EndTime = jiffies + msecs_to_jiffies(100); + + for(;;) { + if (time_after(jiffies, EndTime)) { + rc = false; + break; + } + + spin_lock_irqsave(&info->irq_spinlock,flags); + FifoLevel = usc_InReg(info, TICR) >> 8; + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + if ( FifoLevel < 16 ) + break; + else + if ( FrameSize < 32 ) { + /* This frame is smaller than the entire transmit FIFO */ + /* so wait for the entire frame to be loaded. */ + if ( FifoLevel <= (32 - FrameSize) ) + break; + } + } + + + if ( rc ) + { + /* Enable 16C32 transmitter. */ + + spin_lock_irqsave(&info->irq_spinlock,flags); + + /* Transmit mode Register (TMR), <1..0> = 10, Enable Transmitter */ + usc_TCmd( info, TCmd_SendFrame ); + usc_OutReg( info, TMR, (unsigned short)((usc_InReg(info, TMR) & 0xfffc) | 0x0002) ); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + + /******************************/ + /* WAIT FOR TRANSMIT COMPLETE */ + /******************************/ + + /* Wait 100ms */ + EndTime = jiffies + msecs_to_jiffies(100); + + /* While timer not expired wait for transmit complete */ + + spin_lock_irqsave(&info->irq_spinlock,flags); + status = usc_InReg( info, TCSR ); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) { + if (time_after(jiffies, EndTime)) { + rc = false; + break; + } + + spin_lock_irqsave(&info->irq_spinlock,flags); + status = usc_InReg( info, TCSR ); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + } + } + + + if ( rc ){ + /* CHECK FOR TRANSMIT ERRORS */ + if ( status & (BIT5 + BIT1) ) + rc = false; + } + + if ( rc ) { + /* WAIT FOR RECEIVE COMPLETE */ + + /* Wait 100ms */ + EndTime = jiffies + msecs_to_jiffies(100); + + /* Wait for 16C32 to write receive status to buffer entry. */ + status=info->rx_buffer_list[0].status; + while ( status == 0 ) { + if (time_after(jiffies, EndTime)) { + rc = false; + break; + } + status=info->rx_buffer_list[0].status; + } + } + + + if ( rc ) { + /* CHECK FOR RECEIVE ERRORS */ + status = info->rx_buffer_list[0].status; + + if ( status & (BIT8 + BIT3 + BIT1) ) { + /* receive error has occurred */ + rc = false; + } else { + if ( memcmp( info->tx_buffer_list[0].virt_addr , + info->rx_buffer_list[0].virt_addr, FrameSize ) ){ + rc = false; + } + } + } + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_reset( info ); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + /* restore current port options */ + memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); + + return rc; + +} /* end of mgsl_dma_test() */ + +/* mgsl_adapter_test() + * + * Perform the register, IRQ, and DMA tests for the 16C32. + * + * Arguments: info pointer to device instance data + * Return Value: 0 if success, otherwise -ENODEV + */ +static int mgsl_adapter_test( struct mgsl_struct *info ) +{ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):Testing device %s\n", + __FILE__,__LINE__,info->device_name ); + + if ( !mgsl_register_test( info ) ) { + info->init_error = DiagStatus_AddressFailure; + printk( "%s(%d):Register test failure for device %s Addr=%04X\n", + __FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) ); + return -ENODEV; + } + + if ( !mgsl_irq_test( info ) ) { + info->init_error = DiagStatus_IrqFailure; + printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n", + __FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) ); + return -ENODEV; + } + + if ( !mgsl_dma_test( info ) ) { + info->init_error = DiagStatus_DmaFailure; + printk( "%s(%d):DMA test failure for device %s DMA=%d\n", + __FILE__,__LINE__,info->device_name, (unsigned short)(info->dma_level) ); + return -ENODEV; + } + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):device %s passed diagnostics\n", + __FILE__,__LINE__,info->device_name ); + + return 0; + +} /* end of mgsl_adapter_test() */ + +/* mgsl_memory_test() + * + * Test the shared memory on a PCI adapter. + * + * Arguments: info pointer to device instance data + * Return Value: true if test passed, otherwise false + */ +static bool mgsl_memory_test( struct mgsl_struct *info ) +{ + static unsigned long BitPatterns[] = + { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; + unsigned long Patterncount = ARRAY_SIZE(BitPatterns); + unsigned long i; + unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long); + unsigned long * TestAddr; + + if ( info->bus_type != MGSL_BUS_TYPE_PCI ) + return true; + + TestAddr = (unsigned long *)info->memory_base; + + /* Test data lines with test pattern at one location. */ + + for ( i = 0 ; i < Patterncount ; i++ ) { + *TestAddr = BitPatterns[i]; + if ( *TestAddr != BitPatterns[i] ) + return false; + } + + /* Test address lines with incrementing pattern over */ + /* entire address range. */ + + for ( i = 0 ; i < TestLimit ; i++ ) { + *TestAddr = i * 4; + TestAddr++; + } + + TestAddr = (unsigned long *)info->memory_base; + + for ( i = 0 ; i < TestLimit ; i++ ) { + if ( *TestAddr != i * 4 ) + return false; + TestAddr++; + } + + memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE ); + + return true; + +} /* End Of mgsl_memory_test() */ + + +/* mgsl_load_pci_memory() + * + * Load a large block of data into the PCI shared memory. + * Use this instead of memcpy() or memmove() to move data + * into the PCI shared memory. + * + * Notes: + * + * This function prevents the PCI9050 interface chip from hogging + * the adapter local bus, which can starve the 16C32 by preventing + * 16C32 bus master cycles. + * + * The PCI9050 documentation says that the 9050 will always release + * control of the local bus after completing the current read + * or write operation. + * + * It appears that as long as the PCI9050 write FIFO is full, the + * PCI9050 treats all of the writes as a single burst transaction + * and will not release the bus. This causes DMA latency problems + * at high speeds when copying large data blocks to the shared + * memory. + * + * This function in effect, breaks the a large shared memory write + * into multiple transations by interleaving a shared memory read + * which will flush the write FIFO and 'complete' the write + * transation. This allows any pending DMA request to gain control + * of the local bus in a timely fasion. + * + * Arguments: + * + * TargetPtr pointer to target address in PCI shared memory + * SourcePtr pointer to source buffer for data + * count count in bytes of data to copy + * + * Return Value: None + */ +static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr, + unsigned short count ) +{ + /* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */ +#define PCI_LOAD_INTERVAL 64 + + unsigned short Intervalcount = count / PCI_LOAD_INTERVAL; + unsigned short Index; + unsigned long Dummy; + + for ( Index = 0 ; Index < Intervalcount ; Index++ ) + { + memcpy(TargetPtr, SourcePtr, PCI_LOAD_INTERVAL); + Dummy = *((volatile unsigned long *)TargetPtr); + TargetPtr += PCI_LOAD_INTERVAL; + SourcePtr += PCI_LOAD_INTERVAL; + } + + memcpy( TargetPtr, SourcePtr, count % PCI_LOAD_INTERVAL ); + +} /* End Of mgsl_load_pci_memory() */ + +static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit) +{ + int i; + int linecount; + if (xmit) + printk("%s tx data:\n",info->device_name); + else + printk("%s rx data:\n",info->device_name); + + while(count) { + if (count > 16) + linecount = 16; + else + linecount = count; + + for(i=0;i=040 && data[i]<=0176) + printk("%c",data[i]); + else + printk("."); + } + printk("\n"); + + data += linecount; + count -= linecount; + } +} /* end of mgsl_trace_block() */ + +/* mgsl_tx_timeout() + * + * called when HDLC frame times out + * update stats and do tx completion processing + * + * Arguments: context pointer to device instance data + * Return Value: None + */ +static void mgsl_tx_timeout(unsigned long context) +{ + struct mgsl_struct *info = (struct mgsl_struct*)context; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):mgsl_tx_timeout(%s)\n", + __FILE__,__LINE__,info->device_name); + if(info->tx_active && + (info->params.mode == MGSL_MODE_HDLC || + info->params.mode == MGSL_MODE_RAW) ) { + info->icount.txtimeout++; + } + spin_lock_irqsave(&info->irq_spinlock,flags); + info->tx_active = false; + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) + usc_loopmode_cancel_transmit( info ); + + spin_unlock_irqrestore(&info->irq_spinlock,flags); + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_tx_done(info); + else +#endif + mgsl_bh_transmit(info); + +} /* end of mgsl_tx_timeout() */ + +/* signal that there are no more frames to send, so that + * line is 'released' by echoing RxD to TxD when current + * transmission is complete (or immediately if no tx in progress). + */ +static int mgsl_loopmode_send_done( struct mgsl_struct * info ) +{ + unsigned long flags; + + spin_lock_irqsave(&info->irq_spinlock,flags); + if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) { + if (info->tx_active) + info->loopmode_send_done_requested = true; + else + usc_loopmode_send_done(info); + } + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return 0; +} + +/* release the line by echoing RxD to TxD + * upon completion of a transmit frame + */ +static void usc_loopmode_send_done( struct mgsl_struct * info ) +{ + info->loopmode_send_done_requested = false; + /* clear CMR:13 to 0 to start echoing RxData to TxData */ + info->cmr_value &= ~BIT13; + usc_OutReg(info, CMR, info->cmr_value); +} + +/* abort a transmit in progress while in HDLC LoopMode + */ +static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) +{ + /* reset tx dma channel and purge TxFifo */ + usc_RTCmd( info, RTCmd_PurgeTxFifo ); + usc_DmaCmd( info, DmaCmd_ResetTxChannel ); + usc_loopmode_send_done( info ); +} + +/* for HDLC/SDLC LoopMode, setting CMR:13 after the transmitter is enabled + * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort) + * we must clear CMR:13 to begin repeating TxData to RxData + */ +static void usc_loopmode_insert_request( struct mgsl_struct * info ) +{ + info->loopmode_insert_requested = true; + + /* enable RxAbort irq. On next RxAbort, clear CMR:13 to + * begin repeating TxData on RxData (complete insertion) + */ + usc_OutReg( info, RICR, + (usc_InReg( info, RICR ) | RXSTATUS_ABORT_RECEIVED ) ); + + /* set CMR:13 to insert into loop on next GoAhead (RxAbort) */ + info->cmr_value |= BIT13; + usc_OutReg(info, CMR, info->cmr_value); +} + +/* return 1 if station is inserted into the loop, otherwise 0 + */ +static int usc_loopmode_active( struct mgsl_struct * info) +{ + return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ; +} + +#if SYNCLINK_GENERIC_HDLC + +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) +{ + struct mgsl_struct *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; + + /* return error if TTY interface open */ + if (info->port.count) + return -EBUSY; + + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; + } + + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } + + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgsl_program_hw(info); + + return 0; +} + +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + */ +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct mgsl_struct *info = dev_to_port(dev); + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + info->xmit_cnt = skb->len; + mgsl_load_tx_dma_buffer(info, skb->data, skb->len); + + /* update network statistics */ + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!info->tx_active) + usc_start_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return NETDEV_TX_OK; +} + +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) +{ + struct mgsl_struct *info = dev_to_port(dev); + int rc; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + + /* arbitrate between network and tty opens */ + spin_lock_irqsave(&info->netlock, flags); + if (info->port.count != 0 || info->netcount != 0) { + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); + spin_unlock_irqrestore(&info->netlock, flags); + return -EBUSY; + } + info->netcount=1; + spin_unlock_irqrestore(&info->netlock, flags); + + /* claim resources and init adapter */ + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; + } + + /* assert DTR and RTS, apply hardware settings */ + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + mgsl_program_hw(info); + + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); + + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->irq_spinlock, flags); + usc_get_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock, flags); + if (info->serial_signals & SerialSignal_DCD) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + return 0; +} + +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) +{ + struct mgsl_struct *info = dev_to_port(dev); + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); + + netif_stop_queue(dev); + + /* shutdown adapter and release resources */ + shutdown(info); + + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; +} + +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + struct mgsl_struct *info = dev_to_port(dev); + unsigned int flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); + + /* return error if TTY interface open */ + if (info->port.count) + return -EBUSY; + + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); + + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ + + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgsl_program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } +} + +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) +{ + struct mgsl_struct *info = dev_to_port(dev); + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("hdlcdev_tx_timeout(%s)\n",dev->name); + + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_stop_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + netif_wake_queue(dev); +} + +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(struct mgsl_struct *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) +{ + struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("hdlcdev_rx(%s)\n", dev->name); + + if (skb == NULL) { + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", + dev->name); + dev->stats.rx_dropped++; + return; + } + + memcpy(skb_put(skb, size), buf, size); + + skb->protocol = hdlc_type_trans(skb, dev); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += size; + + netif_rx(skb); +} + +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(struct mgsl_struct *info) +{ + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->base_addr = info->io_base; + dev->irq = info->irq_level; + dev->dma = info->dma_level; + + /* network layer callbacks and settings */ + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; +} + +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(struct mgsl_struct *info) +{ + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; +} + +#endif /* CONFIG_HDLC */ + + +static int __devinit synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) +{ + struct mgsl_struct *info; + + if (pci_enable_device(dev)) { + printk("error enabling pci device %p\n", dev); + return -EIO; + } + + if (!(info = mgsl_allocate_device())) { + printk("can't allocate device instance data.\n"); + return -EIO; + } + + /* Copy user configuration info to device instance data */ + + info->io_base = pci_resource_start(dev, 2); + info->irq_level = dev->irq; + info->phys_memory_base = pci_resource_start(dev, 3); + + /* Because veremap only works on page boundaries we must map + * a larger area than is actually implemented for the LCR + * memory range. We map a full page starting at the page boundary. + */ + info->phys_lcr_base = pci_resource_start(dev, 0); + info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); + info->phys_lcr_base &= ~(PAGE_SIZE-1); + + info->bus_type = MGSL_BUS_TYPE_PCI; + info->io_addr_size = 8; + info->irq_flags = IRQF_SHARED; + + if (dev->device == 0x0210) { + /* Version 1 PCI9030 based universal PCI adapter */ + info->misc_ctrl_value = 0x007c4080; + info->hw_version = 1; + } else { + /* Version 0 PCI9050 based 5V PCI adapter + * A PCI9050 bug prevents reading LCR registers if + * LCR base address bit 7 is set. Maintain shadow + * value so we can write to LCR misc control reg. + */ + info->misc_ctrl_value = 0x087e4546; + info->hw_version = 0; + } + + mgsl_add_device(info); + + return 0; +} + +static void __devexit synclink_remove_one (struct pci_dev *dev) +{ +} + diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c new file mode 100644 index 000000000000..a35dd549a008 --- /dev/null +++ b/drivers/tty/synclink_gt.c @@ -0,0 +1,5161 @@ +/* + * Device driver for Microgate SyncLink GT serial adapters. + * + * written by Paul Fulghum for Microgate Corporation + * paulkf@microgate.com + * + * Microgate and SyncLink are trademarks of Microgate Corporation + * + * This code is released under the GNU General Public License (GPL) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * DEBUG OUTPUT DEFINITIONS + * + * uncomment lines below to enable specific types of debug output + * + * DBGINFO information - most verbose output + * DBGERR serious errors + * DBGBH bottom half service routine debugging + * DBGISR interrupt service routine debugging + * DBGDATA output receive and transmit data + * DBGTBUF output transmit DMA buffers and registers + * DBGRBUF output receive DMA buffers and registers + */ + +#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt +#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt +#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt +#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt +#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) +/*#define DBGTBUF(info) dump_tbufs(info)*/ +/*#define DBGRBUF(info) dump_rbufs(info)*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 +#endif + +/* + * module identification + */ +static char *driver_name = "SyncLink GT"; +static char *tty_driver_name = "synclink_gt"; +static char *tty_dev_prefix = "ttySLG"; +MODULE_LICENSE("GPL"); +#define MGSL_MAGIC 0x5401 +#define MAX_DEVICES 32 + +static struct pci_device_id pci_table[] = { + {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,}, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_table); + +static int init_one(struct pci_dev *dev,const struct pci_device_id *ent); +static void remove_one(struct pci_dev *dev); +static struct pci_driver pci_driver = { + .name = "synclink_gt", + .id_table = pci_table, + .probe = init_one, + .remove = __devexit_p(remove_one), +}; + +static bool pci_registered; + +/* + * module configuration and status + */ +static struct slgt_info *slgt_device_list; +static int slgt_device_count; + +static int ttymajor; +static int debug_level; +static int maxframe[MAX_DEVICES]; + +module_param(ttymajor, int, 0); +module_param(debug_level, int, 0); +module_param_array(maxframe, int, NULL, 0); + +MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); +MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); +MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); + +/* + * tty support and callbacks + */ +static struct tty_driver *serial_driver; + +static int open(struct tty_struct *tty, struct file * filp); +static void close(struct tty_struct *tty, struct file * filp); +static void hangup(struct tty_struct *tty); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); + +static int write(struct tty_struct *tty, const unsigned char *buf, int count); +static int put_char(struct tty_struct *tty, unsigned char ch); +static void send_xchar(struct tty_struct *tty, char ch); +static void wait_until_sent(struct tty_struct *tty, int timeout); +static int write_room(struct tty_struct *tty); +static void flush_chars(struct tty_struct *tty); +static void flush_buffer(struct tty_struct *tty); +static void tx_hold(struct tty_struct *tty); +static void tx_release(struct tty_struct *tty); + +static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); +static int chars_in_buffer(struct tty_struct *tty); +static void throttle(struct tty_struct * tty); +static void unthrottle(struct tty_struct * tty); +static int set_break(struct tty_struct *tty, int break_state); + +/* + * generic HDLC support and callbacks + */ +#if SYNCLINK_GENERIC_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(struct slgt_info *info); +static void hdlcdev_rx(struct slgt_info *info, char *buf, int size); +static int hdlcdev_init(struct slgt_info *info); +static void hdlcdev_exit(struct slgt_info *info); +#endif + + +/* + * device specific structures, macros and functions + */ + +#define SLGT_MAX_PORTS 4 +#define SLGT_REG_SIZE 256 + +/* + * conditional wait facility + */ +struct cond_wait { + struct cond_wait *next; + wait_queue_head_t q; + wait_queue_t wait; + unsigned int data; +}; +static void init_cond_wait(struct cond_wait *w, unsigned int data); +static void add_cond_wait(struct cond_wait **head, struct cond_wait *w); +static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w); +static void flush_cond_wait(struct cond_wait **head); + +/* + * DMA buffer descriptor and access macros + */ +struct slgt_desc +{ + __le16 count; + __le16 status; + __le32 pbuf; /* physical address of data buffer */ + __le32 next; /* physical address of next descriptor */ + + /* driver book keeping */ + char *buf; /* virtual address of data buffer */ + unsigned int pdesc; /* physical address of this descriptor */ + dma_addr_t buf_dma_addr; + unsigned short buf_count; +}; + +#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) +#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) +#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) +#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) +#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b)) +#define desc_count(a) (le16_to_cpu((a).count)) +#define desc_status(a) (le16_to_cpu((a).status)) +#define desc_complete(a) (le16_to_cpu((a).status) & BIT15) +#define desc_eof(a) (le16_to_cpu((a).status) & BIT2) +#define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1) +#define desc_abort(a) (le16_to_cpu((a).status) & BIT0) +#define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3) + +struct _input_signal_events { + int ri_up; + int ri_down; + int dsr_up; + int dsr_down; + int dcd_up; + int dcd_down; + int cts_up; + int cts_down; +}; + +/* + * device instance data structure + */ +struct slgt_info { + void *if_ptr; /* General purpose pointer (used by SPPP) */ + struct tty_port port; + + struct slgt_info *next_device; /* device list link */ + + int magic; + + char device_name[25]; + struct pci_dev *pdev; + + int port_count; /* count of ports on adapter */ + int adapter_num; /* adapter instance number */ + int port_num; /* port instance number */ + + /* array of pointers to port contexts on this adapter */ + struct slgt_info *port_array[SLGT_MAX_PORTS]; + + int line; /* tty line instance number */ + + struct mgsl_icount icount; + + int timeout; + int x_char; /* xon/xoff character */ + unsigned int read_status_mask; + unsigned int ignore_status_mask; + + wait_queue_head_t status_event_wait_q; + wait_queue_head_t event_wait_q; + struct timer_list tx_timer; + struct timer_list rx_timer; + + unsigned int gpio_present; + struct cond_wait *gpio_wait_q; + + spinlock_t lock; /* spinlock for synchronizing with ISR */ + + struct work_struct task; + u32 pending_bh; + bool bh_requested; + bool bh_running; + + int isr_overflow; + bool irq_requested; /* true if IRQ requested */ + bool irq_occurred; /* for diagnostics use */ + + /* device configuration */ + + unsigned int bus_type; + unsigned int irq_level; + unsigned long irq_flags; + + unsigned char __iomem * reg_addr; /* memory mapped registers address */ + u32 phys_reg_addr; + bool reg_addr_requested; + + MGSL_PARAMS params; /* communications parameters */ + u32 idle_mode; + u32 max_frame_size; /* as set by device config */ + + unsigned int rbuf_fill_level; + unsigned int rx_pio; + unsigned int if_mode; + unsigned int base_clock; + unsigned int xsync; + unsigned int xctrl; + + /* device status */ + + bool rx_enabled; + bool rx_restart; + + bool tx_enabled; + bool tx_active; + + unsigned char signals; /* serial signal states */ + int init_error; /* initialization error */ + + unsigned char *tx_buf; + int tx_count; + + char flag_buf[MAX_ASYNC_BUFFER_SIZE]; + char char_buf[MAX_ASYNC_BUFFER_SIZE]; + bool drop_rts_on_tx_done; + struct _input_signal_events input_signal_events; + + int dcd_chkcount; /* check counts to prevent */ + int cts_chkcount; /* too many IRQs if a signal */ + int dsr_chkcount; /* is floating */ + int ri_chkcount; + + char *bufs; /* virtual address of DMA buffer lists */ + dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */ + + unsigned int rbuf_count; + struct slgt_desc *rbufs; + unsigned int rbuf_current; + unsigned int rbuf_index; + unsigned int rbuf_fill_index; + unsigned short rbuf_fill_count; + + unsigned int tbuf_count; + struct slgt_desc *tbufs; + unsigned int tbuf_current; + unsigned int tbuf_start; + + unsigned char *tmp_rbuf; + unsigned int tmp_rbuf_count; + + /* SPPP/Cisco HDLC device parts */ + + int netcount; + spinlock_t netlock; +#if SYNCLINK_GENERIC_HDLC + struct net_device *netdev; +#endif + +}; + +static MGSL_PARAMS default_params = { + .mode = MGSL_MODE_HDLC, + .loopback = 0, + .flags = HDLC_FLAG_UNDERRUN_ABORT15, + .encoding = HDLC_ENCODING_NRZI_SPACE, + .clock_speed = 0, + .addr_filter = 0xff, + .crc_type = HDLC_CRC_16_CCITT, + .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS, + .preamble = HDLC_PREAMBLE_PATTERN_NONE, + .data_rate = 9600, + .data_bits = 8, + .stop_bits = 1, + .parity = ASYNC_PARITY_NONE +}; + + +#define BH_RECEIVE 1 +#define BH_TRANSMIT 2 +#define BH_STATUS 4 +#define IO_PIN_SHUTDOWN_LIMIT 100 + +#define DMABUFSIZE 256 +#define DESC_LIST_SIZE 4096 + +#define MASK_PARITY BIT1 +#define MASK_FRAMING BIT0 +#define MASK_BREAK BIT14 +#define MASK_OVERRUN BIT4 + +#define GSR 0x00 /* global status */ +#define JCR 0x04 /* JTAG control */ +#define IODR 0x08 /* GPIO direction */ +#define IOER 0x0c /* GPIO interrupt enable */ +#define IOVR 0x10 /* GPIO value */ +#define IOSR 0x14 /* GPIO interrupt status */ +#define TDR 0x80 /* tx data */ +#define RDR 0x80 /* rx data */ +#define TCR 0x82 /* tx control */ +#define TIR 0x84 /* tx idle */ +#define TPR 0x85 /* tx preamble */ +#define RCR 0x86 /* rx control */ +#define VCR 0x88 /* V.24 control */ +#define CCR 0x89 /* clock control */ +#define BDR 0x8a /* baud divisor */ +#define SCR 0x8c /* serial control */ +#define SSR 0x8e /* serial status */ +#define RDCSR 0x90 /* rx DMA control/status */ +#define TDCSR 0x94 /* tx DMA control/status */ +#define RDDAR 0x98 /* rx DMA descriptor address */ +#define TDDAR 0x9c /* tx DMA descriptor address */ +#define XSR 0x40 /* extended sync pattern */ +#define XCR 0x44 /* extended control */ + +#define RXIDLE BIT14 +#define RXBREAK BIT14 +#define IRQ_TXDATA BIT13 +#define IRQ_TXIDLE BIT12 +#define IRQ_TXUNDER BIT11 /* HDLC */ +#define IRQ_RXDATA BIT10 +#define IRQ_RXIDLE BIT9 /* HDLC */ +#define IRQ_RXBREAK BIT9 /* async */ +#define IRQ_RXOVER BIT8 +#define IRQ_DSR BIT7 +#define IRQ_CTS BIT6 +#define IRQ_DCD BIT5 +#define IRQ_RI BIT4 +#define IRQ_ALL 0x3ff0 +#define IRQ_MASTER BIT0 + +#define slgt_irq_on(info, mask) \ + wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask))) +#define slgt_irq_off(info, mask) \ + wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask))) + +static __u8 rd_reg8(struct slgt_info *info, unsigned int addr); +static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value); +static __u16 rd_reg16(struct slgt_info *info, unsigned int addr); +static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value); +static __u32 rd_reg32(struct slgt_info *info, unsigned int addr); +static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value); + +static void msc_set_vcr(struct slgt_info *info); + +static int startup(struct slgt_info *info); +static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info); +static void shutdown(struct slgt_info *info); +static void program_hw(struct slgt_info *info); +static void change_params(struct slgt_info *info); + +static int register_test(struct slgt_info *info); +static int irq_test(struct slgt_info *info); +static int loopback_test(struct slgt_info *info); +static int adapter_test(struct slgt_info *info); + +static void reset_adapter(struct slgt_info *info); +static void reset_port(struct slgt_info *info); +static void async_mode(struct slgt_info *info); +static void sync_mode(struct slgt_info *info); + +static void rx_stop(struct slgt_info *info); +static void rx_start(struct slgt_info *info); +static void reset_rbufs(struct slgt_info *info); +static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last); +static void rdma_reset(struct slgt_info *info); +static bool rx_get_frame(struct slgt_info *info); +static bool rx_get_buf(struct slgt_info *info); + +static void tx_start(struct slgt_info *info); +static void tx_stop(struct slgt_info *info); +static void tx_set_idle(struct slgt_info *info); +static unsigned int free_tbuf_count(struct slgt_info *info); +static unsigned int tbuf_bytes(struct slgt_info *info); +static void reset_tbufs(struct slgt_info *info); +static void tdma_reset(struct slgt_info *info); +static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count); + +static void get_signals(struct slgt_info *info); +static void set_signals(struct slgt_info *info); +static void enable_loopback(struct slgt_info *info); +static void set_rate(struct slgt_info *info, u32 data_rate); + +static int bh_action(struct slgt_info *info); +static void bh_handler(struct work_struct *work); +static void bh_transmit(struct slgt_info *info); +static void isr_serial(struct slgt_info *info); +static void isr_rdma(struct slgt_info *info); +static void isr_txeom(struct slgt_info *info, unsigned short status); +static void isr_tdma(struct slgt_info *info); + +static int alloc_dma_bufs(struct slgt_info *info); +static void free_dma_bufs(struct slgt_info *info); +static int alloc_desc(struct slgt_info *info); +static void free_desc(struct slgt_info *info); +static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); +static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); + +static int alloc_tmp_rbuf(struct slgt_info *info); +static void free_tmp_rbuf(struct slgt_info *info); + +static void tx_timeout(unsigned long context); +static void rx_timeout(unsigned long context); + +/* + * ioctl handlers + */ +static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount); +static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params); +static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params); +static int get_txidle(struct slgt_info *info, int __user *idle_mode); +static int set_txidle(struct slgt_info *info, int idle_mode); +static int tx_enable(struct slgt_info *info, int enable); +static int tx_abort(struct slgt_info *info); +static int rx_enable(struct slgt_info *info, int enable); +static int modem_input_wait(struct slgt_info *info,int arg); +static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); +static int tiocmget(struct tty_struct *tty); +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); +static int set_break(struct tty_struct *tty, int break_state); +static int get_interface(struct slgt_info *info, int __user *if_mode); +static int set_interface(struct slgt_info *info, int if_mode); +static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); +static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); +static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); +static int get_xsync(struct slgt_info *info, int __user *if_mode); +static int set_xsync(struct slgt_info *info, int if_mode); +static int get_xctrl(struct slgt_info *info, int __user *if_mode); +static int set_xctrl(struct slgt_info *info, int if_mode); + +/* + * driver functions + */ +static void add_device(struct slgt_info *info); +static void device_init(int adapter_num, struct pci_dev *pdev); +static int claim_resources(struct slgt_info *info); +static void release_resources(struct slgt_info *info); + +/* + * DEBUG OUTPUT CODE + */ +#ifndef DBGINFO +#define DBGINFO(fmt) +#endif +#ifndef DBGERR +#define DBGERR(fmt) +#endif +#ifndef DBGBH +#define DBGBH(fmt) +#endif +#ifndef DBGISR +#define DBGISR(fmt) +#endif + +#ifdef DBGDATA +static void trace_block(struct slgt_info *info, const char *data, int count, const char *label) +{ + int i; + int linecount; + printk("%s %s data:\n",info->device_name, label); + while(count) { + linecount = (count > 16) ? 16 : count; + for(i=0; i < linecount; i++) + printk("%02X ",(unsigned char)data[i]); + for(;i<17;i++) + printk(" "); + for(i=0;i=040 && data[i]<=0176) + printk("%c",data[i]); + else + printk("."); + } + printk("\n"); + data += linecount; + count -= linecount; + } +} +#else +#define DBGDATA(info, buf, size, label) +#endif + +#ifdef DBGTBUF +static void dump_tbufs(struct slgt_info *info) +{ + int i; + printk("tbuf_current=%d\n", info->tbuf_current); + for (i=0 ; i < info->tbuf_count ; i++) { + printk("%d: count=%04X status=%04X\n", + i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status)); + } +} +#else +#define DBGTBUF(info) +#endif + +#ifdef DBGRBUF +static void dump_rbufs(struct slgt_info *info) +{ + int i; + printk("rbuf_current=%d\n", info->rbuf_current); + for (i=0 ; i < info->rbuf_count ; i++) { + printk("%d: count=%04X status=%04X\n", + i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status)); + } +} +#else +#define DBGRBUF(info) +#endif + +static inline int sanity_check(struct slgt_info *info, char *devname, const char *name) +{ +#ifdef SANITY_CHECK + if (!info) { + printk("null struct slgt_info for (%s) in %s\n", devname, name); + return 1; + } + if (info->magic != MGSL_MAGIC) { + printk("bad magic number struct slgt_info (%s) in %s\n", devname, name); + return 1; + } +#else + if (!info) + return 1; +#endif + return 0; +} + +/** + * line discipline callback wrappers + * + * The wrappers maintain line discipline references + * while calling into the line discipline. + * + * ldisc_receive_buf - pass receive data to line discipline + */ +static void ldisc_receive_buf(struct tty_struct *tty, + const __u8 *data, char *flags, int count) +{ + struct tty_ldisc *ld; + if (!tty) + return; + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->ops->receive_buf) + ld->ops->receive_buf(tty, data, flags, count); + tty_ldisc_deref(ld); + } +} + +/* tty callbacks */ + +static int open(struct tty_struct *tty, struct file *filp) +{ + struct slgt_info *info; + int retval, line; + unsigned long flags; + + line = tty->index; + if ((line < 0) || (line >= slgt_device_count)) { + DBGERR(("%s: open with invalid line #%d.\n", driver_name, line)); + return -ENODEV; + } + + info = slgt_device_list; + while(info && info->line != line) + info = info->next_device; + if (sanity_check(info, tty->name, "open")) + return -ENODEV; + if (info->init_error) { + DBGERR(("%s init error=%d\n", info->device_name, info->init_error)); + return -ENODEV; + } + + tty->driver_data = info; + info->port.tty = tty; + + DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count)); + + /* If port is closing, signal caller to try again */ + if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ + if (info->port.flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->port.close_wait); + retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + goto cleanup; + } + + mutex_lock(&info->port.mutex); + info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + spin_lock_irqsave(&info->netlock, flags); + if (info->netcount) { + retval = -EBUSY; + spin_unlock_irqrestore(&info->netlock, flags); + mutex_unlock(&info->port.mutex); + goto cleanup; + } + info->port.count++; + spin_unlock_irqrestore(&info->netlock, flags); + + if (info->port.count == 1) { + /* 1st open on this device, init hardware */ + retval = startup(info); + if (retval < 0) { + mutex_unlock(&info->port.mutex); + goto cleanup; + } + } + mutex_unlock(&info->port.mutex); + retval = block_til_ready(tty, filp, info); + if (retval) { + DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); + goto cleanup; + } + + retval = 0; + +cleanup: + if (retval) { + if (tty->count == 1) + info->port.tty = NULL; /* tty layer will release tty struct */ + if(info->port.count) + info->port.count--; + } + + DBGINFO(("%s open rc=%d\n", info->device_name, retval)); + return retval; +} + +static void close(struct tty_struct *tty, struct file *filp) +{ + struct slgt_info *info = tty->driver_data; + + if (sanity_check(info, tty->name, "close")) + return; + DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); + + if (tty_port_close_start(&info->port, tty, filp) == 0) + goto cleanup; + + mutex_lock(&info->port.mutex); + if (info->port.flags & ASYNC_INITIALIZED) + wait_until_sent(tty, info->timeout); + flush_buffer(tty); + tty_ldisc_flush(tty); + + shutdown(info); + mutex_unlock(&info->port.mutex); + + tty_port_close_end(&info->port, tty); + info->port.tty = NULL; +cleanup: + DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); +} + +static void hangup(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "hangup")) + return; + DBGINFO(("%s hangup\n", info->device_name)); + + flush_buffer(tty); + + mutex_lock(&info->port.mutex); + shutdown(info); + + spin_lock_irqsave(&info->port.lock, flags); + info->port.count = 0; + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; + info->port.tty = NULL; + spin_unlock_irqrestore(&info->port.lock, flags); + mutex_unlock(&info->port.mutex); + + wake_up_interruptible(&info->port.open_wait); +} + +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + DBGINFO(("%s set_termios\n", tty->driver->name)); + + change_params(info); + + /* Handle transition to B0 status */ + if (old_termios->c_cflag & CBAUD && + !(tty->termios->c_cflag & CBAUD)) { + info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + tty->termios->c_cflag & CBAUD) { + info->signals |= SerialSignal_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->signals |= SerialSignal_RTS; + } + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + /* Handle turning off CRTSCTS */ + if (old_termios->c_cflag & CRTSCTS && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + tx_release(tty); + } +} + +static void update_tx_timer(struct slgt_info *info) +{ + /* + * use worst case speed of 1200bps to calculate transmit timeout + * based on data in buffers (tbuf_bytes) and FIFO (128 bytes) + */ + if (info->params.mode == MGSL_MODE_HDLC) { + int timeout = (tbuf_bytes(info) * 7) + 1000; + mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout)); + } +} + +static int write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + int ret = 0; + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "write")) + return -EIO; + + DBGINFO(("%s write count=%d\n", info->device_name, count)); + + if (!info->tx_buf || (count > info->max_frame_size)) + return -EIO; + + if (!count || tty->stopped || tty->hw_stopped) + return 0; + + spin_lock_irqsave(&info->lock, flags); + + if (info->tx_count) { + /* send accumulated data from send_char() */ + if (!tx_load(info, info->tx_buf, info->tx_count)) + goto cleanup; + info->tx_count = 0; + } + + if (tx_load(info, buf, count)) + ret = count; + +cleanup: + spin_unlock_irqrestore(&info->lock, flags); + DBGINFO(("%s write rc=%d\n", info->device_name, ret)); + return ret; +} + +static int put_char(struct tty_struct *tty, unsigned char ch) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + int ret = 0; + + if (sanity_check(info, tty->name, "put_char")) + return 0; + DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); + if (!info->tx_buf) + return 0; + spin_lock_irqsave(&info->lock,flags); + if (info->tx_count < info->max_frame_size) { + info->tx_buf[info->tx_count++] = ch; + ret = 1; + } + spin_unlock_irqrestore(&info->lock,flags); + return ret; +} + +static void send_xchar(struct tty_struct *tty, char ch) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "send_xchar")) + return; + DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch)); + info->x_char = ch; + if (ch) { + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_enabled) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +static void wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct slgt_info *info = tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (!info ) + return; + if (sanity_check(info, tty->name, "wait_until_sent")) + return; + DBGINFO(("%s wait_until_sent entry\n", info->device_name)); + if (!(info->port.flags & ASYNC_INITIALIZED)) + goto exit; + + orig_jiffies = jiffies; + + /* Set check interval to 1/5 of estimated time to + * send a character, and make it at least 1. The check + * interval should also be less than the timeout. + * Note: use tight timings here to satisfy the NIST-PCTS. + */ + + if (info->params.data_rate) { + char_time = info->timeout/(32 * 5); + if (!char_time) + char_time++; + } else + char_time = 1; + + if (timeout) + char_time = min_t(unsigned long, char_time, timeout); + + while (info->tx_active) { + msleep_interruptible(jiffies_to_msecs(char_time)); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } +exit: + DBGINFO(("%s wait_until_sent exit\n", info->device_name)); +} + +static int write_room(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + int ret; + + if (sanity_check(info, tty->name, "write_room")) + return 0; + ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; + DBGINFO(("%s write_room=%d\n", info->device_name, ret)); + return ret; +} + +static void flush_chars(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "flush_chars")) + return; + DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count)); + + if (info->tx_count <= 0 || tty->stopped || + tty->hw_stopped || !info->tx_buf) + return; + + DBGINFO(("%s flush_chars start transmit\n", info->device_name)); + + spin_lock_irqsave(&info->lock,flags); + if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) + info->tx_count = 0; + spin_unlock_irqrestore(&info->lock,flags); +} + +static void flush_buffer(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "flush_buffer")) + return; + DBGINFO(("%s flush_buffer\n", info->device_name)); + + spin_lock_irqsave(&info->lock, flags); + info->tx_count = 0; + spin_unlock_irqrestore(&info->lock, flags); + + tty_wakeup(tty); +} + +/* + * throttle (stop) transmitter + */ +static void tx_hold(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "tx_hold")) + return; + DBGINFO(("%s tx_hold\n", info->device_name)); + spin_lock_irqsave(&info->lock,flags); + if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC) + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* + * release (start) transmitter + */ +static void tx_release(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "tx_release")) + return; + DBGINFO(("%s tx_release\n", info->device_name)); + spin_lock_irqsave(&info->lock, flags); + if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) + info->tx_count = 0; + spin_unlock_irqrestore(&info->lock, flags); +} + +/* + * Service an IOCTL request + * + * Arguments + * + * tty pointer to tty instance data + * cmd IOCTL command code + * arg command argument/context + * + * Return 0 if success, otherwise error code + */ +static int ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct slgt_info *info = tty->driver_data; + void __user *argp = (void __user *)arg; + int ret; + + if (sanity_check(info, tty->name, "ioctl")) + return -ENODEV; + DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case MGSL_IOCWAITEVENT: + return wait_mgsl_event(info, argp); + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); + case MGSL_IOCSGPIO: + return set_gpio(info, argp); + case MGSL_IOCGGPIO: + return get_gpio(info, argp); + case MGSL_IOCWAITGPIO: + return wait_gpio(info, argp); + case MGSL_IOCGXSYNC: + return get_xsync(info, argp); + case MGSL_IOCSXSYNC: + return set_xsync(info, (int)arg); + case MGSL_IOCGXCTRL: + return get_xctrl(info, argp); + case MGSL_IOCSXCTRL: + return set_xctrl(info, (int)arg); + } + mutex_lock(&info->port.mutex); + switch (cmd) { + case MGSL_IOCGPARAMS: + ret = get_params(info, argp); + break; + case MGSL_IOCSPARAMS: + ret = set_params(info, argp); + break; + case MGSL_IOCGTXIDLE: + ret = get_txidle(info, argp); + break; + case MGSL_IOCSTXIDLE: + ret = set_txidle(info, (int)arg); + break; + case MGSL_IOCTXENABLE: + ret = tx_enable(info, (int)arg); + break; + case MGSL_IOCRXENABLE: + ret = rx_enable(info, (int)arg); + break; + case MGSL_IOCTXABORT: + ret = tx_abort(info); + break; + case MGSL_IOCGSTATS: + ret = get_stats(info, argp); + break; + case MGSL_IOCGIF: + ret = get_interface(info, argp); + break; + case MGSL_IOCSIF: + ret = set_interface(info,(int)arg); + break; + default: + ret = -ENOIOCTLCMD; + } + mutex_unlock(&info->port.mutex); + return ret; +} + +static int get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) + +{ + struct slgt_info *info = tty->driver_data; + struct mgsl_icount cnow; /* kernel counter temps */ + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->lock,flags); + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->frame = cnow.frame; + icount->overrun = cnow.overrun; + icount->parity = cnow.parity; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + + return 0; +} + +/* + * support for 32 bit ioctl calls on 64 bit systems + */ +#ifdef CONFIG_COMPAT +static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params) +{ + struct MGSL_PARAMS32 tmp_params; + + DBGINFO(("%s get_params32\n", info->device_name)); + memset(&tmp_params, 0, sizeof(tmp_params)); + tmp_params.mode = (compat_ulong_t)info->params.mode; + tmp_params.loopback = info->params.loopback; + tmp_params.flags = info->params.flags; + tmp_params.encoding = info->params.encoding; + tmp_params.clock_speed = (compat_ulong_t)info->params.clock_speed; + tmp_params.addr_filter = info->params.addr_filter; + tmp_params.crc_type = info->params.crc_type; + tmp_params.preamble_length = info->params.preamble_length; + tmp_params.preamble = info->params.preamble; + tmp_params.data_rate = (compat_ulong_t)info->params.data_rate; + tmp_params.data_bits = info->params.data_bits; + tmp_params.stop_bits = info->params.stop_bits; + tmp_params.parity = info->params.parity; + if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32))) + return -EFAULT; + return 0; +} + +static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params) +{ + struct MGSL_PARAMS32 tmp_params; + + DBGINFO(("%s set_params32\n", info->device_name)); + if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32))) + return -EFAULT; + + spin_lock(&info->lock); + if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) { + info->base_clock = tmp_params.clock_speed; + } else { + info->params.mode = tmp_params.mode; + info->params.loopback = tmp_params.loopback; + info->params.flags = tmp_params.flags; + info->params.encoding = tmp_params.encoding; + info->params.clock_speed = tmp_params.clock_speed; + info->params.addr_filter = tmp_params.addr_filter; + info->params.crc_type = tmp_params.crc_type; + info->params.preamble_length = tmp_params.preamble_length; + info->params.preamble = tmp_params.preamble; + info->params.data_rate = tmp_params.data_rate; + info->params.data_bits = tmp_params.data_bits; + info->params.stop_bits = tmp_params.stop_bits; + info->params.parity = tmp_params.parity; + } + spin_unlock(&info->lock); + + program_hw(info); + + return 0; +} + +static long slgt_compat_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct slgt_info *info = tty->driver_data; + int rc = -ENOIOCTLCMD; + + if (sanity_check(info, tty->name, "compat_ioctl")) + return -ENODEV; + DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd)); + + switch (cmd) { + + case MGSL_IOCSPARAMS32: + rc = set_params32(info, compat_ptr(arg)); + break; + + case MGSL_IOCGPARAMS32: + rc = get_params32(info, compat_ptr(arg)); + break; + + case MGSL_IOCGPARAMS: + case MGSL_IOCSPARAMS: + case MGSL_IOCGTXIDLE: + case MGSL_IOCGSTATS: + case MGSL_IOCWAITEVENT: + case MGSL_IOCGIF: + case MGSL_IOCSGPIO: + case MGSL_IOCGGPIO: + case MGSL_IOCWAITGPIO: + case MGSL_IOCGXSYNC: + case MGSL_IOCGXCTRL: + case MGSL_IOCSTXIDLE: + case MGSL_IOCTXENABLE: + case MGSL_IOCRXENABLE: + case MGSL_IOCTXABORT: + case TIOCMIWAIT: + case MGSL_IOCSIF: + case MGSL_IOCSXSYNC: + case MGSL_IOCSXCTRL: + rc = ioctl(tty, cmd, arg); + break; + } + + DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc)); + return rc; +} +#else +#define slgt_compat_ioctl NULL +#endif /* ifdef CONFIG_COMPAT */ + +/* + * proc fs support + */ +static inline void line_info(struct seq_file *m, struct slgt_info *info) +{ + char stat_buf[30]; + unsigned long flags; + + seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", + info->device_name, info->phys_reg_addr, + info->irq_level, info->max_frame_size); + + /* output current serial signal states */ + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (info->signals & SerialSignal_RTS) + strcat(stat_buf, "|RTS"); + if (info->signals & SerialSignal_CTS) + strcat(stat_buf, "|CTS"); + if (info->signals & SerialSignal_DTR) + strcat(stat_buf, "|DTR"); + if (info->signals & SerialSignal_DSR) + strcat(stat_buf, "|DSR"); + if (info->signals & SerialSignal_DCD) + strcat(stat_buf, "|CD"); + if (info->signals & SerialSignal_RI) + strcat(stat_buf, "|RI"); + + if (info->params.mode != MGSL_MODE_ASYNC) { + seq_printf(m, "\tHDLC txok:%d rxok:%d", + info->icount.txok, info->icount.rxok); + if (info->icount.txunder) + seq_printf(m, " txunder:%d", info->icount.txunder); + if (info->icount.txabort) + seq_printf(m, " txabort:%d", info->icount.txabort); + if (info->icount.rxshort) + seq_printf(m, " rxshort:%d", info->icount.rxshort); + if (info->icount.rxlong) + seq_printf(m, " rxlong:%d", info->icount.rxlong); + if (info->icount.rxover) + seq_printf(m, " rxover:%d", info->icount.rxover); + if (info->icount.rxcrc) + seq_printf(m, " rxcrc:%d", info->icount.rxcrc); + } else { + seq_printf(m, "\tASYNC tx:%d rx:%d", + info->icount.tx, info->icount.rx); + if (info->icount.frame) + seq_printf(m, " fe:%d", info->icount.frame); + if (info->icount.parity) + seq_printf(m, " pe:%d", info->icount.parity); + if (info->icount.brk) + seq_printf(m, " brk:%d", info->icount.brk); + if (info->icount.overrun) + seq_printf(m, " oe:%d", info->icount.overrun); + } + + /* Append serial signal status to end */ + seq_printf(m, " %s\n", stat_buf+1); + + seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", + info->tx_active,info->bh_requested,info->bh_running, + info->pending_bh); +} + +/* Called to print information about devices + */ +static int synclink_gt_proc_show(struct seq_file *m, void *v) +{ + struct slgt_info *info; + + seq_puts(m, "synclink_gt driver\n"); + + info = slgt_device_list; + while( info ) { + line_info(m, info); + info = info->next_device; + } + return 0; +} + +static int synclink_gt_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, synclink_gt_proc_show, NULL); +} + +static const struct file_operations synclink_gt_proc_fops = { + .owner = THIS_MODULE, + .open = synclink_gt_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * return count of bytes in transmit buffer + */ +static int chars_in_buffer(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + int count; + if (sanity_check(info, tty->name, "chars_in_buffer")) + return 0; + count = tbuf_bytes(info); + DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); + return count; +} + +/* + * signal remote device to throttle send data (our receive data) + */ +static void throttle(struct tty_struct * tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "throttle")) + return; + DBGINFO(("%s throttle\n", info->device_name)); + if (I_IXOFF(tty)) + send_xchar(tty, STOP_CHAR(tty)); + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock,flags); + info->signals &= ~SerialSignal_RTS; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* + * signal remote device to stop throttling send data (our receive data) + */ +static void unthrottle(struct tty_struct * tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "unthrottle")) + return; + DBGINFO(("%s unthrottle\n", info->device_name)); + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + send_xchar(tty, START_CHAR(tty)); + } + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock,flags); + info->signals |= SerialSignal_RTS; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* + * set or clear transmit break condition + * break_state -1=set break condition, 0=clear + */ +static int set_break(struct tty_struct *tty, int break_state) +{ + struct slgt_info *info = tty->driver_data; + unsigned short value; + unsigned long flags; + + if (sanity_check(info, tty->name, "set_break")) + return -EINVAL; + DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); + + spin_lock_irqsave(&info->lock,flags); + value = rd_reg16(info, TCR); + if (break_state == -1) + value |= BIT6; + else + value &= ~BIT6; + wr_reg16(info, TCR, value); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +#if SYNCLINK_GENERIC_HDLC + +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) +{ + struct slgt_info *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; + + /* return error if TTY interface open */ + if (info->port.count) + return -EBUSY; + + DBGINFO(("%s hdlcdev_attach\n", info->device_name)); + + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; + } + + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } + + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); + + return 0; +} + +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + */ +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct slgt_info *info = dev_to_port(dev); + unsigned long flags; + + DBGINFO(("%s hdlc_xmit\n", dev->name)); + + if (!skb->len) + return NETDEV_TX_OK; + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* update network statistics */ + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + spin_lock_irqsave(&info->lock, flags); + tx_load(info, skb->data, skb->len); + spin_unlock_irqrestore(&info->lock, flags); + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} + +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) +{ + struct slgt_info *info = dev_to_port(dev); + int rc; + unsigned long flags; + + if (!try_module_get(THIS_MODULE)) + return -EBUSY; + + DBGINFO(("%s hdlcdev_open\n", dev->name)); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + + /* arbitrate between network and tty opens */ + spin_lock_irqsave(&info->netlock, flags); + if (info->port.count != 0 || info->netcount != 0) { + DBGINFO(("%s hdlc_open busy\n", dev->name)); + spin_unlock_irqrestore(&info->netlock, flags); + return -EBUSY; + } + info->netcount=1; + spin_unlock_irqrestore(&info->netlock, flags); + + /* claim resources and init adapter */ + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; + } + + /* assert DTR and RTS, apply hardware settings */ + info->signals |= SerialSignal_RTS + SerialSignal_DTR; + program_hw(info); + + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); + + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); + if (info->signals & SerialSignal_DCD) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + return 0; +} + +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) +{ + struct slgt_info *info = dev_to_port(dev); + unsigned long flags; + + DBGINFO(("%s hdlcdev_close\n", dev->name)); + + netif_stop_queue(dev); + + /* shutdown adapter and release resources */ + shutdown(info); + + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + module_put(THIS_MODULE); + return 0; +} + +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + struct slgt_info *info = dev_to_port(dev); + unsigned int flags; + + DBGINFO(("%s hdlcdev_ioctl\n", dev->name)); + + /* return error if TTY interface open */ + if (info->port.count) + return -EBUSY; + + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); + + memset(&new_line, 0, sizeof(new_line)); + + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ + + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } +} + +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) +{ + struct slgt_info *info = dev_to_port(dev); + unsigned long flags; + + DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name)); + + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; + + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); + + netif_wake_queue(dev); +} + +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(struct slgt_info *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) +{ + struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + + DBGINFO(("%s hdlcdev_rx\n", dev->name)); + + if (skb == NULL) { + DBGERR(("%s: can't alloc skb, drop packet\n", dev->name)); + dev->stats.rx_dropped++; + return; + } + + memcpy(skb_put(skb, size), buf, size); + + skb->protocol = hdlc_type_trans(skb, dev); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += size; + + netif_rx(skb); +} + +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(struct slgt_info *info) +{ + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->mem_start = info->phys_reg_addr; + dev->mem_end = info->phys_reg_addr + SLGT_REG_SIZE - 1; + dev->irq = info->irq_level; + + /* network layer callbacks and settings */ + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; +} + +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(struct slgt_info *info) +{ + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; +} + +#endif /* ifdef CONFIG_HDLC */ + +/* + * get async data from rx DMA buffers + */ +static void rx_async(struct slgt_info *info) +{ + struct tty_struct *tty = info->port.tty; + struct mgsl_icount *icount = &info->icount; + unsigned int start, end; + unsigned char *p; + unsigned char status; + struct slgt_desc *bufs = info->rbufs; + int i, count; + int chars = 0; + int stat; + unsigned char ch; + + start = end = info->rbuf_current; + + while(desc_complete(bufs[end])) { + count = desc_count(bufs[end]) - info->rbuf_index; + p = bufs[end].buf + info->rbuf_index; + + DBGISR(("%s rx_async count=%d\n", info->device_name, count)); + DBGDATA(info, p, count, "rx"); + + for(i=0 ; i < count; i+=2, p+=2) { + ch = *p; + icount->rx++; + + stat = 0; + + if ((status = *(p+1) & (BIT1 + BIT0))) { + if (status & BIT1) + icount->parity++; + else if (status & BIT0) + icount->frame++; + /* discard char if tty control flags say so */ + if (status & info->ignore_status_mask) + continue; + if (status & BIT1) + stat = TTY_PARITY; + else if (status & BIT0) + stat = TTY_FRAME; + } + if (tty) { + tty_insert_flip_char(tty, ch, stat); + chars++; + } + } + + if (i < count) { + /* receive buffer not completed */ + info->rbuf_index += i; + mod_timer(&info->rx_timer, jiffies + 1); + break; + } + + info->rbuf_index = 0; + free_rbufs(info, end, end); + + if (++end == info->rbuf_count) + end = 0; + + /* if entire list searched then no frame available */ + if (end == start) + break; + } + + if (tty && chars) + tty_flip_buffer_push(tty); +} + +/* + * return next bottom half action to perform + */ +static int bh_action(struct slgt_info *info) +{ + unsigned long flags; + int rc; + + spin_lock_irqsave(&info->lock,flags); + + if (info->pending_bh & BH_RECEIVE) { + info->pending_bh &= ~BH_RECEIVE; + rc = BH_RECEIVE; + } else if (info->pending_bh & BH_TRANSMIT) { + info->pending_bh &= ~BH_TRANSMIT; + rc = BH_TRANSMIT; + } else if (info->pending_bh & BH_STATUS) { + info->pending_bh &= ~BH_STATUS; + rc = BH_STATUS; + } else { + /* Mark BH routine as complete */ + info->bh_running = false; + info->bh_requested = false; + rc = 0; + } + + spin_unlock_irqrestore(&info->lock,flags); + + return rc; +} + +/* + * perform bottom half processing + */ +static void bh_handler(struct work_struct *work) +{ + struct slgt_info *info = container_of(work, struct slgt_info, task); + int action; + + if (!info) + return; + info->bh_running = true; + + while((action = bh_action(info))) { + switch (action) { + case BH_RECEIVE: + DBGBH(("%s bh receive\n", info->device_name)); + switch(info->params.mode) { + case MGSL_MODE_ASYNC: + rx_async(info); + break; + case MGSL_MODE_HDLC: + while(rx_get_frame(info)); + break; + case MGSL_MODE_RAW: + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: + case MGSL_MODE_XSYNC: + while(rx_get_buf(info)); + break; + } + /* restart receiver if rx DMA buffers exhausted */ + if (info->rx_restart) + rx_start(info); + break; + case BH_TRANSMIT: + bh_transmit(info); + break; + case BH_STATUS: + DBGBH(("%s bh status\n", info->device_name)); + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + info->dcd_chkcount = 0; + info->cts_chkcount = 0; + break; + default: + DBGBH(("%s unknown action\n", info->device_name)); + break; + } + } + DBGBH(("%s bh_handler exit\n", info->device_name)); +} + +static void bh_transmit(struct slgt_info *info) +{ + struct tty_struct *tty = info->port.tty; + + DBGBH(("%s bh_transmit\n", info->device_name)); + if (tty) + tty_wakeup(tty); +} + +static void dsr_change(struct slgt_info *info, unsigned short status) +{ + if (status & BIT3) { + info->signals |= SerialSignal_DSR; + info->input_signal_events.dsr_up++; + } else { + info->signals &= ~SerialSignal_DSR; + info->input_signal_events.dsr_down++; + } + DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); + if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { + slgt_irq_off(info, IRQ_DSR); + return; + } + info->icount.dsr++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + info->pending_bh |= BH_STATUS; +} + +static void cts_change(struct slgt_info *info, unsigned short status) +{ + if (status & BIT2) { + info->signals |= SerialSignal_CTS; + info->input_signal_events.cts_up++; + } else { + info->signals &= ~SerialSignal_CTS; + info->input_signal_events.cts_down++; + } + DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); + if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { + slgt_irq_off(info, IRQ_CTS); + return; + } + info->icount.cts++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + info->pending_bh |= BH_STATUS; + + if (info->port.flags & ASYNC_CTS_FLOW) { + if (info->port.tty) { + if (info->port.tty->hw_stopped) { + if (info->signals & SerialSignal_CTS) { + info->port.tty->hw_stopped = 0; + info->pending_bh |= BH_TRANSMIT; + return; + } + } else { + if (!(info->signals & SerialSignal_CTS)) + info->port.tty->hw_stopped = 1; + } + } + } +} + +static void dcd_change(struct slgt_info *info, unsigned short status) +{ + if (status & BIT1) { + info->signals |= SerialSignal_DCD; + info->input_signal_events.dcd_up++; + } else { + info->signals &= ~SerialSignal_DCD; + info->input_signal_events.dcd_down++; + } + DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); + if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { + slgt_irq_off(info, IRQ_DCD); + return; + } + info->icount.dcd++; +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) { + if (info->signals & SerialSignal_DCD) + netif_carrier_on(info->netdev); + else + netif_carrier_off(info->netdev); + } +#endif + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + info->pending_bh |= BH_STATUS; + + if (info->port.flags & ASYNC_CHECK_CD) { + if (info->signals & SerialSignal_DCD) + wake_up_interruptible(&info->port.open_wait); + else { + if (info->port.tty) + tty_hangup(info->port.tty); + } + } +} + +static void ri_change(struct slgt_info *info, unsigned short status) +{ + if (status & BIT0) { + info->signals |= SerialSignal_RI; + info->input_signal_events.ri_up++; + } else { + info->signals &= ~SerialSignal_RI; + info->input_signal_events.ri_down++; + } + DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); + if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { + slgt_irq_off(info, IRQ_RI); + return; + } + info->icount.rng++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + info->pending_bh |= BH_STATUS; +} + +static void isr_rxdata(struct slgt_info *info) +{ + unsigned int count = info->rbuf_fill_count; + unsigned int i = info->rbuf_fill_index; + unsigned short reg; + + while (rd_reg16(info, SSR) & IRQ_RXDATA) { + reg = rd_reg16(info, RDR); + DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg)); + if (desc_complete(info->rbufs[i])) { + /* all buffers full */ + rx_stop(info); + info->rx_restart = 1; + continue; + } + info->rbufs[i].buf[count++] = (unsigned char)reg; + /* async mode saves status byte to buffer for each data byte */ + if (info->params.mode == MGSL_MODE_ASYNC) + info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8); + if (count == info->rbuf_fill_level || (reg & BIT10)) { + /* buffer full or end of frame */ + set_desc_count(info->rbufs[i], count); + set_desc_status(info->rbufs[i], BIT15 | (reg >> 8)); + info->rbuf_fill_count = count = 0; + if (++i == info->rbuf_count) + i = 0; + info->pending_bh |= BH_RECEIVE; + } + } + + info->rbuf_fill_index = i; + info->rbuf_fill_count = count; +} + +static void isr_serial(struct slgt_info *info) +{ + unsigned short status = rd_reg16(info, SSR); + + DBGISR(("%s isr_serial status=%04X\n", info->device_name, status)); + + wr_reg16(info, SSR, status); /* clear pending */ + + info->irq_occurred = true; + + if (info->params.mode == MGSL_MODE_ASYNC) { + if (status & IRQ_TXIDLE) { + if (info->tx_active) + isr_txeom(info, status); + } + if (info->rx_pio && (status & IRQ_RXDATA)) + isr_rxdata(info); + if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { + info->icount.brk++; + /* process break detection if tty control allows */ + if (info->port.tty) { + if (!(status & info->ignore_status_mask)) { + if (info->read_status_mask & MASK_BREAK) { + tty_insert_flip_char(info->port.tty, 0, TTY_BREAK); + if (info->port.flags & ASYNC_SAK) + do_SAK(info->port.tty); + } + } + } + } + } else { + if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) + isr_txeom(info, status); + if (info->rx_pio && (status & IRQ_RXDATA)) + isr_rxdata(info); + if (status & IRQ_RXIDLE) { + if (status & RXIDLE) + info->icount.rxidle++; + else + info->icount.exithunt++; + wake_up_interruptible(&info->event_wait_q); + } + + if (status & IRQ_RXOVER) + rx_start(info); + } + + if (status & IRQ_DSR) + dsr_change(info, status); + if (status & IRQ_CTS) + cts_change(info, status); + if (status & IRQ_DCD) + dcd_change(info, status); + if (status & IRQ_RI) + ri_change(info, status); +} + +static void isr_rdma(struct slgt_info *info) +{ + unsigned int status = rd_reg32(info, RDCSR); + + DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status)); + + /* RDCSR (rx DMA control/status) + * + * 31..07 reserved + * 06 save status byte to DMA buffer + * 05 error + * 04 eol (end of list) + * 03 eob (end of buffer) + * 02 IRQ enable + * 01 reset + * 00 enable + */ + wr_reg32(info, RDCSR, status); /* clear pending */ + + if (status & (BIT5 + BIT4)) { + DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name)); + info->rx_restart = true; + } + info->pending_bh |= BH_RECEIVE; +} + +static void isr_tdma(struct slgt_info *info) +{ + unsigned int status = rd_reg32(info, TDCSR); + + DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status)); + + /* TDCSR (tx DMA control/status) + * + * 31..06 reserved + * 05 error + * 04 eol (end of list) + * 03 eob (end of buffer) + * 02 IRQ enable + * 01 reset + * 00 enable + */ + wr_reg32(info, TDCSR, status); /* clear pending */ + + if (status & (BIT5 + BIT4 + BIT3)) { + // another transmit buffer has completed + // run bottom half to get more send data from user + info->pending_bh |= BH_TRANSMIT; + } +} + +/* + * return true if there are unsent tx DMA buffers, otherwise false + * + * if there are unsent buffers then info->tbuf_start + * is set to index of first unsent buffer + */ +static bool unsent_tbufs(struct slgt_info *info) +{ + unsigned int i = info->tbuf_current; + bool rc = false; + + /* + * search backwards from last loaded buffer (precedes tbuf_current) + * for first unsent buffer (desc_count > 0) + */ + + do { + if (i) + i--; + else + i = info->tbuf_count - 1; + if (!desc_count(info->tbufs[i])) + break; + info->tbuf_start = i; + rc = true; + } while (i != info->tbuf_current); + + return rc; +} + +static void isr_txeom(struct slgt_info *info, unsigned short status) +{ + DBGISR(("%s txeom status=%04x\n", info->device_name, status)); + + slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); + tdma_reset(info); + if (status & IRQ_TXUNDER) { + unsigned short val = rd_reg16(info, TCR); + wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ + wr_reg16(info, TCR, val); /* clear reset bit */ + } + + if (info->tx_active) { + if (info->params.mode != MGSL_MODE_ASYNC) { + if (status & IRQ_TXUNDER) + info->icount.txunder++; + else if (status & IRQ_TXIDLE) + info->icount.txok++; + } + + if (unsent_tbufs(info)) { + tx_start(info); + update_tx_timer(info); + return; + } + info->tx_active = false; + + del_timer(&info->tx_timer); + + if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) { + info->signals &= ~SerialSignal_RTS; + info->drop_rts_on_tx_done = false; + set_signals(info); + } + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_tx_done(info); + else +#endif + { + if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { + tx_stop(info); + return; + } + info->pending_bh |= BH_TRANSMIT; + } + } +} + +static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state) +{ + struct cond_wait *w, *prev; + + /* wake processes waiting for specific transitions */ + for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) { + if (w->data & changed) { + w->data = state; + wake_up_interruptible(&w->q); + if (prev != NULL) + prev->next = w->next; + else + info->gpio_wait_q = w->next; + } else + prev = w; + } +} + +/* interrupt service routine + * + * irq interrupt number + * dev_id device ID supplied during interrupt registration + */ +static irqreturn_t slgt_interrupt(int dummy, void *dev_id) +{ + struct slgt_info *info = dev_id; + unsigned int gsr; + unsigned int i; + + DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); + + while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { + DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); + info->irq_occurred = true; + for(i=0; i < info->port_count ; i++) { + if (info->port_array[i] == NULL) + continue; + spin_lock(&info->port_array[i]->lock); + if (gsr & (BIT8 << i)) + isr_serial(info->port_array[i]); + if (gsr & (BIT16 << (i*2))) + isr_rdma(info->port_array[i]); + if (gsr & (BIT17 << (i*2))) + isr_tdma(info->port_array[i]); + spin_unlock(&info->port_array[i]->lock); + } + } + + if (info->gpio_present) { + unsigned int state; + unsigned int changed; + spin_lock(&info->lock); + while ((changed = rd_reg32(info, IOSR)) != 0) { + DBGISR(("%s iosr=%08x\n", info->device_name, changed)); + /* read latched state of GPIO signals */ + state = rd_reg32(info, IOVR); + /* clear pending GPIO interrupt bits */ + wr_reg32(info, IOSR, changed); + for (i=0 ; i < info->port_count ; i++) { + if (info->port_array[i] != NULL) + isr_gpio(info->port_array[i], changed, state); + } + } + spin_unlock(&info->lock); + } + + for(i=0; i < info->port_count ; i++) { + struct slgt_info *port = info->port_array[i]; + if (port == NULL) + continue; + spin_lock(&port->lock); + if ((port->port.count || port->netcount) && + port->pending_bh && !port->bh_running && + !port->bh_requested) { + DBGISR(("%s bh queued\n", port->device_name)); + schedule_work(&port->task); + port->bh_requested = true; + } + spin_unlock(&port->lock); + } + + DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); + return IRQ_HANDLED; +} + +static int startup(struct slgt_info *info) +{ + DBGINFO(("%s startup\n", info->device_name)); + + if (info->port.flags & ASYNC_INITIALIZED) + return 0; + + if (!info->tx_buf) { + info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); + if (!info->tx_buf) { + DBGERR(("%s can't allocate tx buffer\n", info->device_name)); + return -ENOMEM; + } + } + + info->pending_bh = 0; + + memset(&info->icount, 0, sizeof(info->icount)); + + /* program hardware for current parameters */ + change_params(info); + + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); + + info->port.flags |= ASYNC_INITIALIZED; + + return 0; +} + +/* + * called by close() and hangup() to shutdown hardware + */ +static void shutdown(struct slgt_info *info) +{ + unsigned long flags; + + if (!(info->port.flags & ASYNC_INITIALIZED)) + return; + + DBGINFO(("%s shutdown\n", info->device_name)); + + /* clear status wait queue because status changes */ + /* can't happen after shutting down the hardware */ + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + del_timer_sync(&info->tx_timer); + del_timer_sync(&info->rx_timer); + + kfree(info->tx_buf); + info->tx_buf = NULL; + + spin_lock_irqsave(&info->lock,flags); + + tx_stop(info); + rx_stop(info); + + slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); + + if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { + info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + set_signals(info); + } + + flush_cond_wait(&info->gpio_wait_q); + + spin_unlock_irqrestore(&info->lock,flags); + + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); + + info->port.flags &= ~ASYNC_INITIALIZED; +} + +static void program_hw(struct slgt_info *info) +{ + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + + rx_stop(info); + tx_stop(info); + + if (info->params.mode != MGSL_MODE_ASYNC || + info->netcount) + sync_mode(info); + else + async_mode(info); + + set_signals(info); + + info->dcd_chkcount = 0; + info->cts_chkcount = 0; + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + + slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI); + get_signals(info); + + if (info->netcount || + (info->port.tty && info->port.tty->termios->c_cflag & CREAD)) + rx_start(info); + + spin_unlock_irqrestore(&info->lock,flags); +} + +/* + * reconfigure adapter based on new parameters + */ +static void change_params(struct slgt_info *info) +{ + unsigned cflag; + int bits_per_char; + + if (!info->port.tty || !info->port.tty->termios) + return; + DBGINFO(("%s change_params\n", info->device_name)); + + cflag = info->port.tty->termios->c_cflag; + + /* if B0 rate (hangup) specified then negate DTR and RTS */ + /* otherwise assert DTR and RTS */ + if (cflag & CBAUD) + info->signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + + /* byte size and parity */ + + switch (cflag & CSIZE) { + case CS5: info->params.data_bits = 5; break; + case CS6: info->params.data_bits = 6; break; + case CS7: info->params.data_bits = 7; break; + case CS8: info->params.data_bits = 8; break; + default: info->params.data_bits = 7; break; + } + + info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1; + + if (cflag & PARENB) + info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN; + else + info->params.parity = ASYNC_PARITY_NONE; + + /* calculate number of jiffies to transmit a full + * FIFO (32 bytes) at specified data rate + */ + bits_per_char = info->params.data_bits + + info->params.stop_bits + 1; + + info->params.data_rate = tty_get_baud_rate(info->port.tty); + + if (info->params.data_rate) { + info->timeout = (32*HZ*bits_per_char) / + info->params.data_rate; + } + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + if (cflag & CRTSCTS) + info->port.flags |= ASYNC_CTS_FLOW; + else + info->port.flags &= ~ASYNC_CTS_FLOW; + + if (cflag & CLOCAL) + info->port.flags &= ~ASYNC_CHECK_CD; + else + info->port.flags |= ASYNC_CHECK_CD; + + /* process tty input control flags */ + + info->read_status_mask = IRQ_RXOVER; + if (I_INPCK(info->port.tty)) + info->read_status_mask |= MASK_PARITY | MASK_FRAMING; + if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) + info->read_status_mask |= MASK_BREAK; + if (I_IGNPAR(info->port.tty)) + info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING; + if (I_IGNBRK(info->port.tty)) { + info->ignore_status_mask |= MASK_BREAK; + /* If ignoring parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->port.tty)) + info->ignore_status_mask |= MASK_OVERRUN; + } + + program_hw(info); +} + +static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount) +{ + DBGINFO(("%s get_stats\n", info->device_name)); + if (!user_icount) { + memset(&info->icount, 0, sizeof(info->icount)); + } else { + if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount))) + return -EFAULT; + } + return 0; +} + +static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params) +{ + DBGINFO(("%s get_params\n", info->device_name)); + if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS))) + return -EFAULT; + return 0; +} + +static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params) +{ + unsigned long flags; + MGSL_PARAMS tmp_params; + + DBGINFO(("%s set_params\n", info->device_name)); + if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS))) + return -EFAULT; + + spin_lock_irqsave(&info->lock, flags); + if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) + info->base_clock = tmp_params.clock_speed; + else + memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS)); + spin_unlock_irqrestore(&info->lock, flags); + + program_hw(info); + + return 0; +} + +static int get_txidle(struct slgt_info *info, int __user *idle_mode) +{ + DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode)); + if (put_user(info->idle_mode, idle_mode)) + return -EFAULT; + return 0; +} + +static int set_txidle(struct slgt_info *info, int idle_mode) +{ + unsigned long flags; + DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); + spin_lock_irqsave(&info->lock,flags); + info->idle_mode = idle_mode; + if (info->params.mode != MGSL_MODE_ASYNC) + tx_set_idle(info); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int tx_enable(struct slgt_info *info, int enable) +{ + unsigned long flags; + DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable)); + spin_lock_irqsave(&info->lock,flags); + if (enable) { + if (!info->tx_enabled) + tx_start(info); + } else { + if (info->tx_enabled) + tx_stop(info); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +/* + * abort transmit HDLC frame + */ +static int tx_abort(struct slgt_info *info) +{ + unsigned long flags; + DBGINFO(("%s tx_abort\n", info->device_name)); + spin_lock_irqsave(&info->lock,flags); + tdma_reset(info); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int rx_enable(struct slgt_info *info, int enable) +{ + unsigned long flags; + unsigned int rbuf_fill_level; + DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable)); + spin_lock_irqsave(&info->lock,flags); + /* + * enable[31..16] = receive DMA buffer fill level + * 0 = noop (leave fill level unchanged) + * fill level must be multiple of 4 and <= buffer size + */ + rbuf_fill_level = ((unsigned int)enable) >> 16; + if (rbuf_fill_level) { + if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) { + spin_unlock_irqrestore(&info->lock, flags); + return -EINVAL; + } + info->rbuf_fill_level = rbuf_fill_level; + if (rbuf_fill_level < 128) + info->rx_pio = 1; /* PIO mode */ + else + info->rx_pio = 0; /* DMA mode */ + rx_stop(info); /* restart receiver to use new fill level */ + } + + /* + * enable[1..0] = receiver enable command + * 0 = disable + * 1 = enable + * 2 = enable or force hunt mode if already enabled + */ + enable &= 3; + if (enable) { + if (!info->rx_enabled) + rx_start(info); + else if (enable == 2) { + /* force hunt mode (write 1 to RCR[3]) */ + wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3); + } + } else { + if (info->rx_enabled) + rx_stop(info); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +/* + * wait for specified event to occur + */ +static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr) +{ + unsigned long flags; + int s; + int rc=0; + struct mgsl_icount cprev, cnow; + int events; + int mask; + struct _input_signal_events oldsigs, newsigs; + DECLARE_WAITQUEUE(wait, current); + + if (get_user(mask, mask_ptr)) + return -EFAULT; + + DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask)); + + spin_lock_irqsave(&info->lock,flags); + + /* return immediately if state matches requested events */ + get_signals(info); + s = info->signals; + + events = mask & + ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + + ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + + ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + + ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); + if (events) { + spin_unlock_irqrestore(&info->lock,flags); + goto exit; + } + + /* save current irq counts */ + cprev = info->icount; + oldsigs = info->input_signal_events; + + /* enable hunt and idle irqs if needed */ + if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) { + unsigned short val = rd_reg16(info, SCR); + if (!(val & IRQ_RXIDLE)) + wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE)); + } + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&info->event_wait_q, &wait); + + spin_unlock_irqrestore(&info->lock,flags); + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get current irq counts */ + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + newsigs = info->input_signal_events; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + /* if no change, wait aborted for some reason */ + if (newsigs.dsr_up == oldsigs.dsr_up && + newsigs.dsr_down == oldsigs.dsr_down && + newsigs.dcd_up == oldsigs.dcd_up && + newsigs.dcd_down == oldsigs.dcd_down && + newsigs.cts_up == oldsigs.cts_up && + newsigs.cts_down == oldsigs.cts_down && + newsigs.ri_up == oldsigs.ri_up && + newsigs.ri_down == oldsigs.ri_down && + cnow.exithunt == cprev.exithunt && + cnow.rxidle == cprev.rxidle) { + rc = -EIO; + break; + } + + events = mask & + ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + + (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + + (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + + (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + + (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + + (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + + (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + + (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + + (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + + (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); + if (events) + break; + + cprev = cnow; + oldsigs = newsigs; + } + + remove_wait_queue(&info->event_wait_q, &wait); + set_current_state(TASK_RUNNING); + + + if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { + spin_lock_irqsave(&info->lock,flags); + if (!waitqueue_active(&info->event_wait_q)) { + /* disable enable exit hunt mode/idle rcvd IRQs */ + wr_reg16(info, SCR, + (unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE)); + } + spin_unlock_irqrestore(&info->lock,flags); + } +exit: + if (rc == 0) + rc = put_user(events, mask_ptr); + return rc; +} + +static int get_interface(struct slgt_info *info, int __user *if_mode) +{ + DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode)); + if (put_user(info->if_mode, if_mode)) + return -EFAULT; + return 0; +} + +static int set_interface(struct slgt_info *info, int if_mode) +{ + unsigned long flags; + unsigned short val; + + DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode)); + spin_lock_irqsave(&info->lock,flags); + info->if_mode = if_mode; + + msc_set_vcr(info); + + /* TCR (tx control) 07 1=RTS driver control */ + val = rd_reg16(info, TCR); + if (info->if_mode & MGSL_INTERFACE_RTS_EN) + val |= BIT7; + else + val &= ~BIT7; + wr_reg16(info, TCR, val); + + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int get_xsync(struct slgt_info *info, int __user *xsync) +{ + DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync)); + if (put_user(info->xsync, xsync)) + return -EFAULT; + return 0; +} + +/* + * set extended sync pattern (1 to 4 bytes) for extended sync mode + * + * sync pattern is contained in least significant bytes of value + * most significant byte of sync pattern is oldest (1st sent/detected) + */ +static int set_xsync(struct slgt_info *info, int xsync) +{ + unsigned long flags; + + DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync)); + spin_lock_irqsave(&info->lock, flags); + info->xsync = xsync; + wr_reg32(info, XSR, xsync); + spin_unlock_irqrestore(&info->lock, flags); + return 0; +} + +static int get_xctrl(struct slgt_info *info, int __user *xctrl) +{ + DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl)); + if (put_user(info->xctrl, xctrl)) + return -EFAULT; + return 0; +} + +/* + * set extended control options + * + * xctrl[31:19] reserved, must be zero + * xctrl[18:17] extended sync pattern length in bytes + * 00 = 1 byte in xsr[7:0] + * 01 = 2 bytes in xsr[15:0] + * 10 = 3 bytes in xsr[23:0] + * 11 = 4 bytes in xsr[31:0] + * xctrl[16] 1 = enable terminal count, 0=disabled + * xctrl[15:0] receive terminal count for fixed length packets + * value is count minus one (0 = 1 byte packet) + * when terminal count is reached, receiver + * automatically returns to hunt mode and receive + * FIFO contents are flushed to DMA buffers with + * end of frame (EOF) status + */ +static int set_xctrl(struct slgt_info *info, int xctrl) +{ + unsigned long flags; + + DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl)); + spin_lock_irqsave(&info->lock, flags); + info->xctrl = xctrl; + wr_reg32(info, XCR, xctrl); + spin_unlock_irqrestore(&info->lock, flags); + return 0; +} + +/* + * set general purpose IO pin state and direction + * + * user_gpio fields: + * state each bit indicates a pin state + * smask set bit indicates pin state to set + * dir each bit indicates a pin direction (0=input, 1=output) + * dmask set bit indicates pin direction to set + */ +static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) +{ + unsigned long flags; + struct gpio_desc gpio; + __u32 data; + + if (!info->gpio_present) + return -EINVAL; + if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) + return -EFAULT; + DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n", + info->device_name, gpio.state, gpio.smask, + gpio.dir, gpio.dmask)); + + spin_lock_irqsave(&info->port_array[0]->lock, flags); + if (gpio.dmask) { + data = rd_reg32(info, IODR); + data |= gpio.dmask & gpio.dir; + data &= ~(gpio.dmask & ~gpio.dir); + wr_reg32(info, IODR, data); + } + if (gpio.smask) { + data = rd_reg32(info, IOVR); + data |= gpio.smask & gpio.state; + data &= ~(gpio.smask & ~gpio.state); + wr_reg32(info, IOVR, data); + } + spin_unlock_irqrestore(&info->port_array[0]->lock, flags); + + return 0; +} + +/* + * get general purpose IO pin state and direction + */ +static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) +{ + struct gpio_desc gpio; + if (!info->gpio_present) + return -EINVAL; + gpio.state = rd_reg32(info, IOVR); + gpio.smask = 0xffffffff; + gpio.dir = rd_reg32(info, IODR); + gpio.dmask = 0xffffffff; + if (copy_to_user(user_gpio, &gpio, sizeof(gpio))) + return -EFAULT; + DBGINFO(("%s get_gpio state=%08x dir=%08x\n", + info->device_name, gpio.state, gpio.dir)); + return 0; +} + +/* + * conditional wait facility + */ +static void init_cond_wait(struct cond_wait *w, unsigned int data) +{ + init_waitqueue_head(&w->q); + init_waitqueue_entry(&w->wait, current); + w->data = data; +} + +static void add_cond_wait(struct cond_wait **head, struct cond_wait *w) +{ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&w->q, &w->wait); + w->next = *head; + *head = w; +} + +static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw) +{ + struct cond_wait *w, *prev; + remove_wait_queue(&cw->q, &cw->wait); + set_current_state(TASK_RUNNING); + for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) { + if (w == cw) { + if (prev != NULL) + prev->next = w->next; + else + *head = w->next; + break; + } + } +} + +static void flush_cond_wait(struct cond_wait **head) +{ + while (*head != NULL) { + wake_up_interruptible(&(*head)->q); + *head = (*head)->next; + } +} + +/* + * wait for general purpose I/O pin(s) to enter specified state + * + * user_gpio fields: + * state - bit indicates target pin state + * smask - set bit indicates watched pin + * + * The wait ends when at least one watched pin enters the specified + * state. When 0 (no error) is returned, user_gpio->state is set to the + * state of all GPIO pins when the wait ends. + * + * Note: Each pin may be a dedicated input, dedicated output, or + * configurable input/output. The number and configuration of pins + * varies with the specific adapter model. Only input pins (dedicated + * or configured) can be monitored with this function. + */ +static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) +{ + unsigned long flags; + int rc = 0; + struct gpio_desc gpio; + struct cond_wait wait; + u32 state; + + if (!info->gpio_present) + return -EINVAL; + if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) + return -EFAULT; + DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n", + info->device_name, gpio.state, gpio.smask)); + /* ignore output pins identified by set IODR bit */ + if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0) + return -EINVAL; + init_cond_wait(&wait, gpio.smask); + + spin_lock_irqsave(&info->port_array[0]->lock, flags); + /* enable interrupts for watched pins */ + wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); + /* get current pin states */ + state = rd_reg32(info, IOVR); + + if (gpio.smask & ~(state ^ gpio.state)) { + /* already in target state */ + gpio.state = state; + } else { + /* wait for target state */ + add_cond_wait(&info->gpio_wait_q, &wait); + spin_unlock_irqrestore(&info->port_array[0]->lock, flags); + schedule(); + if (signal_pending(current)) + rc = -ERESTARTSYS; + else + gpio.state = wait.data; + spin_lock_irqsave(&info->port_array[0]->lock, flags); + remove_cond_wait(&info->gpio_wait_q, &wait); + } + + /* disable all GPIO interrupts if no waiting processes */ + if (info->gpio_wait_q == NULL) + wr_reg32(info, IOER, 0); + spin_unlock_irqrestore(&info->port_array[0]->lock, flags); + + if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) + rc = -EFAULT; + return rc; +} + +static int modem_input_wait(struct slgt_info *info,int arg) +{ + unsigned long flags; + int rc; + struct mgsl_icount cprev, cnow; + DECLARE_WAITQUEUE(wait, current); + + /* save current irq counts */ + spin_lock_irqsave(&info->lock,flags); + cprev = info->icount; + add_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get new irq counts */ + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + /* if no change, wait aborted for some reason */ + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + rc = -EIO; + break; + } + + /* check for change in caller specified modem input */ + if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || + (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || + (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || + (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { + rc = 0; + break; + } + + cprev = cnow; + } + remove_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_RUNNING); + return rc; +} + +/* + * return state of serial control and status signals + */ +static int tiocmget(struct tty_struct *tty) +{ + struct slgt_info *info = tty->driver_data; + unsigned int result; + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) + + ((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) + + ((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) + + ((info->signals & SerialSignal_RI) ? TIOCM_RNG:0) + + ((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) + + ((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0); + + DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result)); + return result; +} + +/* + * set modem control signals (DTR/RTS) + * + * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit + * TIOCMSET = set/clear signal values + * value bit mask for command + */ +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct slgt_info *info = tty->driver_data; + unsigned long flags; + + DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear)); + + if (set & TIOCM_RTS) + info->signals |= SerialSignal_RTS; + if (set & TIOCM_DTR) + info->signals |= SerialSignal_DTR; + if (clear & TIOCM_RTS) + info->signals &= ~SerialSignal_RTS; + if (clear & TIOCM_DTR) + info->signals &= ~SerialSignal_DTR; + + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int carrier_raised(struct tty_port *port) +{ + unsigned long flags; + struct slgt_info *info = container_of(port, struct slgt_info, port); + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + return (info->signals & SerialSignal_DCD) ? 1 : 0; +} + +static void dtr_rts(struct tty_port *port, int on) +{ + unsigned long flags; + struct slgt_info *info = container_of(port, struct slgt_info, port); + + spin_lock_irqsave(&info->lock,flags); + if (on) + info->signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); +} + + +/* + * block current process until the device is ready to open + */ +static int block_til_ready(struct tty_struct *tty, struct file *filp, + struct slgt_info *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + bool do_clocal = false; + bool extra_count = false; + unsigned long flags; + int cd; + struct tty_port *port = &info->port; + + DBGINFO(("%s block_til_ready\n", tty->driver->name)); + + if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ + /* nonblock mode is set or port is not enabled */ + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = true; + + /* Wait for carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, port->count is dropped by one, so that + * close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + + retval = 0; + add_wait_queue(&port->open_wait, &wait); + + spin_lock_irqsave(&info->lock, flags); + if (!tty_hung_up_p(filp)) { + extra_count = true; + port->count--; + } + spin_unlock_irqrestore(&info->lock, flags); + port->blocked_open++; + + while (1) { + if ((tty->termios->c_cflag & CBAUD)) + tty_port_raise_dtr_rts(port); + + set_current_state(TASK_INTERRUPTIBLE); + + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ + retval = (port->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS; + break; + } + + cd = tty_port_carrier_raised(port); + + if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd )) + break; + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + + DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); + tty_unlock(); + schedule(); + tty_lock(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + + if (extra_count) + port->count++; + port->blocked_open--; + + if (!retval) + port->flags |= ASYNC_NORMAL_ACTIVE; + + DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); + return retval; +} + +static int alloc_tmp_rbuf(struct slgt_info *info) +{ + info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL); + if (info->tmp_rbuf == NULL) + return -ENOMEM; + return 0; +} + +static void free_tmp_rbuf(struct slgt_info *info) +{ + kfree(info->tmp_rbuf); + info->tmp_rbuf = NULL; +} + +/* + * allocate DMA descriptor lists. + */ +static int alloc_desc(struct slgt_info *info) +{ + unsigned int i; + unsigned int pbufs; + + /* allocate memory to hold descriptor lists */ + info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr); + if (info->bufs == NULL) + return -ENOMEM; + + memset(info->bufs, 0, DESC_LIST_SIZE); + + info->rbufs = (struct slgt_desc*)info->bufs; + info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count; + + pbufs = (unsigned int)info->bufs_dma_addr; + + /* + * Build circular lists of descriptors + */ + + for (i=0; i < info->rbuf_count; i++) { + /* physical address of this descriptor */ + info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc)); + + /* physical address of next descriptor */ + if (i == info->rbuf_count - 1) + info->rbufs[i].next = cpu_to_le32(pbufs); + else + info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc))); + set_desc_count(info->rbufs[i], DMABUFSIZE); + } + + for (i=0; i < info->tbuf_count; i++) { + /* physical address of this descriptor */ + info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc)); + + /* physical address of next descriptor */ + if (i == info->tbuf_count - 1) + info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc)); + else + info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc))); + } + + return 0; +} + +static void free_desc(struct slgt_info *info) +{ + if (info->bufs != NULL) { + pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr); + info->bufs = NULL; + info->rbufs = NULL; + info->tbufs = NULL; + } +} + +static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) +{ + int i; + for (i=0; i < count; i++) { + if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL) + return -ENOMEM; + bufs[i].pbuf = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr); + } + return 0; +} + +static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) +{ + int i; + for (i=0; i < count; i++) { + if (bufs[i].buf == NULL) + continue; + pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr); + bufs[i].buf = NULL; + } +} + +static int alloc_dma_bufs(struct slgt_info *info) +{ + info->rbuf_count = 32; + info->tbuf_count = 32; + + if (alloc_desc(info) < 0 || + alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 || + alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 || + alloc_tmp_rbuf(info) < 0) { + DBGERR(("%s DMA buffer alloc fail\n", info->device_name)); + return -ENOMEM; + } + reset_rbufs(info); + return 0; +} + +static void free_dma_bufs(struct slgt_info *info) +{ + if (info->bufs) { + free_bufs(info, info->rbufs, info->rbuf_count); + free_bufs(info, info->tbufs, info->tbuf_count); + free_desc(info); + } + free_tmp_rbuf(info); +} + +static int claim_resources(struct slgt_info *info) +{ + if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) { + DBGERR(("%s reg addr conflict, addr=%08X\n", + info->device_name, info->phys_reg_addr)); + info->init_error = DiagStatus_AddressConflict; + goto errout; + } + else + info->reg_addr_requested = true; + + info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE); + if (!info->reg_addr) { + DBGERR(("%s cant map device registers, addr=%08X\n", + info->device_name, info->phys_reg_addr)); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + return 0; + +errout: + release_resources(info); + return -ENODEV; +} + +static void release_resources(struct slgt_info *info) +{ + if (info->irq_requested) { + free_irq(info->irq_level, info); + info->irq_requested = false; + } + + if (info->reg_addr_requested) { + release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE); + info->reg_addr_requested = false; + } + + if (info->reg_addr) { + iounmap(info->reg_addr); + info->reg_addr = NULL; + } +} + +/* Add the specified device instance data structure to the + * global linked list of devices and increment the device count. + */ +static void add_device(struct slgt_info *info) +{ + char *devstr; + + info->next_device = NULL; + info->line = slgt_device_count; + sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line); + + if (info->line < MAX_DEVICES) { + if (maxframe[info->line]) + info->max_frame_size = maxframe[info->line]; + } + + slgt_device_count++; + + if (!slgt_device_list) + slgt_device_list = info; + else { + struct slgt_info *current_dev = slgt_device_list; + while(current_dev->next_device) + current_dev = current_dev->next_device; + current_dev->next_device = info; + } + + if (info->max_frame_size < 4096) + info->max_frame_size = 4096; + else if (info->max_frame_size > 65535) + info->max_frame_size = 65535; + + switch(info->pdev->device) { + case SYNCLINK_GT_DEVICE_ID: + devstr = "GT"; + break; + case SYNCLINK_GT2_DEVICE_ID: + devstr = "GT2"; + break; + case SYNCLINK_GT4_DEVICE_ID: + devstr = "GT4"; + break; + case SYNCLINK_AC_DEVICE_ID: + devstr = "AC"; + info->params.mode = MGSL_MODE_ASYNC; + break; + default: + devstr = "(unknown model)"; + } + printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n", + devstr, info->device_name, info->phys_reg_addr, + info->irq_level, info->max_frame_size); + +#if SYNCLINK_GENERIC_HDLC + hdlcdev_init(info); +#endif +} + +static const struct tty_port_operations slgt_port_ops = { + .carrier_raised = carrier_raised, + .dtr_rts = dtr_rts, +}; + +/* + * allocate device instance structure, return NULL on failure + */ +static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) +{ + struct slgt_info *info; + + info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL); + + if (!info) { + DBGERR(("%s device alloc failed adapter=%d port=%d\n", + driver_name, adapter_num, port_num)); + } else { + tty_port_init(&info->port); + info->port.ops = &slgt_port_ops; + info->magic = MGSL_MAGIC; + INIT_WORK(&info->task, bh_handler); + info->max_frame_size = 4096; + info->base_clock = 14745600; + info->rbuf_fill_level = DMABUFSIZE; + info->port.close_delay = 5*HZ/10; + info->port.closing_wait = 30*HZ; + init_waitqueue_head(&info->status_event_wait_q); + init_waitqueue_head(&info->event_wait_q); + spin_lock_init(&info->netlock); + memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); + info->idle_mode = HDLC_TXIDLE_FLAGS; + info->adapter_num = adapter_num; + info->port_num = port_num; + + 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; + info->irq_level = pdev->irq; + info->phys_reg_addr = pci_resource_start(pdev,0); + + info->bus_type = MGSL_BUS_TYPE_PCI; + info->irq_flags = IRQF_SHARED; + + info->init_error = -1; /* assume error, set to 0 on successful init */ + } + + return info; +} + +static void device_init(int adapter_num, struct pci_dev *pdev) +{ + struct slgt_info *port_array[SLGT_MAX_PORTS]; + int i; + int port_count = 1; + + if (pdev->device == SYNCLINK_GT2_DEVICE_ID) + port_count = 2; + else if (pdev->device == SYNCLINK_GT4_DEVICE_ID) + port_count = 4; + + /* allocate device instances for all ports */ + for (i=0; i < port_count; ++i) { + port_array[i] = alloc_dev(adapter_num, i, pdev); + if (port_array[i] == NULL) { + for (--i; i >= 0; --i) + kfree(port_array[i]); + return; + } + } + + /* give copy of port_array to all ports and add to device list */ + for (i=0; i < port_count; ++i) { + memcpy(port_array[i]->port_array, port_array, sizeof(port_array)); + add_device(port_array[i]); + port_array[i]->port_count = port_count; + spin_lock_init(&port_array[i]->lock); + } + + /* Allocate and claim adapter resources */ + if (!claim_resources(port_array[0])) { + + alloc_dma_bufs(port_array[0]); + + /* copy resource information from first port to others */ + for (i = 1; i < port_count; ++i) { + port_array[i]->irq_level = port_array[0]->irq_level; + port_array[i]->reg_addr = port_array[0]->reg_addr; + alloc_dma_bufs(port_array[i]); + } + + if (request_irq(port_array[0]->irq_level, + slgt_interrupt, + port_array[0]->irq_flags, + port_array[0]->device_name, + port_array[0]) < 0) { + DBGERR(("%s request_irq failed IRQ=%d\n", + port_array[0]->device_name, + port_array[0]->irq_level)); + } else { + port_array[0]->irq_requested = true; + adapter_test(port_array[0]); + for (i=1 ; i < port_count ; i++) { + port_array[i]->init_error = port_array[0]->init_error; + port_array[i]->gpio_present = port_array[0]->gpio_present; + } + } + } + + for (i=0; i < port_count; ++i) + tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev)); +} + +static int __devinit init_one(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + if (pci_enable_device(dev)) { + printk("error enabling pci device %p\n", dev); + return -EIO; + } + pci_set_master(dev); + device_init(slgt_device_count, dev); + return 0; +} + +static void __devexit remove_one(struct pci_dev *dev) +{ +} + +static const struct tty_operations ops = { + .open = open, + .close = close, + .write = write, + .put_char = put_char, + .flush_chars = flush_chars, + .write_room = write_room, + .chars_in_buffer = chars_in_buffer, + .flush_buffer = flush_buffer, + .ioctl = ioctl, + .compat_ioctl = slgt_compat_ioctl, + .throttle = throttle, + .unthrottle = unthrottle, + .send_xchar = send_xchar, + .break_ctl = set_break, + .wait_until_sent = wait_until_sent, + .set_termios = set_termios, + .stop = tx_hold, + .start = tx_release, + .hangup = hangup, + .tiocmget = tiocmget, + .tiocmset = tiocmset, + .get_icount = get_icount, + .proc_fops = &synclink_gt_proc_fops, +}; + +static void slgt_cleanup(void) +{ + int rc; + struct slgt_info *info; + struct slgt_info *tmp; + + printk(KERN_INFO "unload %s\n", driver_name); + + if (serial_driver) { + for (info=slgt_device_list ; info != NULL ; info=info->next_device) + tty_unregister_device(serial_driver, info->line); + if ((rc = tty_unregister_driver(serial_driver))) + DBGERR(("tty_unregister_driver error=%d\n", rc)); + put_tty_driver(serial_driver); + } + + /* reset devices */ + info = slgt_device_list; + while(info) { + reset_port(info); + info = info->next_device; + } + + /* release devices */ + info = slgt_device_list; + while(info) { +#if SYNCLINK_GENERIC_HDLC + hdlcdev_exit(info); +#endif + free_dma_bufs(info); + free_tmp_rbuf(info); + if (info->port_num == 0) + release_resources(info); + tmp = info; + info = info->next_device; + kfree(tmp); + } + + if (pci_registered) + pci_unregister_driver(&pci_driver); +} + +/* + * Driver initialization entry point. + */ +static int __init slgt_init(void) +{ + int rc; + + printk(KERN_INFO "%s\n", driver_name); + + serial_driver = alloc_tty_driver(MAX_DEVICES); + if (!serial_driver) { + printk("%s can't allocate tty driver\n", driver_name); + return -ENOMEM; + } + + /* Initialize the tty_driver structure */ + + serial_driver->owner = THIS_MODULE; + serial_driver->driver_name = tty_driver_name; + serial_driver->name = tty_dev_prefix; + serial_driver->major = ttymajor; + serial_driver->minor_start = 64; + serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_driver->subtype = SERIAL_TYPE_NORMAL; + serial_driver->init_termios = tty_std_termios; + serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; + serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(serial_driver, &ops); + if ((rc = tty_register_driver(serial_driver)) < 0) { + DBGERR(("%s can't register serial driver\n", driver_name)); + put_tty_driver(serial_driver); + serial_driver = NULL; + goto error; + } + + printk(KERN_INFO "%s, tty major#%d\n", + driver_name, serial_driver->major); + + slgt_device_count = 0; + if ((rc = pci_register_driver(&pci_driver)) < 0) { + printk("%s pci_register_driver error=%d\n", driver_name, rc); + goto error; + } + pci_registered = true; + + if (!slgt_device_list) + printk("%s no devices found\n",driver_name); + + return 0; + +error: + slgt_cleanup(); + return rc; +} + +static void __exit slgt_exit(void) +{ + slgt_cleanup(); +} + +module_init(slgt_init); +module_exit(slgt_exit); + +/* + * register access routines + */ + +#define CALC_REGADDR() \ + unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ + if (addr >= 0x80) \ + reg_addr += (info->port_num) * 32; \ + else if (addr >= 0x40) \ + reg_addr += (info->port_num) * 16; + +static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) +{ + CALC_REGADDR(); + return readb((void __iomem *)reg_addr); +} + +static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value) +{ + CALC_REGADDR(); + writeb(value, (void __iomem *)reg_addr); +} + +static __u16 rd_reg16(struct slgt_info *info, unsigned int addr) +{ + CALC_REGADDR(); + return readw((void __iomem *)reg_addr); +} + +static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value) +{ + CALC_REGADDR(); + writew(value, (void __iomem *)reg_addr); +} + +static __u32 rd_reg32(struct slgt_info *info, unsigned int addr) +{ + CALC_REGADDR(); + return readl((void __iomem *)reg_addr); +} + +static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value) +{ + CALC_REGADDR(); + writel(value, (void __iomem *)reg_addr); +} + +static void rdma_reset(struct slgt_info *info) +{ + unsigned int i; + + /* set reset bit */ + wr_reg32(info, RDCSR, BIT1); + + /* wait for enable bit cleared */ + for(i=0 ; i < 1000 ; i++) + if (!(rd_reg32(info, RDCSR) & BIT0)) + break; +} + +static void tdma_reset(struct slgt_info *info) +{ + unsigned int i; + + /* set reset bit */ + wr_reg32(info, TDCSR, BIT1); + + /* wait for enable bit cleared */ + for(i=0 ; i < 1000 ; i++) + if (!(rd_reg32(info, TDCSR) & BIT0)) + break; +} + +/* + * enable internal loopback + * TxCLK and RxCLK are generated from BRG + * and TxD is looped back to RxD internally. + */ +static void enable_loopback(struct slgt_info *info) +{ + /* SCR (serial control) BIT2=looopback enable */ + wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2)); + + if (info->params.mode != MGSL_MODE_ASYNC) { + /* CCR (clock control) + * 07..05 tx clock source (010 = BRG) + * 04..02 rx clock source (010 = BRG) + * 01 auxclk enable (0 = disable) + * 00 BRG enable (1 = enable) + * + * 0100 1001 + */ + wr_reg8(info, CCR, 0x49); + + /* set speed if available, otherwise use default */ + if (info->params.clock_speed) + set_rate(info, info->params.clock_speed); + else + set_rate(info, 3686400); + } +} + +/* + * set baud rate generator to specified rate + */ +static void set_rate(struct slgt_info *info, u32 rate) +{ + unsigned int div; + unsigned int osc = info->base_clock; + + /* div = osc/rate - 1 + * + * Round div up if osc/rate is not integer to + * force to next slowest rate. + */ + + if (rate) { + div = osc/rate; + if (!(osc % rate) && div) + div--; + wr_reg16(info, BDR, (unsigned short)div); + } +} + +static void rx_stop(struct slgt_info *info) +{ + unsigned short val; + + /* disable and reset receiver */ + val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ + wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ + wr_reg16(info, RCR, val); /* clear reset bit */ + + slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE); + + /* clear pending rx interrupts */ + wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER); + + rdma_reset(info); + + info->rx_enabled = false; + info->rx_restart = false; +} + +static void rx_start(struct slgt_info *info) +{ + unsigned short val; + + slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA); + + /* clear pending rx overrun IRQ */ + wr_reg16(info, SSR, IRQ_RXOVER); + + /* reset and disable receiver */ + val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ + wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ + wr_reg16(info, RCR, val); /* clear reset bit */ + + rdma_reset(info); + reset_rbufs(info); + + if (info->rx_pio) { + /* rx request when rx FIFO not empty */ + wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14)); + slgt_irq_on(info, IRQ_RXDATA); + if (info->params.mode == MGSL_MODE_ASYNC) { + /* enable saving of rx status */ + wr_reg32(info, RDCSR, BIT6); + } + } else { + /* rx request when rx FIFO half full */ + wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14)); + /* set 1st descriptor address */ + wr_reg32(info, RDDAR, info->rbufs[0].pdesc); + + if (info->params.mode != MGSL_MODE_ASYNC) { + /* enable rx DMA and DMA interrupt */ + wr_reg32(info, RDCSR, (BIT2 + BIT0)); + } else { + /* enable saving of rx status, rx DMA and DMA interrupt */ + wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); + } + } + + slgt_irq_on(info, IRQ_RXOVER); + + /* enable receiver */ + wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1)); + + info->rx_restart = false; + info->rx_enabled = true; +} + +static void tx_start(struct slgt_info *info) +{ + if (!info->tx_enabled) { + wr_reg16(info, TCR, + (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2)); + info->tx_enabled = true; + } + + if (desc_count(info->tbufs[info->tbuf_start])) { + info->drop_rts_on_tx_done = false; + + if (info->params.mode != MGSL_MODE_ASYNC) { + if (info->params.flags & HDLC_FLAG_AUTO_RTS) { + get_signals(info); + if (!(info->signals & SerialSignal_RTS)) { + info->signals |= SerialSignal_RTS; + set_signals(info); + info->drop_rts_on_tx_done = true; + } + } + + slgt_irq_off(info, IRQ_TXDATA); + slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); + /* clear tx idle and underrun status bits */ + wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); + } else { + slgt_irq_off(info, IRQ_TXDATA); + slgt_irq_on(info, IRQ_TXIDLE); + /* clear tx idle status bit */ + wr_reg16(info, SSR, IRQ_TXIDLE); + } + /* set 1st descriptor address and start DMA */ + wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); + wr_reg32(info, TDCSR, BIT2 + BIT0); + info->tx_active = true; + } +} + +static void tx_stop(struct slgt_info *info) +{ + unsigned short val; + + del_timer(&info->tx_timer); + + tdma_reset(info); + + /* reset and disable transmitter */ + val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */ + wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ + + slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); + + /* clear tx idle and underrun status bit */ + wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); + + reset_tbufs(info); + + info->tx_enabled = false; + info->tx_active = false; +} + +static void reset_port(struct slgt_info *info) +{ + if (!info->reg_addr) + return; + + tx_stop(info); + rx_stop(info); + + info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + set_signals(info); + + slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); +} + +static void reset_adapter(struct slgt_info *info) +{ + int i; + for (i=0; i < info->port_count; ++i) { + if (info->port_array[i]) + reset_port(info->port_array[i]); + } +} + +static void async_mode(struct slgt_info *info) +{ + unsigned short val; + + slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); + tx_stop(info); + rx_stop(info); + + /* TCR (tx control) + * + * 15..13 mode, 010=async + * 12..10 encoding, 000=NRZ + * 09 parity enable + * 08 1=odd parity, 0=even parity + * 07 1=RTS driver control + * 06 1=break enable + * 05..04 character length + * 00=5 bits + * 01=6 bits + * 10=7 bits + * 11=8 bits + * 03 0=1 stop bit, 1=2 stop bits + * 02 reset + * 01 enable + * 00 auto-CTS enable + */ + val = 0x4000; + + if (info->if_mode & MGSL_INTERFACE_RTS_EN) + val |= BIT7; + + if (info->params.parity != ASYNC_PARITY_NONE) { + val |= BIT9; + if (info->params.parity == ASYNC_PARITY_ODD) + val |= BIT8; + } + + switch (info->params.data_bits) + { + case 6: val |= BIT4; break; + case 7: val |= BIT5; break; + case 8: val |= BIT5 + BIT4; break; + } + + if (info->params.stop_bits != 1) + val |= BIT3; + + if (info->params.flags & HDLC_FLAG_AUTO_CTS) + val |= BIT0; + + wr_reg16(info, TCR, val); + + /* RCR (rx control) + * + * 15..13 mode, 010=async + * 12..10 encoding, 000=NRZ + * 09 parity enable + * 08 1=odd parity, 0=even parity + * 07..06 reserved, must be 0 + * 05..04 character length + * 00=5 bits + * 01=6 bits + * 10=7 bits + * 11=8 bits + * 03 reserved, must be zero + * 02 reset + * 01 enable + * 00 auto-DCD enable + */ + val = 0x4000; + + if (info->params.parity != ASYNC_PARITY_NONE) { + val |= BIT9; + if (info->params.parity == ASYNC_PARITY_ODD) + val |= BIT8; + } + + switch (info->params.data_bits) + { + case 6: val |= BIT4; break; + case 7: val |= BIT5; break; + case 8: val |= BIT5 + BIT4; break; + } + + if (info->params.flags & HDLC_FLAG_AUTO_DCD) + val |= BIT0; + + wr_reg16(info, RCR, val); + + /* CCR (clock control) + * + * 07..05 011 = tx clock source is BRG/16 + * 04..02 010 = rx clock source is BRG + * 01 0 = auxclk disabled + * 00 1 = BRG enabled + * + * 0110 1001 + */ + wr_reg8(info, CCR, 0x69); + + msc_set_vcr(info); + + /* SCR (serial control) + * + * 15 1=tx req on FIFO half empty + * 14 1=rx req on FIFO half full + * 13 tx data IRQ enable + * 12 tx idle IRQ enable + * 11 rx break on IRQ enable + * 10 rx data IRQ enable + * 09 rx break off IRQ enable + * 08 overrun IRQ enable + * 07 DSR IRQ enable + * 06 CTS IRQ enable + * 05 DCD IRQ enable + * 04 RI IRQ enable + * 03 0=16x sampling, 1=8x sampling + * 02 1=txd->rxd internal loopback enable + * 01 reserved, must be zero + * 00 1=master IRQ enable + */ + val = BIT15 + BIT14 + BIT0; + /* JCR[8] : 1 = x8 async mode feature available */ + if ((rd_reg32(info, JCR) & BIT8) && info->params.data_rate && + ((info->base_clock < (info->params.data_rate * 16)) || + (info->base_clock % (info->params.data_rate * 16)))) { + /* use 8x sampling */ + val |= BIT3; + set_rate(info, info->params.data_rate * 8); + } else { + /* use 16x sampling */ + set_rate(info, info->params.data_rate * 16); + } + wr_reg16(info, SCR, val); + + slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER); + + if (info->params.loopback) + enable_loopback(info); +} + +static void sync_mode(struct slgt_info *info) +{ + unsigned short val; + + slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); + tx_stop(info); + rx_stop(info); + + /* TCR (tx control) + * + * 15..13 mode + * 000=HDLC/SDLC + * 001=raw bit synchronous + * 010=asynchronous/isochronous + * 011=monosync byte synchronous + * 100=bisync byte synchronous + * 101=xsync byte synchronous + * 12..10 encoding + * 09 CRC enable + * 08 CRC32 + * 07 1=RTS driver control + * 06 preamble enable + * 05..04 preamble length + * 03 share open/close flag + * 02 reset + * 01 enable + * 00 auto-CTS enable + */ + val = BIT2; + + switch(info->params.mode) { + case MGSL_MODE_XSYNC: + val |= BIT15 + BIT13; + break; + case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; + case MGSL_MODE_BISYNC: val |= BIT15; break; + case MGSL_MODE_RAW: val |= BIT13; break; + } + if (info->if_mode & MGSL_INTERFACE_RTS_EN) + val |= BIT7; + + switch(info->params.encoding) + { + case HDLC_ENCODING_NRZB: val |= BIT10; break; + case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; + case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; + case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; + case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; + case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; + } + + switch (info->params.crc_type & HDLC_CRC_MASK) + { + case HDLC_CRC_16_CCITT: val |= BIT9; break; + case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; + } + + if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) + val |= BIT6; + + switch (info->params.preamble_length) + { + case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break; + case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break; + case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break; + } + + if (info->params.flags & HDLC_FLAG_AUTO_CTS) + val |= BIT0; + + wr_reg16(info, TCR, val); + + /* TPR (transmit preamble) */ + + switch (info->params.preamble) + { + case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break; + case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break; + case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break; + case HDLC_PREAMBLE_PATTERN_10: val = 0x55; break; + case HDLC_PREAMBLE_PATTERN_01: val = 0xaa; break; + default: val = 0x7e; break; + } + wr_reg8(info, TPR, (unsigned char)val); + + /* RCR (rx control) + * + * 15..13 mode + * 000=HDLC/SDLC + * 001=raw bit synchronous + * 010=asynchronous/isochronous + * 011=monosync byte synchronous + * 100=bisync byte synchronous + * 101=xsync byte synchronous + * 12..10 encoding + * 09 CRC enable + * 08 CRC32 + * 07..03 reserved, must be 0 + * 02 reset + * 01 enable + * 00 auto-DCD enable + */ + val = 0; + + switch(info->params.mode) { + case MGSL_MODE_XSYNC: + val |= BIT15 + BIT13; + break; + case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; + case MGSL_MODE_BISYNC: val |= BIT15; break; + case MGSL_MODE_RAW: val |= BIT13; break; + } + + switch(info->params.encoding) + { + case HDLC_ENCODING_NRZB: val |= BIT10; break; + case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; + case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; + case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; + case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; + case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; + } + + switch (info->params.crc_type & HDLC_CRC_MASK) + { + case HDLC_CRC_16_CCITT: val |= BIT9; break; + case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; + } + + if (info->params.flags & HDLC_FLAG_AUTO_DCD) + val |= BIT0; + + wr_reg16(info, RCR, val); + + /* CCR (clock control) + * + * 07..05 tx clock source + * 04..02 rx clock source + * 01 auxclk enable + * 00 BRG enable + */ + val = 0; + + if (info->params.flags & HDLC_FLAG_TXC_BRG) + { + // when RxC source is DPLL, BRG generates 16X DPLL + // reference clock, so take TxC from BRG/16 to get + // transmit clock at actual data rate + if (info->params.flags & HDLC_FLAG_RXC_DPLL) + val |= BIT6 + BIT5; /* 011, txclk = BRG/16 */ + else + val |= BIT6; /* 010, txclk = BRG */ + } + else if (info->params.flags & HDLC_FLAG_TXC_DPLL) + val |= BIT7; /* 100, txclk = DPLL Input */ + else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN) + val |= BIT5; /* 001, txclk = RXC Input */ + + if (info->params.flags & HDLC_FLAG_RXC_BRG) + val |= BIT3; /* 010, rxclk = BRG */ + else if (info->params.flags & HDLC_FLAG_RXC_DPLL) + val |= BIT4; /* 100, rxclk = DPLL */ + else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN) + val |= BIT2; /* 001, rxclk = TXC Input */ + + if (info->params.clock_speed) + val |= BIT1 + BIT0; + + wr_reg8(info, CCR, (unsigned char)val); + + if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL)) + { + // program DPLL mode + switch(info->params.encoding) + { + case HDLC_ENCODING_BIPHASE_MARK: + case HDLC_ENCODING_BIPHASE_SPACE: + val = BIT7; break; + case HDLC_ENCODING_BIPHASE_LEVEL: + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: + val = BIT7 + BIT6; break; + default: val = BIT6; // NRZ encodings + } + wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val)); + + // DPLL requires a 16X reference clock from BRG + set_rate(info, info->params.clock_speed * 16); + } + else + set_rate(info, info->params.clock_speed); + + tx_set_idle(info); + + msc_set_vcr(info); + + /* SCR (serial control) + * + * 15 1=tx req on FIFO half empty + * 14 1=rx req on FIFO half full + * 13 tx data IRQ enable + * 12 tx idle IRQ enable + * 11 underrun IRQ enable + * 10 rx data IRQ enable + * 09 rx idle IRQ enable + * 08 overrun IRQ enable + * 07 DSR IRQ enable + * 06 CTS IRQ enable + * 05 DCD IRQ enable + * 04 RI IRQ enable + * 03 reserved, must be zero + * 02 1=txd->rxd internal loopback enable + * 01 reserved, must be zero + * 00 1=master IRQ enable + */ + wr_reg16(info, SCR, BIT15 + BIT14 + BIT0); + + if (info->params.loopback) + enable_loopback(info); +} + +/* + * set transmit idle mode + */ +static void tx_set_idle(struct slgt_info *info) +{ + unsigned char val; + unsigned short tcr; + + /* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits + * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits + */ + tcr = rd_reg16(info, TCR); + if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) { + /* disable preamble, set idle size to 16 bits */ + tcr = (tcr & ~(BIT6 + BIT5)) | BIT4; + /* MSB of 16 bit idle specified in tx preamble register (TPR) */ + wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff)); + } else if (!(tcr & BIT6)) { + /* preamble is disabled, set idle size to 8 bits */ + tcr &= ~(BIT5 + BIT4); + } + wr_reg16(info, TCR, tcr); + + if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) { + /* LSB of custom tx idle specified in tx idle register */ + val = (unsigned char)(info->idle_mode & 0xff); + } else { + /* standard 8 bit idle patterns */ + switch(info->idle_mode) + { + case HDLC_TXIDLE_FLAGS: val = 0x7e; break; + case HDLC_TXIDLE_ALT_ZEROS_ONES: + case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; + case HDLC_TXIDLE_ZEROS: + case HDLC_TXIDLE_SPACE: val = 0x00; break; + default: val = 0xff; + } + } + + wr_reg8(info, TIR, val); +} + +/* + * get state of V24 status (input) signals + */ +static void get_signals(struct slgt_info *info) +{ + unsigned short status = rd_reg16(info, SSR); + + /* clear all serial signals except DTR and RTS */ + info->signals &= SerialSignal_DTR + SerialSignal_RTS; + + if (status & BIT3) + info->signals |= SerialSignal_DSR; + if (status & BIT2) + info->signals |= SerialSignal_CTS; + if (status & BIT1) + info->signals |= SerialSignal_DCD; + if (status & BIT0) + info->signals |= SerialSignal_RI; +} + +/* + * set V.24 Control Register based on current configuration + */ +static void msc_set_vcr(struct slgt_info *info) +{ + unsigned char val = 0; + + /* VCR (V.24 control) + * + * 07..04 serial IF select + * 03 DTR + * 02 RTS + * 01 LL + * 00 RL + */ + + switch(info->if_mode & MGSL_INTERFACE_MASK) + { + case MGSL_INTERFACE_RS232: + val |= BIT5; /* 0010 */ + break; + case MGSL_INTERFACE_V35: + val |= BIT7 + BIT6 + BIT5; /* 1110 */ + break; + case MGSL_INTERFACE_RS422: + val |= BIT6; /* 0100 */ + break; + } + + if (info->if_mode & MGSL_INTERFACE_MSB_FIRST) + val |= BIT4; + if (info->signals & SerialSignal_DTR) + val |= BIT3; + if (info->signals & SerialSignal_RTS) + val |= BIT2; + if (info->if_mode & MGSL_INTERFACE_LL) + val |= BIT1; + if (info->if_mode & MGSL_INTERFACE_RL) + val |= BIT0; + wr_reg8(info, VCR, val); +} + +/* + * set state of V24 control (output) signals + */ +static void set_signals(struct slgt_info *info) +{ + unsigned char val = rd_reg8(info, VCR); + if (info->signals & SerialSignal_DTR) + val |= BIT3; + else + val &= ~BIT3; + if (info->signals & SerialSignal_RTS) + val |= BIT2; + else + val &= ~BIT2; + wr_reg8(info, VCR, val); +} + +/* + * free range of receive DMA buffers (i to last) + */ +static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last) +{ + int done = 0; + + while(!done) { + /* reset current buffer for reuse */ + info->rbufs[i].status = 0; + set_desc_count(info->rbufs[i], info->rbuf_fill_level); + if (i == last) + done = 1; + if (++i == info->rbuf_count) + i = 0; + } + info->rbuf_current = i; +} + +/* + * mark all receive DMA buffers as free + */ +static void reset_rbufs(struct slgt_info *info) +{ + free_rbufs(info, 0, info->rbuf_count - 1); + info->rbuf_fill_index = 0; + info->rbuf_fill_count = 0; +} + +/* + * pass receive HDLC frame to upper layer + * + * return true if frame available, otherwise false + */ +static bool rx_get_frame(struct slgt_info *info) +{ + unsigned int start, end; + unsigned short status; + unsigned int framesize = 0; + unsigned long flags; + struct tty_struct *tty = info->port.tty; + unsigned char addr_field = 0xff; + unsigned int crc_size = 0; + + switch (info->params.crc_type & HDLC_CRC_MASK) { + case HDLC_CRC_16_CCITT: crc_size = 2; break; + case HDLC_CRC_32_CCITT: crc_size = 4; break; + } + +check_again: + + framesize = 0; + addr_field = 0xff; + start = end = info->rbuf_current; + + for (;;) { + if (!desc_complete(info->rbufs[end])) + goto cleanup; + + if (framesize == 0 && info->params.addr_filter != 0xff) + addr_field = info->rbufs[end].buf[0]; + + framesize += desc_count(info->rbufs[end]); + + if (desc_eof(info->rbufs[end])) + break; + + if (++end == info->rbuf_count) + end = 0; + + if (end == info->rbuf_current) { + if (info->rx_enabled){ + spin_lock_irqsave(&info->lock,flags); + rx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } + goto cleanup; + } + } + + /* status + * + * 15 buffer complete + * 14..06 reserved + * 05..04 residue + * 02 eof (end of frame) + * 01 CRC error + * 00 abort + */ + status = desc_status(info->rbufs[end]); + + /* ignore CRC bit if not using CRC (bit is undefined) */ + if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE) + status &= ~BIT1; + + if (framesize == 0 || + (addr_field != 0xff && addr_field != info->params.addr_filter)) { + free_rbufs(info, start, end); + goto check_again; + } + + if (framesize < (2 + crc_size) || status & BIT0) { + info->icount.rxshort++; + framesize = 0; + } else if (status & BIT1) { + info->icount.rxcrc++; + if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) + framesize = 0; + } + +#if SYNCLINK_GENERIC_HDLC + if (framesize == 0) { + info->netdev->stats.rx_errors++; + info->netdev->stats.rx_frame_errors++; + } +#endif + + DBGBH(("%s rx frame status=%04X size=%d\n", + info->device_name, status, framesize)); + DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx"); + + if (framesize) { + if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { + framesize -= crc_size; + crc_size = 0; + } + + if (framesize > info->max_frame_size + crc_size) + info->icount.rxlong++; + else { + /* copy dma buffer(s) to contiguous temp buffer */ + int copy_count = framesize; + int i = start; + unsigned char *p = info->tmp_rbuf; + info->tmp_rbuf_count = framesize; + + info->icount.rxok++; + + while(copy_count) { + int partial_count = min_t(int, copy_count, info->rbuf_fill_level); + memcpy(p, info->rbufs[i].buf, partial_count); + p += partial_count; + copy_count -= partial_count; + if (++i == info->rbuf_count) + i = 0; + } + + if (info->params.crc_type & HDLC_CRC_RETURN_EX) { + *p = (status & BIT1) ? RX_CRC_ERROR : RX_OK; + framesize++; + } + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_rx(info,info->tmp_rbuf, framesize); + else +#endif + ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize); + } + } + free_rbufs(info, start, end); + return true; + +cleanup: + return false; +} + +/* + * pass receive buffer (RAW synchronous mode) to tty layer + * return true if buffer available, otherwise false + */ +static bool rx_get_buf(struct slgt_info *info) +{ + unsigned int i = info->rbuf_current; + unsigned int count; + + if (!desc_complete(info->rbufs[i])) + return false; + count = desc_count(info->rbufs[i]); + switch(info->params.mode) { + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: + case MGSL_MODE_XSYNC: + /* ignore residue in byte synchronous modes */ + if (desc_residue(info->rbufs[i])) + count--; + break; + } + DBGDATA(info, info->rbufs[i].buf, count, "rx"); + DBGINFO(("rx_get_buf size=%d\n", count)); + if (count) + ldisc_receive_buf(info->port.tty, info->rbufs[i].buf, + info->flag_buf, count); + free_rbufs(info, i, i); + return true; +} + +static void reset_tbufs(struct slgt_info *info) +{ + unsigned int i; + info->tbuf_current = 0; + for (i=0 ; i < info->tbuf_count ; i++) { + info->tbufs[i].status = 0; + info->tbufs[i].count = 0; + } +} + +/* + * return number of free transmit DMA buffers + */ +static unsigned int free_tbuf_count(struct slgt_info *info) +{ + unsigned int count = 0; + unsigned int i = info->tbuf_current; + + do + { + if (desc_count(info->tbufs[i])) + break; /* buffer in use */ + ++count; + if (++i == info->tbuf_count) + i=0; + } while (i != info->tbuf_current); + + /* if tx DMA active, last zero count buffer is in use */ + if (count && (rd_reg32(info, TDCSR) & BIT0)) + --count; + + return count; +} + +/* + * return number of bytes in unsent transmit DMA buffers + * and the serial controller tx FIFO + */ +static unsigned int tbuf_bytes(struct slgt_info *info) +{ + unsigned int total_count = 0; + unsigned int i = info->tbuf_current; + unsigned int reg_value; + unsigned int count; + unsigned int active_buf_count = 0; + + /* + * Add descriptor counts for all tx DMA buffers. + * If count is zero (cleared by DMA controller after read), + * the buffer is complete or is actively being read from. + * + * Record buf_count of last buffer with zero count starting + * from current ring position. buf_count is mirror + * copy of count and is not cleared by serial controller. + * If DMA controller is active, that buffer is actively + * being read so add to total. + */ + do { + count = desc_count(info->tbufs[i]); + if (count) + total_count += count; + else if (!total_count) + active_buf_count = info->tbufs[i].buf_count; + if (++i == info->tbuf_count) + i = 0; + } while (i != info->tbuf_current); + + /* read tx DMA status register */ + reg_value = rd_reg32(info, TDCSR); + + /* if tx DMA active, last zero count buffer is in use */ + if (reg_value & BIT0) + total_count += active_buf_count; + + /* add tx FIFO count = reg_value[15..8] */ + total_count += (reg_value >> 8) & 0xff; + + /* if transmitter active add one byte for shift register */ + if (info->tx_active) + total_count++; + + return total_count; +} + +/* + * load data into transmit DMA buffer ring and start transmitter if needed + * return true if data accepted, otherwise false (buffers full) + */ +static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size) +{ + unsigned short count; + unsigned int i; + struct slgt_desc *d; + + /* check required buffer space */ + if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info)) + return false; + + DBGDATA(info, buf, size, "tx"); + + /* + * copy data to one or more DMA buffers in circular ring + * tbuf_start = first buffer for this data + * tbuf_current = next free buffer + * + * Copy all data before making data visible to DMA controller by + * setting descriptor count of the first buffer. + * This prevents an active DMA controller from reading the first DMA + * buffers of a frame and stopping before the final buffers are filled. + */ + + info->tbuf_start = i = info->tbuf_current; + + while (size) { + d = &info->tbufs[i]; + + count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); + memcpy(d->buf, buf, count); + + size -= count; + buf += count; + + /* + * set EOF bit for last buffer of HDLC frame or + * for every buffer in raw mode + */ + if ((!size && info->params.mode == MGSL_MODE_HDLC) || + info->params.mode == MGSL_MODE_RAW) + set_desc_eof(*d, 1); + else + set_desc_eof(*d, 0); + + /* set descriptor count for all but first buffer */ + if (i != info->tbuf_start) + set_desc_count(*d, count); + d->buf_count = count; + + if (++i == info->tbuf_count) + i = 0; + } + + info->tbuf_current = i; + + /* set first buffer count to make new data visible to DMA controller */ + d = &info->tbufs[info->tbuf_start]; + set_desc_count(*d, d->buf_count); + + /* start transmitter if needed and update transmit timeout */ + if (!info->tx_active) + tx_start(info); + update_tx_timer(info); + + return true; +} + +static int register_test(struct slgt_info *info) +{ + static unsigned short patterns[] = + {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696}; + static unsigned int count = ARRAY_SIZE(patterns); + unsigned int i; + int rc = 0; + + for (i=0 ; i < count ; i++) { + wr_reg16(info, TIR, patterns[i]); + wr_reg16(info, BDR, patterns[(i+1)%count]); + if ((rd_reg16(info, TIR) != patterns[i]) || + (rd_reg16(info, BDR) != patterns[(i+1)%count])) { + rc = -ENODEV; + break; + } + } + info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0; + info->init_error = rc ? 0 : DiagStatus_AddressFailure; + return rc; +} + +static int irq_test(struct slgt_info *info) +{ + unsigned long timeout; + unsigned long flags; + struct tty_struct *oldtty = info->port.tty; + u32 speed = info->params.data_rate; + + info->params.data_rate = 921600; + info->port.tty = NULL; + + spin_lock_irqsave(&info->lock, flags); + async_mode(info); + slgt_irq_on(info, IRQ_TXIDLE); + + /* enable transmitter */ + wr_reg16(info, TCR, + (unsigned short)(rd_reg16(info, TCR) | BIT1)); + + /* write one byte and wait for tx idle */ + wr_reg16(info, TDR, 0); + + /* assume failure */ + info->init_error = DiagStatus_IrqFailure; + info->irq_occurred = false; + + spin_unlock_irqrestore(&info->lock, flags); + + timeout=100; + while(timeout-- && !info->irq_occurred) + msleep_interruptible(10); + + spin_lock_irqsave(&info->lock,flags); + reset_port(info); + spin_unlock_irqrestore(&info->lock,flags); + + info->params.data_rate = speed; + info->port.tty = oldtty; + + info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure; + return info->irq_occurred ? 0 : -ENODEV; +} + +static int loopback_test_rx(struct slgt_info *info) +{ + unsigned char *src, *dest; + int count; + + if (desc_complete(info->rbufs[0])) { + count = desc_count(info->rbufs[0]); + src = info->rbufs[0].buf; + dest = info->tmp_rbuf; + + for( ; count ; count-=2, src+=2) { + /* src=data byte (src+1)=status byte */ + if (!(*(src+1) & (BIT9 + BIT8))) { + *dest = *src; + dest++; + info->tmp_rbuf_count++; + } + } + DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx"); + return 1; + } + return 0; +} + +static int loopback_test(struct slgt_info *info) +{ +#define TESTFRAMESIZE 20 + + unsigned long timeout; + u16 count = TESTFRAMESIZE; + unsigned char buf[TESTFRAMESIZE]; + int rc = -ENODEV; + unsigned long flags; + + struct tty_struct *oldtty = info->port.tty; + MGSL_PARAMS params; + + memcpy(¶ms, &info->params, sizeof(params)); + + info->params.mode = MGSL_MODE_ASYNC; + info->params.data_rate = 921600; + info->params.loopback = 1; + info->port.tty = NULL; + + /* build and send transmit frame */ + for (count = 0; count < TESTFRAMESIZE; ++count) + buf[count] = (unsigned char)count; + + info->tmp_rbuf_count = 0; + memset(info->tmp_rbuf, 0, TESTFRAMESIZE); + + /* program hardware for HDLC and enabled receiver */ + spin_lock_irqsave(&info->lock,flags); + async_mode(info); + rx_start(info); + tx_load(info, buf, count); + spin_unlock_irqrestore(&info->lock, flags); + + /* wait for receive complete */ + for (timeout = 100; timeout; --timeout) { + msleep_interruptible(10); + if (loopback_test_rx(info)) { + rc = 0; + break; + } + } + + /* verify received frame length and contents */ + if (!rc && (info->tmp_rbuf_count != count || + memcmp(buf, info->tmp_rbuf, count))) { + rc = -ENODEV; + } + + spin_lock_irqsave(&info->lock,flags); + reset_adapter(info); + spin_unlock_irqrestore(&info->lock,flags); + + memcpy(&info->params, ¶ms, sizeof(info->params)); + info->port.tty = oldtty; + + info->init_error = rc ? DiagStatus_DmaFailure : 0; + return rc; +} + +static int adapter_test(struct slgt_info *info) +{ + DBGINFO(("testing %s\n", info->device_name)); + if (register_test(info) < 0) { + printk("register test failure %s addr=%08X\n", + info->device_name, info->phys_reg_addr); + } else if (irq_test(info) < 0) { + printk("IRQ test failure %s IRQ=%d\n", + info->device_name, info->irq_level); + } else if (loopback_test(info) < 0) { + printk("loopback test failure %s\n", info->device_name); + } + return info->init_error; +} + +/* + * transmit timeout handler + */ +static void tx_timeout(unsigned long context) +{ + struct slgt_info *info = (struct slgt_info*)context; + unsigned long flags; + + DBGINFO(("%s tx_timeout\n", info->device_name)); + if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) { + info->icount.txtimeout++; + } + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_tx_done(info); + else +#endif + bh_transmit(info); +} + +/* + * receive buffer polling timer + */ +static void rx_timeout(unsigned long context) +{ + struct slgt_info *info = (struct slgt_info*)context; + unsigned long flags; + + DBGINFO(("%s rx_timeout\n", info->device_name)); + spin_lock_irqsave(&info->lock, flags); + info->pending_bh |= BH_RECEIVE; + spin_unlock_irqrestore(&info->lock, flags); + bh_handler(&info->task); +} + diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c new file mode 100644 index 000000000000..327343694473 --- /dev/null +++ b/drivers/tty/synclinkmp.c @@ -0,0 +1,5600 @@ +/* + * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $ + * + * Device driver for Microgate SyncLink Multiport + * high speed multiprotocol serial adapter. + * + * written by Paul Fulghum for Microgate Corporation + * paulkf@microgate.com + * + * Microgate and SyncLink are trademarks of Microgate Corporation + * + * Derived from serial.c written by Theodore Ts'o and Linus Torvalds + * This code is released under the GNU General Public License (GPL) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) +#if defined(__i386__) +# define BREAKPOINT() asm(" int $3"); +#else +# define BREAKPOINT() { } +#endif + +#define MAX_DEVICES 12 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 +#endif + +#define GET_USER(error,value,addr) error = get_user(value,addr) +#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 +#define PUT_USER(error,value,addr) error = put_user(value,addr) +#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 + +#include + +static MGSL_PARAMS default_params = { + MGSL_MODE_HDLC, /* unsigned long mode */ + 0, /* unsigned char loopback; */ + HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */ + HDLC_ENCODING_NRZI_SPACE, /* unsigned char encoding; */ + 0, /* unsigned long clock_speed; */ + 0xff, /* unsigned char addr_filter; */ + HDLC_CRC_16_CCITT, /* unsigned short crc_type; */ + HDLC_PREAMBLE_LENGTH_8BITS, /* unsigned char preamble_length; */ + HDLC_PREAMBLE_PATTERN_NONE, /* unsigned char preamble; */ + 9600, /* unsigned long data_rate; */ + 8, /* unsigned char data_bits; */ + 1, /* unsigned char stop_bits; */ + ASYNC_PARITY_NONE /* unsigned char parity; */ +}; + +/* size in bytes of DMA data buffers */ +#define SCABUFSIZE 1024 +#define SCA_MEM_SIZE 0x40000 +#define SCA_BASE_SIZE 512 +#define SCA_REG_SIZE 16 +#define SCA_MAX_PORTS 4 +#define SCAMAXDESC 128 + +#define BUFFERLISTSIZE 4096 + +/* SCA-I style DMA buffer descriptor */ +typedef struct _SCADESC +{ + u16 next; /* lower l6 bits of next descriptor addr */ + u16 buf_ptr; /* lower 16 bits of buffer addr */ + u8 buf_base; /* upper 8 bits of buffer addr */ + u8 pad1; + u16 length; /* length of buffer */ + u8 status; /* status of buffer */ + u8 pad2; +} SCADESC, *PSCADESC; + +typedef struct _SCADESC_EX +{ + /* device driver bookkeeping section */ + char *virt_addr; /* virtual address of data buffer */ + u16 phys_entry; /* lower 16-bits of physical address of this descriptor */ +} SCADESC_EX, *PSCADESC_EX; + +/* The queue of BH actions to be performed */ + +#define BH_RECEIVE 1 +#define BH_TRANSMIT 2 +#define BH_STATUS 4 + +#define IO_PIN_SHUTDOWN_LIMIT 100 + +struct _input_signal_events { + int ri_up; + int ri_down; + int dsr_up; + int dsr_down; + int dcd_up; + int dcd_down; + int cts_up; + int cts_down; +}; + +/* + * Device instance data structure + */ +typedef struct _synclinkmp_info { + void *if_ptr; /* General purpose pointer (used by SPPP) */ + int magic; + struct tty_port port; + int line; + unsigned short close_delay; + unsigned short closing_wait; /* time to wait before closing */ + + struct mgsl_icount icount; + + int timeout; + int x_char; /* xon/xoff character */ + u16 read_status_mask1; /* break detection (SR1 indications) */ + u16 read_status_mask2; /* parity/framing/overun (SR2 indications) */ + unsigned char ignore_status_mask1; /* break detection (SR1 indications) */ + unsigned char ignore_status_mask2; /* parity/framing/overun (SR2 indications) */ + unsigned char *tx_buf; + int tx_put; + int tx_get; + int tx_count; + + wait_queue_head_t status_event_wait_q; + wait_queue_head_t event_wait_q; + struct timer_list tx_timer; /* HDLC transmit timeout timer */ + struct _synclinkmp_info *next_device; /* device list link */ + struct timer_list status_timer; /* input signal status check timer */ + + spinlock_t lock; /* spinlock for synchronizing with ISR */ + struct work_struct task; /* task structure for scheduling bh */ + + u32 max_frame_size; /* as set by device config */ + + u32 pending_bh; + + bool bh_running; /* Protection from multiple */ + int isr_overflow; + bool bh_requested; + + int dcd_chkcount; /* check counts to prevent */ + int cts_chkcount; /* too many IRQs if a signal */ + int dsr_chkcount; /* is floating */ + int ri_chkcount; + + char *buffer_list; /* virtual address of Rx & Tx buffer lists */ + unsigned long buffer_list_phys; + + unsigned int rx_buf_count; /* count of total allocated Rx buffers */ + SCADESC *rx_buf_list; /* list of receive buffer entries */ + SCADESC_EX rx_buf_list_ex[SCAMAXDESC]; /* list of receive buffer entries */ + unsigned int current_rx_buf; + + unsigned int tx_buf_count; /* count of total allocated Tx buffers */ + SCADESC *tx_buf_list; /* list of transmit buffer entries */ + SCADESC_EX tx_buf_list_ex[SCAMAXDESC]; /* list of transmit buffer entries */ + unsigned int last_tx_buf; + + unsigned char *tmp_rx_buf; + unsigned int tmp_rx_buf_count; + + bool rx_enabled; + bool rx_overflow; + + bool tx_enabled; + bool tx_active; + u32 idle_mode; + + unsigned char ie0_value; + unsigned char ie1_value; + unsigned char ie2_value; + unsigned char ctrlreg_value; + unsigned char old_signals; + + char device_name[25]; /* device instance name */ + + int port_count; + int adapter_num; + int port_num; + + struct _synclinkmp_info *port_array[SCA_MAX_PORTS]; + + unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */ + + unsigned int irq_level; /* interrupt level */ + unsigned long irq_flags; + bool irq_requested; /* true if IRQ requested */ + + MGSL_PARAMS params; /* communications parameters */ + + unsigned char serial_signals; /* current serial signal states */ + + bool irq_occurred; /* for diagnostics use */ + unsigned int init_error; /* Initialization startup error */ + + u32 last_mem_alloc; + unsigned char* memory_base; /* shared memory address (PCI only) */ + u32 phys_memory_base; + int shared_mem_requested; + + unsigned char* sca_base; /* HD64570 SCA Memory address */ + u32 phys_sca_base; + u32 sca_offset; + bool sca_base_requested; + + unsigned char* lcr_base; /* local config registers (PCI only) */ + u32 phys_lcr_base; + u32 lcr_offset; + int lcr_mem_requested; + + unsigned char* statctrl_base; /* status/control register memory */ + u32 phys_statctrl_base; + u32 statctrl_offset; + bool sca_statctrl_requested; + + u32 misc_ctrl_value; + char flag_buf[MAX_ASYNC_BUFFER_SIZE]; + char char_buf[MAX_ASYNC_BUFFER_SIZE]; + bool drop_rts_on_tx_done; + + struct _input_signal_events input_signal_events; + + /* SPPP/Cisco HDLC device parts */ + int netcount; + spinlock_t netlock; + +#if SYNCLINK_GENERIC_HDLC + struct net_device *netdev; +#endif + +} SLMP_INFO; + +#define MGSL_MAGIC 0x5401 + +/* + * define serial signal status change macros + */ +#define MISCSTATUS_DCD_LATCHED (SerialSignal_DCD<<8) /* indicates change in DCD */ +#define MISCSTATUS_RI_LATCHED (SerialSignal_RI<<8) /* indicates change in RI */ +#define MISCSTATUS_CTS_LATCHED (SerialSignal_CTS<<8) /* indicates change in CTS */ +#define MISCSTATUS_DSR_LATCHED (SerialSignal_DSR<<8) /* change in DSR */ + +/* Common Register macros */ +#define LPR 0x00 +#define PABR0 0x02 +#define PABR1 0x03 +#define WCRL 0x04 +#define WCRM 0x05 +#define WCRH 0x06 +#define DPCR 0x08 +#define DMER 0x09 +#define ISR0 0x10 +#define ISR1 0x11 +#define ISR2 0x12 +#define IER0 0x14 +#define IER1 0x15 +#define IER2 0x16 +#define ITCR 0x18 +#define INTVR 0x1a +#define IMVR 0x1c + +/* MSCI Register macros */ +#define TRB 0x20 +#define TRBL 0x20 +#define TRBH 0x21 +#define SR0 0x22 +#define SR1 0x23 +#define SR2 0x24 +#define SR3 0x25 +#define FST 0x26 +#define IE0 0x28 +#define IE1 0x29 +#define IE2 0x2a +#define FIE 0x2b +#define CMD 0x2c +#define MD0 0x2e +#define MD1 0x2f +#define MD2 0x30 +#define CTL 0x31 +#define SA0 0x32 +#define SA1 0x33 +#define IDL 0x34 +#define TMC 0x35 +#define RXS 0x36 +#define TXS 0x37 +#define TRC0 0x38 +#define TRC1 0x39 +#define RRC 0x3a +#define CST0 0x3c +#define CST1 0x3d + +/* Timer Register Macros */ +#define TCNT 0x60 +#define TCNTL 0x60 +#define TCNTH 0x61 +#define TCONR 0x62 +#define TCONRL 0x62 +#define TCONRH 0x63 +#define TMCS 0x64 +#define TEPR 0x65 + +/* DMA Controller Register macros */ +#define DARL 0x80 +#define DARH 0x81 +#define DARB 0x82 +#define BAR 0x80 +#define BARL 0x80 +#define BARH 0x81 +#define BARB 0x82 +#define SAR 0x84 +#define SARL 0x84 +#define SARH 0x85 +#define SARB 0x86 +#define CPB 0x86 +#define CDA 0x88 +#define CDAL 0x88 +#define CDAH 0x89 +#define EDA 0x8a +#define EDAL 0x8a +#define EDAH 0x8b +#define BFL 0x8c +#define BFLL 0x8c +#define BFLH 0x8d +#define BCR 0x8e +#define BCRL 0x8e +#define BCRH 0x8f +#define DSR 0x90 +#define DMR 0x91 +#define FCT 0x93 +#define DIR 0x94 +#define DCMD 0x95 + +/* combine with timer or DMA register address */ +#define TIMER0 0x00 +#define TIMER1 0x08 +#define TIMER2 0x10 +#define TIMER3 0x18 +#define RXDMA 0x00 +#define TXDMA 0x20 + +/* SCA Command Codes */ +#define NOOP 0x00 +#define TXRESET 0x01 +#define TXENABLE 0x02 +#define TXDISABLE 0x03 +#define TXCRCINIT 0x04 +#define TXCRCEXCL 0x05 +#define TXEOM 0x06 +#define TXABORT 0x07 +#define MPON 0x08 +#define TXBUFCLR 0x09 +#define RXRESET 0x11 +#define RXENABLE 0x12 +#define RXDISABLE 0x13 +#define RXCRCINIT 0x14 +#define RXREJECT 0x15 +#define SEARCHMP 0x16 +#define RXCRCEXCL 0x17 +#define RXCRCCALC 0x18 +#define CHRESET 0x21 +#define HUNT 0x31 + +/* DMA command codes */ +#define SWABORT 0x01 +#define FEICLEAR 0x02 + +/* IE0 */ +#define TXINTE BIT7 +#define RXINTE BIT6 +#define TXRDYE BIT1 +#define RXRDYE BIT0 + +/* IE1 & SR1 */ +#define UDRN BIT7 +#define IDLE BIT6 +#define SYNCD BIT4 +#define FLGD BIT4 +#define CCTS BIT3 +#define CDCD BIT2 +#define BRKD BIT1 +#define ABTD BIT1 +#define GAPD BIT1 +#define BRKE BIT0 +#define IDLD BIT0 + +/* IE2 & SR2 */ +#define EOM BIT7 +#define PMP BIT6 +#define SHRT BIT6 +#define PE BIT5 +#define ABT BIT5 +#define FRME BIT4 +#define RBIT BIT4 +#define OVRN BIT3 +#define CRCE BIT2 + + +/* + * Global linked list of SyncLink devices + */ +static SLMP_INFO *synclinkmp_device_list = NULL; +static int synclinkmp_adapter_count = -1; +static int synclinkmp_device_count = 0; + +/* + * Set this param to non-zero to load eax with the + * .text section address and breakpoint on module load. + * This is useful for use with gdb and add-symbol-file command. + */ +static int break_on_load = 0; + +/* + * Driver major number, defaults to zero to get auto + * assigned major number. May be forced as module parameter. + */ +static int ttymajor = 0; + +/* + * Array of user specified options for ISA adapters. + */ +static int debug_level = 0; +static int maxframe[MAX_DEVICES] = {0,}; + +module_param(break_on_load, bool, 0); +module_param(ttymajor, int, 0); +module_param(debug_level, int, 0); +module_param_array(maxframe, int, NULL, 0); + +static char *driver_name = "SyncLink MultiPort driver"; +static char *driver_version = "$Revision: 4.38 $"; + +static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); +static void synclinkmp_remove_one(struct pci_dev *dev); + +static struct pci_device_id synclinkmp_pci_tbl[] = { + { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_SCA, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl); + +MODULE_LICENSE("GPL"); + +static struct pci_driver synclinkmp_pci_driver = { + .name = "synclinkmp", + .id_table = synclinkmp_pci_tbl, + .probe = synclinkmp_init_one, + .remove = __devexit_p(synclinkmp_remove_one), +}; + + +static struct tty_driver *serial_driver; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + + +/* tty callbacks */ + +static int open(struct tty_struct *tty, struct file * filp); +static void close(struct tty_struct *tty, struct file * filp); +static void hangup(struct tty_struct *tty); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); + +static int write(struct tty_struct *tty, const unsigned char *buf, int count); +static int put_char(struct tty_struct *tty, unsigned char ch); +static void send_xchar(struct tty_struct *tty, char ch); +static void wait_until_sent(struct tty_struct *tty, int timeout); +static int write_room(struct tty_struct *tty); +static void flush_chars(struct tty_struct *tty); +static void flush_buffer(struct tty_struct *tty); +static void tx_hold(struct tty_struct *tty); +static void tx_release(struct tty_struct *tty); + +static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); +static int chars_in_buffer(struct tty_struct *tty); +static void throttle(struct tty_struct * tty); +static void unthrottle(struct tty_struct * tty); +static int set_break(struct tty_struct *tty, int break_state); + +#if SYNCLINK_GENERIC_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(SLMP_INFO *info); +static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size); +static int hdlcdev_init(SLMP_INFO *info); +static void hdlcdev_exit(SLMP_INFO *info); +#endif + +/* ioctl handlers */ + +static int get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount); +static int get_params(SLMP_INFO *info, MGSL_PARAMS __user *params); +static int set_params(SLMP_INFO *info, MGSL_PARAMS __user *params); +static int get_txidle(SLMP_INFO *info, int __user *idle_mode); +static int set_txidle(SLMP_INFO *info, int idle_mode); +static int tx_enable(SLMP_INFO *info, int enable); +static int tx_abort(SLMP_INFO *info); +static int rx_enable(SLMP_INFO *info, int enable); +static int modem_input_wait(SLMP_INFO *info,int arg); +static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); +static int tiocmget(struct tty_struct *tty); +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); +static int set_break(struct tty_struct *tty, int break_state); + +static void add_device(SLMP_INFO *info); +static void device_init(int adapter_num, struct pci_dev *pdev); +static int claim_resources(SLMP_INFO *info); +static void release_resources(SLMP_INFO *info); + +static int startup(SLMP_INFO *info); +static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); +static int carrier_raised(struct tty_port *port); +static void shutdown(SLMP_INFO *info); +static void program_hw(SLMP_INFO *info); +static void change_params(SLMP_INFO *info); + +static bool init_adapter(SLMP_INFO *info); +static bool register_test(SLMP_INFO *info); +static bool irq_test(SLMP_INFO *info); +static bool loopback_test(SLMP_INFO *info); +static int adapter_test(SLMP_INFO *info); +static bool memory_test(SLMP_INFO *info); + +static void reset_adapter(SLMP_INFO *info); +static void reset_port(SLMP_INFO *info); +static void async_mode(SLMP_INFO *info); +static void hdlc_mode(SLMP_INFO *info); + +static void rx_stop(SLMP_INFO *info); +static void rx_start(SLMP_INFO *info); +static void rx_reset_buffers(SLMP_INFO *info); +static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last); +static bool rx_get_frame(SLMP_INFO *info); + +static void tx_start(SLMP_INFO *info); +static void tx_stop(SLMP_INFO *info); +static void tx_load_fifo(SLMP_INFO *info); +static void tx_set_idle(SLMP_INFO *info); +static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count); + +static void get_signals(SLMP_INFO *info); +static void set_signals(SLMP_INFO *info); +static void enable_loopback(SLMP_INFO *info, int enable); +static void set_rate(SLMP_INFO *info, u32 data_rate); + +static int bh_action(SLMP_INFO *info); +static void bh_handler(struct work_struct *work); +static void bh_receive(SLMP_INFO *info); +static void bh_transmit(SLMP_INFO *info); +static void bh_status(SLMP_INFO *info); +static void isr_timer(SLMP_INFO *info); +static void isr_rxint(SLMP_INFO *info); +static void isr_rxrdy(SLMP_INFO *info); +static void isr_txint(SLMP_INFO *info); +static void isr_txrdy(SLMP_INFO *info); +static void isr_rxdmaok(SLMP_INFO *info); +static void isr_rxdmaerror(SLMP_INFO *info); +static void isr_txdmaok(SLMP_INFO *info); +static void isr_txdmaerror(SLMP_INFO *info); +static void isr_io_pin(SLMP_INFO *info, u16 status); + +static int alloc_dma_bufs(SLMP_INFO *info); +static void free_dma_bufs(SLMP_INFO *info); +static int alloc_buf_list(SLMP_INFO *info); +static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *list, SCADESC_EX *list_ex,int count); +static int alloc_tmp_rx_buf(SLMP_INFO *info); +static void free_tmp_rx_buf(SLMP_INFO *info); + +static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count); +static void trace_block(SLMP_INFO *info, const char* data, int count, int xmit); +static void tx_timeout(unsigned long context); +static void status_timeout(unsigned long context); + +static unsigned char read_reg(SLMP_INFO *info, unsigned char addr); +static void write_reg(SLMP_INFO *info, unsigned char addr, unsigned char val); +static u16 read_reg16(SLMP_INFO *info, unsigned char addr); +static void write_reg16(SLMP_INFO *info, unsigned char addr, u16 val); +static unsigned char read_status_reg(SLMP_INFO * info); +static void write_control_reg(SLMP_INFO * info); + + +static unsigned char rx_active_fifo_level = 16; // rx request FIFO activation level in bytes +static unsigned char tx_active_fifo_level = 16; // tx request FIFO activation level in bytes +static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes + +static u32 misc_ctrl_value = 0x007e4040; +static u32 lcr1_brdr_value = 0x00800028; + +static u32 read_ahead_count = 8; + +/* DPCR, DMA Priority Control + * + * 07..05 Not used, must be 0 + * 04 BRC, bus release condition: 0=all transfers complete + * 1=release after 1 xfer on all channels + * 03 CCC, channel change condition: 0=every cycle + * 1=after each channel completes all xfers + * 02..00 PR<2..0>, priority 100=round robin + * + * 00000100 = 0x00 + */ +static unsigned char dma_priority = 0x04; + +// Number of bytes that can be written to shared RAM +// in a single write operation +static u32 sca_pci_load_interval = 64; + +/* + * 1st function defined in .text section. Calling this function in + * init_module() followed by a breakpoint allows a remote debugger + * (gdb) to get the .text address for the add-symbol-file command. + * This allows remote debugging of dynamically loadable modules. + */ +static void* synclinkmp_get_text_ptr(void); +static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;} + +static inline int sanity_check(SLMP_INFO *info, + char *name, const char *routine) +{ +#ifdef SANITY_CHECK + static const char *badmagic = + "Warning: bad magic number for synclinkmp_struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null synclinkmp_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, name, routine); + return 1; + } + if (info->magic != MGSL_MAGIC) { + printk(badmagic, name, routine); + return 1; + } +#else + if (!info) + return 1; +#endif + return 0; +} + +/** + * line discipline callback wrappers + * + * The wrappers maintain line discipline references + * while calling into the line discipline. + * + * ldisc_receive_buf - pass receive data to line discipline + */ + +static void ldisc_receive_buf(struct tty_struct *tty, + const __u8 *data, char *flags, int count) +{ + struct tty_ldisc *ld; + if (!tty) + return; + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->ops->receive_buf) + ld->ops->receive_buf(tty, data, flags, count); + tty_ldisc_deref(ld); + } +} + +/* tty callbacks */ + +/* Called when a port is opened. Init and enable port. + */ +static int open(struct tty_struct *tty, struct file *filp) +{ + SLMP_INFO *info; + int retval, line; + unsigned long flags; + + line = tty->index; + if ((line < 0) || (line >= synclinkmp_device_count)) { + printk("%s(%d): open with invalid line #%d.\n", + __FILE__,__LINE__,line); + return -ENODEV; + } + + info = synclinkmp_device_list; + while(info && info->line != line) + info = info->next_device; + if (sanity_check(info, tty->name, "open")) + return -ENODEV; + if ( info->init_error ) { + printk("%s(%d):%s device is not allocated, init error=%d\n", + __FILE__,__LINE__,info->device_name,info->init_error); + return -ENODEV; + } + + tty->driver_data = info; + info->port.tty = tty; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s open(), old ref count = %d\n", + __FILE__,__LINE__,tty->driver->name, info->port.count); + + /* If port is closing, signal caller to try again */ + if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ + if (info->port.flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->port.close_wait); + retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + goto cleanup; + } + + info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + spin_lock_irqsave(&info->netlock, flags); + if (info->netcount) { + retval = -EBUSY; + spin_unlock_irqrestore(&info->netlock, flags); + goto cleanup; + } + info->port.count++; + spin_unlock_irqrestore(&info->netlock, flags); + + if (info->port.count == 1) { + /* 1st open on this device, init hardware */ + retval = startup(info); + if (retval < 0) + goto cleanup; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s block_til_ready() returned %d\n", + __FILE__,__LINE__, info->device_name, retval); + goto cleanup; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s open() success\n", + __FILE__,__LINE__, info->device_name); + retval = 0; + +cleanup: + if (retval) { + if (tty->count == 1) + info->port.tty = NULL; /* tty layer will release tty struct */ + if(info->port.count) + info->port.count--; + } + + return retval; +} + +/* Called when port is closed. Wait for remaining data to be + * sent. Disable port and free resources. + */ +static void close(struct tty_struct *tty, struct file *filp) +{ + SLMP_INFO * info = tty->driver_data; + + if (sanity_check(info, tty->name, "close")) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s close() entry, count=%d\n", + __FILE__,__LINE__, info->device_name, info->port.count); + + if (tty_port_close_start(&info->port, tty, filp) == 0) + goto cleanup; + + mutex_lock(&info->port.mutex); + if (info->port.flags & ASYNC_INITIALIZED) + wait_until_sent(tty, info->timeout); + + flush_buffer(tty); + tty_ldisc_flush(tty); + shutdown(info); + mutex_unlock(&info->port.mutex); + + tty_port_close_end(&info->port, tty); + info->port.tty = NULL; +cleanup: + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, + tty->driver->name, info->port.count); +} + +/* Called by tty_hangup() when a hangup is signaled. + * This is the same as closing all open descriptors for the port. + */ +static void hangup(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s hangup()\n", + __FILE__,__LINE__, info->device_name ); + + if (sanity_check(info, tty->name, "hangup")) + return; + + mutex_lock(&info->port.mutex); + flush_buffer(tty); + shutdown(info); + + spin_lock_irqsave(&info->port.lock, flags); + info->port.count = 0; + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; + info->port.tty = NULL; + spin_unlock_irqrestore(&info->port.lock, flags); + mutex_unlock(&info->port.mutex); + + wake_up_interruptible(&info->port.open_wait); +} + +/* Set new termios settings + */ +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__, + tty->driver->name ); + + change_params(info); + + /* Handle transition to B0 status */ + if (old_termios->c_cflag & CBAUD && + !(tty->termios->c_cflag & CBAUD)) { + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + tty->termios->c_cflag & CBAUD) { + info->serial_signals |= SerialSignal_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->serial_signals |= SerialSignal_RTS; + } + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + /* Handle turning off CRTSCTS */ + if (old_termios->c_cflag & CRTSCTS && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + tx_release(tty); + } +} + +/* Send a block of data + * + * Arguments: + * + * tty pointer to tty information structure + * buf pointer to buffer containing send data + * count size of send data in bytes + * + * Return Value: number of characters written + */ +static int write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + int c, ret = 0; + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s write() count=%d\n", + __FILE__,__LINE__,info->device_name,count); + + if (sanity_check(info, tty->name, "write")) + goto cleanup; + + if (!info->tx_buf) + goto cleanup; + + if (info->params.mode == MGSL_MODE_HDLC) { + if (count > info->max_frame_size) { + ret = -EIO; + goto cleanup; + } + if (info->tx_active) + goto cleanup; + if (info->tx_count) { + /* send accumulated data from send_char() calls */ + /* as frame and wait before accepting more data. */ + tx_load_dma_buffer(info, info->tx_buf, info->tx_count); + goto start; + } + ret = info->tx_count = count; + tx_load_dma_buffer(info, buf, count); + goto start; + } + + for (;;) { + c = min_t(int, count, + min(info->max_frame_size - info->tx_count - 1, + info->max_frame_size - info->tx_put)); + if (c <= 0) + break; + + memcpy(info->tx_buf + info->tx_put, buf, c); + + spin_lock_irqsave(&info->lock,flags); + info->tx_put += c; + if (info->tx_put >= info->max_frame_size) + info->tx_put -= info->max_frame_size; + info->tx_count += c; + spin_unlock_irqrestore(&info->lock,flags); + + buf += c; + count -= c; + ret += c; + } + + if (info->params.mode == MGSL_MODE_HDLC) { + if (count) { + ret = info->tx_count = 0; + goto cleanup; + } + tx_load_dma_buffer(info, info->tx_buf, info->tx_count); + } +start: + if (info->tx_count && !tty->stopped && !tty->hw_stopped) { + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } + +cleanup: + if (debug_level >= DEBUG_LEVEL_INFO) + printk( "%s(%d):%s write() returning=%d\n", + __FILE__,__LINE__,info->device_name,ret); + return ret; +} + +/* Add a character to the transmit buffer. + */ +static int put_char(struct tty_struct *tty, unsigned char ch) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + int ret = 0; + + if ( debug_level >= DEBUG_LEVEL_INFO ) { + printk( "%s(%d):%s put_char(%d)\n", + __FILE__,__LINE__,info->device_name,ch); + } + + if (sanity_check(info, tty->name, "put_char")) + return 0; + + if (!info->tx_buf) + return 0; + + spin_lock_irqsave(&info->lock,flags); + + if ( (info->params.mode != MGSL_MODE_HDLC) || + !info->tx_active ) { + + if (info->tx_count < info->max_frame_size - 1) { + info->tx_buf[info->tx_put++] = ch; + if (info->tx_put >= info->max_frame_size) + info->tx_put -= info->max_frame_size; + info->tx_count++; + ret = 1; + } + } + + spin_unlock_irqrestore(&info->lock,flags); + return ret; +} + +/* Send a high-priority XON/XOFF character + */ +static void send_xchar(struct tty_struct *tty, char ch) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s send_xchar(%d)\n", + __FILE__,__LINE__, info->device_name, ch ); + + if (sanity_check(info, tty->name, "send_xchar")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_enabled) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* Wait until the transmitter is empty. + */ +static void wait_until_sent(struct tty_struct *tty, int timeout) +{ + SLMP_INFO * info = tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (!info ) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s wait_until_sent() entry\n", + __FILE__,__LINE__, info->device_name ); + + if (sanity_check(info, tty->name, "wait_until_sent")) + return; + + if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags)) + goto exit; + + orig_jiffies = jiffies; + + /* Set check interval to 1/5 of estimated time to + * send a character, and make it at least 1. The check + * interval should also be less than the timeout. + * Note: use tight timings here to satisfy the NIST-PCTS. + */ + + if ( info->params.data_rate ) { + char_time = info->timeout/(32 * 5); + if (!char_time) + char_time++; + } else + char_time = 1; + + if (timeout) + char_time = min_t(unsigned long, char_time, timeout); + + if ( info->params.mode == MGSL_MODE_HDLC ) { + while (info->tx_active) { + msleep_interruptible(jiffies_to_msecs(char_time)); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + } else { + /* + * TODO: determine if there is something similar to USC16C32 + * TXSTATUS_ALL_SENT status + */ + while ( info->tx_active && info->tx_enabled) { + msleep_interruptible(jiffies_to_msecs(char_time)); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + } + +exit: + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s wait_until_sent() exit\n", + __FILE__,__LINE__, info->device_name ); +} + +/* Return the count of free bytes in transmit buffer + */ +static int write_room(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + int ret; + + if (sanity_check(info, tty->name, "write_room")) + return 0; + + if (info->params.mode == MGSL_MODE_HDLC) { + ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; + } else { + ret = info->max_frame_size - info->tx_count - 1; + if (ret < 0) + ret = 0; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s write_room()=%d\n", + __FILE__, __LINE__, info->device_name, ret); + + return ret; +} + +/* enable transmitter and send remaining buffered characters + */ +static void flush_chars(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s flush_chars() entry tx_count=%d\n", + __FILE__,__LINE__,info->device_name,info->tx_count); + + if (sanity_check(info, tty->name, "flush_chars")) + return; + + if (info->tx_count <= 0 || tty->stopped || tty->hw_stopped || + !info->tx_buf) + return; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s flush_chars() entry, starting transmitter\n", + __FILE__,__LINE__,info->device_name ); + + spin_lock_irqsave(&info->lock,flags); + + if (!info->tx_active) { + if ( (info->params.mode == MGSL_MODE_HDLC) && + info->tx_count ) { + /* operating in synchronous (frame oriented) mode */ + /* copy data from circular tx_buf to */ + /* transmit DMA buffer. */ + tx_load_dma_buffer(info, + info->tx_buf,info->tx_count); + } + tx_start(info); + } + + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Discard all data in the send buffer + */ +static void flush_buffer(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s flush_buffer() entry\n", + __FILE__,__LINE__, info->device_name ); + + if (sanity_check(info, tty->name, "flush_buffer")) + return; + + spin_lock_irqsave(&info->lock,flags); + info->tx_count = info->tx_put = info->tx_get = 0; + del_timer(&info->tx_timer); + spin_unlock_irqrestore(&info->lock,flags); + + tty_wakeup(tty); +} + +/* throttle (stop) transmitter + */ +static void tx_hold(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "tx_hold")) + return; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s(%d):%s tx_hold()\n", + __FILE__,__LINE__,info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if (info->tx_enabled) + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* release (start) transmitter + */ +static void tx_release(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (sanity_check(info, tty->name, "tx_release")) + return; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s(%d):%s tx_release()\n", + __FILE__,__LINE__,info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_enabled) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Service an IOCTL request + * + * Arguments: + * + * tty pointer to tty instance data + * cmd IOCTL command code + * arg command argument/context + * + * Return Value: 0 if success, otherwise error code + */ +static int ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + SLMP_INFO *info = tty->driver_data; + void __user *argp = (void __user *)arg; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__, + info->device_name, cmd ); + + if (sanity_check(info, tty->name, "ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCMIWAIT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case MGSL_IOCGPARAMS: + return get_params(info, argp); + case MGSL_IOCSPARAMS: + return set_params(info, argp); + case MGSL_IOCGTXIDLE: + return get_txidle(info, argp); + case MGSL_IOCSTXIDLE: + return set_txidle(info, (int)arg); + case MGSL_IOCTXENABLE: + return tx_enable(info, (int)arg); + case MGSL_IOCRXENABLE: + return rx_enable(info, (int)arg); + case MGSL_IOCTXABORT: + return tx_abort(info); + case MGSL_IOCGSTATS: + return get_stats(info, argp); + case MGSL_IOCWAITEVENT: + return wait_mgsl_event(info, argp); + case MGSL_IOCLOOPTXDONE: + return 0; // TODO: Not supported, need to document + /* Wait for modem input (DCD,RI,DSR,CTS) change + * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS) + */ + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + SLMP_INFO *info = tty->driver_data; + struct mgsl_icount cnow; /* kernel counter temps */ + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->lock,flags); + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->frame = cnow.frame; + icount->overrun = cnow.overrun; + icount->parity = cnow.parity; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline void line_info(struct seq_file *m, SLMP_INFO *info) +{ + char stat_buf[30]; + unsigned long flags; + + seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" + "\tIRQ=%d MaxFrameSize=%u\n", + info->device_name, + info->phys_sca_base, + info->phys_memory_base, + info->phys_statctrl_base, + info->phys_lcr_base, + info->irq_level, + info->max_frame_size ); + + /* output current serial signal states */ + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (info->serial_signals & SerialSignal_RTS) + strcat(stat_buf, "|RTS"); + if (info->serial_signals & SerialSignal_CTS) + strcat(stat_buf, "|CTS"); + if (info->serial_signals & SerialSignal_DTR) + strcat(stat_buf, "|DTR"); + if (info->serial_signals & SerialSignal_DSR) + strcat(stat_buf, "|DSR"); + if (info->serial_signals & SerialSignal_DCD) + strcat(stat_buf, "|CD"); + if (info->serial_signals & SerialSignal_RI) + strcat(stat_buf, "|RI"); + + if (info->params.mode == MGSL_MODE_HDLC) { + seq_printf(m, "\tHDLC txok:%d rxok:%d", + info->icount.txok, info->icount.rxok); + if (info->icount.txunder) + seq_printf(m, " txunder:%d", info->icount.txunder); + if (info->icount.txabort) + seq_printf(m, " txabort:%d", info->icount.txabort); + if (info->icount.rxshort) + seq_printf(m, " rxshort:%d", info->icount.rxshort); + if (info->icount.rxlong) + seq_printf(m, " rxlong:%d", info->icount.rxlong); + if (info->icount.rxover) + seq_printf(m, " rxover:%d", info->icount.rxover); + if (info->icount.rxcrc) + seq_printf(m, " rxlong:%d", info->icount.rxcrc); + } else { + seq_printf(m, "\tASYNC tx:%d rx:%d", + info->icount.tx, info->icount.rx); + if (info->icount.frame) + seq_printf(m, " fe:%d", info->icount.frame); + if (info->icount.parity) + seq_printf(m, " pe:%d", info->icount.parity); + if (info->icount.brk) + seq_printf(m, " brk:%d", info->icount.brk); + if (info->icount.overrun) + seq_printf(m, " oe:%d", info->icount.overrun); + } + + /* Append serial signal status to end */ + seq_printf(m, " %s\n", stat_buf+1); + + seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", + info->tx_active,info->bh_requested,info->bh_running, + info->pending_bh); +} + +/* Called to print information about devices + */ +static int synclinkmp_proc_show(struct seq_file *m, void *v) +{ + SLMP_INFO *info; + + seq_printf(m, "synclinkmp driver:%s\n", driver_version); + + info = synclinkmp_device_list; + while( info ) { + line_info(m, info); + info = info->next_device; + } + return 0; +} + +static int synclinkmp_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, synclinkmp_proc_show, NULL); +} + +static const struct file_operations synclinkmp_proc_fops = { + .owner = THIS_MODULE, + .open = synclinkmp_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* Return the count of bytes in transmit buffer + */ +static int chars_in_buffer(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + + if (sanity_check(info, tty->name, "chars_in_buffer")) + return 0; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s chars_in_buffer()=%d\n", + __FILE__, __LINE__, info->device_name, info->tx_count); + + return info->tx_count; +} + +/* Signal remote device to throttle send data (our receive data) + */ +static void throttle(struct tty_struct * tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s throttle() entry\n", + __FILE__,__LINE__, info->device_name ); + + if (sanity_check(info, tty->name, "throttle")) + return; + + if (I_IXOFF(tty)) + send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock,flags); + info->serial_signals &= ~SerialSignal_RTS; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* Signal remote device to stop throttling send data (our receive data) + */ +static void unthrottle(struct tty_struct * tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s unthrottle() entry\n", + __FILE__,__LINE__, info->device_name ); + + if (sanity_check(info, tty->name, "unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + send_xchar(tty, START_CHAR(tty)); + } + + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock,flags); + info->serial_signals |= SerialSignal_RTS; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* set or clear transmit break condition + * break_state -1=set break condition, 0=clear + */ +static int set_break(struct tty_struct *tty, int break_state) +{ + unsigned char RegValue; + SLMP_INFO * info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s set_break(%d)\n", + __FILE__,__LINE__, info->device_name, break_state); + + if (sanity_check(info, tty->name, "set_break")) + return -EINVAL; + + spin_lock_irqsave(&info->lock,flags); + RegValue = read_reg(info, CTL); + if (break_state == -1) + RegValue |= BIT3; + else + RegValue &= ~BIT3; + write_reg(info, CTL, RegValue); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +#if SYNCLINK_GENERIC_HDLC + +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) +{ + SLMP_INFO *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; + + /* return error if TTY interface open */ + if (info->port.count) + return -EBUSY; + + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; + } + + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } + + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); + + return 0; +} + +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + */ +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + SLMP_INFO *info = dev_to_port(dev); + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + info->tx_count = skb->len; + tx_load_dma_buffer(info, skb->data, skb->len); + + /* update network statistics */ + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + return NETDEV_TX_OK; +} + +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) +{ + SLMP_INFO *info = dev_to_port(dev); + int rc; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + + /* arbitrate between network and tty opens */ + spin_lock_irqsave(&info->netlock, flags); + if (info->port.count != 0 || info->netcount != 0) { + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); + spin_unlock_irqrestore(&info->netlock, flags); + return -EBUSY; + } + info->netcount=1; + spin_unlock_irqrestore(&info->netlock, flags); + + /* claim resources and init adapter */ + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; + } + + /* assert DTR and RTS, apply hardware settings */ + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + program_hw(info); + + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); + + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); + if (info->serial_signals & SerialSignal_DCD) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + return 0; +} + +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) +{ + SLMP_INFO *info = dev_to_port(dev); + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); + + netif_stop_queue(dev); + + /* shutdown adapter and release resources */ + shutdown(info); + + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; +} + +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + SLMP_INFO *info = dev_to_port(dev); + unsigned int flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); + + /* return error if TTY interface open */ + if (info->port.count) + return -EBUSY; + + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); + + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ + + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } +} + +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) +{ + SLMP_INFO *info = dev_to_port(dev); + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("hdlcdev_tx_timeout(%s)\n",dev->name); + + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; + + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); + + netif_wake_queue(dev); +} + +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(SLMP_INFO *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) +{ + struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("hdlcdev_rx(%s)\n",dev->name); + + if (skb == NULL) { + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", + dev->name); + dev->stats.rx_dropped++; + return; + } + + memcpy(skb_put(skb, size), buf, size); + + skb->protocol = hdlc_type_trans(skb, dev); + + dev->stats.rx_packets++; + dev->stats.rx_bytes += size; + + netif_rx(skb); +} + +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(SLMP_INFO *info) +{ + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->mem_start = info->phys_sca_base; + dev->mem_end = info->phys_sca_base + SCA_BASE_SIZE - 1; + dev->irq = info->irq_level; + + /* network layer callbacks and settings */ + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; +} + +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(SLMP_INFO *info) +{ + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; +} + +#endif /* CONFIG_HDLC */ + + +/* Return next bottom half action to perform. + * Return Value: BH action code or 0 if nothing to do. + */ +static int bh_action(SLMP_INFO *info) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&info->lock,flags); + + if (info->pending_bh & BH_RECEIVE) { + info->pending_bh &= ~BH_RECEIVE; + rc = BH_RECEIVE; + } else if (info->pending_bh & BH_TRANSMIT) { + info->pending_bh &= ~BH_TRANSMIT; + rc = BH_TRANSMIT; + } else if (info->pending_bh & BH_STATUS) { + info->pending_bh &= ~BH_STATUS; + rc = BH_STATUS; + } + + if (!rc) { + /* Mark BH routine as complete */ + info->bh_running = false; + info->bh_requested = false; + } + + spin_unlock_irqrestore(&info->lock,flags); + + return rc; +} + +/* Perform bottom half processing of work items queued by ISR. + */ +static void bh_handler(struct work_struct *work) +{ + SLMP_INFO *info = container_of(work, SLMP_INFO, task); + int action; + + if (!info) + return; + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):%s bh_handler() entry\n", + __FILE__,__LINE__,info->device_name); + + info->bh_running = true; + + while((action = bh_action(info)) != 0) { + + /* Process work item */ + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):%s bh_handler() work item action=%d\n", + __FILE__,__LINE__,info->device_name, action); + + switch (action) { + + case BH_RECEIVE: + bh_receive(info); + break; + case BH_TRANSMIT: + bh_transmit(info); + break; + case BH_STATUS: + bh_status(info); + break; + default: + /* unknown work item ID */ + printk("%s(%d):%s Unknown work item ID=%08X!\n", + __FILE__,__LINE__,info->device_name,action); + break; + } + } + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):%s bh_handler() exit\n", + __FILE__,__LINE__,info->device_name); +} + +static void bh_receive(SLMP_INFO *info) +{ + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):%s bh_receive()\n", + __FILE__,__LINE__,info->device_name); + + while( rx_get_frame(info) ); +} + +static void bh_transmit(SLMP_INFO *info) +{ + struct tty_struct *tty = info->port.tty; + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):%s bh_transmit() entry\n", + __FILE__,__LINE__,info->device_name); + + if (tty) + tty_wakeup(tty); +} + +static void bh_status(SLMP_INFO *info) +{ + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):%s bh_status() entry\n", + __FILE__,__LINE__,info->device_name); + + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + info->dcd_chkcount = 0; + info->cts_chkcount = 0; +} + +static void isr_timer(SLMP_INFO * info) +{ + unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0; + + /* IER2<7..4> = timer<3..0> interrupt enables (0=disabled) */ + write_reg(info, IER2, 0); + + /* TMCS, Timer Control/Status Register + * + * 07 CMF, Compare match flag (read only) 1=match + * 06 ECMI, CMF Interrupt Enable: 0=disabled + * 05 Reserved, must be 0 + * 04 TME, Timer Enable + * 03..00 Reserved, must be 0 + * + * 0000 0000 + */ + write_reg(info, (unsigned char)(timer + TMCS), 0); + + info->irq_occurred = true; + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_timer()\n", + __FILE__,__LINE__,info->device_name); +} + +static void isr_rxint(SLMP_INFO * info) +{ + struct tty_struct *tty = info->port.tty; + struct mgsl_icount *icount = &info->icount; + unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD); + unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN; + + /* clear status bits */ + if (status) + write_reg(info, SR1, status); + + if (status2) + write_reg(info, SR2, status2); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_rxint status=%02X %02x\n", + __FILE__,__LINE__,info->device_name,status,status2); + + if (info->params.mode == MGSL_MODE_ASYNC) { + if (status & BRKD) { + icount->brk++; + + /* process break detection if tty control + * is not set to ignore it + */ + if ( tty ) { + if (!(status & info->ignore_status_mask1)) { + if (info->read_status_mask1 & BRKD) { + tty_insert_flip_char(tty, 0, TTY_BREAK); + if (info->port.flags & ASYNC_SAK) + do_SAK(tty); + } + } + } + } + } + else { + if (status & (FLGD|IDLD)) { + if (status & FLGD) + info->icount.exithunt++; + else if (status & IDLD) + info->icount.rxidle++; + wake_up_interruptible(&info->event_wait_q); + } + } + + if (status & CDCD) { + /* simulate a common modem status change interrupt + * for our handler + */ + get_signals( info ); + isr_io_pin(info, + MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD)); + } +} + +/* + * handle async rx data interrupts + */ +static void isr_rxrdy(SLMP_INFO * info) +{ + u16 status; + unsigned char DataByte; + struct tty_struct *tty = info->port.tty; + struct mgsl_icount *icount = &info->icount; + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_rxrdy\n", + __FILE__,__LINE__,info->device_name); + + while((status = read_reg(info,CST0)) & BIT0) + { + int flag = 0; + bool over = false; + DataByte = read_reg(info,TRB); + + icount->rx++; + + if ( status & (PE + FRME + OVRN) ) { + printk("%s(%d):%s rxerr=%04X\n", + __FILE__,__LINE__,info->device_name,status); + + /* update error statistics */ + if (status & PE) + icount->parity++; + else if (status & FRME) + icount->frame++; + else if (status & OVRN) + icount->overrun++; + + /* discard char if tty control flags say so */ + if (status & info->ignore_status_mask2) + continue; + + status &= info->read_status_mask2; + + if ( tty ) { + if (status & PE) + flag = TTY_PARITY; + else if (status & FRME) + flag = TTY_FRAME; + if (status & OVRN) { + /* Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + over = true; + } + } + } /* end of if (error) */ + + if ( tty ) { + tty_insert_flip_char(tty, DataByte, flag); + if (over) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + } + + if ( debug_level >= DEBUG_LEVEL_ISR ) { + printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n", + __FILE__,__LINE__,info->device_name, + icount->rx,icount->brk,icount->parity, + icount->frame,icount->overrun); + } + + if ( tty ) + tty_flip_buffer_push(tty); +} + +static void isr_txeom(SLMP_INFO * info, unsigned char status) +{ + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_txeom status=%02x\n", + __FILE__,__LINE__,info->device_name,status); + + write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ + write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */ + write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + + if (status & UDRN) { + write_reg(info, CMD, TXRESET); + write_reg(info, CMD, TXENABLE); + } else + write_reg(info, CMD, TXBUFCLR); + + /* disable and clear tx interrupts */ + info->ie0_value &= ~TXRDYE; + info->ie1_value &= ~(IDLE + UDRN); + write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); + write_reg(info, SR1, (unsigned char)(UDRN + IDLE)); + + if ( info->tx_active ) { + if (info->params.mode != MGSL_MODE_ASYNC) { + if (status & UDRN) + info->icount.txunder++; + else if (status & IDLE) + info->icount.txok++; + } + + info->tx_active = false; + info->tx_count = info->tx_put = info->tx_get = 0; + + del_timer(&info->tx_timer); + + if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) { + info->serial_signals &= ~SerialSignal_RTS; + info->drop_rts_on_tx_done = false; + set_signals(info); + } + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_tx_done(info); + else +#endif + { + if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { + tx_stop(info); + return; + } + info->pending_bh |= BH_TRANSMIT; + } + } +} + + +/* + * handle tx status interrupts + */ +static void isr_txint(SLMP_INFO * info) +{ + unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS); + + /* clear status bits */ + write_reg(info, SR1, status); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_txint status=%02x\n", + __FILE__,__LINE__,info->device_name,status); + + if (status & (UDRN + IDLE)) + isr_txeom(info, status); + + if (status & CCTS) { + /* simulate a common modem status change interrupt + * for our handler + */ + get_signals( info ); + isr_io_pin(info, + MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS)); + + } +} + +/* + * handle async tx data interrupts + */ +static void isr_txrdy(SLMP_INFO * info) +{ + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_txrdy() tx_count=%d\n", + __FILE__,__LINE__,info->device_name,info->tx_count); + + if (info->params.mode != MGSL_MODE_ASYNC) { + /* disable TXRDY IRQ, enable IDLE IRQ */ + info->ie0_value &= ~TXRDYE; + info->ie1_value |= IDLE; + write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); + return; + } + + if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { + tx_stop(info); + return; + } + + if ( info->tx_count ) + tx_load_fifo( info ); + else { + info->tx_active = false; + info->ie0_value &= ~TXRDYE; + write_reg(info, IE0, info->ie0_value); + } + + if (info->tx_count < WAKEUP_CHARS) + info->pending_bh |= BH_TRANSMIT; +} + +static void isr_rxdmaok(SLMP_INFO * info) +{ + /* BIT7 = EOT (end of transfer) + * BIT6 = EOM (end of message/frame) + */ + unsigned char status = read_reg(info,RXDMA + DSR) & 0xc0; + + /* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */ + write_reg(info, RXDMA + DSR, (unsigned char)(status | 1)); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_rxdmaok(), status=%02x\n", + __FILE__,__LINE__,info->device_name,status); + + info->pending_bh |= BH_RECEIVE; +} + +static void isr_rxdmaerror(SLMP_INFO * info) +{ + /* BIT5 = BOF (buffer overflow) + * BIT4 = COF (counter overflow) + */ + unsigned char status = read_reg(info,RXDMA + DSR) & 0x30; + + /* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */ + write_reg(info, RXDMA + DSR, (unsigned char)(status | 1)); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n", + __FILE__,__LINE__,info->device_name,status); + + info->rx_overflow = true; + info->pending_bh |= BH_RECEIVE; +} + +static void isr_txdmaok(SLMP_INFO * info) +{ + unsigned char status_reg1 = read_reg(info, SR1); + + write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ + write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */ + write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_txdmaok(), status=%02x\n", + __FILE__,__LINE__,info->device_name,status_reg1); + + /* program TXRDY as FIFO empty flag, enable TXRDY IRQ */ + write_reg16(info, TRC0, 0); + info->ie0_value |= TXRDYE; + write_reg(info, IE0, info->ie0_value); +} + +static void isr_txdmaerror(SLMP_INFO * info) +{ + /* BIT5 = BOF (buffer overflow) + * BIT4 = COF (counter overflow) + */ + unsigned char status = read_reg(info,TXDMA + DSR) & 0x30; + + /* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */ + write_reg(info, TXDMA + DSR, (unsigned char)(status | 1)); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s isr_txdmaerror(), status=%02x\n", + __FILE__,__LINE__,info->device_name,status); +} + +/* handle input serial signal changes + */ +static void isr_io_pin( SLMP_INFO *info, u16 status ) +{ + struct mgsl_icount *icount; + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):isr_io_pin status=%04X\n", + __FILE__,__LINE__,status); + + if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED | + MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) { + icount = &info->icount; + /* update input line counters */ + if (status & MISCSTATUS_RI_LATCHED) { + icount->rng++; + if ( status & SerialSignal_RI ) + info->input_signal_events.ri_up++; + else + info->input_signal_events.ri_down++; + } + if (status & MISCSTATUS_DSR_LATCHED) { + icount->dsr++; + if ( status & SerialSignal_DSR ) + info->input_signal_events.dsr_up++; + else + info->input_signal_events.dsr_down++; + } + if (status & MISCSTATUS_DCD_LATCHED) { + if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) { + info->ie1_value &= ~CDCD; + write_reg(info, IE1, info->ie1_value); + } + icount->dcd++; + if (status & SerialSignal_DCD) { + info->input_signal_events.dcd_up++; + } else + info->input_signal_events.dcd_down++; +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) { + if (status & SerialSignal_DCD) + netif_carrier_on(info->netdev); + else + netif_carrier_off(info->netdev); + } +#endif + } + if (status & MISCSTATUS_CTS_LATCHED) + { + if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) { + info->ie1_value &= ~CCTS; + write_reg(info, IE1, info->ie1_value); + } + icount->cts++; + if ( status & SerialSignal_CTS ) + info->input_signal_events.cts_up++; + else + info->input_signal_events.cts_down++; + } + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + if ( (info->port.flags & ASYNC_CHECK_CD) && + (status & MISCSTATUS_DCD_LATCHED) ) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s CD now %s...", info->device_name, + (status & SerialSignal_DCD) ? "on" : "off"); + if (status & SerialSignal_DCD) + wake_up_interruptible(&info->port.open_wait); + else { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("doing serial hangup..."); + if (info->port.tty) + tty_hangup(info->port.tty); + } + } + + if ( (info->port.flags & ASYNC_CTS_FLOW) && + (status & MISCSTATUS_CTS_LATCHED) ) { + if ( info->port.tty ) { + if (info->port.tty->hw_stopped) { + if (status & SerialSignal_CTS) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("CTS tx start..."); + info->port.tty->hw_stopped = 0; + tx_start(info); + info->pending_bh |= BH_TRANSMIT; + return; + } + } else { + if (!(status & SerialSignal_CTS)) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("CTS tx stop..."); + info->port.tty->hw_stopped = 1; + tx_stop(info); + } + } + } + } + } + + info->pending_bh |= BH_STATUS; +} + +/* Interrupt service routine entry point. + * + * Arguments: + * irq interrupt number that caused interrupt + * dev_id device ID supplied during interrupt registration + * regs interrupted processor context + */ +static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id) +{ + SLMP_INFO *info = dev_id; + unsigned char status, status0, status1=0; + unsigned char dmastatus, dmastatus0, dmastatus1=0; + unsigned char timerstatus0, timerstatus1=0; + unsigned char shift; + unsigned int i; + unsigned short tmp; + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n", + __FILE__, __LINE__, info->irq_level); + + spin_lock(&info->lock); + + for(;;) { + + /* get status for SCA0 (ports 0-1) */ + tmp = read_reg16(info, ISR0); /* get ISR0 and ISR1 in one read */ + status0 = (unsigned char)tmp; + dmastatus0 = (unsigned char)(tmp>>8); + timerstatus0 = read_reg(info, ISR2); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n", + __FILE__, __LINE__, info->device_name, + status0, dmastatus0, timerstatus0); + + if (info->port_count == 4) { + /* get status for SCA1 (ports 2-3) */ + tmp = read_reg16(info->port_array[2], ISR0); + status1 = (unsigned char)tmp; + dmastatus1 = (unsigned char)(tmp>>8); + timerstatus1 = read_reg(info->port_array[2], ISR2); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s status1=%02x, dmastatus1=%02x, timerstatus1=%02x\n", + __FILE__,__LINE__,info->device_name, + status1,dmastatus1,timerstatus1); + } + + if (!status0 && !dmastatus0 && !timerstatus0 && + !status1 && !dmastatus1 && !timerstatus1) + break; + + for(i=0; i < info->port_count ; i++) { + if (info->port_array[i] == NULL) + continue; + if (i < 2) { + status = status0; + dmastatus = dmastatus0; + } else { + status = status1; + dmastatus = dmastatus1; + } + + shift = i & 1 ? 4 :0; + + if (status & BIT0 << shift) + isr_rxrdy(info->port_array[i]); + if (status & BIT1 << shift) + isr_txrdy(info->port_array[i]); + if (status & BIT2 << shift) + isr_rxint(info->port_array[i]); + if (status & BIT3 << shift) + isr_txint(info->port_array[i]); + + if (dmastatus & BIT0 << shift) + isr_rxdmaerror(info->port_array[i]); + if (dmastatus & BIT1 << shift) + isr_rxdmaok(info->port_array[i]); + if (dmastatus & BIT2 << shift) + isr_txdmaerror(info->port_array[i]); + if (dmastatus & BIT3 << shift) + isr_txdmaok(info->port_array[i]); + } + + if (timerstatus0 & (BIT5 | BIT4)) + isr_timer(info->port_array[0]); + if (timerstatus0 & (BIT7 | BIT6)) + isr_timer(info->port_array[1]); + if (timerstatus1 & (BIT5 | BIT4)) + isr_timer(info->port_array[2]); + if (timerstatus1 & (BIT7 | BIT6)) + isr_timer(info->port_array[3]); + } + + for(i=0; i < info->port_count ; i++) { + SLMP_INFO * port = info->port_array[i]; + + /* Request bottom half processing if there's something + * for it to do and the bh is not already running. + * + * Note: startup adapter diags require interrupts. + * do not request bottom half processing if the + * device is not open in a normal mode. + */ + if ( port && (port->port.count || port->netcount) && + port->pending_bh && !port->bh_running && + !port->bh_requested ) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s queueing bh task.\n", + __FILE__,__LINE__,port->device_name); + schedule_work(&port->task); + port->bh_requested = true; + } + } + + spin_unlock(&info->lock); + + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n", + __FILE__, __LINE__, info->irq_level); + return IRQ_HANDLED; +} + +/* Initialize and start device. + */ +static int startup(SLMP_INFO * info) +{ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s(%d):%s tx_releaseup()\n",__FILE__,__LINE__,info->device_name); + + if (info->port.flags & ASYNC_INITIALIZED) + return 0; + + if (!info->tx_buf) { + info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); + if (!info->tx_buf) { + printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", + __FILE__,__LINE__,info->device_name); + return -ENOMEM; + } + } + + info->pending_bh = 0; + + memset(&info->icount, 0, sizeof(info->icount)); + + /* program hardware for current parameters */ + reset_port(info); + + change_params(info); + + mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); + + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); + + info->port.flags |= ASYNC_INITIALIZED; + + return 0; +} + +/* Called by close() and hangup() to shutdown hardware + */ +static void shutdown(SLMP_INFO * info) +{ + unsigned long flags; + + if (!(info->port.flags & ASYNC_INITIALIZED)) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s synclinkmp_shutdown()\n", + __FILE__,__LINE__, info->device_name ); + + /* clear status wait queue because status changes */ + /* can't happen after shutting down the hardware */ + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + del_timer(&info->tx_timer); + del_timer(&info->status_timer); + + kfree(info->tx_buf); + info->tx_buf = NULL; + + spin_lock_irqsave(&info->lock,flags); + + reset_port(info); + + if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) { + info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + set_signals(info); + } + + spin_unlock_irqrestore(&info->lock,flags); + + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); + + info->port.flags &= ~ASYNC_INITIALIZED; +} + +static void program_hw(SLMP_INFO *info) +{ + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + + rx_stop(info); + tx_stop(info); + + info->tx_count = info->tx_put = info->tx_get = 0; + + if (info->params.mode == MGSL_MODE_HDLC || info->netcount) + hdlc_mode(info); + else + async_mode(info); + + set_signals(info); + + info->dcd_chkcount = 0; + info->cts_chkcount = 0; + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + + info->ie1_value |= (CDCD|CCTS); + write_reg(info, IE1, info->ie1_value); + + get_signals(info); + + if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) ) + rx_start(info); + + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Reconfigure adapter based on new parameters + */ +static void change_params(SLMP_INFO *info) +{ + unsigned cflag; + int bits_per_char; + + if (!info->port.tty || !info->port.tty->termios) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s change_params()\n", + __FILE__,__LINE__, info->device_name ); + + cflag = info->port.tty->termios->c_cflag; + + /* if B0 rate (hangup) specified then negate DTR and RTS */ + /* otherwise assert DTR and RTS */ + if (cflag & CBAUD) + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + + /* byte size and parity */ + + switch (cflag & CSIZE) { + case CS5: info->params.data_bits = 5; break; + case CS6: info->params.data_bits = 6; break; + case CS7: info->params.data_bits = 7; break; + case CS8: info->params.data_bits = 8; break; + /* Never happens, but GCC is too dumb to figure it out */ + default: info->params.data_bits = 7; break; + } + + if (cflag & CSTOPB) + info->params.stop_bits = 2; + else + info->params.stop_bits = 1; + + info->params.parity = ASYNC_PARITY_NONE; + if (cflag & PARENB) { + if (cflag & PARODD) + info->params.parity = ASYNC_PARITY_ODD; + else + info->params.parity = ASYNC_PARITY_EVEN; +#ifdef CMSPAR + if (cflag & CMSPAR) + info->params.parity = ASYNC_PARITY_SPACE; +#endif + } + + /* calculate number of jiffies to transmit a full + * FIFO (32 bytes) at specified data rate + */ + bits_per_char = info->params.data_bits + + info->params.stop_bits + 1; + + /* if port data rate is set to 460800 or less then + * allow tty settings to override, otherwise keep the + * current data rate. + */ + if (info->params.data_rate <= 460800) { + info->params.data_rate = tty_get_baud_rate(info->port.tty); + } + + if ( info->params.data_rate ) { + info->timeout = (32*HZ*bits_per_char) / + info->params.data_rate; + } + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + if (cflag & CRTSCTS) + info->port.flags |= ASYNC_CTS_FLOW; + else + info->port.flags &= ~ASYNC_CTS_FLOW; + + if (cflag & CLOCAL) + info->port.flags &= ~ASYNC_CHECK_CD; + else + info->port.flags |= ASYNC_CHECK_CD; + + /* process tty input control flags */ + + info->read_status_mask2 = OVRN; + if (I_INPCK(info->port.tty)) + info->read_status_mask2 |= PE | FRME; + if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) + info->read_status_mask1 |= BRKD; + if (I_IGNPAR(info->port.tty)) + info->ignore_status_mask2 |= PE | FRME; + if (I_IGNBRK(info->port.tty)) { + info->ignore_status_mask1 |= BRKD; + /* If ignoring parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->port.tty)) + info->ignore_status_mask2 |= OVRN; + } + + program_hw(info); +} + +static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) +{ + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s get_params()\n", + __FILE__,__LINE__, info->device_name); + + if (!user_icount) { + memset(&info->icount, 0, sizeof(info->icount)); + } else { + mutex_lock(&info->port.mutex); + COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); + mutex_unlock(&info->port.mutex); + if (err) + return -EFAULT; + } + + return 0; +} + +static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params) +{ + int err; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s get_params()\n", + __FILE__,__LINE__, info->device_name); + + mutex_lock(&info->port.mutex); + COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); + mutex_unlock(&info->port.mutex); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s get_params() user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + return 0; +} + +static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params) +{ + unsigned long flags; + MGSL_PARAMS tmp_params; + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s set_params\n", + __FILE__,__LINE__,info->device_name ); + COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s set_params() user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + mutex_lock(&info->port.mutex); + spin_lock_irqsave(&info->lock,flags); + memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); + spin_unlock_irqrestore(&info->lock,flags); + + change_params(info); + mutex_unlock(&info->port.mutex); + + return 0; +} + +static int get_txidle(SLMP_INFO * info, int __user *idle_mode) +{ + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s get_txidle()=%d\n", + __FILE__,__LINE__, info->device_name, info->idle_mode); + + COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int)); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s get_txidle() user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + return 0; +} + +static int set_txidle(SLMP_INFO * info, int idle_mode) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s set_txidle(%d)\n", + __FILE__,__LINE__,info->device_name, idle_mode ); + + spin_lock_irqsave(&info->lock,flags); + info->idle_mode = idle_mode; + tx_set_idle( info ); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int tx_enable(SLMP_INFO * info, int enable) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s tx_enable(%d)\n", + __FILE__,__LINE__,info->device_name, enable); + + spin_lock_irqsave(&info->lock,flags); + if ( enable ) { + if ( !info->tx_enabled ) { + tx_start(info); + } + } else { + if ( info->tx_enabled ) + tx_stop(info); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +/* abort send HDLC frame + */ +static int tx_abort(SLMP_INFO * info) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s tx_abort()\n", + __FILE__,__LINE__,info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) { + info->ie1_value &= ~UDRN; + info->ie1_value |= IDLE; + write_reg(info, IE1, info->ie1_value); /* disable tx status interrupts */ + write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); /* clear pending */ + + write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ + write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + + write_reg(info, CMD, TXABORT); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int rx_enable(SLMP_INFO * info, int enable) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s rx_enable(%d)\n", + __FILE__,__LINE__,info->device_name,enable); + + spin_lock_irqsave(&info->lock,flags); + if ( enable ) { + if ( !info->rx_enabled ) + rx_start(info); + } else { + if ( info->rx_enabled ) + rx_stop(info); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +/* wait for specified event to occur + */ +static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) +{ + unsigned long flags; + int s; + int rc=0; + struct mgsl_icount cprev, cnow; + int events; + int mask; + struct _input_signal_events oldsigs, newsigs; + DECLARE_WAITQUEUE(wait, current); + + COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int)); + if (rc) { + return -EFAULT; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s wait_mgsl_event(%d)\n", + __FILE__,__LINE__,info->device_name,mask); + + spin_lock_irqsave(&info->lock,flags); + + /* return immediately if state matches requested events */ + get_signals(info); + s = info->serial_signals; + + events = mask & + ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + + ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + + ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + + ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); + if (events) { + spin_unlock_irqrestore(&info->lock,flags); + goto exit; + } + + /* save current irq counts */ + cprev = info->icount; + oldsigs = info->input_signal_events; + + /* enable hunt and idle irqs if needed */ + if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) { + unsigned char oldval = info->ie1_value; + unsigned char newval = oldval + + (mask & MgslEvent_ExitHuntMode ? FLGD:0) + + (mask & MgslEvent_IdleReceived ? IDLD:0); + if ( oldval != newval ) { + info->ie1_value = newval; + write_reg(info, IE1, info->ie1_value); + } + } + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&info->event_wait_q, &wait); + + spin_unlock_irqrestore(&info->lock,flags); + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get current irq counts */ + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + newsigs = info->input_signal_events; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + /* if no change, wait aborted for some reason */ + if (newsigs.dsr_up == oldsigs.dsr_up && + newsigs.dsr_down == oldsigs.dsr_down && + newsigs.dcd_up == oldsigs.dcd_up && + newsigs.dcd_down == oldsigs.dcd_down && + newsigs.cts_up == oldsigs.cts_up && + newsigs.cts_down == oldsigs.cts_down && + newsigs.ri_up == oldsigs.ri_up && + newsigs.ri_down == oldsigs.ri_down && + cnow.exithunt == cprev.exithunt && + cnow.rxidle == cprev.rxidle) { + rc = -EIO; + break; + } + + events = mask & + ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + + (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + + (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + + (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + + (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + + (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + + (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + + (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + + (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + + (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); + if (events) + break; + + cprev = cnow; + oldsigs = newsigs; + } + + remove_wait_queue(&info->event_wait_q, &wait); + set_current_state(TASK_RUNNING); + + + if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { + spin_lock_irqsave(&info->lock,flags); + if (!waitqueue_active(&info->event_wait_q)) { + /* disable enable exit hunt mode/idle rcvd IRQs */ + info->ie1_value &= ~(FLGD|IDLD); + write_reg(info, IE1, info->ie1_value); + } + spin_unlock_irqrestore(&info->lock,flags); + } +exit: + if ( rc == 0 ) + PUT_USER(rc, events, mask_ptr); + + return rc; +} + +static int modem_input_wait(SLMP_INFO *info,int arg) +{ + unsigned long flags; + int rc; + struct mgsl_icount cprev, cnow; + DECLARE_WAITQUEUE(wait, current); + + /* save current irq counts */ + spin_lock_irqsave(&info->lock,flags); + cprev = info->icount; + add_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get new irq counts */ + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + /* if no change, wait aborted for some reason */ + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + rc = -EIO; + break; + } + + /* check for change in caller specified modem input */ + if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || + (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || + (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || + (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { + rc = 0; + break; + } + + cprev = cnow; + } + remove_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_RUNNING); + return rc; +} + +/* return the state of the serial control and status signals + */ +static int tiocmget(struct tty_struct *tty) +{ + SLMP_INFO *info = tty->driver_data; + unsigned int result; + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) + + ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) + + ((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) + + ((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) + + ((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) + + ((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0); + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s tiocmget() value=%08X\n", + __FILE__,__LINE__, info->device_name, result ); + return result; +} + +/* set modem control signals (DTR/RTS) + */ +static int tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + SLMP_INFO *info = tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s tiocmset(%x,%x)\n", + __FILE__,__LINE__,info->device_name, set, clear); + + if (set & TIOCM_RTS) + info->serial_signals |= SerialSignal_RTS; + if (set & TIOCM_DTR) + info->serial_signals |= SerialSignal_DTR; + if (clear & TIOCM_RTS) + info->serial_signals &= ~SerialSignal_RTS; + if (clear & TIOCM_DTR) + info->serial_signals &= ~SerialSignal_DTR; + + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; +} + +static int carrier_raised(struct tty_port *port) +{ + SLMP_INFO *info = container_of(port, SLMP_INFO, port); + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; +} + +static void dtr_rts(struct tty_port *port, int on) +{ + SLMP_INFO *info = container_of(port, SLMP_INFO, port); + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + if (on) + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Block the current process until the specified port is ready to open. + */ +static int block_til_ready(struct tty_struct *tty, struct file *filp, + SLMP_INFO *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + bool do_clocal = false; + bool extra_count = false; + unsigned long flags; + int cd; + struct tty_port *port = &info->port; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s block_til_ready()\n", + __FILE__,__LINE__, tty->driver->name ); + + if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ + /* nonblock mode is set or port is not enabled */ + /* just verify that callout device is not active */ + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = true; + + /* Wait for carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, port->count is dropped by one, so that + * close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + + retval = 0; + add_wait_queue(&port->open_wait, &wait); + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s block_til_ready() before block, count=%d\n", + __FILE__,__LINE__, tty->driver->name, port->count ); + + spin_lock_irqsave(&info->lock, flags); + if (!tty_hung_up_p(filp)) { + extra_count = true; + port->count--; + } + spin_unlock_irqrestore(&info->lock, flags); + port->blocked_open++; + + while (1) { + if (tty->termios->c_cflag & CBAUD) + tty_port_raise_dtr_rts(port); + + set_current_state(TASK_INTERRUPTIBLE); + + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ + retval = (port->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS; + break; + } + + cd = tty_port_carrier_raised(port); + + if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd)) + break; + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s block_til_ready() count=%d\n", + __FILE__,__LINE__, tty->driver->name, port->count ); + + tty_unlock(); + schedule(); + tty_lock(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + + if (extra_count) + port->count++; + port->blocked_open--; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):%s block_til_ready() after, count=%d\n", + __FILE__,__LINE__, tty->driver->name, port->count ); + + if (!retval) + port->flags |= ASYNC_NORMAL_ACTIVE; + + return retval; +} + +static int alloc_dma_bufs(SLMP_INFO *info) +{ + unsigned short BuffersPerFrame; + unsigned short BufferCount; + + // Force allocation to start at 64K boundary for each port. + // This is necessary because *all* buffer descriptors for a port + // *must* be in the same 64K block. All descriptors on a port + // share a common 'base' address (upper 8 bits of 24 bits) programmed + // into the CBP register. + info->port_array[0]->last_mem_alloc = (SCA_MEM_SIZE/4) * info->port_num; + + /* Calculate the number of DMA buffers necessary to hold the */ + /* largest allowable frame size. Note: If the max frame size is */ + /* not an even multiple of the DMA buffer size then we need to */ + /* round the buffer count per frame up one. */ + + BuffersPerFrame = (unsigned short)(info->max_frame_size/SCABUFSIZE); + if ( info->max_frame_size % SCABUFSIZE ) + BuffersPerFrame++; + + /* calculate total number of data buffers (SCABUFSIZE) possible + * in one ports memory (SCA_MEM_SIZE/4) after allocating memory + * for the descriptor list (BUFFERLISTSIZE). + */ + BufferCount = (SCA_MEM_SIZE/4 - BUFFERLISTSIZE)/SCABUFSIZE; + + /* limit number of buffers to maximum amount of descriptors */ + if (BufferCount > BUFFERLISTSIZE/sizeof(SCADESC)) + BufferCount = BUFFERLISTSIZE/sizeof(SCADESC); + + /* use enough buffers to transmit one max size frame */ + info->tx_buf_count = BuffersPerFrame + 1; + + /* never use more than half the available buffers for transmit */ + if (info->tx_buf_count > (BufferCount/2)) + info->tx_buf_count = BufferCount/2; + + if (info->tx_buf_count > SCAMAXDESC) + info->tx_buf_count = SCAMAXDESC; + + /* use remaining buffers for receive */ + info->rx_buf_count = BufferCount - info->tx_buf_count; + + if (info->rx_buf_count > SCAMAXDESC) + info->rx_buf_count = SCAMAXDESC; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("%s(%d):%s Allocating %d TX and %d RX DMA buffers.\n", + __FILE__,__LINE__, info->device_name, + info->tx_buf_count,info->rx_buf_count); + + if ( alloc_buf_list( info ) < 0 || + alloc_frame_bufs(info, + info->rx_buf_list, + info->rx_buf_list_ex, + info->rx_buf_count) < 0 || + alloc_frame_bufs(info, + info->tx_buf_list, + info->tx_buf_list_ex, + info->tx_buf_count) < 0 || + alloc_tmp_rx_buf(info) < 0 ) { + printk("%s(%d):%s Can't allocate DMA buffer memory\n", + __FILE__,__LINE__, info->device_name); + return -ENOMEM; + } + + rx_reset_buffers( info ); + + return 0; +} + +/* Allocate DMA buffers for the transmit and receive descriptor lists. + */ +static int alloc_buf_list(SLMP_INFO *info) +{ + unsigned int i; + + /* build list in adapter shared memory */ + info->buffer_list = info->memory_base + info->port_array[0]->last_mem_alloc; + info->buffer_list_phys = info->port_array[0]->last_mem_alloc; + info->port_array[0]->last_mem_alloc += BUFFERLISTSIZE; + + memset(info->buffer_list, 0, BUFFERLISTSIZE); + + /* Save virtual address pointers to the receive and */ + /* transmit buffer lists. (Receive 1st). These pointers will */ + /* be used by the processor to access the lists. */ + info->rx_buf_list = (SCADESC *)info->buffer_list; + + info->tx_buf_list = (SCADESC *)info->buffer_list; + info->tx_buf_list += info->rx_buf_count; + + /* Build links for circular buffer entry lists (tx and rx) + * + * Note: links are physical addresses read by the SCA device + * to determine the next buffer entry to use. + */ + + for ( i = 0; i < info->rx_buf_count; i++ ) { + /* calculate and store physical address of this buffer entry */ + info->rx_buf_list_ex[i].phys_entry = + info->buffer_list_phys + (i * sizeof(SCABUFSIZE)); + + /* calculate and store physical address of */ + /* next entry in cirular list of entries */ + info->rx_buf_list[i].next = info->buffer_list_phys; + if ( i < info->rx_buf_count - 1 ) + info->rx_buf_list[i].next += (i + 1) * sizeof(SCADESC); + + info->rx_buf_list[i].length = SCABUFSIZE; + } + + for ( i = 0; i < info->tx_buf_count; i++ ) { + /* calculate and store physical address of this buffer entry */ + info->tx_buf_list_ex[i].phys_entry = info->buffer_list_phys + + ((info->rx_buf_count + i) * sizeof(SCADESC)); + + /* calculate and store physical address of */ + /* next entry in cirular list of entries */ + + info->tx_buf_list[i].next = info->buffer_list_phys + + info->rx_buf_count * sizeof(SCADESC); + + if ( i < info->tx_buf_count - 1 ) + info->tx_buf_list[i].next += (i + 1) * sizeof(SCADESC); + } + + return 0; +} + +/* Allocate the frame DMA buffers used by the specified buffer list. + */ +static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count) +{ + int i; + unsigned long phys_addr; + + for ( i = 0; i < count; i++ ) { + buf_list_ex[i].virt_addr = info->memory_base + info->port_array[0]->last_mem_alloc; + phys_addr = info->port_array[0]->last_mem_alloc; + info->port_array[0]->last_mem_alloc += SCABUFSIZE; + + buf_list[i].buf_ptr = (unsigned short)phys_addr; + buf_list[i].buf_base = (unsigned char)(phys_addr >> 16); + } + + return 0; +} + +static void free_dma_bufs(SLMP_INFO *info) +{ + info->buffer_list = NULL; + info->rx_buf_list = NULL; + info->tx_buf_list = NULL; +} + +/* allocate buffer large enough to hold max_frame_size. + * This buffer is used to pass an assembled frame to the line discipline. + */ +static int alloc_tmp_rx_buf(SLMP_INFO *info) +{ + info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); + if (info->tmp_rx_buf == NULL) + return -ENOMEM; + return 0; +} + +static void free_tmp_rx_buf(SLMP_INFO *info) +{ + kfree(info->tmp_rx_buf); + info->tmp_rx_buf = NULL; +} + +static int claim_resources(SLMP_INFO *info) +{ + if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) { + printk( "%s(%d):%s mem addr conflict, Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base); + info->init_error = DiagStatus_AddressConflict; + goto errout; + } + else + info->shared_mem_requested = true; + + if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) { + printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base); + info->init_error = DiagStatus_AddressConflict; + goto errout; + } + else + info->lcr_mem_requested = true; + + if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) { + printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_sca_base); + info->init_error = DiagStatus_AddressConflict; + goto errout; + } + else + info->sca_base_requested = true; + + if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) { + printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_statctrl_base); + info->init_error = DiagStatus_AddressConflict; + goto errout; + } + else + info->sca_statctrl_requested = true; + + info->memory_base = ioremap_nocache(info->phys_memory_base, + SCA_MEM_SIZE); + if (!info->memory_base) { + printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + + info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE); + if (!info->lcr_base) { + printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + info->lcr_base += info->lcr_offset; + + info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE); + if (!info->sca_base) { + printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_sca_base ); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + info->sca_base += info->sca_offset; + + info->statctrl_base = ioremap_nocache(info->phys_statctrl_base, + PAGE_SIZE); + if (!info->statctrl_base) { + printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_statctrl_base ); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + info->statctrl_base += info->statctrl_offset; + + if ( !memory_test(info) ) { + printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + info->init_error = DiagStatus_MemoryError; + goto errout; + } + + return 0; + +errout: + release_resources( info ); + return -ENODEV; +} + +static void release_resources(SLMP_INFO *info) +{ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s release_resources() entry\n", + __FILE__,__LINE__,info->device_name ); + + if ( info->irq_requested ) { + free_irq(info->irq_level, info); + info->irq_requested = false; + } + + if ( info->shared_mem_requested ) { + release_mem_region(info->phys_memory_base,SCA_MEM_SIZE); + info->shared_mem_requested = false; + } + if ( info->lcr_mem_requested ) { + release_mem_region(info->phys_lcr_base + info->lcr_offset,128); + info->lcr_mem_requested = false; + } + if ( info->sca_base_requested ) { + release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE); + info->sca_base_requested = false; + } + if ( info->sca_statctrl_requested ) { + release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE); + info->sca_statctrl_requested = false; + } + + if (info->memory_base){ + iounmap(info->memory_base); + info->memory_base = NULL; + } + + if (info->sca_base) { + iounmap(info->sca_base - info->sca_offset); + info->sca_base=NULL; + } + + if (info->statctrl_base) { + iounmap(info->statctrl_base - info->statctrl_offset); + info->statctrl_base=NULL; + } + + if (info->lcr_base){ + iounmap(info->lcr_base - info->lcr_offset); + info->lcr_base = NULL; + } + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s release_resources() exit\n", + __FILE__,__LINE__,info->device_name ); +} + +/* Add the specified device instance data structure to the + * global linked list of devices and increment the device count. + */ +static void add_device(SLMP_INFO *info) +{ + info->next_device = NULL; + info->line = synclinkmp_device_count; + sprintf(info->device_name,"ttySLM%dp%d",info->adapter_num,info->port_num); + + if (info->line < MAX_DEVICES) { + if (maxframe[info->line]) + info->max_frame_size = maxframe[info->line]; + } + + synclinkmp_device_count++; + + if ( !synclinkmp_device_list ) + synclinkmp_device_list = info; + else { + SLMP_INFO *current_dev = synclinkmp_device_list; + while( current_dev->next_device ) + current_dev = current_dev->next_device; + current_dev->next_device = info; + } + + if ( info->max_frame_size < 4096 ) + info->max_frame_size = 4096; + else if ( info->max_frame_size > 65535 ) + info->max_frame_size = 65535; + + printk( "SyncLink MultiPort %s: " + "Mem=(%08x %08X %08x %08X) IRQ=%d MaxFrameSize=%u\n", + info->device_name, + info->phys_sca_base, + info->phys_memory_base, + info->phys_statctrl_base, + info->phys_lcr_base, + info->irq_level, + info->max_frame_size ); + +#if SYNCLINK_GENERIC_HDLC + hdlcdev_init(info); +#endif +} + +static const struct tty_port_operations port_ops = { + .carrier_raised = carrier_raised, + .dtr_rts = dtr_rts, +}; + +/* Allocate and initialize a device instance structure + * + * Return Value: pointer to SLMP_INFO if success, otherwise NULL + */ +static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) +{ + SLMP_INFO *info; + + info = kzalloc(sizeof(SLMP_INFO), + GFP_KERNEL); + + if (!info) { + printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n", + __FILE__,__LINE__, adapter_num, port_num); + } else { + tty_port_init(&info->port); + info->port.ops = &port_ops; + info->magic = MGSL_MAGIC; + INIT_WORK(&info->task, bh_handler); + info->max_frame_size = 4096; + info->port.close_delay = 5*HZ/10; + info->port.closing_wait = 30*HZ; + init_waitqueue_head(&info->status_event_wait_q); + init_waitqueue_head(&info->event_wait_q); + spin_lock_init(&info->netlock); + memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); + info->idle_mode = HDLC_TXIDLE_FLAGS; + info->adapter_num = adapter_num; + info->port_num = port_num; + + /* Copy configuration info to device instance data */ + info->irq_level = pdev->irq; + info->phys_lcr_base = pci_resource_start(pdev,0); + info->phys_sca_base = pci_resource_start(pdev,2); + info->phys_memory_base = pci_resource_start(pdev,3); + info->phys_statctrl_base = pci_resource_start(pdev,4); + + /* Because veremap only works on page boundaries we must map + * a larger area than is actually implemented for the LCR + * memory range. We map a full page starting at the page boundary. + */ + info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); + info->phys_lcr_base &= ~(PAGE_SIZE-1); + + info->sca_offset = info->phys_sca_base & (PAGE_SIZE-1); + info->phys_sca_base &= ~(PAGE_SIZE-1); + + info->statctrl_offset = info->phys_statctrl_base & (PAGE_SIZE-1); + info->phys_statctrl_base &= ~(PAGE_SIZE-1); + + info->bus_type = MGSL_BUS_TYPE_PCI; + info->irq_flags = IRQF_SHARED; + + 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 + * BIOS assigns an LCR base address with bit 7 set. + * + * Only the misc control register is accessed for which only + * write access is needed, so set an initial value and change + * bits to the device instance data as we write the value + * to the actual misc control register. + */ + info->misc_ctrl_value = 0x087e4546; + + /* initial port state is unknown - if startup errors + * occur, init_error will be set to indicate the + * problem. Once the port is fully initialized, + * this value will be set to 0 to indicate the + * port is available. + */ + info->init_error = -1; + } + + return info; +} + +static void device_init(int adapter_num, struct pci_dev *pdev) +{ + SLMP_INFO *port_array[SCA_MAX_PORTS]; + int port; + + /* allocate device instances for up to SCA_MAX_PORTS devices */ + for ( port = 0; port < SCA_MAX_PORTS; ++port ) { + port_array[port] = alloc_dev(adapter_num,port,pdev); + if( port_array[port] == NULL ) { + for ( --port; port >= 0; --port ) + kfree(port_array[port]); + return; + } + } + + /* give copy of port_array to all ports and add to device list */ + for ( port = 0; port < SCA_MAX_PORTS; ++port ) { + memcpy(port_array[port]->port_array,port_array,sizeof(port_array)); + add_device( port_array[port] ); + spin_lock_init(&port_array[port]->lock); + } + + /* Allocate and claim adapter resources */ + if ( !claim_resources(port_array[0]) ) { + + alloc_dma_bufs(port_array[0]); + + /* copy resource information from first port to others */ + for ( port = 1; port < SCA_MAX_PORTS; ++port ) { + port_array[port]->lock = port_array[0]->lock; + port_array[port]->irq_level = port_array[0]->irq_level; + port_array[port]->memory_base = port_array[0]->memory_base; + port_array[port]->sca_base = port_array[0]->sca_base; + port_array[port]->statctrl_base = port_array[0]->statctrl_base; + port_array[port]->lcr_base = port_array[0]->lcr_base; + alloc_dma_bufs(port_array[port]); + } + + if ( request_irq(port_array[0]->irq_level, + synclinkmp_interrupt, + port_array[0]->irq_flags, + port_array[0]->device_name, + port_array[0]) < 0 ) { + printk( "%s(%d):%s Cant request interrupt, IRQ=%d\n", + __FILE__,__LINE__, + port_array[0]->device_name, + port_array[0]->irq_level ); + } + else { + port_array[0]->irq_requested = true; + adapter_test(port_array[0]); + } + } +} + +static const struct tty_operations ops = { + .open = open, + .close = close, + .write = write, + .put_char = put_char, + .flush_chars = flush_chars, + .write_room = write_room, + .chars_in_buffer = chars_in_buffer, + .flush_buffer = flush_buffer, + .ioctl = ioctl, + .throttle = throttle, + .unthrottle = unthrottle, + .send_xchar = send_xchar, + .break_ctl = set_break, + .wait_until_sent = wait_until_sent, + .set_termios = set_termios, + .stop = tx_hold, + .start = tx_release, + .hangup = hangup, + .tiocmget = tiocmget, + .tiocmset = tiocmset, + .get_icount = get_icount, + .proc_fops = &synclinkmp_proc_fops, +}; + + +static void synclinkmp_cleanup(void) +{ + int rc; + SLMP_INFO *info; + SLMP_INFO *tmp; + + printk("Unloading %s %s\n", driver_name, driver_version); + + if (serial_driver) { + if ((rc = tty_unregister_driver(serial_driver))) + printk("%s(%d) failed to unregister tty driver err=%d\n", + __FILE__,__LINE__,rc); + put_tty_driver(serial_driver); + } + + /* reset devices */ + info = synclinkmp_device_list; + while(info) { + reset_port(info); + info = info->next_device; + } + + /* release devices */ + info = synclinkmp_device_list; + while(info) { +#if SYNCLINK_GENERIC_HDLC + hdlcdev_exit(info); +#endif + free_dma_bufs(info); + free_tmp_rx_buf(info); + if ( info->port_num == 0 ) { + if (info->sca_base) + write_reg(info, LPR, 1); /* set low power mode */ + release_resources(info); + } + tmp = info; + info = info->next_device; + kfree(tmp); + } + + pci_unregister_driver(&synclinkmp_pci_driver); +} + +/* Driver initialization entry point. + */ + +static int __init synclinkmp_init(void) +{ + int rc; + + if (break_on_load) { + synclinkmp_get_text_ptr(); + BREAKPOINT(); + } + + printk("%s %s\n", driver_name, driver_version); + + if ((rc = pci_register_driver(&synclinkmp_pci_driver)) < 0) { + printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc); + return rc; + } + + serial_driver = alloc_tty_driver(128); + if (!serial_driver) { + rc = -ENOMEM; + goto error; + } + + /* Initialize the tty_driver structure */ + + serial_driver->owner = THIS_MODULE; + serial_driver->driver_name = "synclinkmp"; + serial_driver->name = "ttySLM"; + serial_driver->major = ttymajor; + serial_driver->minor_start = 64; + serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_driver->subtype = SERIAL_TYPE_NORMAL; + serial_driver->init_termios = tty_std_termios; + serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; + serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(serial_driver, &ops); + if ((rc = tty_register_driver(serial_driver)) < 0) { + printk("%s(%d):Couldn't register serial driver\n", + __FILE__,__LINE__); + put_tty_driver(serial_driver); + serial_driver = NULL; + goto error; + } + + printk("%s %s, tty major#%d\n", + driver_name, driver_version, + serial_driver->major); + + return 0; + +error: + synclinkmp_cleanup(); + return rc; +} + +static void __exit synclinkmp_exit(void) +{ + synclinkmp_cleanup(); +} + +module_init(synclinkmp_init); +module_exit(synclinkmp_exit); + +/* Set the port for internal loopback mode. + * The TxCLK and RxCLK signals are generated from the BRG and + * the TxD is looped back to the RxD internally. + */ +static void enable_loopback(SLMP_INFO *info, int enable) +{ + if (enable) { + /* MD2 (Mode Register 2) + * 01..00 CNCT<1..0> Channel Connection 11=Local Loopback + */ + write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) | (BIT1 + BIT0))); + + /* degate external TxC clock source */ + info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2)); + write_control_reg(info); + + /* RXS/TXS (Rx/Tx clock source) + * 07 Reserved, must be 0 + * 06..04 Clock Source, 100=BRG + * 03..00 Clock Divisor, 0000=1 + */ + write_reg(info, RXS, 0x40); + write_reg(info, TXS, 0x40); + + } else { + /* MD2 (Mode Register 2) + * 01..00 CNCT<1..0> Channel connection, 0=normal + */ + write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) & ~(BIT1 + BIT0))); + + /* RXS/TXS (Rx/Tx clock source) + * 07 Reserved, must be 0 + * 06..04 Clock Source, 000=RxC/TxC Pin + * 03..00 Clock Divisor, 0000=1 + */ + write_reg(info, RXS, 0x00); + write_reg(info, TXS, 0x00); + } + + /* set LinkSpeed if available, otherwise default to 2Mbps */ + if (info->params.clock_speed) + set_rate(info, info->params.clock_speed); + else + set_rate(info, 3686400); +} + +/* Set the baud rate register to the desired speed + * + * data_rate data rate of clock in bits per second + * A data rate of 0 disables the AUX clock. + */ +static void set_rate( SLMP_INFO *info, u32 data_rate ) +{ + u32 TMCValue; + unsigned char BRValue; + u32 Divisor=0; + + /* fBRG = fCLK/(TMC * 2^BR) + */ + if (data_rate != 0) { + Divisor = 14745600/data_rate; + if (!Divisor) + Divisor = 1; + + TMCValue = Divisor; + + BRValue = 0; + if (TMCValue != 1 && TMCValue != 2) { + /* BRValue of 0 provides 50/50 duty cycle *only* when + * TMCValue is 1 or 2. BRValue of 1 to 9 always provides + * 50/50 duty cycle. + */ + BRValue = 1; + TMCValue >>= 1; + } + + /* while TMCValue is too big for TMC register, divide + * by 2 and increment BR exponent. + */ + for(; TMCValue > 256 && BRValue < 10; BRValue++) + TMCValue >>= 1; + + write_reg(info, TXS, + (unsigned char)((read_reg(info, TXS) & 0xf0) | BRValue)); + write_reg(info, RXS, + (unsigned char)((read_reg(info, RXS) & 0xf0) | BRValue)); + write_reg(info, TMC, (unsigned char)TMCValue); + } + else { + write_reg(info, TXS,0); + write_reg(info, RXS,0); + write_reg(info, TMC, 0); + } +} + +/* Disable receiver + */ +static void rx_stop(SLMP_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):%s rx_stop()\n", + __FILE__,__LINE__, info->device_name ); + + write_reg(info, CMD, RXRESET); + + info->ie0_value &= ~RXRDYE; + write_reg(info, IE0, info->ie0_value); /* disable Rx data interrupts */ + + write_reg(info, RXDMA + DSR, 0); /* disable Rx DMA */ + write_reg(info, RXDMA + DCMD, SWABORT); /* reset/init Rx DMA */ + write_reg(info, RXDMA + DIR, 0); /* disable Rx DMA interrupts */ + + info->rx_enabled = false; + info->rx_overflow = false; +} + +/* enable the receiver + */ +static void rx_start(SLMP_INFO *info) +{ + int i; + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):%s rx_start()\n", + __FILE__,__LINE__, info->device_name ); + + write_reg(info, CMD, RXRESET); + + if ( info->params.mode == MGSL_MODE_HDLC ) { + /* HDLC, disabe IRQ on rxdata */ + info->ie0_value &= ~RXRDYE; + write_reg(info, IE0, info->ie0_value); + + /* Reset all Rx DMA buffers and program rx dma */ + write_reg(info, RXDMA + DSR, 0); /* disable Rx DMA */ + write_reg(info, RXDMA + DCMD, SWABORT); /* reset/init Rx DMA */ + + for (i = 0; i < info->rx_buf_count; i++) { + info->rx_buf_list[i].status = 0xff; + + // throttle to 4 shared memory writes at a time to prevent + // hogging local bus (keep latency time for DMA requests low). + if (!(i % 4)) + read_status_reg(info); + } + info->current_rx_buf = 0; + + /* set current/1st descriptor address */ + write_reg16(info, RXDMA + CDA, + info->rx_buf_list_ex[0].phys_entry); + + /* set new last rx descriptor address */ + write_reg16(info, RXDMA + EDA, + info->rx_buf_list_ex[info->rx_buf_count - 1].phys_entry); + + /* set buffer length (shared by all rx dma data buffers) */ + write_reg16(info, RXDMA + BFL, SCABUFSIZE); + + write_reg(info, RXDMA + DIR, 0x60); /* enable Rx DMA interrupts (EOM/BOF) */ + write_reg(info, RXDMA + DSR, 0xf2); /* clear Rx DMA IRQs, enable Rx DMA */ + } else { + /* async, enable IRQ on rxdata */ + info->ie0_value |= RXRDYE; + write_reg(info, IE0, info->ie0_value); + } + + write_reg(info, CMD, RXENABLE); + + info->rx_overflow = false; + info->rx_enabled = true; +} + +/* Enable the transmitter and send a transmit frame if + * one is loaded in the DMA buffers. + */ +static void tx_start(SLMP_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):%s tx_start() tx_count=%d\n", + __FILE__,__LINE__, info->device_name,info->tx_count ); + + if (!info->tx_enabled ) { + write_reg(info, CMD, TXRESET); + write_reg(info, CMD, TXENABLE); + info->tx_enabled = true; + } + + if ( info->tx_count ) { + + /* If auto RTS enabled and RTS is inactive, then assert */ + /* RTS and set a flag indicating that the driver should */ + /* negate RTS when the transmission completes. */ + + info->drop_rts_on_tx_done = false; + + if (info->params.mode != MGSL_MODE_ASYNC) { + + if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) { + get_signals( info ); + if ( !(info->serial_signals & SerialSignal_RTS) ) { + info->serial_signals |= SerialSignal_RTS; + set_signals( info ); + info->drop_rts_on_tx_done = true; + } + } + + write_reg16(info, TRC0, + (unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level)); + + write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ + write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + + /* set TX CDA (current descriptor address) */ + write_reg16(info, TXDMA + CDA, + info->tx_buf_list_ex[0].phys_entry); + + /* set TX EDA (last descriptor address) */ + write_reg16(info, TXDMA + EDA, + info->tx_buf_list_ex[info->last_tx_buf].phys_entry); + + /* enable underrun IRQ */ + info->ie1_value &= ~IDLE; + info->ie1_value |= UDRN; + write_reg(info, IE1, info->ie1_value); + write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); + + write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ + write_reg(info, TXDMA + DSR, 0xf2); /* clear Tx DMA IRQs, enable Tx DMA */ + + mod_timer(&info->tx_timer, jiffies + + msecs_to_jiffies(5000)); + } + else { + tx_load_fifo(info); + /* async, enable IRQ on txdata */ + info->ie0_value |= TXRDYE; + write_reg(info, IE0, info->ie0_value); + } + + info->tx_active = true; + } +} + +/* stop the transmitter and DMA + */ +static void tx_stop( SLMP_INFO *info ) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):%s tx_stop()\n", + __FILE__,__LINE__, info->device_name ); + + del_timer(&info->tx_timer); + + write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ + write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + + write_reg(info, CMD, TXRESET); + + info->ie1_value &= ~(UDRN + IDLE); + write_reg(info, IE1, info->ie1_value); /* disable tx status interrupts */ + write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); /* clear pending */ + + info->ie0_value &= ~TXRDYE; + write_reg(info, IE0, info->ie0_value); /* disable tx data interrupts */ + + info->tx_enabled = false; + info->tx_active = false; +} + +/* Fill the transmit FIFO until the FIFO is full or + * there is no more data to load. + */ +static void tx_load_fifo(SLMP_INFO *info) +{ + u8 TwoBytes[2]; + + /* do nothing is now tx data available and no XON/XOFF pending */ + + if ( !info->tx_count && !info->x_char ) + return; + + /* load the Transmit FIFO until FIFOs full or all data sent */ + + while( info->tx_count && (read_reg(info,SR0) & BIT1) ) { + + /* there is more space in the transmit FIFO and */ + /* there is more data in transmit buffer */ + + if ( (info->tx_count > 1) && !info->x_char ) { + /* write 16-bits */ + TwoBytes[0] = info->tx_buf[info->tx_get++]; + if (info->tx_get >= info->max_frame_size) + info->tx_get -= info->max_frame_size; + TwoBytes[1] = info->tx_buf[info->tx_get++]; + if (info->tx_get >= info->max_frame_size) + info->tx_get -= info->max_frame_size; + + write_reg16(info, TRB, *((u16 *)TwoBytes)); + + info->tx_count -= 2; + info->icount.tx += 2; + } else { + /* only 1 byte left to transmit or 1 FIFO slot left */ + + if (info->x_char) { + /* transmit pending high priority char */ + write_reg(info, TRB, info->x_char); + info->x_char = 0; + } else { + write_reg(info, TRB, info->tx_buf[info->tx_get++]); + if (info->tx_get >= info->max_frame_size) + info->tx_get -= info->max_frame_size; + info->tx_count--; + } + info->icount.tx++; + } + } +} + +/* Reset a port to a known state + */ +static void reset_port(SLMP_INFO *info) +{ + if (info->sca_base) { + + tx_stop(info); + rx_stop(info); + + info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + set_signals(info); + + /* disable all port interrupts */ + info->ie0_value = 0; + info->ie1_value = 0; + info->ie2_value = 0; + write_reg(info, IE0, info->ie0_value); + write_reg(info, IE1, info->ie1_value); + write_reg(info, IE2, info->ie2_value); + + write_reg(info, CMD, CHRESET); + } +} + +/* Reset all the ports to a known state. + */ +static void reset_adapter(SLMP_INFO *info) +{ + int i; + + for ( i=0; i < SCA_MAX_PORTS; ++i) { + if (info->port_array[i]) + reset_port(info->port_array[i]); + } +} + +/* Program port for asynchronous communications. + */ +static void async_mode(SLMP_INFO *info) +{ + + unsigned char RegValue; + + tx_stop(info); + rx_stop(info); + + /* MD0, Mode Register 0 + * + * 07..05 PRCTL<2..0>, Protocol Mode, 000=async + * 04 AUTO, Auto-enable (RTS/CTS/DCD) + * 03 Reserved, must be 0 + * 02 CRCCC, CRC Calculation, 0=disabled + * 01..00 STOP<1..0> Stop bits (00=1,10=2) + * + * 0000 0000 + */ + RegValue = 0x00; + if (info->params.stop_bits != 1) + RegValue |= BIT1; + write_reg(info, MD0, RegValue); + + /* MD1, Mode Register 1 + * + * 07..06 BRATE<1..0>, bit rate, 00=1/1 01=1/16 10=1/32 11=1/64 + * 05..04 TXCHR<1..0>, tx char size, 00=8 bits,01=7,10=6,11=5 + * 03..02 RXCHR<1..0>, rx char size + * 01..00 PMPM<1..0>, Parity mode, 00=none 10=even 11=odd + * + * 0100 0000 + */ + RegValue = 0x40; + switch (info->params.data_bits) { + case 7: RegValue |= BIT4 + BIT2; break; + case 6: RegValue |= BIT5 + BIT3; break; + case 5: RegValue |= BIT5 + BIT4 + BIT3 + BIT2; break; + } + if (info->params.parity != ASYNC_PARITY_NONE) { + RegValue |= BIT1; + if (info->params.parity == ASYNC_PARITY_ODD) + RegValue |= BIT0; + } + write_reg(info, MD1, RegValue); + + /* MD2, Mode Register 2 + * + * 07..02 Reserved, must be 0 + * 01..00 CNCT<1..0> Channel connection, 00=normal 11=local loopback + * + * 0000 0000 + */ + RegValue = 0x00; + if (info->params.loopback) + RegValue |= (BIT1 + BIT0); + write_reg(info, MD2, RegValue); + + /* RXS, Receive clock source + * + * 07 Reserved, must be 0 + * 06..04 RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL + * 03..00 RXBR<3..0>, rate divisor, 0000=1 + */ + RegValue=BIT6; + write_reg(info, RXS, RegValue); + + /* TXS, Transmit clock source + * + * 07 Reserved, must be 0 + * 06..04 RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock + * 03..00 RXBR<3..0>, rate divisor, 0000=1 + */ + RegValue=BIT6; + write_reg(info, TXS, RegValue); + + /* Control Register + * + * 6,4,2,0 CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out + */ + info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2)); + write_control_reg(info); + + tx_set_idle(info); + + /* RRC Receive Ready Control 0 + * + * 07..05 Reserved, must be 0 + * 04..00 RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte + */ + write_reg(info, RRC, 0x00); + + /* TRC0 Transmit Ready Control 0 + * + * 07..05 Reserved, must be 0 + * 04..00 TRC<4..0> Tx FIFO trigger active 0x10 = 16 bytes + */ + write_reg(info, TRC0, 0x10); + + /* TRC1 Transmit Ready Control 1 + * + * 07..05 Reserved, must be 0 + * 04..00 TRC<4..0> Tx FIFO trigger inactive 0x1e = 31 bytes (full-1) + */ + write_reg(info, TRC1, 0x1e); + + /* CTL, MSCI control register + * + * 07..06 Reserved, set to 0 + * 05 UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC) + * 04 IDLC, idle control, 0=mark 1=idle register + * 03 BRK, break, 0=off 1 =on (async) + * 02 SYNCLD, sync char load enable (BSC) 1=enabled + * 01 GOP, go active on poll (LOOP mode) 1=enabled + * 00 RTS, RTS output control, 0=active 1=inactive + * + * 0001 0001 + */ + RegValue = 0x10; + if (!(info->serial_signals & SerialSignal_RTS)) + RegValue |= 0x01; + write_reg(info, CTL, RegValue); + + /* enable status interrupts */ + info->ie0_value |= TXINTE + RXINTE; + write_reg(info, IE0, info->ie0_value); + + /* enable break detect interrupt */ + info->ie1_value = BRKD; + write_reg(info, IE1, info->ie1_value); + + /* enable rx overrun interrupt */ + info->ie2_value = OVRN; + write_reg(info, IE2, info->ie2_value); + + set_rate( info, info->params.data_rate * 16 ); +} + +/* Program the SCA for HDLC communications. + */ +static void hdlc_mode(SLMP_INFO *info) +{ + unsigned char RegValue; + u32 DpllDivisor; + + // Can't use DPLL because SCA outputs recovered clock on RxC when + // DPLL mode selected. This causes output contention with RxC receiver. + // Use of DPLL would require external hardware to disable RxC receiver + // when DPLL mode selected. + info->params.flags &= ~(HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL); + + /* disable DMA interrupts */ + write_reg(info, TXDMA + DIR, 0); + write_reg(info, RXDMA + DIR, 0); + + /* MD0, Mode Register 0 + * + * 07..05 PRCTL<2..0>, Protocol Mode, 100=HDLC + * 04 AUTO, Auto-enable (RTS/CTS/DCD) + * 03 Reserved, must be 0 + * 02 CRCCC, CRC Calculation, 1=enabled + * 01 CRC1, CRC selection, 0=CRC-16,1=CRC-CCITT-16 + * 00 CRC0, CRC initial value, 1 = all 1s + * + * 1000 0001 + */ + RegValue = 0x81; + if (info->params.flags & HDLC_FLAG_AUTO_CTS) + RegValue |= BIT4; + if (info->params.flags & HDLC_FLAG_AUTO_DCD) + RegValue |= BIT4; + if (info->params.crc_type == HDLC_CRC_16_CCITT) + RegValue |= BIT2 + BIT1; + write_reg(info, MD0, RegValue); + + /* MD1, Mode Register 1 + * + * 07..06 ADDRS<1..0>, Address detect, 00=no addr check + * 05..04 TXCHR<1..0>, tx char size, 00=8 bits + * 03..02 RXCHR<1..0>, rx char size, 00=8 bits + * 01..00 PMPM<1..0>, Parity mode, 00=no parity + * + * 0000 0000 + */ + RegValue = 0x00; + write_reg(info, MD1, RegValue); + + /* MD2, Mode Register 2 + * + * 07 NRZFM, 0=NRZ, 1=FM + * 06..05 CODE<1..0> Encoding, 00=NRZ + * 04..03 DRATE<1..0> DPLL Divisor, 00=8 + * 02 Reserved, must be 0 + * 01..00 CNCT<1..0> Channel connection, 0=normal + * + * 0000 0000 + */ + RegValue = 0x00; + switch(info->params.encoding) { + case HDLC_ENCODING_NRZI: RegValue |= BIT5; break; + case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT7 + BIT5; break; /* aka FM1 */ + case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT7 + BIT6; break; /* aka FM0 */ + case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT7; break; /* aka Manchester */ +#if 0 + case HDLC_ENCODING_NRZB: /* not supported */ + case HDLC_ENCODING_NRZI_MARK: /* not supported */ + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: /* not supported */ +#endif + } + if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { + DpllDivisor = 16; + RegValue |= BIT3; + } else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) { + DpllDivisor = 8; + } else { + DpllDivisor = 32; + RegValue |= BIT4; + } + write_reg(info, MD2, RegValue); + + + /* RXS, Receive clock source + * + * 07 Reserved, must be 0 + * 06..04 RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL + * 03..00 RXBR<3..0>, rate divisor, 0000=1 + */ + RegValue=0; + if (info->params.flags & HDLC_FLAG_RXC_BRG) + RegValue |= BIT6; + if (info->params.flags & HDLC_FLAG_RXC_DPLL) + RegValue |= BIT6 + BIT5; + write_reg(info, RXS, RegValue); + + /* TXS, Transmit clock source + * + * 07 Reserved, must be 0 + * 06..04 RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock + * 03..00 RXBR<3..0>, rate divisor, 0000=1 + */ + RegValue=0; + if (info->params.flags & HDLC_FLAG_TXC_BRG) + RegValue |= BIT6; + if (info->params.flags & HDLC_FLAG_TXC_DPLL) + RegValue |= BIT6 + BIT5; + write_reg(info, TXS, RegValue); + + if (info->params.flags & HDLC_FLAG_RXC_DPLL) + set_rate(info, info->params.clock_speed * DpllDivisor); + else + set_rate(info, info->params.clock_speed); + + /* GPDATA (General Purpose I/O Data Register) + * + * 6,4,2,0 CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out + */ + if (info->params.flags & HDLC_FLAG_TXC_BRG) + info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2)); + else + info->port_array[0]->ctrlreg_value &= ~(BIT0 << (info->port_num * 2)); + write_control_reg(info); + + /* RRC Receive Ready Control 0 + * + * 07..05 Reserved, must be 0 + * 04..00 RRC<4..0> Rx FIFO trigger active + */ + write_reg(info, RRC, rx_active_fifo_level); + + /* TRC0 Transmit Ready Control 0 + * + * 07..05 Reserved, must be 0 + * 04..00 TRC<4..0> Tx FIFO trigger active + */ + write_reg(info, TRC0, tx_active_fifo_level); + + /* TRC1 Transmit Ready Control 1 + * + * 07..05 Reserved, must be 0 + * 04..00 TRC<4..0> Tx FIFO trigger inactive 0x1f = 32 bytes (full) + */ + write_reg(info, TRC1, (unsigned char)(tx_negate_fifo_level - 1)); + + /* DMR, DMA Mode Register + * + * 07..05 Reserved, must be 0 + * 04 TMOD, Transfer Mode: 1=chained-block + * 03 Reserved, must be 0 + * 02 NF, Number of Frames: 1=multi-frame + * 01 CNTE, Frame End IRQ Counter enable: 0=disabled + * 00 Reserved, must be 0 + * + * 0001 0100 + */ + write_reg(info, TXDMA + DMR, 0x14); + write_reg(info, RXDMA + DMR, 0x14); + + /* Set chain pointer base (upper 8 bits of 24 bit addr) */ + write_reg(info, RXDMA + CPB, + (unsigned char)(info->buffer_list_phys >> 16)); + + /* Set chain pointer base (upper 8 bits of 24 bit addr) */ + write_reg(info, TXDMA + CPB, + (unsigned char)(info->buffer_list_phys >> 16)); + + /* enable status interrupts. other code enables/disables + * the individual sources for these two interrupt classes. + */ + info->ie0_value |= TXINTE + RXINTE; + write_reg(info, IE0, info->ie0_value); + + /* CTL, MSCI control register + * + * 07..06 Reserved, set to 0 + * 05 UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC) + * 04 IDLC, idle control, 0=mark 1=idle register + * 03 BRK, break, 0=off 1 =on (async) + * 02 SYNCLD, sync char load enable (BSC) 1=enabled + * 01 GOP, go active on poll (LOOP mode) 1=enabled + * 00 RTS, RTS output control, 0=active 1=inactive + * + * 0001 0001 + */ + RegValue = 0x10; + if (!(info->serial_signals & SerialSignal_RTS)) + RegValue |= 0x01; + write_reg(info, CTL, RegValue); + + /* preamble not supported ! */ + + tx_set_idle(info); + tx_stop(info); + rx_stop(info); + + set_rate(info, info->params.clock_speed); + + if (info->params.loopback) + enable_loopback(info,1); +} + +/* Set the transmit HDLC idle mode + */ +static void tx_set_idle(SLMP_INFO *info) +{ + unsigned char RegValue = 0xff; + + /* Map API idle mode to SCA register bits */ + switch(info->idle_mode) { + case HDLC_TXIDLE_FLAGS: RegValue = 0x7e; break; + case HDLC_TXIDLE_ALT_ZEROS_ONES: RegValue = 0xaa; break; + case HDLC_TXIDLE_ZEROS: RegValue = 0x00; break; + case HDLC_TXIDLE_ONES: RegValue = 0xff; break; + case HDLC_TXIDLE_ALT_MARK_SPACE: RegValue = 0xaa; break; + case HDLC_TXIDLE_SPACE: RegValue = 0x00; break; + case HDLC_TXIDLE_MARK: RegValue = 0xff; break; + } + + write_reg(info, IDL, RegValue); +} + +/* Query the adapter for the state of the V24 status (input) signals. + */ +static void get_signals(SLMP_INFO *info) +{ + u16 status = read_reg(info, SR3); + u16 gpstatus = read_status_reg(info); + u16 testbit; + + /* clear all serial signals except DTR and RTS */ + info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS; + + /* set serial signal bits to reflect MISR */ + + if (!(status & BIT3)) + info->serial_signals |= SerialSignal_CTS; + + if ( !(status & BIT2)) + info->serial_signals |= SerialSignal_DCD; + + testbit = BIT1 << (info->port_num * 2); // Port 0..3 RI is GPDATA<1,3,5,7> + if (!(gpstatus & testbit)) + info->serial_signals |= SerialSignal_RI; + + testbit = BIT0 << (info->port_num * 2); // Port 0..3 DSR is GPDATA<0,2,4,6> + if (!(gpstatus & testbit)) + info->serial_signals |= SerialSignal_DSR; +} + +/* Set the state of DTR and RTS based on contents of + * serial_signals member of device context. + */ +static void set_signals(SLMP_INFO *info) +{ + unsigned char RegValue; + u16 EnableBit; + + RegValue = read_reg(info, CTL); + if (info->serial_signals & SerialSignal_RTS) + RegValue &= ~BIT0; + else + RegValue |= BIT0; + write_reg(info, CTL, RegValue); + + // Port 0..3 DTR is ctrl reg <1,3,5,7> + EnableBit = BIT1 << (info->port_num*2); + if (info->serial_signals & SerialSignal_DTR) + info->port_array[0]->ctrlreg_value &= ~EnableBit; + else + info->port_array[0]->ctrlreg_value |= EnableBit; + write_control_reg(info); +} + +/*******************/ +/* DMA Buffer Code */ +/*******************/ + +/* Set the count for all receive buffers to SCABUFSIZE + * and set the current buffer to the first buffer. This effectively + * makes all buffers free and discards any data in buffers. + */ +static void rx_reset_buffers(SLMP_INFO *info) +{ + rx_free_frame_buffers(info, 0, info->rx_buf_count - 1); +} + +/* Free the buffers used by a received frame + * + * info pointer to device instance data + * first index of 1st receive buffer of frame + * last index of last receive buffer of frame + */ +static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last) +{ + bool done = false; + + while(!done) { + /* reset current buffer for reuse */ + info->rx_buf_list[first].status = 0xff; + + if (first == last) { + done = true; + /* set new last rx descriptor address */ + write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry); + } + + first++; + if (first == info->rx_buf_count) + first = 0; + } + + /* set current buffer to next buffer after last buffer of frame */ + info->current_rx_buf = first; +} + +/* Return a received frame from the receive DMA buffers. + * Only frames received without errors are returned. + * + * Return Value: true if frame returned, otherwise false + */ +static bool rx_get_frame(SLMP_INFO *info) +{ + unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ + unsigned short status; + unsigned int framesize = 0; + bool ReturnCode = false; + unsigned long flags; + struct tty_struct *tty = info->port.tty; + unsigned char addr_field = 0xff; + SCADESC *desc; + SCADESC_EX *desc_ex; + +CheckAgain: + /* assume no frame returned, set zero length */ + framesize = 0; + addr_field = 0xff; + + /* + * current_rx_buf points to the 1st buffer of the next available + * receive frame. To find the last buffer of the frame look for + * a non-zero status field in the buffer entries. (The status + * field is set by the 16C32 after completing a receive frame. + */ + StartIndex = EndIndex = info->current_rx_buf; + + for ( ;; ) { + desc = &info->rx_buf_list[EndIndex]; + desc_ex = &info->rx_buf_list_ex[EndIndex]; + + if (desc->status == 0xff) + goto Cleanup; /* current desc still in use, no frames available */ + + if (framesize == 0 && info->params.addr_filter != 0xff) + addr_field = desc_ex->virt_addr[0]; + + framesize += desc->length; + + /* Status != 0 means last buffer of frame */ + if (desc->status) + break; + + EndIndex++; + if (EndIndex == info->rx_buf_count) + EndIndex = 0; + + if (EndIndex == info->current_rx_buf) { + /* all buffers have been 'used' but none mark */ + /* the end of a frame. Reset buffers and receiver. */ + if ( info->rx_enabled ){ + spin_lock_irqsave(&info->lock,flags); + rx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } + goto Cleanup; + } + + } + + /* check status of receive frame */ + + /* frame status is byte stored after frame data + * + * 7 EOM (end of msg), 1 = last buffer of frame + * 6 Short Frame, 1 = short frame + * 5 Abort, 1 = frame aborted + * 4 Residue, 1 = last byte is partial + * 3 Overrun, 1 = overrun occurred during frame reception + * 2 CRC, 1 = CRC error detected + * + */ + status = desc->status; + + /* ignore CRC bit if not using CRC (bit is undefined) */ + /* Note:CRC is not save to data buffer */ + if (info->params.crc_type == HDLC_CRC_NONE) + status &= ~BIT2; + + if (framesize == 0 || + (addr_field != 0xff && addr_field != info->params.addr_filter)) { + /* discard 0 byte frames, this seems to occur sometime + * when remote is idling flags. + */ + rx_free_frame_buffers(info, StartIndex, EndIndex); + goto CheckAgain; + } + + if (framesize < 2) + status |= BIT6; + + if (status & (BIT6+BIT5+BIT3+BIT2)) { + /* received frame has errors, + * update counts and mark frame size as 0 + */ + if (status & BIT6) + info->icount.rxshort++; + else if (status & BIT5) + info->icount.rxabort++; + else if (status & BIT3) + info->icount.rxover++; + else + info->icount.rxcrc++; + + framesize = 0; +#if SYNCLINK_GENERIC_HDLC + { + info->netdev->stats.rx_errors++; + info->netdev->stats.rx_frame_errors++; + } +#endif + } + + if ( debug_level >= DEBUG_LEVEL_BH ) + printk("%s(%d):%s rx_get_frame() status=%04X size=%d\n", + __FILE__,__LINE__,info->device_name,status,framesize); + + if ( debug_level >= DEBUG_LEVEL_DATA ) + trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr, + min_t(int, framesize,SCABUFSIZE),0); + + if (framesize) { + if (framesize > info->max_frame_size) + info->icount.rxlong++; + else { + /* copy dma buffer(s) to contiguous intermediate buffer */ + int copy_count = framesize; + int index = StartIndex; + unsigned char *ptmp = info->tmp_rx_buf; + info->tmp_rx_buf_count = framesize; + + info->icount.rxok++; + + while(copy_count) { + int partial_count = min(copy_count,SCABUFSIZE); + memcpy( ptmp, + info->rx_buf_list_ex[index].virt_addr, + partial_count ); + ptmp += partial_count; + copy_count -= partial_count; + + if ( ++index == info->rx_buf_count ) + index = 0; + } + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_rx(info,info->tmp_rx_buf,framesize); + else +#endif + ldisc_receive_buf(tty,info->tmp_rx_buf, + info->flag_buf, framesize); + } + } + /* Free the buffers used by this frame. */ + rx_free_frame_buffers( info, StartIndex, EndIndex ); + + ReturnCode = true; + +Cleanup: + if ( info->rx_enabled && info->rx_overflow ) { + /* Receiver is enabled, but needs to restarted due to + * rx buffer overflow. If buffers are empty, restart receiver. + */ + if (info->rx_buf_list[EndIndex].status == 0xff) { + spin_lock_irqsave(&info->lock,flags); + rx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } + } + + return ReturnCode; +} + +/* load the transmit DMA buffer with data + */ +static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count) +{ + unsigned short copy_count; + unsigned int i = 0; + SCADESC *desc; + SCADESC_EX *desc_ex; + + if ( debug_level >= DEBUG_LEVEL_DATA ) + trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1); + + /* Copy source buffer to one or more DMA buffers, starting with + * the first transmit dma buffer. + */ + for(i=0;;) + { + copy_count = min_t(unsigned short,count,SCABUFSIZE); + + desc = &info->tx_buf_list[i]; + desc_ex = &info->tx_buf_list_ex[i]; + + load_pci_memory(info, desc_ex->virt_addr,buf,copy_count); + + desc->length = copy_count; + desc->status = 0; + + buf += copy_count; + count -= copy_count; + + if (!count) + break; + + i++; + if (i >= info->tx_buf_count) + i = 0; + } + + info->tx_buf_list[i].status = 0x81; /* set EOM and EOT status */ + info->last_tx_buf = ++i; +} + +static bool register_test(SLMP_INFO *info) +{ + static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96}; + static unsigned int count = ARRAY_SIZE(testval); + unsigned int i; + bool rc = true; + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + reset_port(info); + + /* assume failure */ + info->init_error = DiagStatus_AddressFailure; + + /* Write bit patterns to various registers but do it out of */ + /* sync, then read back and verify values. */ + + for (i = 0 ; i < count ; i++) { + write_reg(info, TMC, testval[i]); + write_reg(info, IDL, testval[(i+1)%count]); + write_reg(info, SA0, testval[(i+2)%count]); + write_reg(info, SA1, testval[(i+3)%count]); + + if ( (read_reg(info, TMC) != testval[i]) || + (read_reg(info, IDL) != testval[(i+1)%count]) || + (read_reg(info, SA0) != testval[(i+2)%count]) || + (read_reg(info, SA1) != testval[(i+3)%count]) ) + { + rc = false; + break; + } + } + + reset_port(info); + spin_unlock_irqrestore(&info->lock,flags); + + return rc; +} + +static bool irq_test(SLMP_INFO *info) +{ + unsigned long timeout; + unsigned long flags; + + unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0; + + spin_lock_irqsave(&info->lock,flags); + reset_port(info); + + /* assume failure */ + info->init_error = DiagStatus_IrqFailure; + info->irq_occurred = false; + + /* setup timer0 on SCA0 to interrupt */ + + /* IER2<7..4> = timer<3..0> interrupt enables (1=enabled) */ + write_reg(info, IER2, (unsigned char)((info->port_num & 1) ? BIT6 : BIT4)); + + write_reg(info, (unsigned char)(timer + TEPR), 0); /* timer expand prescale */ + write_reg16(info, (unsigned char)(timer + TCONR), 1); /* timer constant */ + + + /* TMCS, Timer Control/Status Register + * + * 07 CMF, Compare match flag (read only) 1=match + * 06 ECMI, CMF Interrupt Enable: 1=enabled + * 05 Reserved, must be 0 + * 04 TME, Timer Enable + * 03..00 Reserved, must be 0 + * + * 0101 0000 + */ + write_reg(info, (unsigned char)(timer + TMCS), 0x50); + + spin_unlock_irqrestore(&info->lock,flags); + + timeout=100; + while( timeout-- && !info->irq_occurred ) { + msleep_interruptible(10); + } + + spin_lock_irqsave(&info->lock,flags); + reset_port(info); + spin_unlock_irqrestore(&info->lock,flags); + + return info->irq_occurred; +} + +/* initialize individual SCA device (2 ports) + */ +static bool sca_init(SLMP_INFO *info) +{ + /* set wait controller to single mem partition (low), no wait states */ + write_reg(info, PABR0, 0); /* wait controller addr boundary 0 */ + write_reg(info, PABR1, 0); /* wait controller addr boundary 1 */ + write_reg(info, WCRL, 0); /* wait controller low range */ + write_reg(info, WCRM, 0); /* wait controller mid range */ + write_reg(info, WCRH, 0); /* wait controller high range */ + + /* DPCR, DMA Priority Control + * + * 07..05 Not used, must be 0 + * 04 BRC, bus release condition: 0=all transfers complete + * 03 CCC, channel change condition: 0=every cycle + * 02..00 PR<2..0>, priority 100=round robin + * + * 00000100 = 0x04 + */ + write_reg(info, DPCR, dma_priority); + + /* DMA Master Enable, BIT7: 1=enable all channels */ + write_reg(info, DMER, 0x80); + + /* enable all interrupt classes */ + write_reg(info, IER0, 0xff); /* TxRDY,RxRDY,TxINT,RxINT (ports 0-1) */ + write_reg(info, IER1, 0xff); /* DMIB,DMIA (channels 0-3) */ + write_reg(info, IER2, 0xf0); /* TIRQ (timers 0-3) */ + + /* ITCR, interrupt control register + * 07 IPC, interrupt priority, 0=MSCI->DMA + * 06..05 IAK<1..0>, Acknowledge cycle, 00=non-ack cycle + * 04 VOS, Vector Output, 0=unmodified vector + * 03..00 Reserved, must be 0 + */ + write_reg(info, ITCR, 0); + + return true; +} + +/* initialize adapter hardware + */ +static bool init_adapter(SLMP_INFO *info) +{ + int i; + + /* Set BIT30 of Local Control Reg 0x50 to reset SCA */ + volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); + u32 readval; + + info->misc_ctrl_value |= BIT30; + *MiscCtrl = info->misc_ctrl_value; + + /* + * Force at least 170ns delay before clearing + * reset bit. Each read from LCR takes at least + * 30ns so 10 times for 300ns to be safe. + */ + for(i=0;i<10;i++) + readval = *MiscCtrl; + + info->misc_ctrl_value &= ~BIT30; + *MiscCtrl = info->misc_ctrl_value; + + /* init control reg (all DTRs off, all clksel=input) */ + info->ctrlreg_value = 0xaa; + write_control_reg(info); + + { + volatile u32 *LCR1BRDR = (u32 *)(info->lcr_base + 0x2c); + lcr1_brdr_value &= ~(BIT5 + BIT4 + BIT3); + + switch(read_ahead_count) + { + case 16: + lcr1_brdr_value |= BIT5 + BIT4 + BIT3; + break; + case 8: + lcr1_brdr_value |= BIT5 + BIT4; + break; + case 4: + lcr1_brdr_value |= BIT5 + BIT3; + break; + case 0: + lcr1_brdr_value |= BIT5; + break; + } + + *LCR1BRDR = lcr1_brdr_value; + *MiscCtrl = misc_ctrl_value; + } + + sca_init(info->port_array[0]); + sca_init(info->port_array[2]); + + return true; +} + +/* Loopback an HDLC frame to test the hardware + * interrupt and DMA functions. + */ +static bool loopback_test(SLMP_INFO *info) +{ +#define TESTFRAMESIZE 20 + + unsigned long timeout; + u16 count = TESTFRAMESIZE; + unsigned char buf[TESTFRAMESIZE]; + bool rc = false; + unsigned long flags; + + struct tty_struct *oldtty = info->port.tty; + u32 speed = info->params.clock_speed; + + info->params.clock_speed = 3686400; + info->port.tty = NULL; + + /* assume failure */ + info->init_error = DiagStatus_DmaFailure; + + /* build and send transmit frame */ + for (count = 0; count < TESTFRAMESIZE;++count) + buf[count] = (unsigned char)count; + + memset(info->tmp_rx_buf,0,TESTFRAMESIZE); + + /* program hardware for HDLC and enabled receiver */ + spin_lock_irqsave(&info->lock,flags); + hdlc_mode(info); + enable_loopback(info,1); + rx_start(info); + info->tx_count = count; + tx_load_dma_buffer(info,buf,count); + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + /* wait for receive complete */ + /* Set a timeout for waiting for interrupt. */ + for ( timeout = 100; timeout; --timeout ) { + msleep_interruptible(10); + + if (rx_get_frame(info)) { + rc = true; + break; + } + } + + /* verify received frame length and contents */ + if (rc && + ( info->tmp_rx_buf_count != count || + memcmp(buf, info->tmp_rx_buf,count))) { + rc = false; + } + + spin_lock_irqsave(&info->lock,flags); + reset_adapter(info); + spin_unlock_irqrestore(&info->lock,flags); + + info->params.clock_speed = speed; + info->port.tty = oldtty; + + return rc; +} + +/* Perform diagnostics on hardware + */ +static int adapter_test( SLMP_INFO *info ) +{ + unsigned long flags; + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):Testing device %s\n", + __FILE__,__LINE__,info->device_name ); + + spin_lock_irqsave(&info->lock,flags); + init_adapter(info); + spin_unlock_irqrestore(&info->lock,flags); + + info->port_array[0]->port_count = 0; + + if ( register_test(info->port_array[0]) && + register_test(info->port_array[1])) { + + info->port_array[0]->port_count = 2; + + if ( register_test(info->port_array[2]) && + register_test(info->port_array[3]) ) + info->port_array[0]->port_count += 2; + } + else { + printk( "%s(%d):Register test failure for device %s Addr=%08lX\n", + __FILE__,__LINE__,info->device_name, (unsigned long)(info->phys_sca_base)); + return -ENODEV; + } + + if ( !irq_test(info->port_array[0]) || + !irq_test(info->port_array[1]) || + (info->port_count == 4 && !irq_test(info->port_array[2])) || + (info->port_count == 4 && !irq_test(info->port_array[3]))) { + printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n", + __FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) ); + return -ENODEV; + } + + if (!loopback_test(info->port_array[0]) || + !loopback_test(info->port_array[1]) || + (info->port_count == 4 && !loopback_test(info->port_array[2])) || + (info->port_count == 4 && !loopback_test(info->port_array[3]))) { + printk( "%s(%d):DMA test failure for device %s\n", + __FILE__,__LINE__,info->device_name); + return -ENODEV; + } + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):device %s passed diagnostics\n", + __FILE__,__LINE__,info->device_name ); + + info->port_array[0]->init_error = 0; + info->port_array[1]->init_error = 0; + if ( info->port_count > 2 ) { + info->port_array[2]->init_error = 0; + info->port_array[3]->init_error = 0; + } + + return 0; +} + +/* Test the shared memory on a PCI adapter. + */ +static bool memory_test(SLMP_INFO *info) +{ + static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa, + 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; + unsigned long count = ARRAY_SIZE(testval); + unsigned long i; + unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long); + unsigned long * addr = (unsigned long *)info->memory_base; + + /* Test data lines with test pattern at one location. */ + + for ( i = 0 ; i < count ; i++ ) { + *addr = testval[i]; + if ( *addr != testval[i] ) + return false; + } + + /* Test address lines with incrementing pattern over */ + /* entire address range. */ + + for ( i = 0 ; i < limit ; i++ ) { + *addr = i * 4; + addr++; + } + + addr = (unsigned long *)info->memory_base; + + for ( i = 0 ; i < limit ; i++ ) { + if ( *addr != i * 4 ) + return false; + addr++; + } + + memset( info->memory_base, 0, SCA_MEM_SIZE ); + return true; +} + +/* Load data into PCI adapter shared memory. + * + * The PCI9050 releases control of the local bus + * after completing the current read or write operation. + * + * While the PCI9050 write FIFO not empty, the + * PCI9050 treats all of the writes as a single transaction + * and does not release the bus. This causes DMA latency problems + * at high speeds when copying large data blocks to the shared memory. + * + * This function breaks a write into multiple transations by + * interleaving a read which flushes the write FIFO and 'completes' + * the write transation. This allows any pending DMA request to gain control + * of the local bus in a timely fasion. + */ +static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count) +{ + /* A load interval of 16 allows for 4 32-bit writes at */ + /* 136ns each for a maximum latency of 542ns on the local bus.*/ + + unsigned short interval = count / sca_pci_load_interval; + unsigned short i; + + for ( i = 0 ; i < interval ; i++ ) + { + memcpy(dest, src, sca_pci_load_interval); + read_status_reg(info); + dest += sca_pci_load_interval; + src += sca_pci_load_interval; + } + + memcpy(dest, src, count % sca_pci_load_interval); +} + +static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit) +{ + int i; + int linecount; + if (xmit) + printk("%s tx data:\n",info->device_name); + else + printk("%s rx data:\n",info->device_name); + + while(count) { + if (count > 16) + linecount = 16; + else + linecount = count; + + for(i=0;i=040 && data[i]<=0176) + printk("%c",data[i]); + else + printk("."); + } + printk("\n"); + + data += linecount; + count -= linecount; + } +} /* end of trace_block() */ + +/* called when HDLC frame times out + * update stats and do tx completion processing + */ +static void tx_timeout(unsigned long context) +{ + SLMP_INFO *info = (SLMP_INFO*)context; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):%s tx_timeout()\n", + __FILE__,__LINE__,info->device_name); + if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) { + info->icount.txtimeout++; + } + spin_lock_irqsave(&info->lock,flags); + info->tx_active = false; + info->tx_count = info->tx_put = info->tx_get = 0; + + spin_unlock_irqrestore(&info->lock,flags); + +#if SYNCLINK_GENERIC_HDLC + if (info->netcount) + hdlcdev_tx_done(info); + else +#endif + bh_transmit(info); +} + +/* called to periodically check the DSR/RI modem signal input status + */ +static void status_timeout(unsigned long context) +{ + u16 status = 0; + SLMP_INFO *info = (SLMP_INFO*)context; + unsigned long flags; + unsigned char delta; + + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + /* check for DSR/RI state change */ + + delta = info->old_signals ^ info->serial_signals; + info->old_signals = info->serial_signals; + + if (delta & SerialSignal_DSR) + status |= MISCSTATUS_DSR_LATCHED|(info->serial_signals&SerialSignal_DSR); + + if (delta & SerialSignal_RI) + status |= MISCSTATUS_RI_LATCHED|(info->serial_signals&SerialSignal_RI); + + if (delta & SerialSignal_DCD) + status |= MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD); + + if (delta & SerialSignal_CTS) + status |= MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS); + + if (status) + isr_io_pin(info,status); + + mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); +} + + +/* Register Access Routines - + * All registers are memory mapped + */ +#define CALC_REGADDR() \ + unsigned char * RegAddr = (unsigned char*)(info->sca_base + Addr); \ + if (info->port_num > 1) \ + RegAddr += 256; /* port 0-1 SCA0, 2-3 SCA1 */ \ + if ( info->port_num & 1) { \ + if (Addr > 0x7f) \ + RegAddr += 0x40; /* DMA access */ \ + else if (Addr > 0x1f && Addr < 0x60) \ + RegAddr += 0x20; /* MSCI access */ \ + } + + +static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr) +{ + CALC_REGADDR(); + return *RegAddr; +} +static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value) +{ + CALC_REGADDR(); + *RegAddr = Value; +} + +static u16 read_reg16(SLMP_INFO * info, unsigned char Addr) +{ + CALC_REGADDR(); + return *((u16 *)RegAddr); +} + +static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value) +{ + CALC_REGADDR(); + *((u16 *)RegAddr) = Value; +} + +static unsigned char read_status_reg(SLMP_INFO * info) +{ + unsigned char *RegAddr = (unsigned char *)info->statctrl_base; + return *RegAddr; +} + +static void write_control_reg(SLMP_INFO * info) +{ + unsigned char *RegAddr = (unsigned char *)info->statctrl_base; + *RegAddr = info->port_array[0]->ctrlreg_value; +} + + +static int __devinit synclinkmp_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) +{ + if (pci_enable_device(dev)) { + printk("error enabling pci device %p\n", dev); + return -EIO; + } + device_init( ++synclinkmp_adapter_count, dev ); + return 0; +} + +static void __devexit synclinkmp_remove_one (struct pci_dev *dev) +{ +} -- cgit v1.2.3 From 282361a046edd9d58a134f358a3f65a7cb8655d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Feb 2011 16:23:22 -0800 Subject: tty: move ipwireless driver from drivers/char/pcmcia/ to drivers/tty/ As planned by Arnd Bergmann, this moves the ipwireless driver to the drivers/tty/ directory as that's where it really belongs. Cc: Arnd Bergmann Cc: Alan Cox Cc: Jiri Slaby Cc: David Sterba Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- drivers/char/pcmcia/ipwireless/Makefile | 10 - drivers/char/pcmcia/ipwireless/hardware.c | 1764 ----------------------- drivers/char/pcmcia/ipwireless/hardware.h | 62 - drivers/char/pcmcia/ipwireless/main.c | 335 ----- drivers/char/pcmcia/ipwireless/main.h | 68 - drivers/char/pcmcia/ipwireless/network.c | 508 ------- drivers/char/pcmcia/ipwireless/network.h | 53 - drivers/char/pcmcia/ipwireless/setup_protocol.h | 108 -- drivers/char/pcmcia/ipwireless/tty.c | 679 --------- drivers/char/pcmcia/ipwireless/tty.h | 45 - drivers/tty/Makefile | 2 + drivers/tty/ipwireless/Makefile | 10 + drivers/tty/ipwireless/hardware.c | 1764 +++++++++++++++++++++++ drivers/tty/ipwireless/hardware.h | 62 + drivers/tty/ipwireless/main.c | 335 +++++ drivers/tty/ipwireless/main.h | 68 + drivers/tty/ipwireless/network.c | 508 +++++++ drivers/tty/ipwireless/network.h | 53 + drivers/tty/ipwireless/setup_protocol.h | 108 ++ drivers/tty/ipwireless/tty.c | 679 +++++++++ drivers/tty/ipwireless/tty.h | 45 + 22 files changed, 3635 insertions(+), 3633 deletions(-) delete mode 100644 drivers/char/pcmcia/ipwireless/Makefile delete mode 100644 drivers/char/pcmcia/ipwireless/hardware.c delete mode 100644 drivers/char/pcmcia/ipwireless/hardware.h delete mode 100644 drivers/char/pcmcia/ipwireless/main.c delete mode 100644 drivers/char/pcmcia/ipwireless/main.h delete mode 100644 drivers/char/pcmcia/ipwireless/network.c delete mode 100644 drivers/char/pcmcia/ipwireless/network.h delete mode 100644 drivers/char/pcmcia/ipwireless/setup_protocol.h delete mode 100644 drivers/char/pcmcia/ipwireless/tty.c delete mode 100644 drivers/char/pcmcia/ipwireless/tty.h create mode 100644 drivers/tty/ipwireless/Makefile create mode 100644 drivers/tty/ipwireless/hardware.c create mode 100644 drivers/tty/ipwireless/hardware.h create mode 100644 drivers/tty/ipwireless/main.c create mode 100644 drivers/tty/ipwireless/main.h create mode 100644 drivers/tty/ipwireless/network.c create mode 100644 drivers/tty/ipwireless/network.h create mode 100644 drivers/tty/ipwireless/setup_protocol.h create mode 100644 drivers/tty/ipwireless/tty.c create mode 100644 drivers/tty/ipwireless/tty.h (limited to 'drivers/char') diff --git a/MAINTAINERS b/MAINTAINERS index 1eaeda66a525..e39337a1b958 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3423,7 +3423,7 @@ M: Jiri Kosina M: David Sterba S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git -F: drivers/char/pcmcia/ipwireless/ +F: drivers/tty/ipwireless/ IPX NETWORK LAYER M: Arnaldo Carvalho de Melo diff --git a/drivers/char/pcmcia/ipwireless/Makefile b/drivers/char/pcmcia/ipwireless/Makefile deleted file mode 100644 index db80873d7f20..000000000000 --- a/drivers/char/pcmcia/ipwireless/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# drivers/char/pcmcia/ipwireless/Makefile -# -# Makefile for the IPWireless driver -# - -obj-$(CONFIG_IPWIRELESS) += ipwireless.o - -ipwireless-y := hardware.o main.o network.o tty.o - diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c deleted file mode 100644 index 0aeb5a38d296..000000000000 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ /dev/null @@ -1,1764 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#include -#include -#include -#include -#include -#include - -#include "hardware.h" -#include "setup_protocol.h" -#include "network.h" -#include "main.h" - -static void ipw_send_setup_packet(struct ipw_hardware *hw); -static void handle_received_SETUP_packet(struct ipw_hardware *ipw, - unsigned int address, - const unsigned char *data, int len, - int is_last); -static void ipwireless_setup_timer(unsigned long data); -static void handle_received_CTRL_packet(struct ipw_hardware *hw, - unsigned int channel_idx, const unsigned char *data, int len); - -/*#define TIMING_DIAGNOSTICS*/ - -#ifdef TIMING_DIAGNOSTICS - -static struct timing_stats { - unsigned long last_report_time; - unsigned long read_time; - unsigned long write_time; - unsigned long read_bytes; - unsigned long write_bytes; - unsigned long start_time; -}; - -static void start_timing(void) -{ - timing_stats.start_time = jiffies; -} - -static void end_read_timing(unsigned length) -{ - timing_stats.read_time += (jiffies - start_time); - timing_stats.read_bytes += length + 2; - report_timing(); -} - -static void end_write_timing(unsigned length) -{ - timing_stats.write_time += (jiffies - start_time); - timing_stats.write_bytes += length + 2; - report_timing(); -} - -static void report_timing(void) -{ - unsigned long since = jiffies - timing_stats.last_report_time; - - /* If it's been more than one second... */ - if (since >= HZ) { - int first = (timing_stats.last_report_time == 0); - - timing_stats.last_report_time = jiffies; - if (!first) - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n", - jiffies_to_usecs(since), - timing_stats.read_bytes, - jiffies_to_usecs(timing_stats.read_time), - timing_stats.write_bytes, - jiffies_to_usecs(timing_stats.write_time)); - - timing_stats.read_time = 0; - timing_stats.write_time = 0; - timing_stats.read_bytes = 0; - timing_stats.write_bytes = 0; - } -} -#else -static void start_timing(void) { } -static void end_read_timing(unsigned length) { } -static void end_write_timing(unsigned length) { } -#endif - -/* Imported IPW definitions */ - -#define LL_MTU_V1 318 -#define LL_MTU_V2 250 -#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2) - -#define PRIO_DATA 2 -#define PRIO_CTRL 1 -#define PRIO_SETUP 0 - -/* Addresses */ -#define ADDR_SETUP_PROT 0 - -/* Protocol ids */ -enum { - /* Identifier for the Com Data protocol */ - TL_PROTOCOLID_COM_DATA = 0, - - /* Identifier for the Com Control protocol */ - TL_PROTOCOLID_COM_CTRL = 1, - - /* Identifier for the Setup protocol */ - TL_PROTOCOLID_SETUP = 2 -}; - -/* Number of bytes in NL packet header (cannot do - * sizeof(nl_packet_header) since it's a bitfield) */ -#define NL_FIRST_PACKET_HEADER_SIZE 3 - -/* Number of bytes in NL packet header (cannot do - * sizeof(nl_packet_header) since it's a bitfield) */ -#define NL_FOLLOWING_PACKET_HEADER_SIZE 1 - -struct nl_first_packet_header { - unsigned char protocol:3; - unsigned char address:3; - unsigned char packet_rank:2; - unsigned char length_lsb; - unsigned char length_msb; -}; - -struct nl_packet_header { - unsigned char protocol:3; - unsigned char address:3; - unsigned char packet_rank:2; -}; - -/* Value of 'packet_rank' above */ -#define NL_INTERMEDIATE_PACKET 0x0 -#define NL_LAST_PACKET 0x1 -#define NL_FIRST_PACKET 0x2 - -union nl_packet { - /* Network packet header of the first packet (a special case) */ - struct nl_first_packet_header hdr_first; - /* Network packet header of the following packets (if any) */ - struct nl_packet_header hdr; - /* Complete network packet (header + data) */ - unsigned char rawpkt[LL_MTU_MAX]; -} __attribute__ ((__packed__)); - -#define HW_VERSION_UNKNOWN -1 -#define HW_VERSION_1 1 -#define HW_VERSION_2 2 - -/* IPW I/O ports */ -#define IOIER 0x00 /* Interrupt Enable Register */ -#define IOIR 0x02 /* Interrupt Source/ACK register */ -#define IODCR 0x04 /* Data Control Register */ -#define IODRR 0x06 /* Data Read Register */ -#define IODWR 0x08 /* Data Write Register */ -#define IOESR 0x0A /* Embedded Driver Status Register */ -#define IORXR 0x0C /* Rx Fifo Register (Host to Embedded) */ -#define IOTXR 0x0E /* Tx Fifo Register (Embedded to Host) */ - -/* I/O ports and bit definitions for version 1 of the hardware */ - -/* IER bits*/ -#define IER_RXENABLED 0x1 -#define IER_TXENABLED 0x2 - -/* ISR bits */ -#define IR_RXINTR 0x1 -#define IR_TXINTR 0x2 - -/* DCR bits */ -#define DCR_RXDONE 0x1 -#define DCR_TXDONE 0x2 -#define DCR_RXRESET 0x4 -#define DCR_TXRESET 0x8 - -/* I/O ports and bit definitions for version 2 of the hardware */ - -struct MEMCCR { - unsigned short reg_config_option; /* PCCOR: Configuration Option Register */ - unsigned short reg_config_and_status; /* PCCSR: Configuration and Status Register */ - unsigned short reg_pin_replacement; /* PCPRR: Pin Replacemant Register */ - unsigned short reg_socket_and_copy; /* PCSCR: Socket and Copy Register */ - unsigned short reg_ext_status; /* PCESR: Extendend Status Register */ - unsigned short reg_io_base; /* PCIOB: I/O Base Register */ -}; - -struct MEMINFREG { - unsigned short memreg_tx_old; /* TX Register (R/W) */ - unsigned short pad1; - unsigned short memreg_rx_done; /* RXDone Register (R/W) */ - unsigned short pad2; - unsigned short memreg_rx; /* RX Register (R/W) */ - unsigned short pad3; - unsigned short memreg_pc_interrupt_ack; /* PC intr Ack Register (W) */ - unsigned short pad4; - unsigned long memreg_card_present;/* Mask for Host to check (R) for - * CARD_PRESENT_VALUE */ - unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ -}; - -#define CARD_PRESENT_VALUE (0xBEEFCAFEUL) - -#define MEMTX_TX 0x0001 -#define MEMRX_RX 0x0001 -#define MEMRX_RX_DONE 0x0001 -#define MEMRX_PCINTACKK 0x0001 - -#define NL_NUM_OF_PRIORITIES 3 -#define NL_NUM_OF_PROTOCOLS 3 -#define NL_NUM_OF_ADDRESSES NO_OF_IPW_CHANNELS - -struct ipw_hardware { - unsigned int base_port; - short hw_version; - unsigned short ll_mtu; - spinlock_t lock; - - int initializing; - int init_loops; - struct timer_list setup_timer; - - /* Flag if hw is ready to send next packet */ - int tx_ready; - /* Count of pending packets to be sent */ - int tx_queued; - struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; - - int rx_bytes_queued; - struct list_head rx_queue; - /* Pool of rx_packet structures that are not currently used. */ - struct list_head rx_pool; - int rx_pool_size; - /* True if reception of data is blocked while userspace processes it. */ - int blocking_rx; - /* True if there is RX data ready on the hardware. */ - int rx_ready; - unsigned short last_memtx_serial; - /* - * Newer versions of the V2 card firmware send serial numbers in the - * MemTX register. 'serial_number_detected' is set true when we detect - * a non-zero serial number (indicating the new firmware). Thereafter, - * the driver can safely ignore the Timer Recovery re-sends to avoid - * out-of-sync problems. - */ - int serial_number_detected; - struct work_struct work_rx; - - /* True if we are to send the set-up data to the hardware. */ - int to_setup; - - /* Card has been removed */ - int removed; - /* Saved irq value when we disable the interrupt. */ - int irq; - /* True if this driver is shutting down. */ - int shutting_down; - /* Modem control lines */ - unsigned int control_lines[NL_NUM_OF_ADDRESSES]; - struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES]; - - struct tasklet_struct tasklet; - - /* The handle for the network layer, for the sending of events to it. */ - struct ipw_network *network; - struct MEMINFREG __iomem *memory_info_regs; - struct MEMCCR __iomem *memregs_CCR; - void (*reboot_callback) (void *data); - void *reboot_callback_data; - - unsigned short __iomem *memreg_tx; -}; - -/* - * Packet info structure for tx packets. - * Note: not all the fields defined here are required for all protocols - */ -struct ipw_tx_packet { - struct list_head queue; - /* channel idx + 1 */ - unsigned char dest_addr; - /* SETUP, CTRL or DATA */ - unsigned char protocol; - /* Length of data block, which starts at the end of this structure */ - unsigned short length; - /* Sending state */ - /* Offset of where we've sent up to so far */ - unsigned long offset; - /* Count of packet fragments, starting at 0 */ - int fragment_count; - - /* Called after packet is sent and before is freed */ - void (*packet_callback) (void *cb_data, unsigned int packet_length); - void *callback_data; -}; - -/* Signals from DTE */ -#define COMCTRL_RTS 0 -#define COMCTRL_DTR 1 - -/* Signals from DCE */ -#define COMCTRL_CTS 2 -#define COMCTRL_DCD 3 -#define COMCTRL_DSR 4 -#define COMCTRL_RI 5 - -struct ipw_control_packet_body { - /* DTE signal or DCE signal */ - unsigned char sig_no; - /* 0: set signal, 1: clear signal */ - unsigned char value; -} __attribute__ ((__packed__)); - -struct ipw_control_packet { - struct ipw_tx_packet header; - struct ipw_control_packet_body body; -}; - -struct ipw_rx_packet { - struct list_head queue; - unsigned int capacity; - unsigned int length; - unsigned int protocol; - unsigned int channel_idx; -}; - -static char *data_type(const unsigned char *buf, unsigned length) -{ - struct nl_packet_header *hdr = (struct nl_packet_header *) buf; - - if (length == 0) - return " "; - - if (hdr->packet_rank & NL_FIRST_PACKET) { - switch (hdr->protocol) { - case TL_PROTOCOLID_COM_DATA: return "DATA "; - case TL_PROTOCOLID_COM_CTRL: return "CTRL "; - case TL_PROTOCOLID_SETUP: return "SETUP"; - default: return "???? "; - } - } else - return " "; -} - -#define DUMP_MAX_BYTES 64 - -static void dump_data_bytes(const char *type, const unsigned char *data, - unsigned length) -{ - char prefix[56]; - - sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ", - type, data_type(data, length)); - print_hex_dump_bytes(prefix, 0, (void *)data, - length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); -} - -static void swap_packet_bitfield_to_le(unsigned char *data) -{ -#ifdef __BIG_ENDIAN_BITFIELD - unsigned char tmp = *data, ret = 0; - - /* - * transform bits from aa.bbb.ccc to ccc.bbb.aa - */ - ret |= tmp & 0xc0 >> 6; - ret |= tmp & 0x38 >> 1; - ret |= tmp & 0x07 << 5; - *data = ret & 0xff; -#endif -} - -static void swap_packet_bitfield_from_le(unsigned char *data) -{ -#ifdef __BIG_ENDIAN_BITFIELD - unsigned char tmp = *data, ret = 0; - - /* - * transform bits from ccc.bbb.aa to aa.bbb.ccc - */ - ret |= tmp & 0xe0 >> 5; - ret |= tmp & 0x1c << 1; - ret |= tmp & 0x03 << 6; - *data = ret & 0xff; -#endif -} - -static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data, - unsigned length) -{ - unsigned i; - unsigned long flags; - - start_timing(); - BUG_ON(length > hw->ll_mtu); - - if (ipwireless_debug) - dump_data_bytes("send", data, length); - - spin_lock_irqsave(&hw->lock, flags); - - hw->tx_ready = 0; - swap_packet_bitfield_to_le(data); - - if (hw->hw_version == HW_VERSION_1) { - outw((unsigned short) length, hw->base_port + IODWR); - - for (i = 0; i < length; i += 2) { - unsigned short d = data[i]; - __le16 raw_data; - - if (i + 1 < length) - d |= data[i + 1] << 8; - raw_data = cpu_to_le16(d); - outw(raw_data, hw->base_port + IODWR); - } - - outw(DCR_TXDONE, hw->base_port + IODCR); - } else if (hw->hw_version == HW_VERSION_2) { - outw((unsigned short) length, hw->base_port); - - for (i = 0; i < length; i += 2) { - unsigned short d = data[i]; - __le16 raw_data; - - if (i + 1 < length) - d |= data[i + 1] << 8; - raw_data = cpu_to_le16(d); - outw(raw_data, hw->base_port); - } - while ((i & 3) != 2) { - outw((unsigned short) 0xDEAD, hw->base_port); - i += 2; - } - writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); - } - - spin_unlock_irqrestore(&hw->lock, flags); - - end_write_timing(length); -} - -static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) -{ - unsigned short fragment_data_len; - unsigned short data_left = packet->length - packet->offset; - unsigned short header_size; - union nl_packet pkt; - - header_size = - (packet->fragment_count == 0) - ? NL_FIRST_PACKET_HEADER_SIZE - : NL_FOLLOWING_PACKET_HEADER_SIZE; - fragment_data_len = hw->ll_mtu - header_size; - if (data_left < fragment_data_len) - fragment_data_len = data_left; - - /* - * hdr_first is now in machine bitfield order, which will be swapped - * to le just before it goes to hw - */ - pkt.hdr_first.protocol = packet->protocol; - pkt.hdr_first.address = packet->dest_addr; - pkt.hdr_first.packet_rank = 0; - - /* First packet? */ - if (packet->fragment_count == 0) { - pkt.hdr_first.packet_rank |= NL_FIRST_PACKET; - pkt.hdr_first.length_lsb = (unsigned char) packet->length; - pkt.hdr_first.length_msb = - (unsigned char) (packet->length >> 8); - } - - memcpy(pkt.rawpkt + header_size, - ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) + - packet->offset, fragment_data_len); - packet->offset += fragment_data_len; - packet->fragment_count++; - - /* Last packet? (May also be first packet.) */ - if (packet->offset == packet->length) - pkt.hdr_first.packet_rank |= NL_LAST_PACKET; - do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len); - - /* If this packet has unsent data, then re-queue it. */ - if (packet->offset < packet->length) { - /* - * Re-queue it at the head of the highest priority queue so - * it goes before all other packets - */ - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - list_add(&packet->queue, &hw->tx_queue[0]); - hw->tx_queued++; - spin_unlock_irqrestore(&hw->lock, flags); - } else { - if (packet->packet_callback) - packet->packet_callback(packet->callback_data, - packet->length); - kfree(packet); - } -} - -static void ipw_setup_hardware(struct ipw_hardware *hw) -{ - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - if (hw->hw_version == HW_VERSION_1) { - /* Reset RX FIFO */ - outw(DCR_RXRESET, hw->base_port + IODCR); - /* SB: Reset TX FIFO */ - outw(DCR_TXRESET, hw->base_port + IODCR); - - /* Enable TX and RX interrupts. */ - outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER); - } else { - /* - * Set INTRACK bit (bit 0), which means we must explicitly - * acknowledge interrupts by clearing bit 2 of reg_config_and_status. - */ - unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status); - - csr |= 1; - writew(csr, &hw->memregs_CCR->reg_config_and_status); - } - spin_unlock_irqrestore(&hw->lock, flags); -} - -/* - * If 'packet' is NULL, then this function allocates a new packet, setting its - * length to 0 and ensuring it has the specified minimum amount of free space. - * - * If 'packet' is not NULL, then this function enlarges it if it doesn't - * have the specified minimum amount of free space. - * - */ -static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, - struct ipw_rx_packet *packet, - int minimum_free_space) -{ - - if (!packet) { - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - if (!list_empty(&hw->rx_pool)) { - packet = list_first_entry(&hw->rx_pool, - struct ipw_rx_packet, queue); - hw->rx_pool_size--; - spin_unlock_irqrestore(&hw->lock, flags); - list_del(&packet->queue); - } else { - const int min_capacity = - ipwireless_ppp_mru(hw->network) + 2; - int new_capacity; - - spin_unlock_irqrestore(&hw->lock, flags); - new_capacity = - (minimum_free_space > min_capacity - ? minimum_free_space - : min_capacity); - packet = kmalloc(sizeof(struct ipw_rx_packet) - + new_capacity, GFP_ATOMIC); - if (!packet) - return NULL; - packet->capacity = new_capacity; - } - packet->length = 0; - } - - if (packet->length + minimum_free_space > packet->capacity) { - struct ipw_rx_packet *old_packet = packet; - - packet = kmalloc(sizeof(struct ipw_rx_packet) + - old_packet->length + minimum_free_space, - GFP_ATOMIC); - if (!packet) { - kfree(old_packet); - return NULL; - } - memcpy(packet, old_packet, - sizeof(struct ipw_rx_packet) - + old_packet->length); - packet->capacity = old_packet->length + minimum_free_space; - kfree(old_packet); - } - - return packet; -} - -static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) -{ - if (hw->rx_pool_size > 6) - kfree(packet); - else { - hw->rx_pool_size++; - list_add(&packet->queue, &hw->rx_pool); - } -} - -static void queue_received_packet(struct ipw_hardware *hw, - unsigned int protocol, - unsigned int address, - const unsigned char *data, int length, - int is_last) -{ - unsigned int channel_idx = address - 1; - struct ipw_rx_packet *packet = NULL; - unsigned long flags; - - /* Discard packet if channel index is out of range. */ - if (channel_idx >= NL_NUM_OF_ADDRESSES) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": data packet has bad address %u\n", address); - return; - } - - /* - * ->packet_assembler is safe to touch unlocked, this is the only place - */ - if (protocol == TL_PROTOCOLID_COM_DATA) { - struct ipw_rx_packet **assem = - &hw->packet_assembler[channel_idx]; - - /* - * Create a new packet, or assembler already contains one - * enlarge it by 'length' bytes. - */ - (*assem) = pool_allocate(hw, *assem, length); - if (!(*assem)) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": no memory for incomming data packet, dropped!\n"); - return; - } - (*assem)->protocol = protocol; - (*assem)->channel_idx = channel_idx; - - /* Append this packet data onto existing data. */ - memcpy((unsigned char *)(*assem) + - sizeof(struct ipw_rx_packet) - + (*assem)->length, data, length); - (*assem)->length += length; - if (is_last) { - packet = *assem; - *assem = NULL; - /* Count queued DATA bytes only */ - spin_lock_irqsave(&hw->lock, flags); - hw->rx_bytes_queued += packet->length; - spin_unlock_irqrestore(&hw->lock, flags); - } - } else { - /* If it's a CTRL packet, don't assemble, just queue it. */ - packet = pool_allocate(hw, NULL, length); - if (!packet) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": no memory for incomming ctrl packet, dropped!\n"); - return; - } - packet->protocol = protocol; - packet->channel_idx = channel_idx; - memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet), - data, length); - packet->length = length; - } - - /* - * If this is the last packet, then send the assembled packet on to the - * network layer. - */ - if (packet) { - spin_lock_irqsave(&hw->lock, flags); - list_add_tail(&packet->queue, &hw->rx_queue); - /* Block reception of incoming packets if queue is full. */ - hw->blocking_rx = - (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE); - - spin_unlock_irqrestore(&hw->lock, flags); - schedule_work(&hw->work_rx); - } -} - -/* - * Workqueue callback - */ -static void ipw_receive_data_work(struct work_struct *work_rx) -{ - struct ipw_hardware *hw = - container_of(work_rx, struct ipw_hardware, work_rx); - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - while (!list_empty(&hw->rx_queue)) { - struct ipw_rx_packet *packet = - list_first_entry(&hw->rx_queue, - struct ipw_rx_packet, queue); - - if (hw->shutting_down) - break; - list_del(&packet->queue); - - /* - * Note: ipwireless_network_packet_received must be called in a - * process context (i.e. via schedule_work) because the tty - * output code can sleep in the tty_flip_buffer_push call. - */ - if (packet->protocol == TL_PROTOCOLID_COM_DATA) { - if (hw->network != NULL) { - /* If the network hasn't been disconnected. */ - spin_unlock_irqrestore(&hw->lock, flags); - /* - * This must run unlocked due to tty processing - * and mutex locking - */ - ipwireless_network_packet_received( - hw->network, - packet->channel_idx, - (unsigned char *)packet - + sizeof(struct ipw_rx_packet), - packet->length); - spin_lock_irqsave(&hw->lock, flags); - } - /* Count queued DATA bytes only */ - hw->rx_bytes_queued -= packet->length; - } else { - /* - * This is safe to be called locked, callchain does - * not block - */ - handle_received_CTRL_packet(hw, packet->channel_idx, - (unsigned char *)packet - + sizeof(struct ipw_rx_packet), - packet->length); - } - pool_free(hw, packet); - /* - * Unblock reception of incoming packets if queue is no longer - * full. - */ - hw->blocking_rx = - hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; - if (hw->shutting_down) - break; - } - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void handle_received_CTRL_packet(struct ipw_hardware *hw, - unsigned int channel_idx, - const unsigned char *data, int len) -{ - const struct ipw_control_packet_body *body = - (const struct ipw_control_packet_body *) data; - unsigned int changed_mask; - - if (len != sizeof(struct ipw_control_packet_body)) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": control packet was %d bytes - wrong size!\n", - len); - return; - } - - switch (body->sig_no) { - case COMCTRL_CTS: - changed_mask = IPW_CONTROL_LINE_CTS; - break; - case COMCTRL_DCD: - changed_mask = IPW_CONTROL_LINE_DCD; - break; - case COMCTRL_DSR: - changed_mask = IPW_CONTROL_LINE_DSR; - break; - case COMCTRL_RI: - changed_mask = IPW_CONTROL_LINE_RI; - break; - default: - changed_mask = 0; - } - - if (changed_mask != 0) { - if (body->value) - hw->control_lines[channel_idx] |= changed_mask; - else - hw->control_lines[channel_idx] &= ~changed_mask; - if (hw->network) - ipwireless_network_notify_control_line_change( - hw->network, - channel_idx, - hw->control_lines[channel_idx], - changed_mask); - } -} - -static void handle_received_packet(struct ipw_hardware *hw, - const union nl_packet *packet, - unsigned short len) -{ - unsigned int protocol = packet->hdr.protocol; - unsigned int address = packet->hdr.address; - unsigned int header_length; - const unsigned char *data; - unsigned int data_len; - int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; - - if (packet->hdr.packet_rank & NL_FIRST_PACKET) - header_length = NL_FIRST_PACKET_HEADER_SIZE; - else - header_length = NL_FOLLOWING_PACKET_HEADER_SIZE; - - data = packet->rawpkt + header_length; - data_len = len - header_length; - switch (protocol) { - case TL_PROTOCOLID_COM_DATA: - case TL_PROTOCOLID_COM_CTRL: - queue_received_packet(hw, protocol, address, data, data_len, - is_last); - break; - case TL_PROTOCOLID_SETUP: - handle_received_SETUP_packet(hw, address, data, data_len, - is_last); - break; - } -} - -static void acknowledge_data_read(struct ipw_hardware *hw) -{ - if (hw->hw_version == HW_VERSION_1) - outw(DCR_RXDONE, hw->base_port + IODCR); - else - writew(MEMRX_PCINTACKK, - &hw->memory_info_regs->memreg_pc_interrupt_ack); -} - -/* - * Retrieve a packet from the IPW hardware. - */ -static void do_receive_packet(struct ipw_hardware *hw) -{ - unsigned len; - unsigned i; - unsigned char pkt[LL_MTU_MAX]; - - start_timing(); - - if (hw->hw_version == HW_VERSION_1) { - len = inw(hw->base_port + IODRR); - if (len > hw->ll_mtu) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": received a packet of %u bytes - longer than the MTU!\n", len); - outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); - return; - } - - for (i = 0; i < len; i += 2) { - __le16 raw_data = inw(hw->base_port + IODRR); - unsigned short data = le16_to_cpu(raw_data); - - pkt[i] = (unsigned char) data; - pkt[i + 1] = (unsigned char) (data >> 8); - } - } else { - len = inw(hw->base_port); - if (len > hw->ll_mtu) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": received a packet of %u bytes - longer than the MTU!\n", len); - writew(MEMRX_PCINTACKK, - &hw->memory_info_regs->memreg_pc_interrupt_ack); - return; - } - - for (i = 0; i < len; i += 2) { - __le16 raw_data = inw(hw->base_port); - unsigned short data = le16_to_cpu(raw_data); - - pkt[i] = (unsigned char) data; - pkt[i + 1] = (unsigned char) (data >> 8); - } - - while ((i & 3) != 2) { - inw(hw->base_port); - i += 2; - } - } - - acknowledge_data_read(hw); - - swap_packet_bitfield_from_le(pkt); - - if (ipwireless_debug) - dump_data_bytes("recv", pkt, len); - - handle_received_packet(hw, (union nl_packet *) pkt, len); - - end_read_timing(len); -} - -static int get_current_packet_priority(struct ipw_hardware *hw) -{ - /* - * If we're initializing, don't send anything of higher priority than - * PRIO_SETUP. The network layer therefore need not care about - * hardware initialization - any of its stuff will simply be queued - * until setup is complete. - */ - return (hw->to_setup || hw->initializing - ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES); -} - -/* - * return 1 if something has been received from hw - */ -static int get_packets_from_hw(struct ipw_hardware *hw) -{ - int received = 0; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - while (hw->rx_ready && !hw->blocking_rx) { - received = 1; - hw->rx_ready--; - spin_unlock_irqrestore(&hw->lock, flags); - - do_receive_packet(hw); - - spin_lock_irqsave(&hw->lock, flags); - } - spin_unlock_irqrestore(&hw->lock, flags); - - return received; -} - -/* - * Send pending packet up to given priority, prioritize SETUP data until - * hardware is fully setup. - * - * return 1 if more packets can be sent - */ -static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) -{ - int more_to_send = 0; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - if (hw->tx_queued && hw->tx_ready) { - int priority; - struct ipw_tx_packet *packet = NULL; - - /* Pick a packet */ - for (priority = 0; priority < priority_limit; priority++) { - if (!list_empty(&hw->tx_queue[priority])) { - packet = list_first_entry( - &hw->tx_queue[priority], - struct ipw_tx_packet, - queue); - - hw->tx_queued--; - list_del(&packet->queue); - - break; - } - } - if (!packet) { - hw->tx_queued = 0; - spin_unlock_irqrestore(&hw->lock, flags); - return 0; - } - - spin_unlock_irqrestore(&hw->lock, flags); - - /* Send */ - do_send_packet(hw, packet); - - /* Check if more to send */ - spin_lock_irqsave(&hw->lock, flags); - for (priority = 0; priority < priority_limit; priority++) - if (!list_empty(&hw->tx_queue[priority])) { - more_to_send = 1; - break; - } - - if (!more_to_send) - hw->tx_queued = 0; - } - spin_unlock_irqrestore(&hw->lock, flags); - - return more_to_send; -} - -/* - * Send and receive all queued packets. - */ -static void ipwireless_do_tasklet(unsigned long hw_) -{ - struct ipw_hardware *hw = (struct ipw_hardware *) hw_; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - if (hw->shutting_down) { - spin_unlock_irqrestore(&hw->lock, flags); - return; - } - - if (hw->to_setup == 1) { - /* - * Initial setup data sent to hardware - */ - hw->to_setup = 2; - spin_unlock_irqrestore(&hw->lock, flags); - - ipw_setup_hardware(hw); - ipw_send_setup_packet(hw); - - send_pending_packet(hw, PRIO_SETUP + 1); - get_packets_from_hw(hw); - } else { - int priority_limit = get_current_packet_priority(hw); - int again; - - spin_unlock_irqrestore(&hw->lock, flags); - - do { - again = send_pending_packet(hw, priority_limit); - again |= get_packets_from_hw(hw); - } while (again); - } -} - -/* - * return true if the card is physically present. - */ -static int is_card_present(struct ipw_hardware *hw) -{ - if (hw->hw_version == HW_VERSION_1) - return inw(hw->base_port + IOIR) != 0xFFFF; - else - return readl(&hw->memory_info_regs->memreg_card_present) == - CARD_PRESENT_VALUE; -} - -static irqreturn_t ipwireless_handle_v1_interrupt(int irq, - struct ipw_hardware *hw) -{ - unsigned short irqn; - - irqn = inw(hw->base_port + IOIR); - - /* Check if card is present */ - if (irqn == 0xFFFF) - return IRQ_NONE; - else if (irqn != 0) { - unsigned short ack = 0; - unsigned long flags; - - /* Transmit complete. */ - if (irqn & IR_TXINTR) { - ack |= IR_TXINTR; - spin_lock_irqsave(&hw->lock, flags); - hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->lock, flags); - } - /* Received data */ - if (irqn & IR_RXINTR) { - ack |= IR_RXINTR; - spin_lock_irqsave(&hw->lock, flags); - hw->rx_ready++; - spin_unlock_irqrestore(&hw->lock, flags); - } - if (ack != 0) { - outw(ack, hw->base_port + IOIR); - tasklet_schedule(&hw->tasklet); - } - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw) -{ - unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status); - - csr &= 0xfffd; - writew(csr, &hw->memregs_CCR->reg_config_and_status); -} - -static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, - struct ipw_hardware *hw) -{ - int tx = 0; - int rx = 0; - int rx_repeat = 0; - int try_mem_tx_old; - unsigned long flags; - - do { - - unsigned short memtx = readw(hw->memreg_tx); - unsigned short memtx_serial; - unsigned short memrxdone = - readw(&hw->memory_info_regs->memreg_rx_done); - - try_mem_tx_old = 0; - - /* check whether the interrupt was generated by ipwireless card */ - if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) { - - /* check if the card uses memreg_tx_old register */ - if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { - memtx = readw(&hw->memory_info_regs->memreg_tx_old); - if (memtx & MEMTX_TX) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": Using memreg_tx_old\n"); - hw->memreg_tx = - &hw->memory_info_regs->memreg_tx_old; - } else { - return IRQ_NONE; - } - } else - return IRQ_NONE; - } - - /* - * See if the card is physically present. Note that while it is - * powering up, it appears not to be present. - */ - if (!is_card_present(hw)) { - acknowledge_pcmcia_interrupt(hw); - return IRQ_HANDLED; - } - - memtx_serial = memtx & (unsigned short) 0xff00; - if (memtx & MEMTX_TX) { - writew(memtx_serial, hw->memreg_tx); - - if (hw->serial_number_detected) { - if (memtx_serial != hw->last_memtx_serial) { - hw->last_memtx_serial = memtx_serial; - spin_lock_irqsave(&hw->lock, flags); - hw->rx_ready++; - spin_unlock_irqrestore(&hw->lock, flags); - rx = 1; - } else - /* Ignore 'Timer Recovery' duplicates. */ - rx_repeat = 1; - } else { - /* - * If a non-zero serial number is seen, then enable - * serial number checking. - */ - if (memtx_serial != 0) { - hw->serial_number_detected = 1; - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME - ": memreg_tx serial num detected\n"); - - spin_lock_irqsave(&hw->lock, flags); - hw->rx_ready++; - spin_unlock_irqrestore(&hw->lock, flags); - } - rx = 1; - } - } - if (memrxdone & MEMRX_RX_DONE) { - writew(0, &hw->memory_info_regs->memreg_rx_done); - spin_lock_irqsave(&hw->lock, flags); - hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->lock, flags); - tx = 1; - } - if (tx) - writew(MEMRX_PCINTACKK, - &hw->memory_info_regs->memreg_pc_interrupt_ack); - - acknowledge_pcmcia_interrupt(hw); - - if (tx || rx) - tasklet_schedule(&hw->tasklet); - else if (!rx_repeat) { - if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { - if (hw->serial_number_detected) - printk(KERN_WARNING IPWIRELESS_PCCARD_NAME - ": spurious interrupt - new_tx mode\n"); - else { - printk(KERN_WARNING IPWIRELESS_PCCARD_NAME - ": no valid memreg_tx value - switching to the old memreg_tx\n"); - hw->memreg_tx = - &hw->memory_info_regs->memreg_tx_old; - try_mem_tx_old = 1; - } - } else - printk(KERN_WARNING IPWIRELESS_PCCARD_NAME - ": spurious interrupt - old_tx mode\n"); - } - - } while (try_mem_tx_old == 1); - - return IRQ_HANDLED; -} - -irqreturn_t ipwireless_interrupt(int irq, void *dev_id) -{ - struct ipw_dev *ipw = dev_id; - - if (ipw->hardware->hw_version == HW_VERSION_1) - return ipwireless_handle_v1_interrupt(irq, ipw->hardware); - else - return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware); -} - -static void flush_packets_to_hw(struct ipw_hardware *hw) -{ - int priority_limit; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - priority_limit = get_current_packet_priority(hw); - spin_unlock_irqrestore(&hw->lock, flags); - - while (send_pending_packet(hw, priority_limit)); -} - -static void send_packet(struct ipw_hardware *hw, int priority, - struct ipw_tx_packet *packet) -{ - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - list_add_tail(&packet->queue, &hw->tx_queue[priority]); - hw->tx_queued++; - spin_unlock_irqrestore(&hw->lock, flags); - - flush_packets_to_hw(hw); -} - -/* Create data packet, non-atomic allocation */ -static void *alloc_data_packet(int data_size, - unsigned char dest_addr, - unsigned char protocol) -{ - struct ipw_tx_packet *packet = kzalloc( - sizeof(struct ipw_tx_packet) + data_size, - GFP_ATOMIC); - - if (!packet) - return NULL; - - INIT_LIST_HEAD(&packet->queue); - packet->dest_addr = dest_addr; - packet->protocol = protocol; - packet->length = data_size; - - return packet; -} - -static void *alloc_ctrl_packet(int header_size, - unsigned char dest_addr, - unsigned char protocol, - unsigned char sig_no) -{ - /* - * sig_no is located right after ipw_tx_packet struct in every - * CTRL or SETUP packets, we can use ipw_control_packet as a - * common struct - */ - struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC); - - if (!packet) - return NULL; - - INIT_LIST_HEAD(&packet->header.queue); - packet->header.dest_addr = dest_addr; - packet->header.protocol = protocol; - packet->header.length = header_size - sizeof(struct ipw_tx_packet); - packet->body.sig_no = sig_no; - - return packet; -} - -int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, - const unsigned char *data, unsigned int length, - void (*callback) (void *cb, unsigned int length), - void *callback_data) -{ - struct ipw_tx_packet *packet; - - packet = alloc_data_packet(length, (channel_idx + 1), - TL_PROTOCOLID_COM_DATA); - if (!packet) - return -ENOMEM; - packet->packet_callback = callback; - packet->callback_data = callback_data; - memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data, - length); - - send_packet(hw, PRIO_DATA, packet); - return 0; -} - -static int set_control_line(struct ipw_hardware *hw, int prio, - unsigned int channel_idx, int line, int state) -{ - struct ipw_control_packet *packet; - int protocolid = TL_PROTOCOLID_COM_CTRL; - - if (prio == PRIO_SETUP) - protocolid = TL_PROTOCOLID_SETUP; - - packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), - (channel_idx + 1), protocolid, line); - if (!packet) - return -ENOMEM; - packet->header.length = sizeof(struct ipw_control_packet_body); - packet->body.value = (state == 0 ? 0 : 1); - send_packet(hw, prio, &packet->header); - return 0; -} - - -static int set_DTR(struct ipw_hardware *hw, int priority, - unsigned int channel_idx, int state) -{ - if (state != 0) - hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR; - else - hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR; - - return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state); -} - -static int set_RTS(struct ipw_hardware *hw, int priority, - unsigned int channel_idx, int state) -{ - if (state != 0) - hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS; - else - hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS; - - return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state); -} - -int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, - int state) -{ - return set_DTR(hw, PRIO_CTRL, channel_idx, state); -} - -int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, - int state) -{ - return set_RTS(hw, PRIO_CTRL, channel_idx, state); -} - -struct ipw_setup_get_version_query_packet { - struct ipw_tx_packet header; - struct tl_setup_get_version_qry body; -}; - -struct ipw_setup_config_packet { - struct ipw_tx_packet header; - struct tl_setup_config_msg body; -}; - -struct ipw_setup_config_done_packet { - struct ipw_tx_packet header; - struct tl_setup_config_done_msg body; -}; - -struct ipw_setup_open_packet { - struct ipw_tx_packet header; - struct tl_setup_open_msg body; -}; - -struct ipw_setup_info_packet { - struct ipw_tx_packet header; - struct tl_setup_info_msg body; -}; - -struct ipw_setup_reboot_msg_ack { - struct ipw_tx_packet header; - struct TlSetupRebootMsgAck body; -}; - -/* This handles the actual initialization of the card */ -static void __handle_setup_get_version_rsp(struct ipw_hardware *hw) -{ - struct ipw_setup_config_packet *config_packet; - struct ipw_setup_config_done_packet *config_done_packet; - struct ipw_setup_open_packet *open_packet; - struct ipw_setup_info_packet *info_packet; - int port; - unsigned int channel_idx; - - /* generate config packet */ - for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) { - config_packet = alloc_ctrl_packet( - sizeof(struct ipw_setup_config_packet), - ADDR_SETUP_PROT, - TL_PROTOCOLID_SETUP, - TL_SETUP_SIGNO_CONFIG_MSG); - if (!config_packet) - goto exit_nomem; - config_packet->header.length = sizeof(struct tl_setup_config_msg); - config_packet->body.port_no = port; - config_packet->body.prio_data = PRIO_DATA; - config_packet->body.prio_ctrl = PRIO_CTRL; - send_packet(hw, PRIO_SETUP, &config_packet->header); - } - config_done_packet = alloc_ctrl_packet( - sizeof(struct ipw_setup_config_done_packet), - ADDR_SETUP_PROT, - TL_PROTOCOLID_SETUP, - TL_SETUP_SIGNO_CONFIG_DONE_MSG); - if (!config_done_packet) - goto exit_nomem; - config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg); - send_packet(hw, PRIO_SETUP, &config_done_packet->header); - - /* generate open packet */ - for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) { - open_packet = alloc_ctrl_packet( - sizeof(struct ipw_setup_open_packet), - ADDR_SETUP_PROT, - TL_PROTOCOLID_SETUP, - TL_SETUP_SIGNO_OPEN_MSG); - if (!open_packet) - goto exit_nomem; - open_packet->header.length = sizeof(struct tl_setup_open_msg); - open_packet->body.port_no = port; - send_packet(hw, PRIO_SETUP, &open_packet->header); - } - for (channel_idx = 0; - channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) { - int ret; - - ret = set_DTR(hw, PRIO_SETUP, channel_idx, - (hw->control_lines[channel_idx] & - IPW_CONTROL_LINE_DTR) != 0); - if (ret) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": error setting DTR (%d)\n", ret); - return; - } - - set_RTS(hw, PRIO_SETUP, channel_idx, - (hw->control_lines [channel_idx] & - IPW_CONTROL_LINE_RTS) != 0); - if (ret) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": error setting RTS (%d)\n", ret); - return; - } - } - /* - * For NDIS we assume that we are using sync PPP frames, for COM async. - * This driver uses NDIS mode too. We don't bother with translation - * from async -> sync PPP. - */ - info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet), - ADDR_SETUP_PROT, - TL_PROTOCOLID_SETUP, - TL_SETUP_SIGNO_INFO_MSG); - if (!info_packet) - goto exit_nomem; - info_packet->header.length = sizeof(struct tl_setup_info_msg); - info_packet->body.driver_type = NDISWAN_DRIVER; - info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION; - info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION; - send_packet(hw, PRIO_SETUP, &info_packet->header); - - /* Initialization is now complete, so we clear the 'to_setup' flag */ - hw->to_setup = 0; - - return; - -exit_nomem: - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": not enough memory to alloc control packet\n"); - hw->to_setup = -1; -} - -static void handle_setup_get_version_rsp(struct ipw_hardware *hw, - unsigned char vers_no) -{ - del_timer(&hw->setup_timer); - hw->initializing = 0; - printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n"); - - if (vers_no == TL_SETUP_VERSION) - __handle_setup_get_version_rsp(hw); - else - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": invalid hardware version no %u\n", - (unsigned int) vers_no); -} - -static void ipw_send_setup_packet(struct ipw_hardware *hw) -{ - struct ipw_setup_get_version_query_packet *ver_packet; - - ver_packet = alloc_ctrl_packet( - sizeof(struct ipw_setup_get_version_query_packet), - ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, - TL_SETUP_SIGNO_GET_VERSION_QRY); - ver_packet->header.length = sizeof(struct tl_setup_get_version_qry); - - /* - * Response is handled in handle_received_SETUP_packet - */ - send_packet(hw, PRIO_SETUP, &ver_packet->header); -} - -static void handle_received_SETUP_packet(struct ipw_hardware *hw, - unsigned int address, - const unsigned char *data, int len, - int is_last) -{ - const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data; - - if (address != ADDR_SETUP_PROT) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": setup packet has bad address %d\n", address); - return; - } - - switch (rx_msg->sig_no) { - case TL_SETUP_SIGNO_GET_VERSION_RSP: - if (hw->to_setup) - handle_setup_get_version_rsp(hw, - rx_msg->version_rsp_msg.version); - break; - - case TL_SETUP_SIGNO_OPEN_MSG: - if (ipwireless_debug) { - unsigned int channel_idx = rx_msg->open_msg.port_no - 1; - - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": OPEN_MSG [channel %u] reply received\n", - channel_idx); - } - break; - - case TL_SETUP_SIGNO_INFO_MSG_ACK: - if (ipwireless_debug) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME - ": card successfully configured as NDISWAN\n"); - break; - - case TL_SETUP_SIGNO_REBOOT_MSG: - if (hw->to_setup) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME - ": Setup not completed - ignoring reboot msg\n"); - else { - struct ipw_setup_reboot_msg_ack *packet; - - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME - ": Acknowledging REBOOT message\n"); - packet = alloc_ctrl_packet( - sizeof(struct ipw_setup_reboot_msg_ack), - ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, - TL_SETUP_SIGNO_REBOOT_MSG_ACK); - packet->header.length = - sizeof(struct TlSetupRebootMsgAck); - send_packet(hw, PRIO_SETUP, &packet->header); - if (hw->reboot_callback) - hw->reboot_callback(hw->reboot_callback_data); - } - break; - - default: - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": unknown setup message %u received\n", - (unsigned int) rx_msg->sig_no); - } -} - -static void do_close_hardware(struct ipw_hardware *hw) -{ - unsigned int irqn; - - if (hw->hw_version == HW_VERSION_1) { - /* Disable TX and RX interrupts. */ - outw(0, hw->base_port + IOIER); - - /* Acknowledge any outstanding interrupt requests */ - irqn = inw(hw->base_port + IOIR); - if (irqn & IR_TXINTR) - outw(IR_TXINTR, hw->base_port + IOIR); - if (irqn & IR_RXINTR) - outw(IR_RXINTR, hw->base_port + IOIR); - - synchronize_irq(hw->irq); - } -} - -struct ipw_hardware *ipwireless_hardware_create(void) -{ - int i; - struct ipw_hardware *hw = - kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL); - - if (!hw) - return NULL; - - hw->irq = -1; - hw->initializing = 1; - hw->tx_ready = 1; - hw->rx_bytes_queued = 0; - hw->rx_pool_size = 0; - hw->last_memtx_serial = (unsigned short) 0xffff; - for (i = 0; i < NL_NUM_OF_PRIORITIES; i++) - INIT_LIST_HEAD(&hw->tx_queue[i]); - - INIT_LIST_HEAD(&hw->rx_queue); - INIT_LIST_HEAD(&hw->rx_pool); - spin_lock_init(&hw->lock); - tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); - INIT_WORK(&hw->work_rx, ipw_receive_data_work); - setup_timer(&hw->setup_timer, ipwireless_setup_timer, - (unsigned long) hw); - - return hw; -} - -void ipwireless_init_hardware_v1(struct ipw_hardware *hw, - unsigned int base_port, - void __iomem *attr_memory, - void __iomem *common_memory, - int is_v2_card, - void (*reboot_callback) (void *data), - void *reboot_callback_data) -{ - if (hw->removed) { - hw->removed = 0; - enable_irq(hw->irq); - } - hw->base_port = base_port; - hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1); - hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2); - hw->memregs_CCR = (struct MEMCCR __iomem *) - ((unsigned short __iomem *) attr_memory + 0x200); - hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; - hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new; - hw->reboot_callback = reboot_callback; - hw->reboot_callback_data = reboot_callback_data; -} - -void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw) -{ - hw->initializing = 1; - hw->init_loops = 0; - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": waiting for card to start up...\n"); - ipwireless_setup_timer((unsigned long) hw); -} - -static void ipwireless_setup_timer(unsigned long data) -{ - struct ipw_hardware *hw = (struct ipw_hardware *) data; - - hw->init_loops++; - - if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY && - hw->hw_version == HW_VERSION_2 && - hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": failed to startup using TX2, trying TX\n"); - - hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old; - hw->init_loops = 0; - } - /* Give up after a certain number of retries */ - if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) { - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": card failed to start up!\n"); - hw->initializing = 0; - } else { - /* Do not attempt to write to the board if it is not present. */ - if (is_card_present(hw)) { - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - hw->to_setup = 1; - hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->lock, flags); - tasklet_schedule(&hw->tasklet); - } - - mod_timer(&hw->setup_timer, - jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO)); - } -} - -/* - * Stop any interrupts from executing so that, once this function returns, - * other layers of the driver can be sure they won't get any more callbacks. - * Thus must be called on a proper process context. - */ -void ipwireless_stop_interrupts(struct ipw_hardware *hw) -{ - if (!hw->shutting_down) { - /* Tell everyone we are going down. */ - hw->shutting_down = 1; - del_timer(&hw->setup_timer); - - /* Prevent the hardware from sending any more interrupts */ - do_close_hardware(hw); - } -} - -void ipwireless_hardware_free(struct ipw_hardware *hw) -{ - int i; - struct ipw_rx_packet *rp, *rq; - struct ipw_tx_packet *tp, *tq; - - ipwireless_stop_interrupts(hw); - - flush_work_sync(&hw->work_rx); - - for (i = 0; i < NL_NUM_OF_ADDRESSES; i++) - if (hw->packet_assembler[i] != NULL) - kfree(hw->packet_assembler[i]); - - for (i = 0; i < NL_NUM_OF_PRIORITIES; i++) - list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) { - list_del(&tp->queue); - kfree(tp); - } - - list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) { - list_del(&rp->queue); - kfree(rp); - } - - list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) { - list_del(&rp->queue); - kfree(rp); - } - kfree(hw); -} - -/* - * Associate the specified network with this hardware, so it will receive events - * from it. - */ -void ipwireless_associate_network(struct ipw_hardware *hw, - struct ipw_network *network) -{ - hw->network = network; -} diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h deleted file mode 100644 index 90a8590e43b0..000000000000 --- a/drivers/char/pcmcia/ipwireless/hardware.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#ifndef _IPWIRELESS_CS_HARDWARE_H_ -#define _IPWIRELESS_CS_HARDWARE_H_ - -#include -#include -#include - -#define IPW_CONTROL_LINE_CTS 0x0001 -#define IPW_CONTROL_LINE_DCD 0x0002 -#define IPW_CONTROL_LINE_DSR 0x0004 -#define IPW_CONTROL_LINE_RI 0x0008 -#define IPW_CONTROL_LINE_DTR 0x0010 -#define IPW_CONTROL_LINE_RTS 0x0020 - -struct ipw_hardware; -struct ipw_network; - -struct ipw_hardware *ipwireless_hardware_create(void); -void ipwireless_hardware_free(struct ipw_hardware *hw); -irqreturn_t ipwireless_interrupt(int irq, void *dev_id); -int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, - int state); -int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, - int state); -int ipwireless_send_packet(struct ipw_hardware *hw, - unsigned int channel_idx, - const unsigned char *data, - unsigned int length, - void (*packet_sent_callback) (void *cb, - unsigned int length), - void *sent_cb_data); -void ipwireless_associate_network(struct ipw_hardware *hw, - struct ipw_network *net); -void ipwireless_stop_interrupts(struct ipw_hardware *hw); -void ipwireless_init_hardware_v1(struct ipw_hardware *hw, - unsigned int base_port, - void __iomem *attr_memory, - void __iomem *common_memory, - int is_v2_card, - void (*reboot_cb) (void *data), - void *reboot_cb_data); -void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw); -void ipwireless_sleep(unsigned int tenths); - -#endif diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c deleted file mode 100644 index 94b8eb4d691d..000000000000 --- a/drivers/char/pcmcia/ipwireless/main.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#include "hardware.h" -#include "network.h" -#include "main.h" -#include "tty.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -static struct pcmcia_device_id ipw_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), - PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, ipw_ids); - -static void ipwireless_detach(struct pcmcia_device *link); - -/* - * Module params - */ -/* Debug mode: more verbose, print sent/recv bytes */ -int ipwireless_debug; -int ipwireless_loopback; -int ipwireless_out_queue = 10; - -module_param_named(debug, ipwireless_debug, int, 0); -module_param_named(loopback, ipwireless_loopback, int, 0); -module_param_named(out_queue, ipwireless_out_queue, int, 0); -MODULE_PARM_DESC(debug, "switch on debug messages [0]"); -MODULE_PARM_DESC(loopback, - "debug: enable ras_raw channel [0]"); -MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); - -/* Executes in process context. */ -static void signalled_reboot_work(struct work_struct *work_reboot) -{ - struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev, - work_reboot); - struct pcmcia_device *link = ipw->link; - pcmcia_reset_card(link->socket); -} - -static void signalled_reboot_callback(void *callback_data) -{ - struct ipw_dev *ipw = (struct ipw_dev *) callback_data; - - /* Delegate to process context. */ - schedule_work(&ipw->work_reboot); -} - -static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) -{ - struct ipw_dev *ipw = priv_data; - struct resource *io_resource; - int ret; - - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - - /* 0x40 causes it to generate level mode interrupts. */ - /* 0x04 enables IREQ pin. */ - p_dev->config_index |= 0x44; - p_dev->io_lines = 16; - ret = pcmcia_request_io(p_dev); - if (ret) - return ret; - - io_resource = request_region(p_dev->resource[0]->start, - resource_size(p_dev->resource[0]), - IPWIRELESS_PCCARD_NAME); - - p_dev->resource[2]->flags |= - WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; - - ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0); - if (ret != 0) - goto exit1; - - ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr); - if (ret != 0) - goto exit2; - - ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100; - - ipw->attr_memory = ioremap(p_dev->resource[2]->start, - resource_size(p_dev->resource[2])); - request_mem_region(p_dev->resource[2]->start, - resource_size(p_dev->resource[2]), - IPWIRELESS_PCCARD_NAME); - - p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | - WIN_ENABLE; - p_dev->resource[3]->end = 0; /* this used to be 0x1000 */ - ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0); - if (ret != 0) - goto exit2; - - ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0); - if (ret != 0) - goto exit3; - - ipw->attr_memory = ioremap(p_dev->resource[3]->start, - resource_size(p_dev->resource[3])); - request_mem_region(p_dev->resource[3]->start, - resource_size(p_dev->resource[3]), - IPWIRELESS_PCCARD_NAME); - - return 0; - -exit3: -exit2: - if (ipw->common_memory) { - release_mem_region(p_dev->resource[2]->start, - resource_size(p_dev->resource[2])); - iounmap(ipw->common_memory); - } -exit1: - release_resource(io_resource); - pcmcia_disable_device(p_dev); - return -1; -} - -static int config_ipwireless(struct ipw_dev *ipw) -{ - struct pcmcia_device *link = ipw->link; - int ret = 0; - - ipw->is_v2_card = 0; - link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM | - CONF_ENABLE_IRQ; - - ret = pcmcia_loop_config(link, ipwireless_probe, ipw); - if (ret != 0) - return ret; - - INIT_WORK(&ipw->work_reboot, signalled_reboot_work); - - ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start, - ipw->attr_memory, ipw->common_memory, - ipw->is_v2_card, signalled_reboot_callback, - ipw); - - ret = pcmcia_request_irq(link, ipwireless_interrupt); - if (ret != 0) - goto exit; - - printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", - ipw->is_v2_card ? "V2/V3" : "V1"); - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": I/O ports %pR, irq %d\n", link->resource[0], - (unsigned int) link->irq); - if (ipw->attr_memory && ipw->common_memory) - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": attr memory %pR, common memory %pR\n", - link->resource[3], - link->resource[2]); - - ipw->network = ipwireless_network_create(ipw->hardware); - if (!ipw->network) - goto exit; - - ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network); - if (!ipw->tty) - goto exit; - - ipwireless_init_hardware_v2_v3(ipw->hardware); - - /* - * Do the RequestConfiguration last, because it enables interrupts. - * Then we don't get any interrupts before we're ready for them. - */ - ret = pcmcia_enable_device(link); - if (ret != 0) - goto exit; - - return 0; - -exit: - if (ipw->common_memory) { - release_mem_region(link->resource[2]->start, - resource_size(link->resource[2])); - iounmap(ipw->common_memory); - } - if (ipw->attr_memory) { - release_mem_region(link->resource[3]->start, - resource_size(link->resource[3])); - iounmap(ipw->attr_memory); - } - pcmcia_disable_device(link); - return -1; -} - -static void release_ipwireless(struct ipw_dev *ipw) -{ - if (ipw->common_memory) { - release_mem_region(ipw->link->resource[2]->start, - resource_size(ipw->link->resource[2])); - iounmap(ipw->common_memory); - } - if (ipw->attr_memory) { - release_mem_region(ipw->link->resource[3]->start, - resource_size(ipw->link->resource[3])); - iounmap(ipw->attr_memory); - } - pcmcia_disable_device(ipw->link); -} - -/* - * ipwireless_attach() creates an "instance" of the driver, allocating - * local data structures for one device (one interface). The device - * is registered with Card Services. - * - * The pcmcia_device structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a - * card insertion event. - */ -static int ipwireless_attach(struct pcmcia_device *link) -{ - struct ipw_dev *ipw; - int ret; - - ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL); - if (!ipw) - return -ENOMEM; - - ipw->link = link; - link->priv = ipw; - - ipw->hardware = ipwireless_hardware_create(); - if (!ipw->hardware) { - kfree(ipw); - return -ENOMEM; - } - /* RegisterClient will call config_ipwireless */ - - ret = config_ipwireless(ipw); - - if (ret != 0) { - ipwireless_detach(link); - return ret; - } - - return 0; -} - -/* - * This deletes a driver "instance". The device is de-registered with - * Card Services. If it has been released, all local data structures - * are freed. Otherwise, the structures will be freed when the device - * is released. - */ -static void ipwireless_detach(struct pcmcia_device *link) -{ - struct ipw_dev *ipw = link->priv; - - release_ipwireless(ipw); - - if (ipw->tty != NULL) - ipwireless_tty_free(ipw->tty); - if (ipw->network != NULL) - ipwireless_network_free(ipw->network); - if (ipw->hardware != NULL) - ipwireless_hardware_free(ipw->hardware); - kfree(ipw); -} - -static struct pcmcia_driver me = { - .owner = THIS_MODULE, - .probe = ipwireless_attach, - .remove = ipwireless_detach, - .name = IPWIRELESS_PCCARD_NAME, - .id_table = ipw_ids -}; - -/* - * Module insertion : initialisation of the module. - * Register the card with cardmgr... - */ -static int __init init_ipwireless(void) -{ - int ret; - - ret = ipwireless_tty_init(); - if (ret != 0) - return ret; - - ret = pcmcia_register_driver(&me); - if (ret != 0) - ipwireless_tty_release(); - - return ret; -} - -/* - * Module removal - */ -static void __exit exit_ipwireless(void) -{ - pcmcia_unregister_driver(&me); - ipwireless_tty_release(); -} - -module_init(init_ipwireless); -module_exit(exit_ipwireless); - -MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR); -MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h deleted file mode 100644 index f2cbb116bccb..000000000000 --- a/drivers/char/pcmcia/ipwireless/main.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#ifndef _IPWIRELESS_CS_H_ -#define _IPWIRELESS_CS_H_ - -#include -#include - -#include -#include - -#include "hardware.h" - -#define IPWIRELESS_PCCARD_NAME "ipwireless" -#define IPWIRELESS_PCMCIA_VERSION "1.1" -#define IPWIRELESS_PCMCIA_AUTHOR \ - "Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba" - -#define IPWIRELESS_TX_QUEUE_SIZE 262144 -#define IPWIRELESS_RX_QUEUE_SIZE 262144 - -#define IPWIRELESS_STATE_DEBUG - -struct ipw_hardware; -struct ipw_network; -struct ipw_tty; - -struct ipw_dev { - struct pcmcia_device *link; - int is_v2_card; - - void __iomem *attr_memory; - - void __iomem *common_memory; - - /* Reference to attribute memory, containing CIS data */ - void *attribute_memory; - - /* Hardware context */ - struct ipw_hardware *hardware; - /* Network layer context */ - struct ipw_network *network; - /* TTY device context */ - struct ipw_tty *tty; - struct work_struct work_reboot; -}; - -/* Module parametres */ -extern int ipwireless_debug; -extern int ipwireless_loopback; -extern int ipwireless_out_queue; - -#endif diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c deleted file mode 100644 index f7daeea598e4..000000000000 --- a/drivers/char/pcmcia/ipwireless/network.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "network.h" -#include "hardware.h" -#include "main.h" -#include "tty.h" - -#define MAX_ASSOCIATED_TTYS 2 - -#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) - -struct ipw_network { - /* Hardware context, used for calls to hardware layer. */ - struct ipw_hardware *hardware; - /* Context for kernel 'generic_ppp' functionality */ - struct ppp_channel *ppp_channel; - /* tty context connected with IPW console */ - struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS]; - /* True if ppp needs waking up once we're ready to xmit */ - int ppp_blocked; - /* Number of packets queued up in hardware module. */ - int outgoing_packets_queued; - /* Spinlock to avoid interrupts during shutdown */ - spinlock_t lock; - struct mutex close_lock; - - /* PPP ioctl data, not actually used anywere */ - unsigned int flags; - unsigned int rbits; - u32 xaccm[8]; - u32 raccm; - int mru; - - int shutting_down; - unsigned int ras_control_lines; - - struct work_struct work_go_online; - struct work_struct work_go_offline; -}; - -static void notify_packet_sent(void *callback_data, unsigned int packet_length) -{ - struct ipw_network *network = callback_data; - unsigned long flags; - - spin_lock_irqsave(&network->lock, flags); - network->outgoing_packets_queued--; - if (network->ppp_channel != NULL) { - if (network->ppp_blocked) { - network->ppp_blocked = 0; - spin_unlock_irqrestore(&network->lock, flags); - ppp_output_wakeup(network->ppp_channel); - if (ipwireless_debug) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME - ": ppp unblocked\n"); - } else - spin_unlock_irqrestore(&network->lock, flags); - } else - spin_unlock_irqrestore(&network->lock, flags); -} - -/* - * Called by the ppp system when it has a packet to send to the hardware. - */ -static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, - struct sk_buff *skb) -{ - struct ipw_network *network = ppp_channel->private; - unsigned long flags; - - spin_lock_irqsave(&network->lock, flags); - if (network->outgoing_packets_queued < ipwireless_out_queue) { - unsigned char *buf; - static unsigned char header[] = { - PPP_ALLSTATIONS, /* 0xff */ - PPP_UI, /* 0x03 */ - }; - int ret; - - network->outgoing_packets_queued++; - spin_unlock_irqrestore(&network->lock, flags); - - /* - * If we have the requested amount of headroom in the skb we - * were handed, then we can add the header efficiently. - */ - if (skb_headroom(skb) >= 2) { - memcpy(skb_push(skb, 2), header, 2); - ret = ipwireless_send_packet(network->hardware, - IPW_CHANNEL_RAS, skb->data, - skb->len, - notify_packet_sent, - network); - if (ret == -1) { - skb_pull(skb, 2); - return 0; - } - } else { - /* Otherwise (rarely) we do it inefficiently. */ - buf = kmalloc(skb->len + 2, GFP_ATOMIC); - if (!buf) - return 0; - memcpy(buf + 2, skb->data, skb->len); - memcpy(buf, header, 2); - ret = ipwireless_send_packet(network->hardware, - IPW_CHANNEL_RAS, buf, - skb->len + 2, - notify_packet_sent, - network); - kfree(buf); - if (ret == -1) - return 0; - } - kfree_skb(skb); - return 1; - } else { - /* - * Otherwise reject the packet, and flag that the ppp system - * needs to be unblocked once we are ready to send. - */ - network->ppp_blocked = 1; - spin_unlock_irqrestore(&network->lock, flags); - if (ipwireless_debug) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n"); - return 0; - } -} - -/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */ -static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel, - unsigned int cmd, unsigned long arg) -{ - struct ipw_network *network = ppp_channel->private; - int err, val; - u32 accm[8]; - int __user *user_arg = (int __user *) arg; - - err = -EFAULT; - switch (cmd) { - case PPPIOCGFLAGS: - val = network->flags | network->rbits; - if (put_user(val, user_arg)) - break; - err = 0; - break; - - case PPPIOCSFLAGS: - if (get_user(val, user_arg)) - break; - network->flags = val & ~SC_RCV_BITS; - network->rbits = val & SC_RCV_BITS; - err = 0; - break; - - case PPPIOCGASYNCMAP: - if (put_user(network->xaccm[0], user_arg)) - break; - err = 0; - break; - - case PPPIOCSASYNCMAP: - if (get_user(network->xaccm[0], user_arg)) - break; - err = 0; - break; - - case PPPIOCGRASYNCMAP: - if (put_user(network->raccm, user_arg)) - break; - err = 0; - break; - - case PPPIOCSRASYNCMAP: - if (get_user(network->raccm, user_arg)) - break; - err = 0; - break; - - case PPPIOCGXASYNCMAP: - if (copy_to_user((void __user *) arg, network->xaccm, - sizeof(network->xaccm))) - break; - err = 0; - break; - - case PPPIOCSXASYNCMAP: - if (copy_from_user(accm, (void __user *) arg, sizeof(accm))) - break; - accm[2] &= ~0x40000000U; /* can't escape 0x5e */ - accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ - memcpy(network->xaccm, accm, sizeof(network->xaccm)); - err = 0; - break; - - case PPPIOCGMRU: - if (put_user(network->mru, user_arg)) - break; - err = 0; - break; - - case PPPIOCSMRU: - if (get_user(val, user_arg)) - break; - if (val < PPP_MRU) - val = PPP_MRU; - network->mru = val; - err = 0; - break; - - default: - err = -ENOTTY; - } - - return err; -} - -static const struct ppp_channel_ops ipwireless_ppp_channel_ops = { - .start_xmit = ipwireless_ppp_start_xmit, - .ioctl = ipwireless_ppp_ioctl -}; - -static void do_go_online(struct work_struct *work_go_online) -{ - struct ipw_network *network = - container_of(work_go_online, struct ipw_network, - work_go_online); - unsigned long flags; - - spin_lock_irqsave(&network->lock, flags); - if (!network->ppp_channel) { - struct ppp_channel *channel; - - spin_unlock_irqrestore(&network->lock, flags); - channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); - if (!channel) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": unable to allocate PPP channel\n"); - return; - } - channel->private = network; - channel->mtu = 16384; /* Wild guess */ - channel->hdrlen = 2; - channel->ops = &ipwireless_ppp_channel_ops; - - network->flags = 0; - network->rbits = 0; - network->mru = PPP_MRU; - memset(network->xaccm, 0, sizeof(network->xaccm)); - network->xaccm[0] = ~0U; - network->xaccm[3] = 0x60000000U; - network->raccm = ~0U; - ppp_register_channel(channel); - spin_lock_irqsave(&network->lock, flags); - network->ppp_channel = channel; - } - spin_unlock_irqrestore(&network->lock, flags); -} - -static void do_go_offline(struct work_struct *work_go_offline) -{ - struct ipw_network *network = - container_of(work_go_offline, struct ipw_network, - work_go_offline); - unsigned long flags; - - mutex_lock(&network->close_lock); - spin_lock_irqsave(&network->lock, flags); - if (network->ppp_channel != NULL) { - struct ppp_channel *channel = network->ppp_channel; - - network->ppp_channel = NULL; - spin_unlock_irqrestore(&network->lock, flags); - mutex_unlock(&network->close_lock); - ppp_unregister_channel(channel); - } else { - spin_unlock_irqrestore(&network->lock, flags); - mutex_unlock(&network->close_lock); - } -} - -void ipwireless_network_notify_control_line_change(struct ipw_network *network, - unsigned int channel_idx, - unsigned int control_lines, - unsigned int changed_mask) -{ - int i; - - if (channel_idx == IPW_CHANNEL_RAS) - network->ras_control_lines = control_lines; - - for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { - struct ipw_tty *tty = - network->associated_ttys[channel_idx][i]; - - /* - * If it's associated with a tty (other than the RAS channel - * when we're online), then send the data to that tty. The RAS - * channel's data is handled above - it always goes through - * ppp_generic. - */ - if (tty) - ipwireless_tty_notify_control_line_change(tty, - channel_idx, - control_lines, - changed_mask); - } -} - -/* - * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI) - * bytes, which are required on sent packet, but not always present on received - * packets - */ -static struct sk_buff *ipw_packet_received_skb(unsigned char *data, - unsigned int length) -{ - struct sk_buff *skb; - - if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) { - length -= 2; - data += 2; - } - - skb = dev_alloc_skb(length + 4); - skb_reserve(skb, 2); - memcpy(skb_put(skb, length), data, length); - - return skb; -} - -void ipwireless_network_packet_received(struct ipw_network *network, - unsigned int channel_idx, - unsigned char *data, - unsigned int length) -{ - int i; - unsigned long flags; - - for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { - struct ipw_tty *tty = network->associated_ttys[channel_idx][i]; - - if (!tty) - continue; - - /* - * If it's associated with a tty (other than the RAS channel - * when we're online), then send the data to that tty. The RAS - * channel's data is handled above - it always goes through - * ppp_generic. - */ - if (channel_idx == IPW_CHANNEL_RAS - && (network->ras_control_lines & - IPW_CONTROL_LINE_DCD) != 0 - && ipwireless_tty_is_modem(tty)) { - /* - * If data came in on the RAS channel and this tty is - * the modem tty, and we are online, then we send it to - * the PPP layer. - */ - mutex_lock(&network->close_lock); - spin_lock_irqsave(&network->lock, flags); - if (network->ppp_channel != NULL) { - struct sk_buff *skb; - - spin_unlock_irqrestore(&network->lock, - flags); - - /* Send the data to the ppp_generic module. */ - skb = ipw_packet_received_skb(data, length); - ppp_input(network->ppp_channel, skb); - } else - spin_unlock_irqrestore(&network->lock, - flags); - mutex_unlock(&network->close_lock); - } - /* Otherwise we send it out the tty. */ - else - ipwireless_tty_received(tty, data, length); - } -} - -struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) -{ - struct ipw_network *network = - kzalloc(sizeof(struct ipw_network), GFP_ATOMIC); - - if (!network) - return NULL; - - spin_lock_init(&network->lock); - mutex_init(&network->close_lock); - - network->hardware = hw; - - INIT_WORK(&network->work_go_online, do_go_online); - INIT_WORK(&network->work_go_offline, do_go_offline); - - ipwireless_associate_network(hw, network); - - return network; -} - -void ipwireless_network_free(struct ipw_network *network) -{ - network->shutting_down = 1; - - ipwireless_ppp_close(network); - flush_work_sync(&network->work_go_online); - flush_work_sync(&network->work_go_offline); - - ipwireless_stop_interrupts(network->hardware); - ipwireless_associate_network(network->hardware, NULL); - - kfree(network); -} - -void ipwireless_associate_network_tty(struct ipw_network *network, - unsigned int channel_idx, - struct ipw_tty *tty) -{ - int i; - - for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) - if (network->associated_ttys[channel_idx][i] == NULL) { - network->associated_ttys[channel_idx][i] = tty; - break; - } -} - -void ipwireless_disassociate_network_ttys(struct ipw_network *network, - unsigned int channel_idx) -{ - int i; - - for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) - network->associated_ttys[channel_idx][i] = NULL; -} - -void ipwireless_ppp_open(struct ipw_network *network) -{ - if (ipwireless_debug) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n"); - schedule_work(&network->work_go_online); -} - -void ipwireless_ppp_close(struct ipw_network *network) -{ - /* Disconnect from the wireless network. */ - if (ipwireless_debug) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n"); - schedule_work(&network->work_go_offline); -} - -int ipwireless_ppp_channel_index(struct ipw_network *network) -{ - int ret = -1; - unsigned long flags; - - spin_lock_irqsave(&network->lock, flags); - if (network->ppp_channel != NULL) - ret = ppp_channel_index(network->ppp_channel); - spin_unlock_irqrestore(&network->lock, flags); - - return ret; -} - -int ipwireless_ppp_unit_number(struct ipw_network *network) -{ - int ret = -1; - unsigned long flags; - - spin_lock_irqsave(&network->lock, flags); - if (network->ppp_channel != NULL) - ret = ppp_unit_number(network->ppp_channel); - spin_unlock_irqrestore(&network->lock, flags); - - return ret; -} - -int ipwireless_ppp_mru(const struct ipw_network *network) -{ - return network->mru; -} diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h deleted file mode 100644 index 561f765b3334..000000000000 --- a/drivers/char/pcmcia/ipwireless/network.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#ifndef _IPWIRELESS_CS_NETWORK_H_ -#define _IPWIRELESS_CS_NETWORK_H_ - -#include - -struct ipw_network; -struct ipw_tty; -struct ipw_hardware; - -/* Definitions of the different channels on the PCMCIA UE */ -#define IPW_CHANNEL_RAS 0 -#define IPW_CHANNEL_DIALLER 1 -#define IPW_CHANNEL_CONSOLE 2 -#define NO_OF_IPW_CHANNELS 5 - -void ipwireless_network_notify_control_line_change(struct ipw_network *net, - unsigned int channel_idx, unsigned int control_lines, - unsigned int control_mask); -void ipwireless_network_packet_received(struct ipw_network *net, - unsigned int channel_idx, unsigned char *data, - unsigned int length); -struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw); -void ipwireless_network_free(struct ipw_network *net); -void ipwireless_associate_network_tty(struct ipw_network *net, - unsigned int channel_idx, struct ipw_tty *tty); -void ipwireless_disassociate_network_ttys(struct ipw_network *net, - unsigned int channel_idx); - -void ipwireless_ppp_open(struct ipw_network *net); - -void ipwireless_ppp_close(struct ipw_network *net); -int ipwireless_ppp_channel_index(struct ipw_network *net); -int ipwireless_ppp_unit_number(struct ipw_network *net); -int ipwireless_ppp_mru(const struct ipw_network *net); - -#endif diff --git a/drivers/char/pcmcia/ipwireless/setup_protocol.h b/drivers/char/pcmcia/ipwireless/setup_protocol.h deleted file mode 100644 index 9d6bcc77c73c..000000000000 --- a/drivers/char/pcmcia/ipwireless/setup_protocol.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_ -#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_ - -/* Version of the setup protocol and transport protocols */ -#define TL_SETUP_VERSION 1 - -#define TL_SETUP_VERSION_QRY_TMO 1000 -#define TL_SETUP_MAX_VERSION_QRY 30 - -/* Message numbers 0-9 are obsoleted and must not be reused! */ -#define TL_SETUP_SIGNO_GET_VERSION_QRY 10 -#define TL_SETUP_SIGNO_GET_VERSION_RSP 11 -#define TL_SETUP_SIGNO_CONFIG_MSG 12 -#define TL_SETUP_SIGNO_CONFIG_DONE_MSG 13 -#define TL_SETUP_SIGNO_OPEN_MSG 14 -#define TL_SETUP_SIGNO_CLOSE_MSG 15 - -#define TL_SETUP_SIGNO_INFO_MSG 20 -#define TL_SETUP_SIGNO_INFO_MSG_ACK 21 - -#define TL_SETUP_SIGNO_REBOOT_MSG 22 -#define TL_SETUP_SIGNO_REBOOT_MSG_ACK 23 - -/* Synchronous start-messages */ -struct tl_setup_get_version_qry { - unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_QRY */ -} __attribute__ ((__packed__)); - -struct tl_setup_get_version_rsp { - unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_RSP */ - unsigned char version; /* TL_SETUP_VERSION */ -} __attribute__ ((__packed__)); - -struct tl_setup_config_msg { - unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_MSG */ - unsigned char port_no; - unsigned char prio_data; - unsigned char prio_ctrl; -} __attribute__ ((__packed__)); - -struct tl_setup_config_done_msg { - unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */ -} __attribute__ ((__packed__)); - -/* Asyncronous messages */ -struct tl_setup_open_msg { - unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */ - unsigned char port_no; -} __attribute__ ((__packed__)); - -struct tl_setup_close_msg { - unsigned char sig_no; /* TL_SETUP_SIGNO_CLOSE_MSG */ - unsigned char port_no; -} __attribute__ ((__packed__)); - -/* Driver type - for use in tl_setup_info_msg.driver_type */ -#define COMM_DRIVER 0 -#define NDISWAN_DRIVER 1 -#define NDISWAN_DRIVER_MAJOR_VERSION 2 -#define NDISWAN_DRIVER_MINOR_VERSION 0 - -/* - * It should not matter when this message comes over as we just store the - * results and send the ACK. - */ -struct tl_setup_info_msg { - unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG */ - unsigned char driver_type; - unsigned char major_version; - unsigned char minor_version; -} __attribute__ ((__packed__)); - -struct tl_setup_info_msgAck { - unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG_ACK */ -} __attribute__ ((__packed__)); - -struct TlSetupRebootMsgAck { - unsigned char sig_no; /* TL_SETUP_SIGNO_REBOOT_MSG_ACK */ -} __attribute__ ((__packed__)); - -/* Define a union of all the msgs that the driver can receive from the card.*/ -union ipw_setup_rx_msg { - unsigned char sig_no; - struct tl_setup_get_version_rsp version_rsp_msg; - struct tl_setup_open_msg open_msg; - struct tl_setup_close_msg close_msg; - struct tl_setup_info_msg InfoMsg; - struct tl_setup_info_msgAck info_msg_ack; -} __attribute__ ((__packed__)); - -#endif /* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */ diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c deleted file mode 100644 index ef92869502a7..000000000000 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tty.h" -#include "network.h" -#include "hardware.h" -#include "main.h" - -#define IPWIRELESS_PCMCIA_START (0) -#define IPWIRELESS_PCMCIA_MINORS (24) -#define IPWIRELESS_PCMCIA_MINOR_RANGE (8) - -#define TTYTYPE_MODEM (0) -#define TTYTYPE_MONITOR (1) -#define TTYTYPE_RAS_RAW (2) - -struct ipw_tty { - int index; - struct ipw_hardware *hardware; - unsigned int channel_idx; - unsigned int secondary_channel_idx; - int tty_type; - struct ipw_network *network; - struct tty_struct *linux_tty; - int open_count; - unsigned int control_lines; - struct mutex ipw_tty_mutex; - int tx_bytes_queued; - int closing; -}; - -static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS]; - -static struct tty_driver *ipw_tty_driver; - -static char *tty_type_name(int tty_type) -{ - static char *channel_names[] = { - "modem", - "monitor", - "RAS-raw" - }; - - return channel_names[tty_type]; -} - -static void report_registering(struct ipw_tty *tty) -{ - char *iftype = tty_type_name(tty->tty_type); - - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": registering %s device ttyIPWp%d\n", iftype, tty->index); -} - -static void report_deregistering(struct ipw_tty *tty) -{ - char *iftype = tty_type_name(tty->tty_type); - - printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": deregistering %s device ttyIPWp%d\n", iftype, - tty->index); -} - -static struct ipw_tty *get_tty(int minor) -{ - if (minor < ipw_tty_driver->minor_start - || minor >= ipw_tty_driver->minor_start + - IPWIRELESS_PCMCIA_MINORS) - return NULL; - else { - int minor_offset = minor - ipw_tty_driver->minor_start; - - /* - * The 'ras_raw' channel is only available when 'loopback' mode - * is enabled. - * Number of minor starts with 16 (_RANGE * _RAS_RAW). - */ - if (!ipwireless_loopback && - minor_offset >= - IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW) - return NULL; - - return ttys[minor_offset]; - } -} - -static int ipw_open(struct tty_struct *linux_tty, struct file *filp) -{ - int minor = linux_tty->index; - struct ipw_tty *tty = get_tty(minor); - - if (!tty) - return -ENODEV; - - mutex_lock(&tty->ipw_tty_mutex); - - if (tty->closing) { - mutex_unlock(&tty->ipw_tty_mutex); - return -ENODEV; - } - if (tty->open_count == 0) - tty->tx_bytes_queued = 0; - - tty->open_count++; - - tty->linux_tty = linux_tty; - linux_tty->driver_data = tty; - linux_tty->low_latency = 1; - - if (tty->tty_type == TTYTYPE_MODEM) - ipwireless_ppp_open(tty->network); - - mutex_unlock(&tty->ipw_tty_mutex); - - return 0; -} - -static void do_ipw_close(struct ipw_tty *tty) -{ - tty->open_count--; - - if (tty->open_count == 0) { - struct tty_struct *linux_tty = tty->linux_tty; - - if (linux_tty != NULL) { - tty->linux_tty = NULL; - linux_tty->driver_data = NULL; - - if (tty->tty_type == TTYTYPE_MODEM) - ipwireless_ppp_close(tty->network); - } - } -} - -static void ipw_hangup(struct tty_struct *linux_tty) -{ - struct ipw_tty *tty = linux_tty->driver_data; - - if (!tty) - return; - - mutex_lock(&tty->ipw_tty_mutex); - if (tty->open_count == 0) { - mutex_unlock(&tty->ipw_tty_mutex); - return; - } - - do_ipw_close(tty); - - mutex_unlock(&tty->ipw_tty_mutex); -} - -static void ipw_close(struct tty_struct *linux_tty, struct file *filp) -{ - ipw_hangup(linux_tty); -} - -/* Take data received from hardware, and send it out the tty */ -void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, - unsigned int length) -{ - struct tty_struct *linux_tty; - int work = 0; - - mutex_lock(&tty->ipw_tty_mutex); - linux_tty = tty->linux_tty; - if (linux_tty == NULL) { - mutex_unlock(&tty->ipw_tty_mutex); - return; - } - - if (!tty->open_count) { - mutex_unlock(&tty->ipw_tty_mutex); - return; - } - mutex_unlock(&tty->ipw_tty_mutex); - - work = tty_insert_flip_string(linux_tty, data, length); - - if (work != length) - printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME - ": %d chars not inserted to flip buffer!\n", - length - work); - - /* - * This may sleep if ->low_latency is set - */ - if (work) - tty_flip_buffer_push(linux_tty); -} - -static void ipw_write_packet_sent_callback(void *callback_data, - unsigned int packet_length) -{ - struct ipw_tty *tty = callback_data; - - /* - * Packet has been sent, so we subtract the number of bytes from our - * tally of outstanding TX bytes. - */ - tty->tx_bytes_queued -= packet_length; -} - -static int ipw_write(struct tty_struct *linux_tty, - const unsigned char *buf, int count) -{ - struct ipw_tty *tty = linux_tty->driver_data; - int room, ret; - - if (!tty) - return -ENODEV; - - mutex_lock(&tty->ipw_tty_mutex); - if (!tty->open_count) { - mutex_unlock(&tty->ipw_tty_mutex); - return -EINVAL; - } - - room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; - if (room < 0) - room = 0; - /* Don't allow caller to write any more than we have room for */ - if (count > room) - count = room; - - if (count == 0) { - mutex_unlock(&tty->ipw_tty_mutex); - return 0; - } - - ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, - buf, count, - ipw_write_packet_sent_callback, tty); - if (ret == -1) { - mutex_unlock(&tty->ipw_tty_mutex); - return 0; - } - - tty->tx_bytes_queued += count; - mutex_unlock(&tty->ipw_tty_mutex); - - return count; -} - -static int ipw_write_room(struct tty_struct *linux_tty) -{ - struct ipw_tty *tty = linux_tty->driver_data; - int room; - - /* FIXME: Exactly how is the tty object locked here .. */ - if (!tty) - return -ENODEV; - - if (!tty->open_count) - return -EINVAL; - - room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; - if (room < 0) - room = 0; - - return room; -} - -static int ipwireless_get_serial_info(struct ipw_tty *tty, - struct serial_struct __user *retinfo) -{ - struct serial_struct tmp; - - if (!retinfo) - return (-EFAULT); - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = PORT_UNKNOWN; - tmp.line = tty->index; - tmp.port = 0; - tmp.irq = 0; - tmp.flags = 0; - tmp.baud_base = 115200; - tmp.close_delay = 0; - tmp.closing_wait = 0; - tmp.custom_divisor = 0; - tmp.hub6 = 0; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -static int ipw_chars_in_buffer(struct tty_struct *linux_tty) -{ - struct ipw_tty *tty = linux_tty->driver_data; - - if (!tty) - return 0; - - if (!tty->open_count) - return 0; - - return tty->tx_bytes_queued; -} - -static int get_control_lines(struct ipw_tty *tty) -{ - unsigned int my = tty->control_lines; - unsigned int out = 0; - - if (my & IPW_CONTROL_LINE_RTS) - out |= TIOCM_RTS; - if (my & IPW_CONTROL_LINE_DTR) - out |= TIOCM_DTR; - if (my & IPW_CONTROL_LINE_CTS) - out |= TIOCM_CTS; - if (my & IPW_CONTROL_LINE_DSR) - out |= TIOCM_DSR; - if (my & IPW_CONTROL_LINE_DCD) - out |= TIOCM_CD; - - return out; -} - -static int set_control_lines(struct ipw_tty *tty, unsigned int set, - unsigned int clear) -{ - int ret; - - if (set & TIOCM_RTS) { - ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1); - if (ret) - return ret; - if (tty->secondary_channel_idx != -1) { - ret = ipwireless_set_RTS(tty->hardware, - tty->secondary_channel_idx, 1); - if (ret) - return ret; - } - } - if (set & TIOCM_DTR) { - ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1); - if (ret) - return ret; - if (tty->secondary_channel_idx != -1) { - ret = ipwireless_set_DTR(tty->hardware, - tty->secondary_channel_idx, 1); - if (ret) - return ret; - } - } - if (clear & TIOCM_RTS) { - ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0); - if (tty->secondary_channel_idx != -1) { - ret = ipwireless_set_RTS(tty->hardware, - tty->secondary_channel_idx, 0); - if (ret) - return ret; - } - } - if (clear & TIOCM_DTR) { - ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0); - if (tty->secondary_channel_idx != -1) { - ret = ipwireless_set_DTR(tty->hardware, - tty->secondary_channel_idx, 0); - if (ret) - return ret; - } - } - return 0; -} - -static int ipw_tiocmget(struct tty_struct *linux_tty) -{ - struct ipw_tty *tty = linux_tty->driver_data; - /* FIXME: Exactly how is the tty object locked here .. */ - - if (!tty) - return -ENODEV; - - if (!tty->open_count) - return -EINVAL; - - return get_control_lines(tty); -} - -static int -ipw_tiocmset(struct tty_struct *linux_tty, - unsigned int set, unsigned int clear) -{ - struct ipw_tty *tty = linux_tty->driver_data; - /* FIXME: Exactly how is the tty object locked here .. */ - - if (!tty) - return -ENODEV; - - if (!tty->open_count) - return -EINVAL; - - return set_control_lines(tty, set, clear); -} - -static int ipw_ioctl(struct tty_struct *linux_tty, - unsigned int cmd, unsigned long arg) -{ - struct ipw_tty *tty = linux_tty->driver_data; - - if (!tty) - return -ENODEV; - - if (!tty->open_count) - return -EINVAL; - - /* FIXME: Exactly how is the tty object locked here .. */ - - switch (cmd) { - case TIOCGSERIAL: - return ipwireless_get_serial_info(tty, (void __user *) arg); - - case TIOCSSERIAL: - return 0; /* Keeps the PCMCIA scripts happy. */ - } - - if (tty->tty_type == TTYTYPE_MODEM) { - switch (cmd) { - case PPPIOCGCHAN: - { - int chan = ipwireless_ppp_channel_index( - tty->network); - - if (chan < 0) - return -ENODEV; - if (put_user(chan, (int __user *) arg)) - return -EFAULT; - } - return 0; - - case PPPIOCGUNIT: - { - int unit = ipwireless_ppp_unit_number( - tty->network); - - if (unit < 0) - return -ENODEV; - if (put_user(unit, (int __user *) arg)) - return -EFAULT; - } - return 0; - - case FIONREAD: - { - int val = 0; - - if (put_user(val, (int __user *) arg)) - return -EFAULT; - } - return 0; - case TCFLSH: - return tty_perform_flush(linux_tty, arg); - } - } - return -ENOIOCTLCMD; -} - -static int add_tty(int j, - struct ipw_hardware *hardware, - struct ipw_network *network, int channel_idx, - int secondary_channel_idx, int tty_type) -{ - ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL); - if (!ttys[j]) - return -ENOMEM; - ttys[j]->index = j; - ttys[j]->hardware = hardware; - ttys[j]->channel_idx = channel_idx; - ttys[j]->secondary_channel_idx = secondary_channel_idx; - ttys[j]->network = network; - ttys[j]->tty_type = tty_type; - mutex_init(&ttys[j]->ipw_tty_mutex); - - tty_register_device(ipw_tty_driver, j, NULL); - ipwireless_associate_network_tty(network, channel_idx, ttys[j]); - - if (secondary_channel_idx != -1) - ipwireless_associate_network_tty(network, - secondary_channel_idx, - ttys[j]); - if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j]) - report_registering(ttys[j]); - return 0; -} - -struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, - struct ipw_network *network) -{ - int i, j; - - for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) { - int allfree = 1; - - for (j = i; j < IPWIRELESS_PCMCIA_MINORS; - j += IPWIRELESS_PCMCIA_MINOR_RANGE) - if (ttys[j] != NULL) { - allfree = 0; - break; - } - - if (allfree) { - j = i; - - if (add_tty(j, hardware, network, - IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS, - TTYTYPE_MODEM)) - return NULL; - - j += IPWIRELESS_PCMCIA_MINOR_RANGE; - if (add_tty(j, hardware, network, - IPW_CHANNEL_DIALLER, -1, - TTYTYPE_MONITOR)) - return NULL; - - j += IPWIRELESS_PCMCIA_MINOR_RANGE; - if (add_tty(j, hardware, network, - IPW_CHANNEL_RAS, -1, - TTYTYPE_RAS_RAW)) - return NULL; - - return ttys[i]; - } - } - return NULL; -} - -/* - * Must be called before ipwireless_network_free(). - */ -void ipwireless_tty_free(struct ipw_tty *tty) -{ - int j; - struct ipw_network *network = ttys[tty->index]->network; - - for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS; - j += IPWIRELESS_PCMCIA_MINOR_RANGE) { - struct ipw_tty *ttyj = ttys[j]; - - if (ttyj) { - mutex_lock(&ttyj->ipw_tty_mutex); - if (get_tty(j + ipw_tty_driver->minor_start) == ttyj) - report_deregistering(ttyj); - ttyj->closing = 1; - if (ttyj->linux_tty != NULL) { - mutex_unlock(&ttyj->ipw_tty_mutex); - tty_hangup(ttyj->linux_tty); - /* Wait till the tty_hangup has completed */ - flush_work_sync(&ttyj->linux_tty->hangup_work); - /* FIXME: Exactly how is the tty object locked here - against a parallel ioctl etc */ - mutex_lock(&ttyj->ipw_tty_mutex); - } - while (ttyj->open_count) - do_ipw_close(ttyj); - ipwireless_disassociate_network_ttys(network, - ttyj->channel_idx); - tty_unregister_device(ipw_tty_driver, j); - ttys[j] = NULL; - mutex_unlock(&ttyj->ipw_tty_mutex); - kfree(ttyj); - } - } -} - -static const struct tty_operations tty_ops = { - .open = ipw_open, - .close = ipw_close, - .hangup = ipw_hangup, - .write = ipw_write, - .write_room = ipw_write_room, - .ioctl = ipw_ioctl, - .chars_in_buffer = ipw_chars_in_buffer, - .tiocmget = ipw_tiocmget, - .tiocmset = ipw_tiocmset, -}; - -int ipwireless_tty_init(void) -{ - int result; - - ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS); - if (!ipw_tty_driver) - return -ENOMEM; - - ipw_tty_driver->owner = THIS_MODULE; - ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME; - ipw_tty_driver->name = "ttyIPWp"; - ipw_tty_driver->major = 0; - ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START; - ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL; - ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - ipw_tty_driver->init_termios = tty_std_termios; - ipw_tty_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - ipw_tty_driver->init_termios.c_ispeed = 9600; - ipw_tty_driver->init_termios.c_ospeed = 9600; - tty_set_operations(ipw_tty_driver, &tty_ops); - result = tty_register_driver(ipw_tty_driver); - if (result) { - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": failed to register tty driver\n"); - put_tty_driver(ipw_tty_driver); - return result; - } - - return 0; -} - -void ipwireless_tty_release(void) -{ - int ret; - - ret = tty_unregister_driver(ipw_tty_driver); - put_tty_driver(ipw_tty_driver); - if (ret != 0) - printk(KERN_ERR IPWIRELESS_PCCARD_NAME - ": tty_unregister_driver failed with code %d\n", ret); -} - -int ipwireless_tty_is_modem(struct ipw_tty *tty) -{ - return tty->tty_type == TTYTYPE_MODEM; -} - -void -ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, - unsigned int channel_idx, - unsigned int control_lines, - unsigned int changed_mask) -{ - unsigned int old_control_lines = tty->control_lines; - - tty->control_lines = (tty->control_lines & ~changed_mask) - | (control_lines & changed_mask); - - /* - * If DCD is de-asserted, we close the tty so pppd can tell that we - * have gone offline. - */ - if ((old_control_lines & IPW_CONTROL_LINE_DCD) - && !(tty->control_lines & IPW_CONTROL_LINE_DCD) - && tty->linux_tty) { - tty_hangup(tty->linux_tty); - } -} - diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h deleted file mode 100644 index 747b2d637860..000000000000 --- a/drivers/char/pcmcia/ipwireless/tty.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * IPWireless 3G PCMCIA Network Driver - * - * Original code - * by Stephen Blackheath , - * Ben Martel - * - * Copyrighted as follows: - * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) - * - * Various driver changes and rewrites, port to new kernels - * Copyright (C) 2006-2007 Jiri Kosina - * - * Misc code cleanups and updates - * Copyright (C) 2007 David Sterba - */ - -#ifndef _IPWIRELESS_CS_TTY_H_ -#define _IPWIRELESS_CS_TTY_H_ - -#include -#include - -#include -#include - -struct ipw_tty; -struct ipw_network; -struct ipw_hardware; - -int ipwireless_tty_init(void); -void ipwireless_tty_release(void); - -struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw, - struct ipw_network *net); -void ipwireless_tty_free(struct ipw_tty *tty); -void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, - unsigned int length); -int ipwireless_tty_is_modem(struct ipw_tty *tty); -void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, - unsigned int channel_idx, - unsigned int control_lines, - unsigned int changed_mask); - -#endif diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index e549da348a04..690522fcb338 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -24,3 +24,5 @@ obj-$(CONFIG_ROCKETPORT) += rocket.o obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o obj-$(CONFIG_SYNCLINK) += synclink.o + +obj-y += ipwireless/ diff --git a/drivers/tty/ipwireless/Makefile b/drivers/tty/ipwireless/Makefile new file mode 100644 index 000000000000..db80873d7f20 --- /dev/null +++ b/drivers/tty/ipwireless/Makefile @@ -0,0 +1,10 @@ +# +# drivers/char/pcmcia/ipwireless/Makefile +# +# Makefile for the IPWireless driver +# + +obj-$(CONFIG_IPWIRELESS) += ipwireless.o + +ipwireless-y := hardware.o main.o network.o tty.o + diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c new file mode 100644 index 000000000000..0aeb5a38d296 --- /dev/null +++ b/drivers/tty/ipwireless/hardware.c @@ -0,0 +1,1764 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#include +#include +#include +#include +#include +#include + +#include "hardware.h" +#include "setup_protocol.h" +#include "network.h" +#include "main.h" + +static void ipw_send_setup_packet(struct ipw_hardware *hw); +static void handle_received_SETUP_packet(struct ipw_hardware *ipw, + unsigned int address, + const unsigned char *data, int len, + int is_last); +static void ipwireless_setup_timer(unsigned long data); +static void handle_received_CTRL_packet(struct ipw_hardware *hw, + unsigned int channel_idx, const unsigned char *data, int len); + +/*#define TIMING_DIAGNOSTICS*/ + +#ifdef TIMING_DIAGNOSTICS + +static struct timing_stats { + unsigned long last_report_time; + unsigned long read_time; + unsigned long write_time; + unsigned long read_bytes; + unsigned long write_bytes; + unsigned long start_time; +}; + +static void start_timing(void) +{ + timing_stats.start_time = jiffies; +} + +static void end_read_timing(unsigned length) +{ + timing_stats.read_time += (jiffies - start_time); + timing_stats.read_bytes += length + 2; + report_timing(); +} + +static void end_write_timing(unsigned length) +{ + timing_stats.write_time += (jiffies - start_time); + timing_stats.write_bytes += length + 2; + report_timing(); +} + +static void report_timing(void) +{ + unsigned long since = jiffies - timing_stats.last_report_time; + + /* If it's been more than one second... */ + if (since >= HZ) { + int first = (timing_stats.last_report_time == 0); + + timing_stats.last_report_time = jiffies; + if (!first) + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n", + jiffies_to_usecs(since), + timing_stats.read_bytes, + jiffies_to_usecs(timing_stats.read_time), + timing_stats.write_bytes, + jiffies_to_usecs(timing_stats.write_time)); + + timing_stats.read_time = 0; + timing_stats.write_time = 0; + timing_stats.read_bytes = 0; + timing_stats.write_bytes = 0; + } +} +#else +static void start_timing(void) { } +static void end_read_timing(unsigned length) { } +static void end_write_timing(unsigned length) { } +#endif + +/* Imported IPW definitions */ + +#define LL_MTU_V1 318 +#define LL_MTU_V2 250 +#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2) + +#define PRIO_DATA 2 +#define PRIO_CTRL 1 +#define PRIO_SETUP 0 + +/* Addresses */ +#define ADDR_SETUP_PROT 0 + +/* Protocol ids */ +enum { + /* Identifier for the Com Data protocol */ + TL_PROTOCOLID_COM_DATA = 0, + + /* Identifier for the Com Control protocol */ + TL_PROTOCOLID_COM_CTRL = 1, + + /* Identifier for the Setup protocol */ + TL_PROTOCOLID_SETUP = 2 +}; + +/* Number of bytes in NL packet header (cannot do + * sizeof(nl_packet_header) since it's a bitfield) */ +#define NL_FIRST_PACKET_HEADER_SIZE 3 + +/* Number of bytes in NL packet header (cannot do + * sizeof(nl_packet_header) since it's a bitfield) */ +#define NL_FOLLOWING_PACKET_HEADER_SIZE 1 + +struct nl_first_packet_header { + unsigned char protocol:3; + unsigned char address:3; + unsigned char packet_rank:2; + unsigned char length_lsb; + unsigned char length_msb; +}; + +struct nl_packet_header { + unsigned char protocol:3; + unsigned char address:3; + unsigned char packet_rank:2; +}; + +/* Value of 'packet_rank' above */ +#define NL_INTERMEDIATE_PACKET 0x0 +#define NL_LAST_PACKET 0x1 +#define NL_FIRST_PACKET 0x2 + +union nl_packet { + /* Network packet header of the first packet (a special case) */ + struct nl_first_packet_header hdr_first; + /* Network packet header of the following packets (if any) */ + struct nl_packet_header hdr; + /* Complete network packet (header + data) */ + unsigned char rawpkt[LL_MTU_MAX]; +} __attribute__ ((__packed__)); + +#define HW_VERSION_UNKNOWN -1 +#define HW_VERSION_1 1 +#define HW_VERSION_2 2 + +/* IPW I/O ports */ +#define IOIER 0x00 /* Interrupt Enable Register */ +#define IOIR 0x02 /* Interrupt Source/ACK register */ +#define IODCR 0x04 /* Data Control Register */ +#define IODRR 0x06 /* Data Read Register */ +#define IODWR 0x08 /* Data Write Register */ +#define IOESR 0x0A /* Embedded Driver Status Register */ +#define IORXR 0x0C /* Rx Fifo Register (Host to Embedded) */ +#define IOTXR 0x0E /* Tx Fifo Register (Embedded to Host) */ + +/* I/O ports and bit definitions for version 1 of the hardware */ + +/* IER bits*/ +#define IER_RXENABLED 0x1 +#define IER_TXENABLED 0x2 + +/* ISR bits */ +#define IR_RXINTR 0x1 +#define IR_TXINTR 0x2 + +/* DCR bits */ +#define DCR_RXDONE 0x1 +#define DCR_TXDONE 0x2 +#define DCR_RXRESET 0x4 +#define DCR_TXRESET 0x8 + +/* I/O ports and bit definitions for version 2 of the hardware */ + +struct MEMCCR { + unsigned short reg_config_option; /* PCCOR: Configuration Option Register */ + unsigned short reg_config_and_status; /* PCCSR: Configuration and Status Register */ + unsigned short reg_pin_replacement; /* PCPRR: Pin Replacemant Register */ + unsigned short reg_socket_and_copy; /* PCSCR: Socket and Copy Register */ + unsigned short reg_ext_status; /* PCESR: Extendend Status Register */ + unsigned short reg_io_base; /* PCIOB: I/O Base Register */ +}; + +struct MEMINFREG { + unsigned short memreg_tx_old; /* TX Register (R/W) */ + unsigned short pad1; + unsigned short memreg_rx_done; /* RXDone Register (R/W) */ + unsigned short pad2; + unsigned short memreg_rx; /* RX Register (R/W) */ + unsigned short pad3; + unsigned short memreg_pc_interrupt_ack; /* PC intr Ack Register (W) */ + unsigned short pad4; + unsigned long memreg_card_present;/* Mask for Host to check (R) for + * CARD_PRESENT_VALUE */ + unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ +}; + +#define CARD_PRESENT_VALUE (0xBEEFCAFEUL) + +#define MEMTX_TX 0x0001 +#define MEMRX_RX 0x0001 +#define MEMRX_RX_DONE 0x0001 +#define MEMRX_PCINTACKK 0x0001 + +#define NL_NUM_OF_PRIORITIES 3 +#define NL_NUM_OF_PROTOCOLS 3 +#define NL_NUM_OF_ADDRESSES NO_OF_IPW_CHANNELS + +struct ipw_hardware { + unsigned int base_port; + short hw_version; + unsigned short ll_mtu; + spinlock_t lock; + + int initializing; + int init_loops; + struct timer_list setup_timer; + + /* Flag if hw is ready to send next packet */ + int tx_ready; + /* Count of pending packets to be sent */ + int tx_queued; + struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; + + int rx_bytes_queued; + struct list_head rx_queue; + /* Pool of rx_packet structures that are not currently used. */ + struct list_head rx_pool; + int rx_pool_size; + /* True if reception of data is blocked while userspace processes it. */ + int blocking_rx; + /* True if there is RX data ready on the hardware. */ + int rx_ready; + unsigned short last_memtx_serial; + /* + * Newer versions of the V2 card firmware send serial numbers in the + * MemTX register. 'serial_number_detected' is set true when we detect + * a non-zero serial number (indicating the new firmware). Thereafter, + * the driver can safely ignore the Timer Recovery re-sends to avoid + * out-of-sync problems. + */ + int serial_number_detected; + struct work_struct work_rx; + + /* True if we are to send the set-up data to the hardware. */ + int to_setup; + + /* Card has been removed */ + int removed; + /* Saved irq value when we disable the interrupt. */ + int irq; + /* True if this driver is shutting down. */ + int shutting_down; + /* Modem control lines */ + unsigned int control_lines[NL_NUM_OF_ADDRESSES]; + struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES]; + + struct tasklet_struct tasklet; + + /* The handle for the network layer, for the sending of events to it. */ + struct ipw_network *network; + struct MEMINFREG __iomem *memory_info_regs; + struct MEMCCR __iomem *memregs_CCR; + void (*reboot_callback) (void *data); + void *reboot_callback_data; + + unsigned short __iomem *memreg_tx; +}; + +/* + * Packet info structure for tx packets. + * Note: not all the fields defined here are required for all protocols + */ +struct ipw_tx_packet { + struct list_head queue; + /* channel idx + 1 */ + unsigned char dest_addr; + /* SETUP, CTRL or DATA */ + unsigned char protocol; + /* Length of data block, which starts at the end of this structure */ + unsigned short length; + /* Sending state */ + /* Offset of where we've sent up to so far */ + unsigned long offset; + /* Count of packet fragments, starting at 0 */ + int fragment_count; + + /* Called after packet is sent and before is freed */ + void (*packet_callback) (void *cb_data, unsigned int packet_length); + void *callback_data; +}; + +/* Signals from DTE */ +#define COMCTRL_RTS 0 +#define COMCTRL_DTR 1 + +/* Signals from DCE */ +#define COMCTRL_CTS 2 +#define COMCTRL_DCD 3 +#define COMCTRL_DSR 4 +#define COMCTRL_RI 5 + +struct ipw_control_packet_body { + /* DTE signal or DCE signal */ + unsigned char sig_no; + /* 0: set signal, 1: clear signal */ + unsigned char value; +} __attribute__ ((__packed__)); + +struct ipw_control_packet { + struct ipw_tx_packet header; + struct ipw_control_packet_body body; +}; + +struct ipw_rx_packet { + struct list_head queue; + unsigned int capacity; + unsigned int length; + unsigned int protocol; + unsigned int channel_idx; +}; + +static char *data_type(const unsigned char *buf, unsigned length) +{ + struct nl_packet_header *hdr = (struct nl_packet_header *) buf; + + if (length == 0) + return " "; + + if (hdr->packet_rank & NL_FIRST_PACKET) { + switch (hdr->protocol) { + case TL_PROTOCOLID_COM_DATA: return "DATA "; + case TL_PROTOCOLID_COM_CTRL: return "CTRL "; + case TL_PROTOCOLID_SETUP: return "SETUP"; + default: return "???? "; + } + } else + return " "; +} + +#define DUMP_MAX_BYTES 64 + +static void dump_data_bytes(const char *type, const unsigned char *data, + unsigned length) +{ + char prefix[56]; + + sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ", + type, data_type(data, length)); + print_hex_dump_bytes(prefix, 0, (void *)data, + length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); +} + +static void swap_packet_bitfield_to_le(unsigned char *data) +{ +#ifdef __BIG_ENDIAN_BITFIELD + unsigned char tmp = *data, ret = 0; + + /* + * transform bits from aa.bbb.ccc to ccc.bbb.aa + */ + ret |= tmp & 0xc0 >> 6; + ret |= tmp & 0x38 >> 1; + ret |= tmp & 0x07 << 5; + *data = ret & 0xff; +#endif +} + +static void swap_packet_bitfield_from_le(unsigned char *data) +{ +#ifdef __BIG_ENDIAN_BITFIELD + unsigned char tmp = *data, ret = 0; + + /* + * transform bits from ccc.bbb.aa to aa.bbb.ccc + */ + ret |= tmp & 0xe0 >> 5; + ret |= tmp & 0x1c << 1; + ret |= tmp & 0x03 << 6; + *data = ret & 0xff; +#endif +} + +static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data, + unsigned length) +{ + unsigned i; + unsigned long flags; + + start_timing(); + BUG_ON(length > hw->ll_mtu); + + if (ipwireless_debug) + dump_data_bytes("send", data, length); + + spin_lock_irqsave(&hw->lock, flags); + + hw->tx_ready = 0; + swap_packet_bitfield_to_le(data); + + if (hw->hw_version == HW_VERSION_1) { + outw((unsigned short) length, hw->base_port + IODWR); + + for (i = 0; i < length; i += 2) { + unsigned short d = data[i]; + __le16 raw_data; + + if (i + 1 < length) + d |= data[i + 1] << 8; + raw_data = cpu_to_le16(d); + outw(raw_data, hw->base_port + IODWR); + } + + outw(DCR_TXDONE, hw->base_port + IODCR); + } else if (hw->hw_version == HW_VERSION_2) { + outw((unsigned short) length, hw->base_port); + + for (i = 0; i < length; i += 2) { + unsigned short d = data[i]; + __le16 raw_data; + + if (i + 1 < length) + d |= data[i + 1] << 8; + raw_data = cpu_to_le16(d); + outw(raw_data, hw->base_port); + } + while ((i & 3) != 2) { + outw((unsigned short) 0xDEAD, hw->base_port); + i += 2; + } + writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); + } + + spin_unlock_irqrestore(&hw->lock, flags); + + end_write_timing(length); +} + +static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) +{ + unsigned short fragment_data_len; + unsigned short data_left = packet->length - packet->offset; + unsigned short header_size; + union nl_packet pkt; + + header_size = + (packet->fragment_count == 0) + ? NL_FIRST_PACKET_HEADER_SIZE + : NL_FOLLOWING_PACKET_HEADER_SIZE; + fragment_data_len = hw->ll_mtu - header_size; + if (data_left < fragment_data_len) + fragment_data_len = data_left; + + /* + * hdr_first is now in machine bitfield order, which will be swapped + * to le just before it goes to hw + */ + pkt.hdr_first.protocol = packet->protocol; + pkt.hdr_first.address = packet->dest_addr; + pkt.hdr_first.packet_rank = 0; + + /* First packet? */ + if (packet->fragment_count == 0) { + pkt.hdr_first.packet_rank |= NL_FIRST_PACKET; + pkt.hdr_first.length_lsb = (unsigned char) packet->length; + pkt.hdr_first.length_msb = + (unsigned char) (packet->length >> 8); + } + + memcpy(pkt.rawpkt + header_size, + ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) + + packet->offset, fragment_data_len); + packet->offset += fragment_data_len; + packet->fragment_count++; + + /* Last packet? (May also be first packet.) */ + if (packet->offset == packet->length) + pkt.hdr_first.packet_rank |= NL_LAST_PACKET; + do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len); + + /* If this packet has unsent data, then re-queue it. */ + if (packet->offset < packet->length) { + /* + * Re-queue it at the head of the highest priority queue so + * it goes before all other packets + */ + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + list_add(&packet->queue, &hw->tx_queue[0]); + hw->tx_queued++; + spin_unlock_irqrestore(&hw->lock, flags); + } else { + if (packet->packet_callback) + packet->packet_callback(packet->callback_data, + packet->length); + kfree(packet); + } +} + +static void ipw_setup_hardware(struct ipw_hardware *hw) +{ + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + if (hw->hw_version == HW_VERSION_1) { + /* Reset RX FIFO */ + outw(DCR_RXRESET, hw->base_port + IODCR); + /* SB: Reset TX FIFO */ + outw(DCR_TXRESET, hw->base_port + IODCR); + + /* Enable TX and RX interrupts. */ + outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER); + } else { + /* + * Set INTRACK bit (bit 0), which means we must explicitly + * acknowledge interrupts by clearing bit 2 of reg_config_and_status. + */ + unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status); + + csr |= 1; + writew(csr, &hw->memregs_CCR->reg_config_and_status); + } + spin_unlock_irqrestore(&hw->lock, flags); +} + +/* + * If 'packet' is NULL, then this function allocates a new packet, setting its + * length to 0 and ensuring it has the specified minimum amount of free space. + * + * If 'packet' is not NULL, then this function enlarges it if it doesn't + * have the specified minimum amount of free space. + * + */ +static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, + struct ipw_rx_packet *packet, + int minimum_free_space) +{ + + if (!packet) { + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + if (!list_empty(&hw->rx_pool)) { + packet = list_first_entry(&hw->rx_pool, + struct ipw_rx_packet, queue); + hw->rx_pool_size--; + spin_unlock_irqrestore(&hw->lock, flags); + list_del(&packet->queue); + } else { + const int min_capacity = + ipwireless_ppp_mru(hw->network) + 2; + int new_capacity; + + spin_unlock_irqrestore(&hw->lock, flags); + new_capacity = + (minimum_free_space > min_capacity + ? minimum_free_space + : min_capacity); + packet = kmalloc(sizeof(struct ipw_rx_packet) + + new_capacity, GFP_ATOMIC); + if (!packet) + return NULL; + packet->capacity = new_capacity; + } + packet->length = 0; + } + + if (packet->length + minimum_free_space > packet->capacity) { + struct ipw_rx_packet *old_packet = packet; + + packet = kmalloc(sizeof(struct ipw_rx_packet) + + old_packet->length + minimum_free_space, + GFP_ATOMIC); + if (!packet) { + kfree(old_packet); + return NULL; + } + memcpy(packet, old_packet, + sizeof(struct ipw_rx_packet) + + old_packet->length); + packet->capacity = old_packet->length + minimum_free_space; + kfree(old_packet); + } + + return packet; +} + +static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) +{ + if (hw->rx_pool_size > 6) + kfree(packet); + else { + hw->rx_pool_size++; + list_add(&packet->queue, &hw->rx_pool); + } +} + +static void queue_received_packet(struct ipw_hardware *hw, + unsigned int protocol, + unsigned int address, + const unsigned char *data, int length, + int is_last) +{ + unsigned int channel_idx = address - 1; + struct ipw_rx_packet *packet = NULL; + unsigned long flags; + + /* Discard packet if channel index is out of range. */ + if (channel_idx >= NL_NUM_OF_ADDRESSES) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": data packet has bad address %u\n", address); + return; + } + + /* + * ->packet_assembler is safe to touch unlocked, this is the only place + */ + if (protocol == TL_PROTOCOLID_COM_DATA) { + struct ipw_rx_packet **assem = + &hw->packet_assembler[channel_idx]; + + /* + * Create a new packet, or assembler already contains one + * enlarge it by 'length' bytes. + */ + (*assem) = pool_allocate(hw, *assem, length); + if (!(*assem)) { + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": no memory for incomming data packet, dropped!\n"); + return; + } + (*assem)->protocol = protocol; + (*assem)->channel_idx = channel_idx; + + /* Append this packet data onto existing data. */ + memcpy((unsigned char *)(*assem) + + sizeof(struct ipw_rx_packet) + + (*assem)->length, data, length); + (*assem)->length += length; + if (is_last) { + packet = *assem; + *assem = NULL; + /* Count queued DATA bytes only */ + spin_lock_irqsave(&hw->lock, flags); + hw->rx_bytes_queued += packet->length; + spin_unlock_irqrestore(&hw->lock, flags); + } + } else { + /* If it's a CTRL packet, don't assemble, just queue it. */ + packet = pool_allocate(hw, NULL, length); + if (!packet) { + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": no memory for incomming ctrl packet, dropped!\n"); + return; + } + packet->protocol = protocol; + packet->channel_idx = channel_idx; + memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet), + data, length); + packet->length = length; + } + + /* + * If this is the last packet, then send the assembled packet on to the + * network layer. + */ + if (packet) { + spin_lock_irqsave(&hw->lock, flags); + list_add_tail(&packet->queue, &hw->rx_queue); + /* Block reception of incoming packets if queue is full. */ + hw->blocking_rx = + (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE); + + spin_unlock_irqrestore(&hw->lock, flags); + schedule_work(&hw->work_rx); + } +} + +/* + * Workqueue callback + */ +static void ipw_receive_data_work(struct work_struct *work_rx) +{ + struct ipw_hardware *hw = + container_of(work_rx, struct ipw_hardware, work_rx); + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + while (!list_empty(&hw->rx_queue)) { + struct ipw_rx_packet *packet = + list_first_entry(&hw->rx_queue, + struct ipw_rx_packet, queue); + + if (hw->shutting_down) + break; + list_del(&packet->queue); + + /* + * Note: ipwireless_network_packet_received must be called in a + * process context (i.e. via schedule_work) because the tty + * output code can sleep in the tty_flip_buffer_push call. + */ + if (packet->protocol == TL_PROTOCOLID_COM_DATA) { + if (hw->network != NULL) { + /* If the network hasn't been disconnected. */ + spin_unlock_irqrestore(&hw->lock, flags); + /* + * This must run unlocked due to tty processing + * and mutex locking + */ + ipwireless_network_packet_received( + hw->network, + packet->channel_idx, + (unsigned char *)packet + + sizeof(struct ipw_rx_packet), + packet->length); + spin_lock_irqsave(&hw->lock, flags); + } + /* Count queued DATA bytes only */ + hw->rx_bytes_queued -= packet->length; + } else { + /* + * This is safe to be called locked, callchain does + * not block + */ + handle_received_CTRL_packet(hw, packet->channel_idx, + (unsigned char *)packet + + sizeof(struct ipw_rx_packet), + packet->length); + } + pool_free(hw, packet); + /* + * Unblock reception of incoming packets if queue is no longer + * full. + */ + hw->blocking_rx = + hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; + if (hw->shutting_down) + break; + } + spin_unlock_irqrestore(&hw->lock, flags); +} + +static void handle_received_CTRL_packet(struct ipw_hardware *hw, + unsigned int channel_idx, + const unsigned char *data, int len) +{ + const struct ipw_control_packet_body *body = + (const struct ipw_control_packet_body *) data; + unsigned int changed_mask; + + if (len != sizeof(struct ipw_control_packet_body)) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": control packet was %d bytes - wrong size!\n", + len); + return; + } + + switch (body->sig_no) { + case COMCTRL_CTS: + changed_mask = IPW_CONTROL_LINE_CTS; + break; + case COMCTRL_DCD: + changed_mask = IPW_CONTROL_LINE_DCD; + break; + case COMCTRL_DSR: + changed_mask = IPW_CONTROL_LINE_DSR; + break; + case COMCTRL_RI: + changed_mask = IPW_CONTROL_LINE_RI; + break; + default: + changed_mask = 0; + } + + if (changed_mask != 0) { + if (body->value) + hw->control_lines[channel_idx] |= changed_mask; + else + hw->control_lines[channel_idx] &= ~changed_mask; + if (hw->network) + ipwireless_network_notify_control_line_change( + hw->network, + channel_idx, + hw->control_lines[channel_idx], + changed_mask); + } +} + +static void handle_received_packet(struct ipw_hardware *hw, + const union nl_packet *packet, + unsigned short len) +{ + unsigned int protocol = packet->hdr.protocol; + unsigned int address = packet->hdr.address; + unsigned int header_length; + const unsigned char *data; + unsigned int data_len; + int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; + + if (packet->hdr.packet_rank & NL_FIRST_PACKET) + header_length = NL_FIRST_PACKET_HEADER_SIZE; + else + header_length = NL_FOLLOWING_PACKET_HEADER_SIZE; + + data = packet->rawpkt + header_length; + data_len = len - header_length; + switch (protocol) { + case TL_PROTOCOLID_COM_DATA: + case TL_PROTOCOLID_COM_CTRL: + queue_received_packet(hw, protocol, address, data, data_len, + is_last); + break; + case TL_PROTOCOLID_SETUP: + handle_received_SETUP_packet(hw, address, data, data_len, + is_last); + break; + } +} + +static void acknowledge_data_read(struct ipw_hardware *hw) +{ + if (hw->hw_version == HW_VERSION_1) + outw(DCR_RXDONE, hw->base_port + IODCR); + else + writew(MEMRX_PCINTACKK, + &hw->memory_info_regs->memreg_pc_interrupt_ack); +} + +/* + * Retrieve a packet from the IPW hardware. + */ +static void do_receive_packet(struct ipw_hardware *hw) +{ + unsigned len; + unsigned i; + unsigned char pkt[LL_MTU_MAX]; + + start_timing(); + + if (hw->hw_version == HW_VERSION_1) { + len = inw(hw->base_port + IODRR); + if (len > hw->ll_mtu) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": received a packet of %u bytes - longer than the MTU!\n", len); + outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); + return; + } + + for (i = 0; i < len; i += 2) { + __le16 raw_data = inw(hw->base_port + IODRR); + unsigned short data = le16_to_cpu(raw_data); + + pkt[i] = (unsigned char) data; + pkt[i + 1] = (unsigned char) (data >> 8); + } + } else { + len = inw(hw->base_port); + if (len > hw->ll_mtu) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": received a packet of %u bytes - longer than the MTU!\n", len); + writew(MEMRX_PCINTACKK, + &hw->memory_info_regs->memreg_pc_interrupt_ack); + return; + } + + for (i = 0; i < len; i += 2) { + __le16 raw_data = inw(hw->base_port); + unsigned short data = le16_to_cpu(raw_data); + + pkt[i] = (unsigned char) data; + pkt[i + 1] = (unsigned char) (data >> 8); + } + + while ((i & 3) != 2) { + inw(hw->base_port); + i += 2; + } + } + + acknowledge_data_read(hw); + + swap_packet_bitfield_from_le(pkt); + + if (ipwireless_debug) + dump_data_bytes("recv", pkt, len); + + handle_received_packet(hw, (union nl_packet *) pkt, len); + + end_read_timing(len); +} + +static int get_current_packet_priority(struct ipw_hardware *hw) +{ + /* + * If we're initializing, don't send anything of higher priority than + * PRIO_SETUP. The network layer therefore need not care about + * hardware initialization - any of its stuff will simply be queued + * until setup is complete. + */ + return (hw->to_setup || hw->initializing + ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES); +} + +/* + * return 1 if something has been received from hw + */ +static int get_packets_from_hw(struct ipw_hardware *hw) +{ + int received = 0; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + while (hw->rx_ready && !hw->blocking_rx) { + received = 1; + hw->rx_ready--; + spin_unlock_irqrestore(&hw->lock, flags); + + do_receive_packet(hw); + + spin_lock_irqsave(&hw->lock, flags); + } + spin_unlock_irqrestore(&hw->lock, flags); + + return received; +} + +/* + * Send pending packet up to given priority, prioritize SETUP data until + * hardware is fully setup. + * + * return 1 if more packets can be sent + */ +static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) +{ + int more_to_send = 0; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + if (hw->tx_queued && hw->tx_ready) { + int priority; + struct ipw_tx_packet *packet = NULL; + + /* Pick a packet */ + for (priority = 0; priority < priority_limit; priority++) { + if (!list_empty(&hw->tx_queue[priority])) { + packet = list_first_entry( + &hw->tx_queue[priority], + struct ipw_tx_packet, + queue); + + hw->tx_queued--; + list_del(&packet->queue); + + break; + } + } + if (!packet) { + hw->tx_queued = 0; + spin_unlock_irqrestore(&hw->lock, flags); + return 0; + } + + spin_unlock_irqrestore(&hw->lock, flags); + + /* Send */ + do_send_packet(hw, packet); + + /* Check if more to send */ + spin_lock_irqsave(&hw->lock, flags); + for (priority = 0; priority < priority_limit; priority++) + if (!list_empty(&hw->tx_queue[priority])) { + more_to_send = 1; + break; + } + + if (!more_to_send) + hw->tx_queued = 0; + } + spin_unlock_irqrestore(&hw->lock, flags); + + return more_to_send; +} + +/* + * Send and receive all queued packets. + */ +static void ipwireless_do_tasklet(unsigned long hw_) +{ + struct ipw_hardware *hw = (struct ipw_hardware *) hw_; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + if (hw->shutting_down) { + spin_unlock_irqrestore(&hw->lock, flags); + return; + } + + if (hw->to_setup == 1) { + /* + * Initial setup data sent to hardware + */ + hw->to_setup = 2; + spin_unlock_irqrestore(&hw->lock, flags); + + ipw_setup_hardware(hw); + ipw_send_setup_packet(hw); + + send_pending_packet(hw, PRIO_SETUP + 1); + get_packets_from_hw(hw); + } else { + int priority_limit = get_current_packet_priority(hw); + int again; + + spin_unlock_irqrestore(&hw->lock, flags); + + do { + again = send_pending_packet(hw, priority_limit); + again |= get_packets_from_hw(hw); + } while (again); + } +} + +/* + * return true if the card is physically present. + */ +static int is_card_present(struct ipw_hardware *hw) +{ + if (hw->hw_version == HW_VERSION_1) + return inw(hw->base_port + IOIR) != 0xFFFF; + else + return readl(&hw->memory_info_regs->memreg_card_present) == + CARD_PRESENT_VALUE; +} + +static irqreturn_t ipwireless_handle_v1_interrupt(int irq, + struct ipw_hardware *hw) +{ + unsigned short irqn; + + irqn = inw(hw->base_port + IOIR); + + /* Check if card is present */ + if (irqn == 0xFFFF) + return IRQ_NONE; + else if (irqn != 0) { + unsigned short ack = 0; + unsigned long flags; + + /* Transmit complete. */ + if (irqn & IR_TXINTR) { + ack |= IR_TXINTR; + spin_lock_irqsave(&hw->lock, flags); + hw->tx_ready = 1; + spin_unlock_irqrestore(&hw->lock, flags); + } + /* Received data */ + if (irqn & IR_RXINTR) { + ack |= IR_RXINTR; + spin_lock_irqsave(&hw->lock, flags); + hw->rx_ready++; + spin_unlock_irqrestore(&hw->lock, flags); + } + if (ack != 0) { + outw(ack, hw->base_port + IOIR); + tasklet_schedule(&hw->tasklet); + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw) +{ + unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status); + + csr &= 0xfffd; + writew(csr, &hw->memregs_CCR->reg_config_and_status); +} + +static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, + struct ipw_hardware *hw) +{ + int tx = 0; + int rx = 0; + int rx_repeat = 0; + int try_mem_tx_old; + unsigned long flags; + + do { + + unsigned short memtx = readw(hw->memreg_tx); + unsigned short memtx_serial; + unsigned short memrxdone = + readw(&hw->memory_info_regs->memreg_rx_done); + + try_mem_tx_old = 0; + + /* check whether the interrupt was generated by ipwireless card */ + if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) { + + /* check if the card uses memreg_tx_old register */ + if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { + memtx = readw(&hw->memory_info_regs->memreg_tx_old); + if (memtx & MEMTX_TX) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": Using memreg_tx_old\n"); + hw->memreg_tx = + &hw->memory_info_regs->memreg_tx_old; + } else { + return IRQ_NONE; + } + } else + return IRQ_NONE; + } + + /* + * See if the card is physically present. Note that while it is + * powering up, it appears not to be present. + */ + if (!is_card_present(hw)) { + acknowledge_pcmcia_interrupt(hw); + return IRQ_HANDLED; + } + + memtx_serial = memtx & (unsigned short) 0xff00; + if (memtx & MEMTX_TX) { + writew(memtx_serial, hw->memreg_tx); + + if (hw->serial_number_detected) { + if (memtx_serial != hw->last_memtx_serial) { + hw->last_memtx_serial = memtx_serial; + spin_lock_irqsave(&hw->lock, flags); + hw->rx_ready++; + spin_unlock_irqrestore(&hw->lock, flags); + rx = 1; + } else + /* Ignore 'Timer Recovery' duplicates. */ + rx_repeat = 1; + } else { + /* + * If a non-zero serial number is seen, then enable + * serial number checking. + */ + if (memtx_serial != 0) { + hw->serial_number_detected = 1; + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME + ": memreg_tx serial num detected\n"); + + spin_lock_irqsave(&hw->lock, flags); + hw->rx_ready++; + spin_unlock_irqrestore(&hw->lock, flags); + } + rx = 1; + } + } + if (memrxdone & MEMRX_RX_DONE) { + writew(0, &hw->memory_info_regs->memreg_rx_done); + spin_lock_irqsave(&hw->lock, flags); + hw->tx_ready = 1; + spin_unlock_irqrestore(&hw->lock, flags); + tx = 1; + } + if (tx) + writew(MEMRX_PCINTACKK, + &hw->memory_info_regs->memreg_pc_interrupt_ack); + + acknowledge_pcmcia_interrupt(hw); + + if (tx || rx) + tasklet_schedule(&hw->tasklet); + else if (!rx_repeat) { + if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { + if (hw->serial_number_detected) + printk(KERN_WARNING IPWIRELESS_PCCARD_NAME + ": spurious interrupt - new_tx mode\n"); + else { + printk(KERN_WARNING IPWIRELESS_PCCARD_NAME + ": no valid memreg_tx value - switching to the old memreg_tx\n"); + hw->memreg_tx = + &hw->memory_info_regs->memreg_tx_old; + try_mem_tx_old = 1; + } + } else + printk(KERN_WARNING IPWIRELESS_PCCARD_NAME + ": spurious interrupt - old_tx mode\n"); + } + + } while (try_mem_tx_old == 1); + + return IRQ_HANDLED; +} + +irqreturn_t ipwireless_interrupt(int irq, void *dev_id) +{ + struct ipw_dev *ipw = dev_id; + + if (ipw->hardware->hw_version == HW_VERSION_1) + return ipwireless_handle_v1_interrupt(irq, ipw->hardware); + else + return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware); +} + +static void flush_packets_to_hw(struct ipw_hardware *hw) +{ + int priority_limit; + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + priority_limit = get_current_packet_priority(hw); + spin_unlock_irqrestore(&hw->lock, flags); + + while (send_pending_packet(hw, priority_limit)); +} + +static void send_packet(struct ipw_hardware *hw, int priority, + struct ipw_tx_packet *packet) +{ + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + list_add_tail(&packet->queue, &hw->tx_queue[priority]); + hw->tx_queued++; + spin_unlock_irqrestore(&hw->lock, flags); + + flush_packets_to_hw(hw); +} + +/* Create data packet, non-atomic allocation */ +static void *alloc_data_packet(int data_size, + unsigned char dest_addr, + unsigned char protocol) +{ + struct ipw_tx_packet *packet = kzalloc( + sizeof(struct ipw_tx_packet) + data_size, + GFP_ATOMIC); + + if (!packet) + return NULL; + + INIT_LIST_HEAD(&packet->queue); + packet->dest_addr = dest_addr; + packet->protocol = protocol; + packet->length = data_size; + + return packet; +} + +static void *alloc_ctrl_packet(int header_size, + unsigned char dest_addr, + unsigned char protocol, + unsigned char sig_no) +{ + /* + * sig_no is located right after ipw_tx_packet struct in every + * CTRL or SETUP packets, we can use ipw_control_packet as a + * common struct + */ + struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC); + + if (!packet) + return NULL; + + INIT_LIST_HEAD(&packet->header.queue); + packet->header.dest_addr = dest_addr; + packet->header.protocol = protocol; + packet->header.length = header_size - sizeof(struct ipw_tx_packet); + packet->body.sig_no = sig_no; + + return packet; +} + +int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, + const unsigned char *data, unsigned int length, + void (*callback) (void *cb, unsigned int length), + void *callback_data) +{ + struct ipw_tx_packet *packet; + + packet = alloc_data_packet(length, (channel_idx + 1), + TL_PROTOCOLID_COM_DATA); + if (!packet) + return -ENOMEM; + packet->packet_callback = callback; + packet->callback_data = callback_data; + memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data, + length); + + send_packet(hw, PRIO_DATA, packet); + return 0; +} + +static int set_control_line(struct ipw_hardware *hw, int prio, + unsigned int channel_idx, int line, int state) +{ + struct ipw_control_packet *packet; + int protocolid = TL_PROTOCOLID_COM_CTRL; + + if (prio == PRIO_SETUP) + protocolid = TL_PROTOCOLID_SETUP; + + packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), + (channel_idx + 1), protocolid, line); + if (!packet) + return -ENOMEM; + packet->header.length = sizeof(struct ipw_control_packet_body); + packet->body.value = (state == 0 ? 0 : 1); + send_packet(hw, prio, &packet->header); + return 0; +} + + +static int set_DTR(struct ipw_hardware *hw, int priority, + unsigned int channel_idx, int state) +{ + if (state != 0) + hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR; + else + hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR; + + return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state); +} + +static int set_RTS(struct ipw_hardware *hw, int priority, + unsigned int channel_idx, int state) +{ + if (state != 0) + hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS; + else + hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS; + + return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state); +} + +int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, + int state) +{ + return set_DTR(hw, PRIO_CTRL, channel_idx, state); +} + +int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, + int state) +{ + return set_RTS(hw, PRIO_CTRL, channel_idx, state); +} + +struct ipw_setup_get_version_query_packet { + struct ipw_tx_packet header; + struct tl_setup_get_version_qry body; +}; + +struct ipw_setup_config_packet { + struct ipw_tx_packet header; + struct tl_setup_config_msg body; +}; + +struct ipw_setup_config_done_packet { + struct ipw_tx_packet header; + struct tl_setup_config_done_msg body; +}; + +struct ipw_setup_open_packet { + struct ipw_tx_packet header; + struct tl_setup_open_msg body; +}; + +struct ipw_setup_info_packet { + struct ipw_tx_packet header; + struct tl_setup_info_msg body; +}; + +struct ipw_setup_reboot_msg_ack { + struct ipw_tx_packet header; + struct TlSetupRebootMsgAck body; +}; + +/* This handles the actual initialization of the card */ +static void __handle_setup_get_version_rsp(struct ipw_hardware *hw) +{ + struct ipw_setup_config_packet *config_packet; + struct ipw_setup_config_done_packet *config_done_packet; + struct ipw_setup_open_packet *open_packet; + struct ipw_setup_info_packet *info_packet; + int port; + unsigned int channel_idx; + + /* generate config packet */ + for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) { + config_packet = alloc_ctrl_packet( + sizeof(struct ipw_setup_config_packet), + ADDR_SETUP_PROT, + TL_PROTOCOLID_SETUP, + TL_SETUP_SIGNO_CONFIG_MSG); + if (!config_packet) + goto exit_nomem; + config_packet->header.length = sizeof(struct tl_setup_config_msg); + config_packet->body.port_no = port; + config_packet->body.prio_data = PRIO_DATA; + config_packet->body.prio_ctrl = PRIO_CTRL; + send_packet(hw, PRIO_SETUP, &config_packet->header); + } + config_done_packet = alloc_ctrl_packet( + sizeof(struct ipw_setup_config_done_packet), + ADDR_SETUP_PROT, + TL_PROTOCOLID_SETUP, + TL_SETUP_SIGNO_CONFIG_DONE_MSG); + if (!config_done_packet) + goto exit_nomem; + config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg); + send_packet(hw, PRIO_SETUP, &config_done_packet->header); + + /* generate open packet */ + for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) { + open_packet = alloc_ctrl_packet( + sizeof(struct ipw_setup_open_packet), + ADDR_SETUP_PROT, + TL_PROTOCOLID_SETUP, + TL_SETUP_SIGNO_OPEN_MSG); + if (!open_packet) + goto exit_nomem; + open_packet->header.length = sizeof(struct tl_setup_open_msg); + open_packet->body.port_no = port; + send_packet(hw, PRIO_SETUP, &open_packet->header); + } + for (channel_idx = 0; + channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) { + int ret; + + ret = set_DTR(hw, PRIO_SETUP, channel_idx, + (hw->control_lines[channel_idx] & + IPW_CONTROL_LINE_DTR) != 0); + if (ret) { + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": error setting DTR (%d)\n", ret); + return; + } + + set_RTS(hw, PRIO_SETUP, channel_idx, + (hw->control_lines [channel_idx] & + IPW_CONTROL_LINE_RTS) != 0); + if (ret) { + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": error setting RTS (%d)\n", ret); + return; + } + } + /* + * For NDIS we assume that we are using sync PPP frames, for COM async. + * This driver uses NDIS mode too. We don't bother with translation + * from async -> sync PPP. + */ + info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet), + ADDR_SETUP_PROT, + TL_PROTOCOLID_SETUP, + TL_SETUP_SIGNO_INFO_MSG); + if (!info_packet) + goto exit_nomem; + info_packet->header.length = sizeof(struct tl_setup_info_msg); + info_packet->body.driver_type = NDISWAN_DRIVER; + info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION; + info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION; + send_packet(hw, PRIO_SETUP, &info_packet->header); + + /* Initialization is now complete, so we clear the 'to_setup' flag */ + hw->to_setup = 0; + + return; + +exit_nomem: + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": not enough memory to alloc control packet\n"); + hw->to_setup = -1; +} + +static void handle_setup_get_version_rsp(struct ipw_hardware *hw, + unsigned char vers_no) +{ + del_timer(&hw->setup_timer); + hw->initializing = 0; + printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n"); + + if (vers_no == TL_SETUP_VERSION) + __handle_setup_get_version_rsp(hw); + else + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": invalid hardware version no %u\n", + (unsigned int) vers_no); +} + +static void ipw_send_setup_packet(struct ipw_hardware *hw) +{ + struct ipw_setup_get_version_query_packet *ver_packet; + + ver_packet = alloc_ctrl_packet( + sizeof(struct ipw_setup_get_version_query_packet), + ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, + TL_SETUP_SIGNO_GET_VERSION_QRY); + ver_packet->header.length = sizeof(struct tl_setup_get_version_qry); + + /* + * Response is handled in handle_received_SETUP_packet + */ + send_packet(hw, PRIO_SETUP, &ver_packet->header); +} + +static void handle_received_SETUP_packet(struct ipw_hardware *hw, + unsigned int address, + const unsigned char *data, int len, + int is_last) +{ + const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data; + + if (address != ADDR_SETUP_PROT) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": setup packet has bad address %d\n", address); + return; + } + + switch (rx_msg->sig_no) { + case TL_SETUP_SIGNO_GET_VERSION_RSP: + if (hw->to_setup) + handle_setup_get_version_rsp(hw, + rx_msg->version_rsp_msg.version); + break; + + case TL_SETUP_SIGNO_OPEN_MSG: + if (ipwireless_debug) { + unsigned int channel_idx = rx_msg->open_msg.port_no - 1; + + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": OPEN_MSG [channel %u] reply received\n", + channel_idx); + } + break; + + case TL_SETUP_SIGNO_INFO_MSG_ACK: + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME + ": card successfully configured as NDISWAN\n"); + break; + + case TL_SETUP_SIGNO_REBOOT_MSG: + if (hw->to_setup) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME + ": Setup not completed - ignoring reboot msg\n"); + else { + struct ipw_setup_reboot_msg_ack *packet; + + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME + ": Acknowledging REBOOT message\n"); + packet = alloc_ctrl_packet( + sizeof(struct ipw_setup_reboot_msg_ack), + ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, + TL_SETUP_SIGNO_REBOOT_MSG_ACK); + packet->header.length = + sizeof(struct TlSetupRebootMsgAck); + send_packet(hw, PRIO_SETUP, &packet->header); + if (hw->reboot_callback) + hw->reboot_callback(hw->reboot_callback_data); + } + break; + + default: + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": unknown setup message %u received\n", + (unsigned int) rx_msg->sig_no); + } +} + +static void do_close_hardware(struct ipw_hardware *hw) +{ + unsigned int irqn; + + if (hw->hw_version == HW_VERSION_1) { + /* Disable TX and RX interrupts. */ + outw(0, hw->base_port + IOIER); + + /* Acknowledge any outstanding interrupt requests */ + irqn = inw(hw->base_port + IOIR); + if (irqn & IR_TXINTR) + outw(IR_TXINTR, hw->base_port + IOIR); + if (irqn & IR_RXINTR) + outw(IR_RXINTR, hw->base_port + IOIR); + + synchronize_irq(hw->irq); + } +} + +struct ipw_hardware *ipwireless_hardware_create(void) +{ + int i; + struct ipw_hardware *hw = + kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL); + + if (!hw) + return NULL; + + hw->irq = -1; + hw->initializing = 1; + hw->tx_ready = 1; + hw->rx_bytes_queued = 0; + hw->rx_pool_size = 0; + hw->last_memtx_serial = (unsigned short) 0xffff; + for (i = 0; i < NL_NUM_OF_PRIORITIES; i++) + INIT_LIST_HEAD(&hw->tx_queue[i]); + + INIT_LIST_HEAD(&hw->rx_queue); + INIT_LIST_HEAD(&hw->rx_pool); + spin_lock_init(&hw->lock); + tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); + INIT_WORK(&hw->work_rx, ipw_receive_data_work); + setup_timer(&hw->setup_timer, ipwireless_setup_timer, + (unsigned long) hw); + + return hw; +} + +void ipwireless_init_hardware_v1(struct ipw_hardware *hw, + unsigned int base_port, + void __iomem *attr_memory, + void __iomem *common_memory, + int is_v2_card, + void (*reboot_callback) (void *data), + void *reboot_callback_data) +{ + if (hw->removed) { + hw->removed = 0; + enable_irq(hw->irq); + } + hw->base_port = base_port; + hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1); + hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2); + hw->memregs_CCR = (struct MEMCCR __iomem *) + ((unsigned short __iomem *) attr_memory + 0x200); + hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; + hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new; + hw->reboot_callback = reboot_callback; + hw->reboot_callback_data = reboot_callback_data; +} + +void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw) +{ + hw->initializing = 1; + hw->init_loops = 0; + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": waiting for card to start up...\n"); + ipwireless_setup_timer((unsigned long) hw); +} + +static void ipwireless_setup_timer(unsigned long data) +{ + struct ipw_hardware *hw = (struct ipw_hardware *) data; + + hw->init_loops++; + + if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY && + hw->hw_version == HW_VERSION_2 && + hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": failed to startup using TX2, trying TX\n"); + + hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old; + hw->init_loops = 0; + } + /* Give up after a certain number of retries */ + if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) { + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": card failed to start up!\n"); + hw->initializing = 0; + } else { + /* Do not attempt to write to the board if it is not present. */ + if (is_card_present(hw)) { + unsigned long flags; + + spin_lock_irqsave(&hw->lock, flags); + hw->to_setup = 1; + hw->tx_ready = 1; + spin_unlock_irqrestore(&hw->lock, flags); + tasklet_schedule(&hw->tasklet); + } + + mod_timer(&hw->setup_timer, + jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO)); + } +} + +/* + * Stop any interrupts from executing so that, once this function returns, + * other layers of the driver can be sure they won't get any more callbacks. + * Thus must be called on a proper process context. + */ +void ipwireless_stop_interrupts(struct ipw_hardware *hw) +{ + if (!hw->shutting_down) { + /* Tell everyone we are going down. */ + hw->shutting_down = 1; + del_timer(&hw->setup_timer); + + /* Prevent the hardware from sending any more interrupts */ + do_close_hardware(hw); + } +} + +void ipwireless_hardware_free(struct ipw_hardware *hw) +{ + int i; + struct ipw_rx_packet *rp, *rq; + struct ipw_tx_packet *tp, *tq; + + ipwireless_stop_interrupts(hw); + + flush_work_sync(&hw->work_rx); + + for (i = 0; i < NL_NUM_OF_ADDRESSES; i++) + if (hw->packet_assembler[i] != NULL) + kfree(hw->packet_assembler[i]); + + for (i = 0; i < NL_NUM_OF_PRIORITIES; i++) + list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) { + list_del(&tp->queue); + kfree(tp); + } + + list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) { + list_del(&rp->queue); + kfree(rp); + } + + list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) { + list_del(&rp->queue); + kfree(rp); + } + kfree(hw); +} + +/* + * Associate the specified network with this hardware, so it will receive events + * from it. + */ +void ipwireless_associate_network(struct ipw_hardware *hw, + struct ipw_network *network) +{ + hw->network = network; +} diff --git a/drivers/tty/ipwireless/hardware.h b/drivers/tty/ipwireless/hardware.h new file mode 100644 index 000000000000..90a8590e43b0 --- /dev/null +++ b/drivers/tty/ipwireless/hardware.h @@ -0,0 +1,62 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#ifndef _IPWIRELESS_CS_HARDWARE_H_ +#define _IPWIRELESS_CS_HARDWARE_H_ + +#include +#include +#include + +#define IPW_CONTROL_LINE_CTS 0x0001 +#define IPW_CONTROL_LINE_DCD 0x0002 +#define IPW_CONTROL_LINE_DSR 0x0004 +#define IPW_CONTROL_LINE_RI 0x0008 +#define IPW_CONTROL_LINE_DTR 0x0010 +#define IPW_CONTROL_LINE_RTS 0x0020 + +struct ipw_hardware; +struct ipw_network; + +struct ipw_hardware *ipwireless_hardware_create(void); +void ipwireless_hardware_free(struct ipw_hardware *hw); +irqreturn_t ipwireless_interrupt(int irq, void *dev_id); +int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, + int state); +int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, + int state); +int ipwireless_send_packet(struct ipw_hardware *hw, + unsigned int channel_idx, + const unsigned char *data, + unsigned int length, + void (*packet_sent_callback) (void *cb, + unsigned int length), + void *sent_cb_data); +void ipwireless_associate_network(struct ipw_hardware *hw, + struct ipw_network *net); +void ipwireless_stop_interrupts(struct ipw_hardware *hw); +void ipwireless_init_hardware_v1(struct ipw_hardware *hw, + unsigned int base_port, + void __iomem *attr_memory, + void __iomem *common_memory, + int is_v2_card, + void (*reboot_cb) (void *data), + void *reboot_cb_data); +void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw); +void ipwireless_sleep(unsigned int tenths); + +#endif diff --git a/drivers/tty/ipwireless/main.c b/drivers/tty/ipwireless/main.c new file mode 100644 index 000000000000..94b8eb4d691d --- /dev/null +++ b/drivers/tty/ipwireless/main.c @@ -0,0 +1,335 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#include "hardware.h" +#include "network.h" +#include "main.h" +#include "tty.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct pcmcia_device_id ipw_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), + PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, ipw_ids); + +static void ipwireless_detach(struct pcmcia_device *link); + +/* + * Module params + */ +/* Debug mode: more verbose, print sent/recv bytes */ +int ipwireless_debug; +int ipwireless_loopback; +int ipwireless_out_queue = 10; + +module_param_named(debug, ipwireless_debug, int, 0); +module_param_named(loopback, ipwireless_loopback, int, 0); +module_param_named(out_queue, ipwireless_out_queue, int, 0); +MODULE_PARM_DESC(debug, "switch on debug messages [0]"); +MODULE_PARM_DESC(loopback, + "debug: enable ras_raw channel [0]"); +MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); + +/* Executes in process context. */ +static void signalled_reboot_work(struct work_struct *work_reboot) +{ + struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev, + work_reboot); + struct pcmcia_device *link = ipw->link; + pcmcia_reset_card(link->socket); +} + +static void signalled_reboot_callback(void *callback_data) +{ + struct ipw_dev *ipw = (struct ipw_dev *) callback_data; + + /* Delegate to process context. */ + schedule_work(&ipw->work_reboot); +} + +static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) +{ + struct ipw_dev *ipw = priv_data; + struct resource *io_resource; + int ret; + + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + + /* 0x40 causes it to generate level mode interrupts. */ + /* 0x04 enables IREQ pin. */ + p_dev->config_index |= 0x44; + p_dev->io_lines = 16; + ret = pcmcia_request_io(p_dev); + if (ret) + return ret; + + io_resource = request_region(p_dev->resource[0]->start, + resource_size(p_dev->resource[0]), + IPWIRELESS_PCCARD_NAME); + + p_dev->resource[2]->flags |= + WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; + + ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0); + if (ret != 0) + goto exit1; + + ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr); + if (ret != 0) + goto exit2; + + ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100; + + ipw->attr_memory = ioremap(p_dev->resource[2]->start, + resource_size(p_dev->resource[2])); + request_mem_region(p_dev->resource[2]->start, + resource_size(p_dev->resource[2]), + IPWIRELESS_PCCARD_NAME); + + p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | + WIN_ENABLE; + p_dev->resource[3]->end = 0; /* this used to be 0x1000 */ + ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0); + if (ret != 0) + goto exit2; + + ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0); + if (ret != 0) + goto exit3; + + ipw->attr_memory = ioremap(p_dev->resource[3]->start, + resource_size(p_dev->resource[3])); + request_mem_region(p_dev->resource[3]->start, + resource_size(p_dev->resource[3]), + IPWIRELESS_PCCARD_NAME); + + return 0; + +exit3: +exit2: + if (ipw->common_memory) { + release_mem_region(p_dev->resource[2]->start, + resource_size(p_dev->resource[2])); + iounmap(ipw->common_memory); + } +exit1: + release_resource(io_resource); + pcmcia_disable_device(p_dev); + return -1; +} + +static int config_ipwireless(struct ipw_dev *ipw) +{ + struct pcmcia_device *link = ipw->link; + int ret = 0; + + ipw->is_v2_card = 0; + link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM | + CONF_ENABLE_IRQ; + + ret = pcmcia_loop_config(link, ipwireless_probe, ipw); + if (ret != 0) + return ret; + + INIT_WORK(&ipw->work_reboot, signalled_reboot_work); + + ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start, + ipw->attr_memory, ipw->common_memory, + ipw->is_v2_card, signalled_reboot_callback, + ipw); + + ret = pcmcia_request_irq(link, ipwireless_interrupt); + if (ret != 0) + goto exit; + + printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", + ipw->is_v2_card ? "V2/V3" : "V1"); + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": I/O ports %pR, irq %d\n", link->resource[0], + (unsigned int) link->irq); + if (ipw->attr_memory && ipw->common_memory) + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": attr memory %pR, common memory %pR\n", + link->resource[3], + link->resource[2]); + + ipw->network = ipwireless_network_create(ipw->hardware); + if (!ipw->network) + goto exit; + + ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network); + if (!ipw->tty) + goto exit; + + ipwireless_init_hardware_v2_v3(ipw->hardware); + + /* + * Do the RequestConfiguration last, because it enables interrupts. + * Then we don't get any interrupts before we're ready for them. + */ + ret = pcmcia_enable_device(link); + if (ret != 0) + goto exit; + + return 0; + +exit: + if (ipw->common_memory) { + release_mem_region(link->resource[2]->start, + resource_size(link->resource[2])); + iounmap(ipw->common_memory); + } + if (ipw->attr_memory) { + release_mem_region(link->resource[3]->start, + resource_size(link->resource[3])); + iounmap(ipw->attr_memory); + } + pcmcia_disable_device(link); + return -1; +} + +static void release_ipwireless(struct ipw_dev *ipw) +{ + if (ipw->common_memory) { + release_mem_region(ipw->link->resource[2]->start, + resource_size(ipw->link->resource[2])); + iounmap(ipw->common_memory); + } + if (ipw->attr_memory) { + release_mem_region(ipw->link->resource[3]->start, + resource_size(ipw->link->resource[3])); + iounmap(ipw->attr_memory); + } + pcmcia_disable_device(ipw->link); +} + +/* + * ipwireless_attach() creates an "instance" of the driver, allocating + * local data structures for one device (one interface). The device + * is registered with Card Services. + * + * The pcmcia_device structure is initialized, but we don't actually + * configure the card at this point -- we wait until we receive a + * card insertion event. + */ +static int ipwireless_attach(struct pcmcia_device *link) +{ + struct ipw_dev *ipw; + int ret; + + ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL); + if (!ipw) + return -ENOMEM; + + ipw->link = link; + link->priv = ipw; + + ipw->hardware = ipwireless_hardware_create(); + if (!ipw->hardware) { + kfree(ipw); + return -ENOMEM; + } + /* RegisterClient will call config_ipwireless */ + + ret = config_ipwireless(ipw); + + if (ret != 0) { + ipwireless_detach(link); + return ret; + } + + return 0; +} + +/* + * This deletes a driver "instance". The device is de-registered with + * Card Services. If it has been released, all local data structures + * are freed. Otherwise, the structures will be freed when the device + * is released. + */ +static void ipwireless_detach(struct pcmcia_device *link) +{ + struct ipw_dev *ipw = link->priv; + + release_ipwireless(ipw); + + if (ipw->tty != NULL) + ipwireless_tty_free(ipw->tty); + if (ipw->network != NULL) + ipwireless_network_free(ipw->network); + if (ipw->hardware != NULL) + ipwireless_hardware_free(ipw->hardware); + kfree(ipw); +} + +static struct pcmcia_driver me = { + .owner = THIS_MODULE, + .probe = ipwireless_attach, + .remove = ipwireless_detach, + .name = IPWIRELESS_PCCARD_NAME, + .id_table = ipw_ids +}; + +/* + * Module insertion : initialisation of the module. + * Register the card with cardmgr... + */ +static int __init init_ipwireless(void) +{ + int ret; + + ret = ipwireless_tty_init(); + if (ret != 0) + return ret; + + ret = pcmcia_register_driver(&me); + if (ret != 0) + ipwireless_tty_release(); + + return ret; +} + +/* + * Module removal + */ +static void __exit exit_ipwireless(void) +{ + pcmcia_unregister_driver(&me); + ipwireless_tty_release(); +} + +module_init(init_ipwireless); +module_exit(exit_ipwireless); + +MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR); +MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/ipwireless/main.h b/drivers/tty/ipwireless/main.h new file mode 100644 index 000000000000..f2cbb116bccb --- /dev/null +++ b/drivers/tty/ipwireless/main.h @@ -0,0 +1,68 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#ifndef _IPWIRELESS_CS_H_ +#define _IPWIRELESS_CS_H_ + +#include +#include + +#include +#include + +#include "hardware.h" + +#define IPWIRELESS_PCCARD_NAME "ipwireless" +#define IPWIRELESS_PCMCIA_VERSION "1.1" +#define IPWIRELESS_PCMCIA_AUTHOR \ + "Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba" + +#define IPWIRELESS_TX_QUEUE_SIZE 262144 +#define IPWIRELESS_RX_QUEUE_SIZE 262144 + +#define IPWIRELESS_STATE_DEBUG + +struct ipw_hardware; +struct ipw_network; +struct ipw_tty; + +struct ipw_dev { + struct pcmcia_device *link; + int is_v2_card; + + void __iomem *attr_memory; + + void __iomem *common_memory; + + /* Reference to attribute memory, containing CIS data */ + void *attribute_memory; + + /* Hardware context */ + struct ipw_hardware *hardware; + /* Network layer context */ + struct ipw_network *network; + /* TTY device context */ + struct ipw_tty *tty; + struct work_struct work_reboot; +}; + +/* Module parametres */ +extern int ipwireless_debug; +extern int ipwireless_loopback; +extern int ipwireless_out_queue; + +#endif diff --git a/drivers/tty/ipwireless/network.c b/drivers/tty/ipwireless/network.c new file mode 100644 index 000000000000..f7daeea598e4 --- /dev/null +++ b/drivers/tty/ipwireless/network.c @@ -0,0 +1,508 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "network.h" +#include "hardware.h" +#include "main.h" +#include "tty.h" + +#define MAX_ASSOCIATED_TTYS 2 + +#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) + +struct ipw_network { + /* Hardware context, used for calls to hardware layer. */ + struct ipw_hardware *hardware; + /* Context for kernel 'generic_ppp' functionality */ + struct ppp_channel *ppp_channel; + /* tty context connected with IPW console */ + struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS]; + /* True if ppp needs waking up once we're ready to xmit */ + int ppp_blocked; + /* Number of packets queued up in hardware module. */ + int outgoing_packets_queued; + /* Spinlock to avoid interrupts during shutdown */ + spinlock_t lock; + struct mutex close_lock; + + /* PPP ioctl data, not actually used anywere */ + unsigned int flags; + unsigned int rbits; + u32 xaccm[8]; + u32 raccm; + int mru; + + int shutting_down; + unsigned int ras_control_lines; + + struct work_struct work_go_online; + struct work_struct work_go_offline; +}; + +static void notify_packet_sent(void *callback_data, unsigned int packet_length) +{ + struct ipw_network *network = callback_data; + unsigned long flags; + + spin_lock_irqsave(&network->lock, flags); + network->outgoing_packets_queued--; + if (network->ppp_channel != NULL) { + if (network->ppp_blocked) { + network->ppp_blocked = 0; + spin_unlock_irqrestore(&network->lock, flags); + ppp_output_wakeup(network->ppp_channel); + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME + ": ppp unblocked\n"); + } else + spin_unlock_irqrestore(&network->lock, flags); + } else + spin_unlock_irqrestore(&network->lock, flags); +} + +/* + * Called by the ppp system when it has a packet to send to the hardware. + */ +static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, + struct sk_buff *skb) +{ + struct ipw_network *network = ppp_channel->private; + unsigned long flags; + + spin_lock_irqsave(&network->lock, flags); + if (network->outgoing_packets_queued < ipwireless_out_queue) { + unsigned char *buf; + static unsigned char header[] = { + PPP_ALLSTATIONS, /* 0xff */ + PPP_UI, /* 0x03 */ + }; + int ret; + + network->outgoing_packets_queued++; + spin_unlock_irqrestore(&network->lock, flags); + + /* + * If we have the requested amount of headroom in the skb we + * were handed, then we can add the header efficiently. + */ + if (skb_headroom(skb) >= 2) { + memcpy(skb_push(skb, 2), header, 2); + ret = ipwireless_send_packet(network->hardware, + IPW_CHANNEL_RAS, skb->data, + skb->len, + notify_packet_sent, + network); + if (ret == -1) { + skb_pull(skb, 2); + return 0; + } + } else { + /* Otherwise (rarely) we do it inefficiently. */ + buf = kmalloc(skb->len + 2, GFP_ATOMIC); + if (!buf) + return 0; + memcpy(buf + 2, skb->data, skb->len); + memcpy(buf, header, 2); + ret = ipwireless_send_packet(network->hardware, + IPW_CHANNEL_RAS, buf, + skb->len + 2, + notify_packet_sent, + network); + kfree(buf); + if (ret == -1) + return 0; + } + kfree_skb(skb); + return 1; + } else { + /* + * Otherwise reject the packet, and flag that the ppp system + * needs to be unblocked once we are ready to send. + */ + network->ppp_blocked = 1; + spin_unlock_irqrestore(&network->lock, flags); + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n"); + return 0; + } +} + +/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */ +static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel, + unsigned int cmd, unsigned long arg) +{ + struct ipw_network *network = ppp_channel->private; + int err, val; + u32 accm[8]; + int __user *user_arg = (int __user *) arg; + + err = -EFAULT; + switch (cmd) { + case PPPIOCGFLAGS: + val = network->flags | network->rbits; + if (put_user(val, user_arg)) + break; + err = 0; + break; + + case PPPIOCSFLAGS: + if (get_user(val, user_arg)) + break; + network->flags = val & ~SC_RCV_BITS; + network->rbits = val & SC_RCV_BITS; + err = 0; + break; + + case PPPIOCGASYNCMAP: + if (put_user(network->xaccm[0], user_arg)) + break; + err = 0; + break; + + case PPPIOCSASYNCMAP: + if (get_user(network->xaccm[0], user_arg)) + break; + err = 0; + break; + + case PPPIOCGRASYNCMAP: + if (put_user(network->raccm, user_arg)) + break; + err = 0; + break; + + case PPPIOCSRASYNCMAP: + if (get_user(network->raccm, user_arg)) + break; + err = 0; + break; + + case PPPIOCGXASYNCMAP: + if (copy_to_user((void __user *) arg, network->xaccm, + sizeof(network->xaccm))) + break; + err = 0; + break; + + case PPPIOCSXASYNCMAP: + if (copy_from_user(accm, (void __user *) arg, sizeof(accm))) + break; + accm[2] &= ~0x40000000U; /* can't escape 0x5e */ + accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ + memcpy(network->xaccm, accm, sizeof(network->xaccm)); + err = 0; + break; + + case PPPIOCGMRU: + if (put_user(network->mru, user_arg)) + break; + err = 0; + break; + + case PPPIOCSMRU: + if (get_user(val, user_arg)) + break; + if (val < PPP_MRU) + val = PPP_MRU; + network->mru = val; + err = 0; + break; + + default: + err = -ENOTTY; + } + + return err; +} + +static const struct ppp_channel_ops ipwireless_ppp_channel_ops = { + .start_xmit = ipwireless_ppp_start_xmit, + .ioctl = ipwireless_ppp_ioctl +}; + +static void do_go_online(struct work_struct *work_go_online) +{ + struct ipw_network *network = + container_of(work_go_online, struct ipw_network, + work_go_online); + unsigned long flags; + + spin_lock_irqsave(&network->lock, flags); + if (!network->ppp_channel) { + struct ppp_channel *channel; + + spin_unlock_irqrestore(&network->lock, flags); + channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); + if (!channel) { + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": unable to allocate PPP channel\n"); + return; + } + channel->private = network; + channel->mtu = 16384; /* Wild guess */ + channel->hdrlen = 2; + channel->ops = &ipwireless_ppp_channel_ops; + + network->flags = 0; + network->rbits = 0; + network->mru = PPP_MRU; + memset(network->xaccm, 0, sizeof(network->xaccm)); + network->xaccm[0] = ~0U; + network->xaccm[3] = 0x60000000U; + network->raccm = ~0U; + ppp_register_channel(channel); + spin_lock_irqsave(&network->lock, flags); + network->ppp_channel = channel; + } + spin_unlock_irqrestore(&network->lock, flags); +} + +static void do_go_offline(struct work_struct *work_go_offline) +{ + struct ipw_network *network = + container_of(work_go_offline, struct ipw_network, + work_go_offline); + unsigned long flags; + + mutex_lock(&network->close_lock); + spin_lock_irqsave(&network->lock, flags); + if (network->ppp_channel != NULL) { + struct ppp_channel *channel = network->ppp_channel; + + network->ppp_channel = NULL; + spin_unlock_irqrestore(&network->lock, flags); + mutex_unlock(&network->close_lock); + ppp_unregister_channel(channel); + } else { + spin_unlock_irqrestore(&network->lock, flags); + mutex_unlock(&network->close_lock); + } +} + +void ipwireless_network_notify_control_line_change(struct ipw_network *network, + unsigned int channel_idx, + unsigned int control_lines, + unsigned int changed_mask) +{ + int i; + + if (channel_idx == IPW_CHANNEL_RAS) + network->ras_control_lines = control_lines; + + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { + struct ipw_tty *tty = + network->associated_ttys[channel_idx][i]; + + /* + * If it's associated with a tty (other than the RAS channel + * when we're online), then send the data to that tty. The RAS + * channel's data is handled above - it always goes through + * ppp_generic. + */ + if (tty) + ipwireless_tty_notify_control_line_change(tty, + channel_idx, + control_lines, + changed_mask); + } +} + +/* + * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI) + * bytes, which are required on sent packet, but not always present on received + * packets + */ +static struct sk_buff *ipw_packet_received_skb(unsigned char *data, + unsigned int length) +{ + struct sk_buff *skb; + + if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) { + length -= 2; + data += 2; + } + + skb = dev_alloc_skb(length + 4); + skb_reserve(skb, 2); + memcpy(skb_put(skb, length), data, length); + + return skb; +} + +void ipwireless_network_packet_received(struct ipw_network *network, + unsigned int channel_idx, + unsigned char *data, + unsigned int length) +{ + int i; + unsigned long flags; + + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { + struct ipw_tty *tty = network->associated_ttys[channel_idx][i]; + + if (!tty) + continue; + + /* + * If it's associated with a tty (other than the RAS channel + * when we're online), then send the data to that tty. The RAS + * channel's data is handled above - it always goes through + * ppp_generic. + */ + if (channel_idx == IPW_CHANNEL_RAS + && (network->ras_control_lines & + IPW_CONTROL_LINE_DCD) != 0 + && ipwireless_tty_is_modem(tty)) { + /* + * If data came in on the RAS channel and this tty is + * the modem tty, and we are online, then we send it to + * the PPP layer. + */ + mutex_lock(&network->close_lock); + spin_lock_irqsave(&network->lock, flags); + if (network->ppp_channel != NULL) { + struct sk_buff *skb; + + spin_unlock_irqrestore(&network->lock, + flags); + + /* Send the data to the ppp_generic module. */ + skb = ipw_packet_received_skb(data, length); + ppp_input(network->ppp_channel, skb); + } else + spin_unlock_irqrestore(&network->lock, + flags); + mutex_unlock(&network->close_lock); + } + /* Otherwise we send it out the tty. */ + else + ipwireless_tty_received(tty, data, length); + } +} + +struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) +{ + struct ipw_network *network = + kzalloc(sizeof(struct ipw_network), GFP_ATOMIC); + + if (!network) + return NULL; + + spin_lock_init(&network->lock); + mutex_init(&network->close_lock); + + network->hardware = hw; + + INIT_WORK(&network->work_go_online, do_go_online); + INIT_WORK(&network->work_go_offline, do_go_offline); + + ipwireless_associate_network(hw, network); + + return network; +} + +void ipwireless_network_free(struct ipw_network *network) +{ + network->shutting_down = 1; + + ipwireless_ppp_close(network); + flush_work_sync(&network->work_go_online); + flush_work_sync(&network->work_go_offline); + + ipwireless_stop_interrupts(network->hardware); + ipwireless_associate_network(network->hardware, NULL); + + kfree(network); +} + +void ipwireless_associate_network_tty(struct ipw_network *network, + unsigned int channel_idx, + struct ipw_tty *tty) +{ + int i; + + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) + if (network->associated_ttys[channel_idx][i] == NULL) { + network->associated_ttys[channel_idx][i] = tty; + break; + } +} + +void ipwireless_disassociate_network_ttys(struct ipw_network *network, + unsigned int channel_idx) +{ + int i; + + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) + network->associated_ttys[channel_idx][i] = NULL; +} + +void ipwireless_ppp_open(struct ipw_network *network) +{ + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n"); + schedule_work(&network->work_go_online); +} + +void ipwireless_ppp_close(struct ipw_network *network) +{ + /* Disconnect from the wireless network. */ + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n"); + schedule_work(&network->work_go_offline); +} + +int ipwireless_ppp_channel_index(struct ipw_network *network) +{ + int ret = -1; + unsigned long flags; + + spin_lock_irqsave(&network->lock, flags); + if (network->ppp_channel != NULL) + ret = ppp_channel_index(network->ppp_channel); + spin_unlock_irqrestore(&network->lock, flags); + + return ret; +} + +int ipwireless_ppp_unit_number(struct ipw_network *network) +{ + int ret = -1; + unsigned long flags; + + spin_lock_irqsave(&network->lock, flags); + if (network->ppp_channel != NULL) + ret = ppp_unit_number(network->ppp_channel); + spin_unlock_irqrestore(&network->lock, flags); + + return ret; +} + +int ipwireless_ppp_mru(const struct ipw_network *network) +{ + return network->mru; +} diff --git a/drivers/tty/ipwireless/network.h b/drivers/tty/ipwireless/network.h new file mode 100644 index 000000000000..561f765b3334 --- /dev/null +++ b/drivers/tty/ipwireless/network.h @@ -0,0 +1,53 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#ifndef _IPWIRELESS_CS_NETWORK_H_ +#define _IPWIRELESS_CS_NETWORK_H_ + +#include + +struct ipw_network; +struct ipw_tty; +struct ipw_hardware; + +/* Definitions of the different channels on the PCMCIA UE */ +#define IPW_CHANNEL_RAS 0 +#define IPW_CHANNEL_DIALLER 1 +#define IPW_CHANNEL_CONSOLE 2 +#define NO_OF_IPW_CHANNELS 5 + +void ipwireless_network_notify_control_line_change(struct ipw_network *net, + unsigned int channel_idx, unsigned int control_lines, + unsigned int control_mask); +void ipwireless_network_packet_received(struct ipw_network *net, + unsigned int channel_idx, unsigned char *data, + unsigned int length); +struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw); +void ipwireless_network_free(struct ipw_network *net); +void ipwireless_associate_network_tty(struct ipw_network *net, + unsigned int channel_idx, struct ipw_tty *tty); +void ipwireless_disassociate_network_ttys(struct ipw_network *net, + unsigned int channel_idx); + +void ipwireless_ppp_open(struct ipw_network *net); + +void ipwireless_ppp_close(struct ipw_network *net); +int ipwireless_ppp_channel_index(struct ipw_network *net); +int ipwireless_ppp_unit_number(struct ipw_network *net); +int ipwireless_ppp_mru(const struct ipw_network *net); + +#endif diff --git a/drivers/tty/ipwireless/setup_protocol.h b/drivers/tty/ipwireless/setup_protocol.h new file mode 100644 index 000000000000..9d6bcc77c73c --- /dev/null +++ b/drivers/tty/ipwireless/setup_protocol.h @@ -0,0 +1,108 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_ +#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_ + +/* Version of the setup protocol and transport protocols */ +#define TL_SETUP_VERSION 1 + +#define TL_SETUP_VERSION_QRY_TMO 1000 +#define TL_SETUP_MAX_VERSION_QRY 30 + +/* Message numbers 0-9 are obsoleted and must not be reused! */ +#define TL_SETUP_SIGNO_GET_VERSION_QRY 10 +#define TL_SETUP_SIGNO_GET_VERSION_RSP 11 +#define TL_SETUP_SIGNO_CONFIG_MSG 12 +#define TL_SETUP_SIGNO_CONFIG_DONE_MSG 13 +#define TL_SETUP_SIGNO_OPEN_MSG 14 +#define TL_SETUP_SIGNO_CLOSE_MSG 15 + +#define TL_SETUP_SIGNO_INFO_MSG 20 +#define TL_SETUP_SIGNO_INFO_MSG_ACK 21 + +#define TL_SETUP_SIGNO_REBOOT_MSG 22 +#define TL_SETUP_SIGNO_REBOOT_MSG_ACK 23 + +/* Synchronous start-messages */ +struct tl_setup_get_version_qry { + unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_QRY */ +} __attribute__ ((__packed__)); + +struct tl_setup_get_version_rsp { + unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_RSP */ + unsigned char version; /* TL_SETUP_VERSION */ +} __attribute__ ((__packed__)); + +struct tl_setup_config_msg { + unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_MSG */ + unsigned char port_no; + unsigned char prio_data; + unsigned char prio_ctrl; +} __attribute__ ((__packed__)); + +struct tl_setup_config_done_msg { + unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */ +} __attribute__ ((__packed__)); + +/* Asyncronous messages */ +struct tl_setup_open_msg { + unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */ + unsigned char port_no; +} __attribute__ ((__packed__)); + +struct tl_setup_close_msg { + unsigned char sig_no; /* TL_SETUP_SIGNO_CLOSE_MSG */ + unsigned char port_no; +} __attribute__ ((__packed__)); + +/* Driver type - for use in tl_setup_info_msg.driver_type */ +#define COMM_DRIVER 0 +#define NDISWAN_DRIVER 1 +#define NDISWAN_DRIVER_MAJOR_VERSION 2 +#define NDISWAN_DRIVER_MINOR_VERSION 0 + +/* + * It should not matter when this message comes over as we just store the + * results and send the ACK. + */ +struct tl_setup_info_msg { + unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG */ + unsigned char driver_type; + unsigned char major_version; + unsigned char minor_version; +} __attribute__ ((__packed__)); + +struct tl_setup_info_msgAck { + unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG_ACK */ +} __attribute__ ((__packed__)); + +struct TlSetupRebootMsgAck { + unsigned char sig_no; /* TL_SETUP_SIGNO_REBOOT_MSG_ACK */ +} __attribute__ ((__packed__)); + +/* Define a union of all the msgs that the driver can receive from the card.*/ +union ipw_setup_rx_msg { + unsigned char sig_no; + struct tl_setup_get_version_rsp version_rsp_msg; + struct tl_setup_open_msg open_msg; + struct tl_setup_close_msg close_msg; + struct tl_setup_info_msg InfoMsg; + struct tl_setup_info_msgAck info_msg_ack; +} __attribute__ ((__packed__)); + +#endif /* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */ diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c new file mode 100644 index 000000000000..ef92869502a7 --- /dev/null +++ b/drivers/tty/ipwireless/tty.c @@ -0,0 +1,679 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tty.h" +#include "network.h" +#include "hardware.h" +#include "main.h" + +#define IPWIRELESS_PCMCIA_START (0) +#define IPWIRELESS_PCMCIA_MINORS (24) +#define IPWIRELESS_PCMCIA_MINOR_RANGE (8) + +#define TTYTYPE_MODEM (0) +#define TTYTYPE_MONITOR (1) +#define TTYTYPE_RAS_RAW (2) + +struct ipw_tty { + int index; + struct ipw_hardware *hardware; + unsigned int channel_idx; + unsigned int secondary_channel_idx; + int tty_type; + struct ipw_network *network; + struct tty_struct *linux_tty; + int open_count; + unsigned int control_lines; + struct mutex ipw_tty_mutex; + int tx_bytes_queued; + int closing; +}; + +static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS]; + +static struct tty_driver *ipw_tty_driver; + +static char *tty_type_name(int tty_type) +{ + static char *channel_names[] = { + "modem", + "monitor", + "RAS-raw" + }; + + return channel_names[tty_type]; +} + +static void report_registering(struct ipw_tty *tty) +{ + char *iftype = tty_type_name(tty->tty_type); + + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": registering %s device ttyIPWp%d\n", iftype, tty->index); +} + +static void report_deregistering(struct ipw_tty *tty) +{ + char *iftype = tty_type_name(tty->tty_type); + + printk(KERN_INFO IPWIRELESS_PCCARD_NAME + ": deregistering %s device ttyIPWp%d\n", iftype, + tty->index); +} + +static struct ipw_tty *get_tty(int minor) +{ + if (minor < ipw_tty_driver->minor_start + || minor >= ipw_tty_driver->minor_start + + IPWIRELESS_PCMCIA_MINORS) + return NULL; + else { + int minor_offset = minor - ipw_tty_driver->minor_start; + + /* + * The 'ras_raw' channel is only available when 'loopback' mode + * is enabled. + * Number of minor starts with 16 (_RANGE * _RAS_RAW). + */ + if (!ipwireless_loopback && + minor_offset >= + IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW) + return NULL; + + return ttys[minor_offset]; + } +} + +static int ipw_open(struct tty_struct *linux_tty, struct file *filp) +{ + int minor = linux_tty->index; + struct ipw_tty *tty = get_tty(minor); + + if (!tty) + return -ENODEV; + + mutex_lock(&tty->ipw_tty_mutex); + + if (tty->closing) { + mutex_unlock(&tty->ipw_tty_mutex); + return -ENODEV; + } + if (tty->open_count == 0) + tty->tx_bytes_queued = 0; + + tty->open_count++; + + tty->linux_tty = linux_tty; + linux_tty->driver_data = tty; + linux_tty->low_latency = 1; + + if (tty->tty_type == TTYTYPE_MODEM) + ipwireless_ppp_open(tty->network); + + mutex_unlock(&tty->ipw_tty_mutex); + + return 0; +} + +static void do_ipw_close(struct ipw_tty *tty) +{ + tty->open_count--; + + if (tty->open_count == 0) { + struct tty_struct *linux_tty = tty->linux_tty; + + if (linux_tty != NULL) { + tty->linux_tty = NULL; + linux_tty->driver_data = NULL; + + if (tty->tty_type == TTYTYPE_MODEM) + ipwireless_ppp_close(tty->network); + } + } +} + +static void ipw_hangup(struct tty_struct *linux_tty) +{ + struct ipw_tty *tty = linux_tty->driver_data; + + if (!tty) + return; + + mutex_lock(&tty->ipw_tty_mutex); + if (tty->open_count == 0) { + mutex_unlock(&tty->ipw_tty_mutex); + return; + } + + do_ipw_close(tty); + + mutex_unlock(&tty->ipw_tty_mutex); +} + +static void ipw_close(struct tty_struct *linux_tty, struct file *filp) +{ + ipw_hangup(linux_tty); +} + +/* Take data received from hardware, and send it out the tty */ +void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, + unsigned int length) +{ + struct tty_struct *linux_tty; + int work = 0; + + mutex_lock(&tty->ipw_tty_mutex); + linux_tty = tty->linux_tty; + if (linux_tty == NULL) { + mutex_unlock(&tty->ipw_tty_mutex); + return; + } + + if (!tty->open_count) { + mutex_unlock(&tty->ipw_tty_mutex); + return; + } + mutex_unlock(&tty->ipw_tty_mutex); + + work = tty_insert_flip_string(linux_tty, data, length); + + if (work != length) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME + ": %d chars not inserted to flip buffer!\n", + length - work); + + /* + * This may sleep if ->low_latency is set + */ + if (work) + tty_flip_buffer_push(linux_tty); +} + +static void ipw_write_packet_sent_callback(void *callback_data, + unsigned int packet_length) +{ + struct ipw_tty *tty = callback_data; + + /* + * Packet has been sent, so we subtract the number of bytes from our + * tally of outstanding TX bytes. + */ + tty->tx_bytes_queued -= packet_length; +} + +static int ipw_write(struct tty_struct *linux_tty, + const unsigned char *buf, int count) +{ + struct ipw_tty *tty = linux_tty->driver_data; + int room, ret; + + if (!tty) + return -ENODEV; + + mutex_lock(&tty->ipw_tty_mutex); + if (!tty->open_count) { + mutex_unlock(&tty->ipw_tty_mutex); + return -EINVAL; + } + + room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; + if (room < 0) + room = 0; + /* Don't allow caller to write any more than we have room for */ + if (count > room) + count = room; + + if (count == 0) { + mutex_unlock(&tty->ipw_tty_mutex); + return 0; + } + + ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, + buf, count, + ipw_write_packet_sent_callback, tty); + if (ret == -1) { + mutex_unlock(&tty->ipw_tty_mutex); + return 0; + } + + tty->tx_bytes_queued += count; + mutex_unlock(&tty->ipw_tty_mutex); + + return count; +} + +static int ipw_write_room(struct tty_struct *linux_tty) +{ + struct ipw_tty *tty = linux_tty->driver_data; + int room; + + /* FIXME: Exactly how is the tty object locked here .. */ + if (!tty) + return -ENODEV; + + if (!tty->open_count) + return -EINVAL; + + room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; + if (room < 0) + room = 0; + + return room; +} + +static int ipwireless_get_serial_info(struct ipw_tty *tty, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return (-EFAULT); + + memset(&tmp, 0, sizeof(tmp)); + tmp.type = PORT_UNKNOWN; + tmp.line = tty->index; + tmp.port = 0; + tmp.irq = 0; + tmp.flags = 0; + tmp.baud_base = 115200; + tmp.close_delay = 0; + tmp.closing_wait = 0; + tmp.custom_divisor = 0; + tmp.hub6 = 0; + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + + return 0; +} + +static int ipw_chars_in_buffer(struct tty_struct *linux_tty) +{ + struct ipw_tty *tty = linux_tty->driver_data; + + if (!tty) + return 0; + + if (!tty->open_count) + return 0; + + return tty->tx_bytes_queued; +} + +static int get_control_lines(struct ipw_tty *tty) +{ + unsigned int my = tty->control_lines; + unsigned int out = 0; + + if (my & IPW_CONTROL_LINE_RTS) + out |= TIOCM_RTS; + if (my & IPW_CONTROL_LINE_DTR) + out |= TIOCM_DTR; + if (my & IPW_CONTROL_LINE_CTS) + out |= TIOCM_CTS; + if (my & IPW_CONTROL_LINE_DSR) + out |= TIOCM_DSR; + if (my & IPW_CONTROL_LINE_DCD) + out |= TIOCM_CD; + + return out; +} + +static int set_control_lines(struct ipw_tty *tty, unsigned int set, + unsigned int clear) +{ + int ret; + + if (set & TIOCM_RTS) { + ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1); + if (ret) + return ret; + if (tty->secondary_channel_idx != -1) { + ret = ipwireless_set_RTS(tty->hardware, + tty->secondary_channel_idx, 1); + if (ret) + return ret; + } + } + if (set & TIOCM_DTR) { + ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1); + if (ret) + return ret; + if (tty->secondary_channel_idx != -1) { + ret = ipwireless_set_DTR(tty->hardware, + tty->secondary_channel_idx, 1); + if (ret) + return ret; + } + } + if (clear & TIOCM_RTS) { + ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0); + if (tty->secondary_channel_idx != -1) { + ret = ipwireless_set_RTS(tty->hardware, + tty->secondary_channel_idx, 0); + if (ret) + return ret; + } + } + if (clear & TIOCM_DTR) { + ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0); + if (tty->secondary_channel_idx != -1) { + ret = ipwireless_set_DTR(tty->hardware, + tty->secondary_channel_idx, 0); + if (ret) + return ret; + } + } + return 0; +} + +static int ipw_tiocmget(struct tty_struct *linux_tty) +{ + struct ipw_tty *tty = linux_tty->driver_data; + /* FIXME: Exactly how is the tty object locked here .. */ + + if (!tty) + return -ENODEV; + + if (!tty->open_count) + return -EINVAL; + + return get_control_lines(tty); +} + +static int +ipw_tiocmset(struct tty_struct *linux_tty, + unsigned int set, unsigned int clear) +{ + struct ipw_tty *tty = linux_tty->driver_data; + /* FIXME: Exactly how is the tty object locked here .. */ + + if (!tty) + return -ENODEV; + + if (!tty->open_count) + return -EINVAL; + + return set_control_lines(tty, set, clear); +} + +static int ipw_ioctl(struct tty_struct *linux_tty, + unsigned int cmd, unsigned long arg) +{ + struct ipw_tty *tty = linux_tty->driver_data; + + if (!tty) + return -ENODEV; + + if (!tty->open_count) + return -EINVAL; + + /* FIXME: Exactly how is the tty object locked here .. */ + + switch (cmd) { + case TIOCGSERIAL: + return ipwireless_get_serial_info(tty, (void __user *) arg); + + case TIOCSSERIAL: + return 0; /* Keeps the PCMCIA scripts happy. */ + } + + if (tty->tty_type == TTYTYPE_MODEM) { + switch (cmd) { + case PPPIOCGCHAN: + { + int chan = ipwireless_ppp_channel_index( + tty->network); + + if (chan < 0) + return -ENODEV; + if (put_user(chan, (int __user *) arg)) + return -EFAULT; + } + return 0; + + case PPPIOCGUNIT: + { + int unit = ipwireless_ppp_unit_number( + tty->network); + + if (unit < 0) + return -ENODEV; + if (put_user(unit, (int __user *) arg)) + return -EFAULT; + } + return 0; + + case FIONREAD: + { + int val = 0; + + if (put_user(val, (int __user *) arg)) + return -EFAULT; + } + return 0; + case TCFLSH: + return tty_perform_flush(linux_tty, arg); + } + } + return -ENOIOCTLCMD; +} + +static int add_tty(int j, + struct ipw_hardware *hardware, + struct ipw_network *network, int channel_idx, + int secondary_channel_idx, int tty_type) +{ + ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL); + if (!ttys[j]) + return -ENOMEM; + ttys[j]->index = j; + ttys[j]->hardware = hardware; + ttys[j]->channel_idx = channel_idx; + ttys[j]->secondary_channel_idx = secondary_channel_idx; + ttys[j]->network = network; + ttys[j]->tty_type = tty_type; + mutex_init(&ttys[j]->ipw_tty_mutex); + + tty_register_device(ipw_tty_driver, j, NULL); + ipwireless_associate_network_tty(network, channel_idx, ttys[j]); + + if (secondary_channel_idx != -1) + ipwireless_associate_network_tty(network, + secondary_channel_idx, + ttys[j]); + if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j]) + report_registering(ttys[j]); + return 0; +} + +struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, + struct ipw_network *network) +{ + int i, j; + + for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) { + int allfree = 1; + + for (j = i; j < IPWIRELESS_PCMCIA_MINORS; + j += IPWIRELESS_PCMCIA_MINOR_RANGE) + if (ttys[j] != NULL) { + allfree = 0; + break; + } + + if (allfree) { + j = i; + + if (add_tty(j, hardware, network, + IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS, + TTYTYPE_MODEM)) + return NULL; + + j += IPWIRELESS_PCMCIA_MINOR_RANGE; + if (add_tty(j, hardware, network, + IPW_CHANNEL_DIALLER, -1, + TTYTYPE_MONITOR)) + return NULL; + + j += IPWIRELESS_PCMCIA_MINOR_RANGE; + if (add_tty(j, hardware, network, + IPW_CHANNEL_RAS, -1, + TTYTYPE_RAS_RAW)) + return NULL; + + return ttys[i]; + } + } + return NULL; +} + +/* + * Must be called before ipwireless_network_free(). + */ +void ipwireless_tty_free(struct ipw_tty *tty) +{ + int j; + struct ipw_network *network = ttys[tty->index]->network; + + for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS; + j += IPWIRELESS_PCMCIA_MINOR_RANGE) { + struct ipw_tty *ttyj = ttys[j]; + + if (ttyj) { + mutex_lock(&ttyj->ipw_tty_mutex); + if (get_tty(j + ipw_tty_driver->minor_start) == ttyj) + report_deregistering(ttyj); + ttyj->closing = 1; + if (ttyj->linux_tty != NULL) { + mutex_unlock(&ttyj->ipw_tty_mutex); + tty_hangup(ttyj->linux_tty); + /* Wait till the tty_hangup has completed */ + flush_work_sync(&ttyj->linux_tty->hangup_work); + /* FIXME: Exactly how is the tty object locked here + against a parallel ioctl etc */ + mutex_lock(&ttyj->ipw_tty_mutex); + } + while (ttyj->open_count) + do_ipw_close(ttyj); + ipwireless_disassociate_network_ttys(network, + ttyj->channel_idx); + tty_unregister_device(ipw_tty_driver, j); + ttys[j] = NULL; + mutex_unlock(&ttyj->ipw_tty_mutex); + kfree(ttyj); + } + } +} + +static const struct tty_operations tty_ops = { + .open = ipw_open, + .close = ipw_close, + .hangup = ipw_hangup, + .write = ipw_write, + .write_room = ipw_write_room, + .ioctl = ipw_ioctl, + .chars_in_buffer = ipw_chars_in_buffer, + .tiocmget = ipw_tiocmget, + .tiocmset = ipw_tiocmset, +}; + +int ipwireless_tty_init(void) +{ + int result; + + ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS); + if (!ipw_tty_driver) + return -ENOMEM; + + ipw_tty_driver->owner = THIS_MODULE; + ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME; + ipw_tty_driver->name = "ttyIPWp"; + ipw_tty_driver->major = 0; + ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START; + ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL; + ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + ipw_tty_driver->init_termios = tty_std_termios; + ipw_tty_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + ipw_tty_driver->init_termios.c_ispeed = 9600; + ipw_tty_driver->init_termios.c_ospeed = 9600; + tty_set_operations(ipw_tty_driver, &tty_ops); + result = tty_register_driver(ipw_tty_driver); + if (result) { + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": failed to register tty driver\n"); + put_tty_driver(ipw_tty_driver); + return result; + } + + return 0; +} + +void ipwireless_tty_release(void) +{ + int ret; + + ret = tty_unregister_driver(ipw_tty_driver); + put_tty_driver(ipw_tty_driver); + if (ret != 0) + printk(KERN_ERR IPWIRELESS_PCCARD_NAME + ": tty_unregister_driver failed with code %d\n", ret); +} + +int ipwireless_tty_is_modem(struct ipw_tty *tty) +{ + return tty->tty_type == TTYTYPE_MODEM; +} + +void +ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, + unsigned int channel_idx, + unsigned int control_lines, + unsigned int changed_mask) +{ + unsigned int old_control_lines = tty->control_lines; + + tty->control_lines = (tty->control_lines & ~changed_mask) + | (control_lines & changed_mask); + + /* + * If DCD is de-asserted, we close the tty so pppd can tell that we + * have gone offline. + */ + if ((old_control_lines & IPW_CONTROL_LINE_DCD) + && !(tty->control_lines & IPW_CONTROL_LINE_DCD) + && tty->linux_tty) { + tty_hangup(tty->linux_tty); + } +} + diff --git a/drivers/tty/ipwireless/tty.h b/drivers/tty/ipwireless/tty.h new file mode 100644 index 000000000000..747b2d637860 --- /dev/null +++ b/drivers/tty/ipwireless/tty.h @@ -0,0 +1,45 @@ +/* + * IPWireless 3G PCMCIA Network Driver + * + * Original code + * by Stephen Blackheath , + * Ben Martel + * + * Copyrighted as follows: + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) + * + * Various driver changes and rewrites, port to new kernels + * Copyright (C) 2006-2007 Jiri Kosina + * + * Misc code cleanups and updates + * Copyright (C) 2007 David Sterba + */ + +#ifndef _IPWIRELESS_CS_TTY_H_ +#define _IPWIRELESS_CS_TTY_H_ + +#include +#include + +#include +#include + +struct ipw_tty; +struct ipw_network; +struct ipw_hardware; + +int ipwireless_tty_init(void); +void ipwireless_tty_release(void); + +struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw, + struct ipw_network *net); +void ipwireless_tty_free(struct ipw_tty *tty); +void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, + unsigned int length); +int ipwireless_tty_is_modem(struct ipw_tty *tty); +void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, + unsigned int channel_idx, + unsigned int control_lines, + unsigned int changed_mask); + +#endif -- cgit v1.2.3 From 4a6514e6d096716fb7bedf238efaaca877e2a7e8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Feb 2011 16:57:21 -0800 Subject: tty: move obsolete and broken tty drivers to drivers/staging/tty/ As planned by Arnd Bergmann, this moves the following drivers to the drivers/staging/tty/ directory where they will be removed after 2.6.41 if no one steps up to claim them. epca epca ip2 istallion riscom8 serial167 specialix stallion Cc: Arnd Bergmann Cc: Alan Cox Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/m68k/Kconfig | 8 - drivers/char/Kconfig | 79 - drivers/char/Makefile | 7 - drivers/char/epca.c | 2784 --------------------- drivers/char/epca.h | 158 -- drivers/char/epcaconfig.h | 7 - drivers/char/ip2/Makefile | 8 - drivers/char/ip2/i2cmd.c | 210 -- drivers/char/ip2/i2cmd.h | 630 ----- drivers/char/ip2/i2ellis.c | 1403 ----------- drivers/char/ip2/i2ellis.h | 566 ----- drivers/char/ip2/i2hw.h | 652 ----- drivers/char/ip2/i2lib.c | 2214 ----------------- drivers/char/ip2/i2lib.h | 351 --- drivers/char/ip2/i2pack.h | 364 --- drivers/char/ip2/ip2.h | 107 - drivers/char/ip2/ip2ioctl.h | 35 - drivers/char/ip2/ip2main.c | 3234 ------------------------ drivers/char/ip2/ip2trace.h | 42 - drivers/char/ip2/ip2types.h | 57 - drivers/char/istallion.c | 4507 --------------------------------- drivers/char/riscom8.c | 1560 ------------ drivers/char/riscom8.h | 91 - drivers/char/riscom8_reg.h | 254 -- drivers/char/serial167.c | 2489 ------------------- drivers/char/specialix.c | 2368 ------------------ drivers/char/specialix_io8.h | 140 -- drivers/char/stallion.c | 4651 ----------------------------------- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/tty/Kconfig | 87 + drivers/staging/tty/Makefile | 7 + drivers/staging/tty/TODO | 6 + drivers/staging/tty/epca.c | 2784 +++++++++++++++++++++ drivers/staging/tty/epca.h | 158 ++ drivers/staging/tty/epcaconfig.h | 7 + drivers/staging/tty/ip2/Makefile | 8 + drivers/staging/tty/ip2/i2cmd.c | 210 ++ drivers/staging/tty/ip2/i2cmd.h | 630 +++++ drivers/staging/tty/ip2/i2ellis.c | 1403 +++++++++++ drivers/staging/tty/ip2/i2ellis.h | 566 +++++ drivers/staging/tty/ip2/i2hw.h | 652 +++++ drivers/staging/tty/ip2/i2lib.c | 2214 +++++++++++++++++ drivers/staging/tty/ip2/i2lib.h | 351 +++ drivers/staging/tty/ip2/i2pack.h | 364 +++ drivers/staging/tty/ip2/ip2.h | 107 + drivers/staging/tty/ip2/ip2ioctl.h | 35 + drivers/staging/tty/ip2/ip2main.c | 3234 ++++++++++++++++++++++++ drivers/staging/tty/ip2/ip2trace.h | 42 + drivers/staging/tty/ip2/ip2types.h | 57 + drivers/staging/tty/istallion.c | 4507 +++++++++++++++++++++++++++++++++ drivers/staging/tty/riscom8.c | 1560 ++++++++++++ drivers/staging/tty/riscom8.h | 91 + drivers/staging/tty/riscom8_reg.h | 254 ++ drivers/staging/tty/serial167.c | 2489 +++++++++++++++++++ drivers/staging/tty/specialix.c | 2368 ++++++++++++++++++ drivers/staging/tty/specialix_io8.h | 140 ++ drivers/staging/tty/stallion.c | 4651 +++++++++++++++++++++++++++++++++++ 58 files changed, 28985 insertions(+), 28976 deletions(-) delete mode 100644 drivers/char/epca.c delete mode 100644 drivers/char/epca.h delete mode 100644 drivers/char/epcaconfig.h delete mode 100644 drivers/char/ip2/Makefile delete mode 100644 drivers/char/ip2/i2cmd.c delete mode 100644 drivers/char/ip2/i2cmd.h delete mode 100644 drivers/char/ip2/i2ellis.c delete mode 100644 drivers/char/ip2/i2ellis.h delete mode 100644 drivers/char/ip2/i2hw.h delete mode 100644 drivers/char/ip2/i2lib.c delete mode 100644 drivers/char/ip2/i2lib.h delete mode 100644 drivers/char/ip2/i2pack.h delete mode 100644 drivers/char/ip2/ip2.h delete mode 100644 drivers/char/ip2/ip2ioctl.h delete mode 100644 drivers/char/ip2/ip2main.c delete mode 100644 drivers/char/ip2/ip2trace.h delete mode 100644 drivers/char/ip2/ip2types.h delete mode 100644 drivers/char/istallion.c delete mode 100644 drivers/char/riscom8.c delete mode 100644 drivers/char/riscom8.h delete mode 100644 drivers/char/riscom8_reg.h delete mode 100644 drivers/char/serial167.c delete mode 100644 drivers/char/specialix.c delete mode 100644 drivers/char/specialix_io8.h delete mode 100644 drivers/char/stallion.c create mode 100644 drivers/staging/tty/Kconfig create mode 100644 drivers/staging/tty/Makefile create mode 100644 drivers/staging/tty/TODO create mode 100644 drivers/staging/tty/epca.c create mode 100644 drivers/staging/tty/epca.h create mode 100644 drivers/staging/tty/epcaconfig.h create mode 100644 drivers/staging/tty/ip2/Makefile create mode 100644 drivers/staging/tty/ip2/i2cmd.c create mode 100644 drivers/staging/tty/ip2/i2cmd.h create mode 100644 drivers/staging/tty/ip2/i2ellis.c create mode 100644 drivers/staging/tty/ip2/i2ellis.h create mode 100644 drivers/staging/tty/ip2/i2hw.h create mode 100644 drivers/staging/tty/ip2/i2lib.c create mode 100644 drivers/staging/tty/ip2/i2lib.h create mode 100644 drivers/staging/tty/ip2/i2pack.h create mode 100644 drivers/staging/tty/ip2/ip2.h create mode 100644 drivers/staging/tty/ip2/ip2ioctl.h create mode 100644 drivers/staging/tty/ip2/ip2main.c create mode 100644 drivers/staging/tty/ip2/ip2trace.h create mode 100644 drivers/staging/tty/ip2/ip2types.h create mode 100644 drivers/staging/tty/istallion.c create mode 100644 drivers/staging/tty/riscom8.c create mode 100644 drivers/staging/tty/riscom8.h create mode 100644 drivers/staging/tty/riscom8_reg.h create mode 100644 drivers/staging/tty/serial167.c create mode 100644 drivers/staging/tty/specialix.c create mode 100644 drivers/staging/tty/specialix_io8.h create mode 100644 drivers/staging/tty/stallion.c (limited to 'drivers/char') diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index bc9271b85759..a85e251c411f 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -554,14 +554,6 @@ config MVME147_SCC This is the driver for the serial ports on the Motorola MVME147 boards. Everyone using one of these boards should say Y here. -config SERIAL167 - bool "CD2401 support for MVME166/7 serial ports" - depends on MVME16x - help - This is the driver for the serial ports on the Motorola MVME166, - 167, and 172 boards. Everyone using one of these boards should say - Y here. - config MVME162_SCC bool "SCC support for MVME162 serial ports" depends on MVME16x && BROKEN diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 1adfac6a7b0b..7b8cf0295f6c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -15,63 +15,6 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". -config COMPUTONE - tristate "Computone IntelliPort Plus serial support" - depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) - ---help--- - This driver supports the entire family of Intelliport II/Plus - controllers with the exception of the MicroChannel controllers and - products previous to the Intelliport II. These are multiport cards, - which give you many serial ports. You would need something like this - to connect more than two modems to your Linux box, for instance in - order to become a dial-in server. If you have a card like that, say - Y here and read . - - To compile this driver as module, choose M here: the - module will be called ip2. - -config DIGIEPCA - tristate "Digiboard Intelligent Async Support" - depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) - ---help--- - This is a driver for Digi International's Xx, Xeve, and Xem series - of cards which provide multiple serial ports. You would need - something like this to connect more than two modems to your Linux - box, for instance in order to become a dial-in server. This driver - supports the original PC (ISA) boards as well as PCI, and EISA. If - you have a card like this, say Y here and read the file - . - - To compile this driver as a module, choose M here: the - module will be called epca. - -config RISCOM8 - tristate "SDL RISCom/8 card support" - depends on SERIAL_NONSTANDARD - help - This is a driver for the SDL Communications RISCom/8 multiport card, - which gives you many serial ports. You would need something like - this to connect more than two modems to your Linux box, for instance - in order to become a dial-in server. If you have a card like that, - say Y here and read the file . - - Also it's possible to say M here and compile this driver as kernel - loadable module; the module will be called riscom8. - -config SPECIALIX - tristate "Specialix IO8+ card support" - depends on SERIAL_NONSTANDARD - help - This is a driver for the Specialix IO8+ multiport card (both the - ISA and the PCI version) which gives you many serial ports. You - would need something like this to connect more than two modems to - your Linux box, for instance in order to become a dial-in server. - - If you have a card like that, say Y here and read the file - . Also it's possible to say - M here and compile this driver as kernel loadable module which will be - called specialix. - config SX tristate "Specialix SX (and SI) card support" depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN @@ -112,28 +55,6 @@ config STALDRV in this case. If you have never heard about all this, it's safe to say N. -config STALLION - tristate "Stallion EasyIO or EC8/32 support" - depends on STALDRV && (ISA || EISA || PCI) - help - If you have an EasyIO or EasyConnection 8/32 multiport Stallion - card, then this is for you; say Y. Make sure to read - . - - To compile this driver as a module, choose M here: the - module will be called stallion. - -config ISTALLION - tristate "Stallion EC8/64, ONboard, Brumby support" - depends on STALDRV && (ISA || EISA || PCI) - help - If you have an EasyConnection 8/64, ONboard, Brumby or Stallion - serial multiport card, say Y here. Make sure to read - . - - To compile this driver as a module, choose M here: the - module will be called istallion. - config A2232 tristate "Commodore A2232 serial support (EXPERIMENTAL)" depends on EXPERIMENTAL && ZORRO && BROKEN diff --git a/drivers/char/Makefile b/drivers/char/Makefile index f5dc7c9bce6b..48bb8acbea49 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -8,15 +8,8 @@ obj-y += misc.o obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o -obj-$(CONFIG_SERIAL167) += serial167.o -obj-$(CONFIG_STALLION) += stallion.o -obj-$(CONFIG_ISTALLION) += istallion.o -obj-$(CONFIG_DIGIEPCA) += epca.o -obj-$(CONFIG_SPECIALIX) += specialix.o obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o -obj-$(CONFIG_COMPUTONE) += ip2/ -obj-$(CONFIG_RISCOM8) += riscom8.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_RAW_DRIVER) += raw.o diff --git a/drivers/char/epca.c b/drivers/char/epca.c deleted file mode 100644 index 7ad3638967ae..000000000000 --- a/drivers/char/epca.c +++ /dev/null @@ -1,2784 +0,0 @@ -/* - Copyright (C) 1996 Digi International. - - For technical support please email digiLinux@dgii.com or - call Digi tech support at (612) 912-3456 - - ** This driver is no longer supported by Digi ** - - Much of this design and code came from epca.c which was - copyright (C) 1994, 1995 Troy De Jongh, and subsquently - modified by David Nugent, Christoph Lameter, Mike McLagan. - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* See README.epca for change history --DAT*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "digiPCI.h" - - -#include "digi1.h" -#include "digiFep1.h" -#include "epca.h" -#include "epcaconfig.h" - -#define VERSION "1.3.0.1-LK2.6" - -/* This major needs to be submitted to Linux to join the majors list */ -#define DIGIINFOMAJOR 35 /* For Digi specific ioctl */ - - -#define MAXCARDS 7 -#define epcaassert(x, msg) if (!(x)) epca_error(__LINE__, msg) - -#define PFX "epca: " - -static int nbdevs, num_cards, liloconfig; -static int digi_poller_inhibited = 1 ; - -static int setup_error_code; -static int invalid_lilo_config; - -/* - * The ISA boards do window flipping into the same spaces so its only sane with - * a single lock. It's still pretty efficient. This lock guards the hardware - * and the tty_port lock guards the kernel side stuff like use counts. Take - * this lock inside the port lock if you must take both. - */ -static DEFINE_SPINLOCK(epca_lock); - -/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted - to 7 below. */ -static struct board_info boards[MAXBOARDS]; - -static struct tty_driver *pc_driver; -static struct tty_driver *pc_info; - -/* ------------------ Begin Digi specific structures -------------------- */ - -/* - * digi_channels represents an array of structures that keep track of each - * channel of the Digi product. Information such as transmit and receive - * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored - * here. This structure is NOT used to overlay the cards physical channel - * structure. - */ -static struct channel digi_channels[MAX_ALLOC]; - -/* - * card_ptr is an array used to hold the address of the first channel structure - * of each card. This array will hold the addresses of various channels located - * in digi_channels. - */ -static struct channel *card_ptr[MAXCARDS]; - -static struct timer_list epca_timer; - -/* - * Begin generic memory functions. These functions will be alias (point at) - * more specific functions dependent on the board being configured. - */ -static void memwinon(struct board_info *b, unsigned int win); -static void memwinoff(struct board_info *b, unsigned int win); -static void globalwinon(struct channel *ch); -static void rxwinon(struct channel *ch); -static void txwinon(struct channel *ch); -static void memoff(struct channel *ch); -static void assertgwinon(struct channel *ch); -static void assertmemoff(struct channel *ch); - -/* ---- Begin more 'specific' memory functions for cx_like products --- */ - -static void pcxem_memwinon(struct board_info *b, unsigned int win); -static void pcxem_memwinoff(struct board_info *b, unsigned int win); -static void pcxem_globalwinon(struct channel *ch); -static void pcxem_rxwinon(struct channel *ch); -static void pcxem_txwinon(struct channel *ch); -static void pcxem_memoff(struct channel *ch); - -/* ------ Begin more 'specific' memory functions for the pcxe ------- */ - -static void pcxe_memwinon(struct board_info *b, unsigned int win); -static void pcxe_memwinoff(struct board_info *b, unsigned int win); -static void pcxe_globalwinon(struct channel *ch); -static void pcxe_rxwinon(struct channel *ch); -static void pcxe_txwinon(struct channel *ch); -static void pcxe_memoff(struct channel *ch); - -/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ -/* Note : pc64xe and pcxi share the same windowing routines */ - -static void pcxi_memwinon(struct board_info *b, unsigned int win); -static void pcxi_memwinoff(struct board_info *b, unsigned int win); -static void pcxi_globalwinon(struct channel *ch); -static void pcxi_rxwinon(struct channel *ch); -static void pcxi_txwinon(struct channel *ch); -static void pcxi_memoff(struct channel *ch); - -/* - Begin 'specific' do nothing memory functions needed for some cards - */ - -static void dummy_memwinon(struct board_info *b, unsigned int win); -static void dummy_memwinoff(struct board_info *b, unsigned int win); -static void dummy_globalwinon(struct channel *ch); -static void dummy_rxwinon(struct channel *ch); -static void dummy_txwinon(struct channel *ch); -static void dummy_memoff(struct channel *ch); -static void dummy_assertgwinon(struct channel *ch); -static void dummy_assertmemoff(struct channel *ch); - -static struct channel *verifyChannel(struct tty_struct *); -static void pc_sched_event(struct channel *, int); -static void epca_error(int, char *); -static void pc_close(struct tty_struct *, struct file *); -static void shutdown(struct channel *, struct tty_struct *tty); -static void pc_hangup(struct tty_struct *); -static int pc_write_room(struct tty_struct *); -static int pc_chars_in_buffer(struct tty_struct *); -static void pc_flush_buffer(struct tty_struct *); -static void pc_flush_chars(struct tty_struct *); -static int pc_open(struct tty_struct *, struct file *); -static void post_fep_init(unsigned int crd); -static void epcapoll(unsigned long); -static void doevent(int); -static void fepcmd(struct channel *, int, int, int, int, int); -static unsigned termios2digi_h(struct channel *ch, unsigned); -static unsigned termios2digi_i(struct channel *ch, unsigned); -static unsigned termios2digi_c(struct channel *ch, unsigned); -static void epcaparam(struct tty_struct *, struct channel *); -static void receive_data(struct channel *, struct tty_struct *tty); -static int pc_ioctl(struct tty_struct *, - unsigned int, unsigned long); -static int info_ioctl(struct tty_struct *, - unsigned int, unsigned long); -static void pc_set_termios(struct tty_struct *, struct ktermios *); -static void do_softint(struct work_struct *work); -static void pc_stop(struct tty_struct *); -static void pc_start(struct tty_struct *); -static void pc_throttle(struct tty_struct *tty); -static void pc_unthrottle(struct tty_struct *tty); -static int pc_send_break(struct tty_struct *tty, int msec); -static void setup_empty_event(struct tty_struct *tty, struct channel *ch); - -static int pc_write(struct tty_struct *, const unsigned char *, int); -static int pc_init(void); -static int init_PCI(void); - -/* - * Table of functions for each board to handle memory. Mantaining parallelism - * is a *very* good idea here. The idea is for the runtime code to blindly call - * these functions, not knowing/caring about the underlying hardware. This - * stuff should contain no conditionals; if more functionality is needed a - * different entry should be established. These calls are the interface calls - * and are the only functions that should be accessed. Anyone caught making - * direct calls deserves what they get. - */ -static void memwinon(struct board_info *b, unsigned int win) -{ - b->memwinon(b, win); -} - -static void memwinoff(struct board_info *b, unsigned int win) -{ - b->memwinoff(b, win); -} - -static void globalwinon(struct channel *ch) -{ - ch->board->globalwinon(ch); -} - -static void rxwinon(struct channel *ch) -{ - ch->board->rxwinon(ch); -} - -static void txwinon(struct channel *ch) -{ - ch->board->txwinon(ch); -} - -static void memoff(struct channel *ch) -{ - ch->board->memoff(ch); -} -static void assertgwinon(struct channel *ch) -{ - ch->board->assertgwinon(ch); -} - -static void assertmemoff(struct channel *ch) -{ - ch->board->assertmemoff(ch); -} - -/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */ -static void pcxem_memwinon(struct board_info *b, unsigned int win) -{ - outb_p(FEPWIN | win, b->port + 1); -} - -static void pcxem_memwinoff(struct board_info *b, unsigned int win) -{ - outb_p(0, b->port + 1); -} - -static void pcxem_globalwinon(struct channel *ch) -{ - outb_p(FEPWIN, (int)ch->board->port + 1); -} - -static void pcxem_rxwinon(struct channel *ch) -{ - outb_p(ch->rxwin, (int)ch->board->port + 1); -} - -static void pcxem_txwinon(struct channel *ch) -{ - outb_p(ch->txwin, (int)ch->board->port + 1); -} - -static void pcxem_memoff(struct channel *ch) -{ - outb_p(0, (int)ch->board->port + 1); -} - -/* ----------------- Begin pcxe memory window stuff ------------------ */ -static void pcxe_memwinon(struct board_info *b, unsigned int win) -{ - outb_p(FEPWIN | win, b->port + 1); -} - -static void pcxe_memwinoff(struct board_info *b, unsigned int win) -{ - outb_p(inb(b->port) & ~FEPMEM, b->port + 1); - outb_p(0, b->port + 1); -} - -static void pcxe_globalwinon(struct channel *ch) -{ - outb_p(FEPWIN, (int)ch->board->port + 1); -} - -static void pcxe_rxwinon(struct channel *ch) -{ - outb_p(ch->rxwin, (int)ch->board->port + 1); -} - -static void pcxe_txwinon(struct channel *ch) -{ - outb_p(ch->txwin, (int)ch->board->port + 1); -} - -static void pcxe_memoff(struct channel *ch) -{ - outb_p(0, (int)ch->board->port); - outb_p(0, (int)ch->board->port + 1); -} - -/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ -static void pcxi_memwinon(struct board_info *b, unsigned int win) -{ - outb_p(inb(b->port) | FEPMEM, b->port); -} - -static void pcxi_memwinoff(struct board_info *b, unsigned int win) -{ - outb_p(inb(b->port) & ~FEPMEM, b->port); -} - -static void pcxi_globalwinon(struct channel *ch) -{ - outb_p(FEPMEM, ch->board->port); -} - -static void pcxi_rxwinon(struct channel *ch) -{ - outb_p(FEPMEM, ch->board->port); -} - -static void pcxi_txwinon(struct channel *ch) -{ - outb_p(FEPMEM, ch->board->port); -} - -static void pcxi_memoff(struct channel *ch) -{ - outb_p(0, ch->board->port); -} - -static void pcxi_assertgwinon(struct channel *ch) -{ - epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off"); -} - -static void pcxi_assertmemoff(struct channel *ch) -{ - epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on"); -} - -/* - * Not all of the cards need specific memory windowing routines. Some cards - * (Such as PCI) needs no windowing routines at all. We provide these do - * nothing routines so that the same code base can be used. The driver will - * ALWAYS call a windowing routine if it thinks it needs to; regardless of the - * card. However, dependent on the card the routine may or may not do anything. - */ -static void dummy_memwinon(struct board_info *b, unsigned int win) -{ -} - -static void dummy_memwinoff(struct board_info *b, unsigned int win) -{ -} - -static void dummy_globalwinon(struct channel *ch) -{ -} - -static void dummy_rxwinon(struct channel *ch) -{ -} - -static void dummy_txwinon(struct channel *ch) -{ -} - -static void dummy_memoff(struct channel *ch) -{ -} - -static void dummy_assertgwinon(struct channel *ch) -{ -} - -static void dummy_assertmemoff(struct channel *ch) -{ -} - -static struct channel *verifyChannel(struct tty_struct *tty) -{ - /* - * This routine basically provides a sanity check. It insures that the - * channel returned is within the proper range of addresses as well as - * properly initialized. If some bogus info gets passed in - * through tty->driver_data this should catch it. - */ - if (tty) { - struct channel *ch = tty->driver_data; - if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { - if (ch->magic == EPCA_MAGIC) - return ch; - } - } - return NULL; -} - -static void pc_sched_event(struct channel *ch, int event) -{ - /* - * We call this to schedule interrupt processing on some event. The - * kernel sees our request and calls the related routine in OUR driver. - */ - ch->event |= 1 << event; - schedule_work(&ch->tqueue); -} - -static void epca_error(int line, char *msg) -{ - printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg); -} - -static void pc_close(struct tty_struct *tty, struct file *filp) -{ - struct channel *ch; - struct tty_port *port; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch == NULL) - return; - port = &ch->port; - - if (tty_port_close_start(port, tty, filp) == 0) - return; - - pc_flush_buffer(tty); - shutdown(ch, tty); - - tty_port_close_end(port, tty); - ch->event = 0; /* FIXME: review ch->event locking */ - tty_port_tty_set(port, NULL); -} - -static void shutdown(struct channel *ch, struct tty_struct *tty) -{ - unsigned long flags; - struct board_chan __iomem *bc; - struct tty_port *port = &ch->port; - - if (!(port->flags & ASYNC_INITIALIZED)) - return; - - spin_lock_irqsave(&epca_lock, flags); - - globalwinon(ch); - bc = ch->brdchan; - - /* - * In order for an event to be generated on the receipt of data the - * idata flag must be set. Since we are shutting down, this is not - * necessary clear this flag. - */ - if (bc) - writeb(0, &bc->idata); - - /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */ - if (tty->termios->c_cflag & HUPCL) { - ch->omodem &= ~(ch->m_rts | ch->m_dtr); - fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); - } - memoff(ch); - - /* - * The channel has officialy been closed. The next time it is opened it - * will have to reinitialized. Set a flag to indicate this. - */ - /* Prevent future Digi programmed interrupts from coming active */ - port->flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&epca_lock, flags); -} - -static void pc_hangup(struct tty_struct *tty) -{ - struct channel *ch; - - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - pc_flush_buffer(tty); - tty_ldisc_flush(tty); - shutdown(ch, tty); - - ch->event = 0; /* FIXME: review locking of ch->event */ - tty_port_hangup(&ch->port); - } -} - -static int pc_write(struct tty_struct *tty, - const unsigned char *buf, int bytesAvailable) -{ - unsigned int head, tail; - int dataLen; - int size; - int amountCopied; - struct channel *ch; - unsigned long flags; - int remain; - struct board_chan __iomem *bc; - - /* - * pc_write is primarily called directly by the kernel routine - * tty_write (Though it can also be called by put_char) found in - * tty_io.c. pc_write is passed a line discipline buffer where the data - * to be written out is stored. The line discipline implementation - * itself is done at the kernel level and is not brought into the - * driver. - */ - - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch == NULL) - return 0; - - /* Make a pointer to the channel data structure found on the board. */ - bc = ch->brdchan; - size = ch->txbufsize; - amountCopied = 0; - - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - - head = readw(&bc->tin) & (size - 1); - tail = readw(&bc->tout); - - if (tail != readw(&bc->tout)) - tail = readw(&bc->tout); - tail &= (size - 1); - - if (head >= tail) { - /* head has not wrapped */ - /* - * remain (much like dataLen above) represents the total amount - * of space available on the card for data. Here dataLen - * represents the space existing between the head pointer and - * the end of buffer. This is important because a memcpy cannot - * be told to automatically wrap around when it hits the buffer - * end. - */ - dataLen = size - head; - remain = size - (head - tail) - 1; - } else { - /* head has wrapped around */ - remain = tail - head - 1; - dataLen = remain; - } - /* - * Check the space on the card. If we have more data than space; reduce - * the amount of data to fit the space. - */ - bytesAvailable = min(remain, bytesAvailable); - txwinon(ch); - while (bytesAvailable > 0) { - /* there is data to copy onto card */ - - /* - * If head is not wrapped, the below will make sure the first - * data copy fills to the end of card buffer. - */ - dataLen = min(bytesAvailable, dataLen); - memcpy_toio(ch->txptr + head, buf, dataLen); - buf += dataLen; - head += dataLen; - amountCopied += dataLen; - bytesAvailable -= dataLen; - - if (head >= size) { - head = 0; - dataLen = tail; - } - } - ch->statusflags |= TXBUSY; - globalwinon(ch); - writew(head, &bc->tin); - - if ((ch->statusflags & LOWWAIT) == 0) { - ch->statusflags |= LOWWAIT; - writeb(1, &bc->ilow); - } - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - return amountCopied; -} - -static int pc_write_room(struct tty_struct *tty) -{ - int remain = 0; - struct channel *ch; - unsigned long flags; - unsigned int head, tail; - struct board_chan __iomem *bc; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - - bc = ch->brdchan; - head = readw(&bc->tin) & (ch->txbufsize - 1); - tail = readw(&bc->tout); - - if (tail != readw(&bc->tout)) - tail = readw(&bc->tout); - /* Wrap tail if necessary */ - tail &= (ch->txbufsize - 1); - remain = tail - head - 1; - if (remain < 0) - remain += ch->txbufsize; - - if (remain && (ch->statusflags & LOWWAIT) == 0) { - ch->statusflags |= LOWWAIT; - writeb(1, &bc->ilow); - } - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - } - /* Return how much room is left on card */ - return remain; -} - -static int pc_chars_in_buffer(struct tty_struct *tty) -{ - int chars; - unsigned int ctail, head, tail; - int remain; - unsigned long flags; - struct channel *ch; - struct board_chan __iomem *bc; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch == NULL) - return 0; - - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - - bc = ch->brdchan; - tail = readw(&bc->tout); - head = readw(&bc->tin); - ctail = readw(&ch->mailbox->cout); - - if (tail == head && readw(&ch->mailbox->cin) == ctail && - readb(&bc->tbusy) == 0) - chars = 0; - else { /* Begin if some space on the card has been used */ - head = readw(&bc->tin) & (ch->txbufsize - 1); - tail &= (ch->txbufsize - 1); - /* - * The logic here is basically opposite of the above - * pc_write_room here we are finding the amount of bytes in the - * buffer filled. Not the amount of bytes empty. - */ - remain = tail - head - 1; - if (remain < 0) - remain += ch->txbufsize; - chars = (int)(ch->txbufsize - remain); - /* - * Make it possible to wakeup anything waiting for output in - * tty_ioctl.c, etc. - * - * If not already set. Setup an event to indicate when the - * transmit buffer empties. - */ - if (!(ch->statusflags & EMPTYWAIT)) - setup_empty_event(tty, ch); - } /* End if some space on the card has been used */ - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - /* Return number of characters residing on card. */ - return chars; -} - -static void pc_flush_buffer(struct tty_struct *tty) -{ - unsigned int tail; - unsigned long flags; - struct channel *ch; - struct board_chan __iomem *bc; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch == NULL) - return; - - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - bc = ch->brdchan; - tail = readw(&bc->tout); - /* Have FEP move tout pointer; effectively flushing transmit buffer */ - fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - tty_wakeup(tty); -} - -static void pc_flush_chars(struct tty_struct *tty) -{ - struct channel *ch; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - unsigned long flags; - spin_lock_irqsave(&epca_lock, flags); - /* - * If not already set and the transmitter is busy setup an - * event to indicate when the transmit empties. - */ - if ((ch->statusflags & TXBUSY) && - !(ch->statusflags & EMPTYWAIT)) - setup_empty_event(tty, ch); - spin_unlock_irqrestore(&epca_lock, flags); - } -} - -static int epca_carrier_raised(struct tty_port *port) -{ - struct channel *ch = container_of(port, struct channel, port); - if (ch->imodem & ch->dcd) - return 1; - return 0; -} - -static void epca_dtr_rts(struct tty_port *port, int onoff) -{ -} - -static int pc_open(struct tty_struct *tty, struct file *filp) -{ - struct channel *ch; - struct tty_port *port; - unsigned long flags; - int line, retval, boardnum; - struct board_chan __iomem *bc; - unsigned int head; - - line = tty->index; - if (line < 0 || line >= nbdevs) - return -ENODEV; - - ch = &digi_channels[line]; - port = &ch->port; - boardnum = ch->boardnum; - - /* Check status of board configured in system. */ - - /* - * I check to see if the epca_setup routine detected a user error. It - * might be better to put this in pc_init, but for the moment it goes - * here. - */ - if (invalid_lilo_config) { - if (setup_error_code & INVALID_BOARD_TYPE) - printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n"); - if (setup_error_code & INVALID_NUM_PORTS) - printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n"); - if (setup_error_code & INVALID_MEM_BASE) - printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n"); - if (setup_error_code & INVALID_PORT_BASE) - printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n"); - if (setup_error_code & INVALID_BOARD_STATUS) - printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n"); - if (setup_error_code & INVALID_ALTPIN) - printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n"); - tty->driver_data = NULL; /* Mark this device as 'down' */ - return -ENODEV; - } - if (boardnum >= num_cards || boards[boardnum].status == DISABLED) { - tty->driver_data = NULL; /* Mark this device as 'down' */ - return(-ENODEV); - } - - bc = ch->brdchan; - if (bc == NULL) { - tty->driver_data = NULL; - return -ENODEV; - } - - spin_lock_irqsave(&port->lock, flags); - /* - * Every time a channel is opened, increment a counter. This is - * necessary because we do not wish to flush and shutdown the channel - * until the last app holding the channel open, closes it. - */ - port->count++; - /* - * Set a kernel structures pointer to our local channel structure. This - * way we can get to it when passed only a tty struct. - */ - tty->driver_data = ch; - port->tty = tty; - /* - * If this is the first time the channel has been opened, initialize - * the tty->termios struct otherwise let pc_close handle it. - */ - spin_lock(&epca_lock); - globalwinon(ch); - ch->statusflags = 0; - - /* Save boards current modem status */ - ch->imodem = readb(&bc->mstat); - - /* - * Set receive head and tail ptrs to each other. This indicates no data - * available to read. - */ - head = readw(&bc->rin); - writew(head, &bc->rout); - - /* Set the channels associated tty structure */ - - /* - * The below routine generally sets up parity, baud, flow control - * issues, etc.... It effect both control flags and input flags. - */ - epcaparam(tty, ch); - memoff(ch); - spin_unlock(&epca_lock); - port->flags |= ASYNC_INITIALIZED; - spin_unlock_irqrestore(&port->lock, flags); - - retval = tty_port_block_til_ready(port, tty, filp); - if (retval) - return retval; - /* - * Set this again in case a hangup set it to zero while this open() was - * waiting for the line... - */ - spin_lock_irqsave(&port->lock, flags); - port->tty = tty; - spin_lock(&epca_lock); - globalwinon(ch); - /* Enable Digi Data events */ - writeb(1, &bc->idata); - memoff(ch); - spin_unlock(&epca_lock); - spin_unlock_irqrestore(&port->lock, flags); - return 0; -} - -static int __init epca_module_init(void) -{ - return pc_init(); -} -module_init(epca_module_init); - -static struct pci_driver epca_driver; - -static void __exit epca_module_exit(void) -{ - int count, crd; - struct board_info *bd; - struct channel *ch; - - del_timer_sync(&epca_timer); - - if (tty_unregister_driver(pc_driver) || - tty_unregister_driver(pc_info)) { - printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); - return; - } - put_tty_driver(pc_driver); - put_tty_driver(pc_info); - - for (crd = 0; crd < num_cards; crd++) { - bd = &boards[crd]; - if (!bd) { /* sanity check */ - printk(KERN_ERR " - Digi : cleanup_module failed\n"); - return; - } - ch = card_ptr[crd]; - for (count = 0; count < bd->numports; count++, ch++) { - struct tty_struct *tty = tty_port_tty_get(&ch->port); - if (tty) { - tty_hangup(tty); - tty_kref_put(tty); - } - } - } - pci_unregister_driver(&epca_driver); -} -module_exit(epca_module_exit); - -static const struct tty_operations pc_ops = { - .open = pc_open, - .close = pc_close, - .write = pc_write, - .write_room = pc_write_room, - .flush_buffer = pc_flush_buffer, - .chars_in_buffer = pc_chars_in_buffer, - .flush_chars = pc_flush_chars, - .ioctl = pc_ioctl, - .set_termios = pc_set_termios, - .stop = pc_stop, - .start = pc_start, - .throttle = pc_throttle, - .unthrottle = pc_unthrottle, - .hangup = pc_hangup, - .break_ctl = pc_send_break -}; - -static const struct tty_port_operations epca_port_ops = { - .carrier_raised = epca_carrier_raised, - .dtr_rts = epca_dtr_rts, -}; - -static int info_open(struct tty_struct *tty, struct file *filp) -{ - return 0; -} - -static const struct tty_operations info_ops = { - .open = info_open, - .ioctl = info_ioctl, -}; - -static int __init pc_init(void) -{ - int crd; - struct board_info *bd; - unsigned char board_id = 0; - int err = -ENOMEM; - - int pci_boards_found, pci_count; - - pci_count = 0; - - pc_driver = alloc_tty_driver(MAX_ALLOC); - if (!pc_driver) - goto out1; - - pc_info = alloc_tty_driver(MAX_ALLOC); - if (!pc_info) - goto out2; - - /* - * If epca_setup has not been ran by LILO set num_cards to defaults; - * copy board structure defined by digiConfig into drivers board - * structure. Note : If LILO has ran epca_setup then epca_setup will - * handle defining num_cards as well as copying the data into the board - * structure. - */ - if (!liloconfig) { - /* driver has been configured via. epcaconfig */ - nbdevs = NBDEVS; - num_cards = NUMCARDS; - memcpy(&boards, &static_boards, - sizeof(struct board_info) * NUMCARDS); - } - - /* - * Note : If lilo was used to configure the driver and the ignore - * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards - * will equal 0 at this point. This is okay; PCI cards will still be - * picked up if detected. - */ - - /* - * Set up interrupt, we will worry about memory allocation in - * post_fep_init. - */ - printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION); - - /* - * NOTE : This code assumes that the number of ports found in the - * boards array is correct. This could be wrong if the card in question - * is PCI (And therefore has no ports entry in the boards structure.) - * The rest of the information will be valid for PCI because the - * beginning of pc_init scans for PCI and determines i/o and base - * memory addresses. I am not sure if it is possible to read the number - * of ports supported by the card prior to it being booted (Since that - * is the state it is in when pc_init is run). Because it is not - * possible to query the number of supported ports until after the card - * has booted; we are required to calculate the card_ptrs as the card - * is initialized (Inside post_fep_init). The negative thing about this - * approach is that digiDload's call to GET_INFO will have a bad port - * value. (Since this is called prior to post_fep_init.) - */ - pci_boards_found = 0; - if (num_cards < MAXBOARDS) - pci_boards_found += init_PCI(); - num_cards += pci_boards_found; - - pc_driver->owner = THIS_MODULE; - pc_driver->name = "ttyD"; - pc_driver->major = DIGI_MAJOR; - pc_driver->minor_start = 0; - pc_driver->type = TTY_DRIVER_TYPE_SERIAL; - pc_driver->subtype = SERIAL_TYPE_NORMAL; - pc_driver->init_termios = tty_std_termios; - pc_driver->init_termios.c_iflag = 0; - pc_driver->init_termios.c_oflag = 0; - pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; - pc_driver->init_termios.c_lflag = 0; - pc_driver->init_termios.c_ispeed = 9600; - pc_driver->init_termios.c_ospeed = 9600; - pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; - tty_set_operations(pc_driver, &pc_ops); - - pc_info->owner = THIS_MODULE; - pc_info->name = "digi_ctl"; - pc_info->major = DIGIINFOMAJOR; - pc_info->minor_start = 0; - pc_info->type = TTY_DRIVER_TYPE_SERIAL; - pc_info->subtype = SERIAL_TYPE_INFO; - pc_info->init_termios = tty_std_termios; - pc_info->init_termios.c_iflag = 0; - pc_info->init_termios.c_oflag = 0; - pc_info->init_termios.c_lflag = 0; - pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; - pc_info->init_termios.c_ispeed = 9600; - pc_info->init_termios.c_ospeed = 9600; - pc_info->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(pc_info, &info_ops); - - - for (crd = 0; crd < num_cards; crd++) { - /* - * This is where the appropriate memory handlers for the - * hardware is set. Everything at runtime blindly jumps through - * these vectors. - */ - - /* defined in epcaconfig.h */ - bd = &boards[crd]; - - switch (bd->type) { - case PCXEM: - case EISAXEM: - bd->memwinon = pcxem_memwinon; - bd->memwinoff = pcxem_memwinoff; - bd->globalwinon = pcxem_globalwinon; - bd->txwinon = pcxem_txwinon; - bd->rxwinon = pcxem_rxwinon; - bd->memoff = pcxem_memoff; - bd->assertgwinon = dummy_assertgwinon; - bd->assertmemoff = dummy_assertmemoff; - break; - - case PCIXEM: - case PCIXRJ: - case PCIXR: - bd->memwinon = dummy_memwinon; - bd->memwinoff = dummy_memwinoff; - bd->globalwinon = dummy_globalwinon; - bd->txwinon = dummy_txwinon; - bd->rxwinon = dummy_rxwinon; - bd->memoff = dummy_memoff; - bd->assertgwinon = dummy_assertgwinon; - bd->assertmemoff = dummy_assertmemoff; - break; - - case PCXE: - case PCXEVE: - bd->memwinon = pcxe_memwinon; - bd->memwinoff = pcxe_memwinoff; - bd->globalwinon = pcxe_globalwinon; - bd->txwinon = pcxe_txwinon; - bd->rxwinon = pcxe_rxwinon; - bd->memoff = pcxe_memoff; - bd->assertgwinon = dummy_assertgwinon; - bd->assertmemoff = dummy_assertmemoff; - break; - - case PCXI: - case PC64XE: - bd->memwinon = pcxi_memwinon; - bd->memwinoff = pcxi_memwinoff; - bd->globalwinon = pcxi_globalwinon; - bd->txwinon = pcxi_txwinon; - bd->rxwinon = pcxi_rxwinon; - bd->memoff = pcxi_memoff; - bd->assertgwinon = pcxi_assertgwinon; - bd->assertmemoff = pcxi_assertmemoff; - break; - - default: - break; - } - - /* - * Some cards need a memory segment to be defined for use in - * transmit and receive windowing operations. These boards are - * listed in the below switch. In the case of the XI the amount - * of memory on the board is variable so the memory_seg is also - * variable. This code determines what they segment should be. - */ - switch (bd->type) { - case PCXE: - case PCXEVE: - case PC64XE: - bd->memory_seg = 0xf000; - break; - - case PCXI: - board_id = inb((int)bd->port); - if ((board_id & 0x1) == 0x1) { - /* it's an XI card */ - /* Is it a 64K board */ - if ((board_id & 0x30) == 0) - bd->memory_seg = 0xf000; - - /* Is it a 128K board */ - if ((board_id & 0x30) == 0x10) - bd->memory_seg = 0xe000; - - /* Is is a 256K board */ - if ((board_id & 0x30) == 0x20) - bd->memory_seg = 0xc000; - - /* Is it a 512K board */ - if ((board_id & 0x30) == 0x30) - bd->memory_seg = 0x8000; - } else - printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port); - break; - } - } - - err = tty_register_driver(pc_driver); - if (err) { - printk(KERN_ERR "Couldn't register Digi PC/ driver"); - goto out3; - } - - err = tty_register_driver(pc_info); - if (err) { - printk(KERN_ERR "Couldn't register Digi PC/ info "); - goto out4; - } - - /* Start up the poller to check for events on all enabled boards */ - init_timer(&epca_timer); - epca_timer.function = epcapoll; - mod_timer(&epca_timer, jiffies + HZ/25); - return 0; - -out4: - tty_unregister_driver(pc_driver); -out3: - put_tty_driver(pc_info); -out2: - put_tty_driver(pc_driver); -out1: - return err; -} - -static void post_fep_init(unsigned int crd) -{ - int i; - void __iomem *memaddr; - struct global_data __iomem *gd; - struct board_info *bd; - struct board_chan __iomem *bc; - struct channel *ch; - int shrinkmem = 0, lowwater; - - /* - * This call is made by the user via. the ioctl call DIGI_INIT. It is - * responsible for setting up all the card specific stuff. - */ - bd = &boards[crd]; - - /* - * If this is a PCI board, get the port info. Remember PCI cards do not - * have entries into the epcaconfig.h file, so we can't get the number - * of ports from it. Unfortunetly, this means that anyone doing a - * DIGI_GETINFO before the board has booted will get an invalid number - * of ports returned (It should return 0). Calls to DIGI_GETINFO after - * DIGI_INIT has been called will return the proper values. - */ - if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */ - /* - * Below we use XEMPORTS as a memory offset regardless of which - * PCI card it is. This is because all of the supported PCI - * cards have the same memory offset for the channel data. This - * will have to be changed if we ever develop a PCI/XE card. - * NOTE : The FEP manual states that the port offset is 0xC22 - * as opposed to 0xC02. This is only true for PC/XE, and PC/XI - * cards; not for the XEM, or CX series. On the PCI cards the - * number of ports is determined by reading a ID PROM located - * in the box attached to the card. The card can then determine - * the index the id to determine the number of ports available. - * (FYI - The id should be located at 0x1ac (And may use up to - * 4 bytes if the box in question is a XEM or CX)). - */ - /* PCI cards are already remapped at this point ISA are not */ - bd->numports = readw(bd->re_map_membase + XEMPORTS); - epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports"); - nbdevs += (bd->numports); - } else { - /* Fix up the mappings for ISA/EISA etc */ - /* FIXME: 64K - can we be smarter ? */ - bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000); - } - - if (crd != 0) - card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; - else - card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ - - ch = card_ptr[crd]; - epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); - - memaddr = bd->re_map_membase; - - /* - * The below assignment will set bc to point at the BEGINING of the - * cards channel structures. For 1 card there will be between 8 and 64 - * of these structures. - */ - bc = memaddr + CHANSTRUCT; - - /* - * The below assignment will set gd to point at the BEGINING of global - * memory address 0xc00. The first data in that global memory actually - * starts at address 0xc1a. The command in pointer begins at 0xd10. - */ - gd = memaddr + GLOBAL; - - /* - * XEPORTS (address 0xc22) points at the number of channels the card - * supports. (For 64XE, XI, XEM, and XR use 0xc02) - */ - if ((bd->type == PCXEVE || bd->type == PCXE) && - (readw(memaddr + XEPORTS) < 3)) - shrinkmem = 1; - if (bd->type < PCIXEM) - if (!request_region((int)bd->port, 4, board_desc[bd->type])) - return; - memwinon(bd, 0); - - /* - * Remember ch is the main drivers channels structure, while bc is the - * cards channel structure. - */ - for (i = 0; i < bd->numports; i++, ch++, bc++) { - unsigned long flags; - u16 tseg, rseg; - - tty_port_init(&ch->port); - ch->port.ops = &epca_port_ops; - ch->brdchan = bc; - ch->mailbox = gd; - INIT_WORK(&ch->tqueue, do_softint); - ch->board = &boards[crd]; - - spin_lock_irqsave(&epca_lock, flags); - switch (bd->type) { - /* - * Since some of the boards use different bitmaps for - * their control signals we cannot hard code these - * values and retain portability. We virtualize this - * data here. - */ - case EISAXEM: - case PCXEM: - case PCIXEM: - case PCIXRJ: - case PCIXR: - ch->m_rts = 0x02; - ch->m_dcd = 0x80; - ch->m_dsr = 0x20; - ch->m_cts = 0x10; - ch->m_ri = 0x40; - ch->m_dtr = 0x01; - break; - - case PCXE: - case PCXEVE: - case PCXI: - case PC64XE: - ch->m_rts = 0x02; - ch->m_dcd = 0x08; - ch->m_dsr = 0x10; - ch->m_cts = 0x20; - ch->m_ri = 0x40; - ch->m_dtr = 0x80; - break; - } - - if (boards[crd].altpin) { - ch->dsr = ch->m_dcd; - ch->dcd = ch->m_dsr; - ch->digiext.digi_flags |= DIGI_ALTPIN; - } else { - ch->dcd = ch->m_dcd; - ch->dsr = ch->m_dsr; - } - - ch->boardnum = crd; - ch->channelnum = i; - ch->magic = EPCA_MAGIC; - tty_port_tty_set(&ch->port, NULL); - - if (shrinkmem) { - fepcmd(ch, SETBUFFER, 32, 0, 0, 0); - shrinkmem = 0; - } - - tseg = readw(&bc->tseg); - rseg = readw(&bc->rseg); - - switch (bd->type) { - case PCIXEM: - case PCIXRJ: - case PCIXR: - /* Cover all the 2MEG cards */ - ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); - ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); - ch->txwin = FEPWIN | (tseg >> 11); - ch->rxwin = FEPWIN | (rseg >> 11); - break; - - case PCXEM: - case EISAXEM: - /* Cover all the 32K windowed cards */ - /* Mask equal to window size - 1 */ - ch->txptr = memaddr + ((tseg << 4) & 0x7fff); - ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); - ch->txwin = FEPWIN | (tseg >> 11); - ch->rxwin = FEPWIN | (rseg >> 11); - break; - - case PCXEVE: - case PCXE: - ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) - & 0x1fff); - ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); - ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) - & 0x1fff); - ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9); - break; - - case PCXI: - case PC64XE: - ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); - ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); - ch->txwin = ch->rxwin = 0; - break; - } - - ch->txbufhead = 0; - ch->txbufsize = readw(&bc->tmax) + 1; - - ch->rxbufhead = 0; - ch->rxbufsize = readw(&bc->rmax) + 1; - - lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); - - /* Set transmitter low water mark */ - fepcmd(ch, STXLWATER, lowwater, 0, 10, 0); - - /* Set receiver low water mark */ - fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0); - - /* Set receiver high water mark */ - fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); - - writew(100, &bc->edelay); - writeb(1, &bc->idata); - - ch->startc = readb(&bc->startc); - ch->stopc = readb(&bc->stopc); - ch->startca = readb(&bc->startca); - ch->stopca = readb(&bc->stopca); - - ch->fepcflag = 0; - ch->fepiflag = 0; - ch->fepoflag = 0; - ch->fepstartc = 0; - ch->fepstopc = 0; - ch->fepstartca = 0; - ch->fepstopca = 0; - - ch->port.close_delay = 50; - - spin_unlock_irqrestore(&epca_lock, flags); - } - - printk(KERN_INFO - "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", - VERSION, board_desc[bd->type], (long)bd->port, - (long)bd->membase, bd->numports); - memwinoff(bd, 0); -} - -static void epcapoll(unsigned long ignored) -{ - unsigned long flags; - int crd; - unsigned int head, tail; - struct channel *ch; - struct board_info *bd; - - /* - * This routine is called upon every timer interrupt. Even though the - * Digi series cards are capable of generating interrupts this method - * of non-looping polling is more efficient. This routine checks for - * card generated events (Such as receive data, are transmit buffer - * empty) and acts on those events. - */ - for (crd = 0; crd < num_cards; crd++) { - bd = &boards[crd]; - ch = card_ptr[crd]; - - if ((bd->status == DISABLED) || digi_poller_inhibited) - continue; - - /* - * assertmemoff is not needed here; indeed it is an empty - * subroutine. It is being kept because future boards may need - * this as well as some legacy boards. - */ - spin_lock_irqsave(&epca_lock, flags); - - assertmemoff(ch); - - globalwinon(ch); - - /* - * In this case head and tail actually refer to the event queue - * not the transmit or receive queue. - */ - head = readw(&ch->mailbox->ein); - tail = readw(&ch->mailbox->eout); - - /* If head isn't equal to tail we have an event */ - if (head != tail) - doevent(crd); - memoff(ch); - - spin_unlock_irqrestore(&epca_lock, flags); - } /* End for each card */ - mod_timer(&epca_timer, jiffies + (HZ / 25)); -} - -static void doevent(int crd) -{ - void __iomem *eventbuf; - struct channel *ch, *chan0; - static struct tty_struct *tty; - struct board_info *bd; - struct board_chan __iomem *bc; - unsigned int tail, head; - int event, channel; - int mstat, lstat; - - /* - * This subroutine is called by epcapoll when an event is detected - * in the event queue. This routine responds to those events. - */ - bd = &boards[crd]; - - chan0 = card_ptr[crd]; - epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); - assertgwinon(chan0); - while ((tail = readw(&chan0->mailbox->eout)) != - (head = readw(&chan0->mailbox->ein))) { - /* Begin while something in event queue */ - assertgwinon(chan0); - eventbuf = bd->re_map_membase + tail + ISTART; - /* Get the channel the event occurred on */ - channel = readb(eventbuf); - /* Get the actual event code that occurred */ - event = readb(eventbuf + 1); - /* - * The two assignments below get the current modem status - * (mstat) and the previous modem status (lstat). These are - * useful becuase an event could signal a change in modem - * signals itself. - */ - mstat = readb(eventbuf + 2); - lstat = readb(eventbuf + 3); - - ch = chan0 + channel; - if ((unsigned)channel >= bd->numports || !ch) { - if (channel >= bd->numports) - ch = chan0; - bc = ch->brdchan; - goto next; - } - - bc = ch->brdchan; - if (bc == NULL) - goto next; - - tty = tty_port_tty_get(&ch->port); - if (event & DATA_IND) { /* Begin DATA_IND */ - receive_data(ch, tty); - assertgwinon(ch); - } /* End DATA_IND */ - /* else *//* Fix for DCD transition missed bug */ - if (event & MODEMCHG_IND) { - /* A modem signal change has been indicated */ - ch->imodem = mstat; - if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) { - /* We are now receiving dcd */ - if (mstat & ch->dcd) - wake_up_interruptible(&ch->port.open_wait); - else /* No dcd; hangup */ - pc_sched_event(ch, EPCA_EVENT_HANGUP); - } - } - if (tty) { - if (event & BREAK_IND) { - /* A break has been indicated */ - tty_insert_flip_char(tty, 0, TTY_BREAK); - tty_schedule_flip(tty); - } else if (event & LOWTX_IND) { - if (ch->statusflags & LOWWAIT) { - ch->statusflags &= ~LOWWAIT; - tty_wakeup(tty); - } - } else if (event & EMPTYTX_IND) { - /* This event is generated by - setup_empty_event */ - ch->statusflags &= ~TXBUSY; - if (ch->statusflags & EMPTYWAIT) { - ch->statusflags &= ~EMPTYWAIT; - tty_wakeup(tty); - } - } - tty_kref_put(tty); - } -next: - globalwinon(ch); - BUG_ON(!bc); - writew(1, &bc->idata); - writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout); - globalwinon(chan0); - } /* End while something in event queue */ -} - -static void fepcmd(struct channel *ch, int cmd, int word_or_byte, - int byte2, int ncmds, int bytecmd) -{ - unchar __iomem *memaddr; - unsigned int head, cmdTail, cmdStart, cmdMax; - long count; - int n; - - /* This is the routine in which commands may be passed to the card. */ - - if (ch->board->status == DISABLED) - return; - assertgwinon(ch); - /* Remember head (As well as max) is just an offset not a base addr */ - head = readw(&ch->mailbox->cin); - /* cmdStart is a base address */ - cmdStart = readw(&ch->mailbox->cstart); - /* - * We do the addition below because we do not want a max pointer - * relative to cmdStart. We want a max pointer that points at the - * physical end of the command queue. - */ - cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax)); - memaddr = ch->board->re_map_membase; - - if (head >= (cmdMax - cmdStart) || (head & 03)) { - printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", - __LINE__, cmd, head); - printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", - __LINE__, cmdMax, cmdStart); - return; - } - if (bytecmd) { - writeb(cmd, memaddr + head + cmdStart + 0); - writeb(ch->channelnum, memaddr + head + cmdStart + 1); - /* Below word_or_byte is bits to set */ - writeb(word_or_byte, memaddr + head + cmdStart + 2); - /* Below byte2 is bits to reset */ - writeb(byte2, memaddr + head + cmdStart + 3); - } else { - writeb(cmd, memaddr + head + cmdStart + 0); - writeb(ch->channelnum, memaddr + head + cmdStart + 1); - writeb(word_or_byte, memaddr + head + cmdStart + 2); - } - head = (head + 4) & (cmdMax - cmdStart - 4); - writew(head, &ch->mailbox->cin); - count = FEPTIMEOUT; - - for (;;) { - count--; - if (count == 0) { - printk(KERN_ERR " - Fep not responding in fepcmd()\n"); - return; - } - head = readw(&ch->mailbox->cin); - cmdTail = readw(&ch->mailbox->cout); - n = (head - cmdTail) & (cmdMax - cmdStart - 4); - /* - * Basically this will break when the FEP acknowledges the - * command by incrementing cmdTail (Making it equal to head). - */ - if (n <= ncmds * (sizeof(short) * 4)) - break; - } -} - -/* - * Digi products use fields in their channels structures that are very similar - * to the c_cflag and c_iflag fields typically found in UNIX termios - * structures. The below three routines allow mappings between these hardware - * "flags" and their respective Linux flags. - */ -static unsigned termios2digi_h(struct channel *ch, unsigned cflag) -{ - unsigned res = 0; - - if (cflag & CRTSCTS) { - ch->digiext.digi_flags |= (RTSPACE | CTSPACE); - res |= ((ch->m_cts) | (ch->m_rts)); - } - - if (ch->digiext.digi_flags & RTSPACE) - res |= ch->m_rts; - - if (ch->digiext.digi_flags & DTRPACE) - res |= ch->m_dtr; - - if (ch->digiext.digi_flags & CTSPACE) - res |= ch->m_cts; - - if (ch->digiext.digi_flags & DSRPACE) - res |= ch->dsr; - - if (ch->digiext.digi_flags & DCDPACE) - res |= ch->dcd; - - if (res & (ch->m_rts)) - ch->digiext.digi_flags |= RTSPACE; - - if (res & (ch->m_cts)) - ch->digiext.digi_flags |= CTSPACE; - - return res; -} - -static unsigned termios2digi_i(struct channel *ch, unsigned iflag) -{ - unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | - INPCK | ISTRIP | IXON | IXANY | IXOFF); - if (ch->digiext.digi_flags & DIGI_AIXON) - res |= IAIXON; - return res; -} - -static unsigned termios2digi_c(struct channel *ch, unsigned cflag) -{ - unsigned res = 0; - if (cflag & CBAUDEX) { - ch->digiext.digi_flags |= DIGI_FAST; - /* - * HUPCL bit is used by FEP to indicate fast baud table is to - * be used. - */ - res |= FEP_HUPCL; - } else - ch->digiext.digi_flags &= ~DIGI_FAST; - /* - * CBAUD has bit position 0x1000 set these days to indicate Linux - * baud rate remap. Digi hardware can't handle the bit assignment. - * (We use a different bit assignment for high speed.). Clear this - * bit out. - */ - res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); - /* - * This gets a little confusing. The Digi cards have their own - * representation of c_cflags controlling baud rate. For the most part - * this is identical to the Linux implementation. However; Digi - * supports one rate (76800) that Linux doesn't. This means that the - * c_cflag entry that would normally mean 76800 for Digi actually means - * 115200 under Linux. Without the below mapping, a stty 115200 would - * only drive the board at 76800. Since the rate 230400 is also found - * after 76800, the same problem afflicts us when we choose a rate of - * 230400. Without the below modificiation stty 230400 would actually - * give us 115200. - * - * There are two additional differences. The Linux value for CLOCAL - * (0x800; 0004000) has no meaning to the Digi hardware. Also in later - * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000) - * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be - * checked for a screened out prior to termios2digi_c returning. Since - * CLOCAL isn't used by the board this can be ignored as long as the - * returned value is used only by Digi hardware. - */ - if (cflag & CBAUDEX) { - /* - * The below code is trying to guarantee that only baud rates - * 115200 and 230400 are remapped. We use exclusive or because - * the various baud rates share common bit positions and - * therefore can't be tested for easily. - */ - if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || - (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) - res += 1; - } - return res; -} - -/* Caller must hold the locks */ -static void epcaparam(struct tty_struct *tty, struct channel *ch) -{ - unsigned int cmdHead; - struct ktermios *ts; - struct board_chan __iomem *bc; - unsigned mval, hflow, cflag, iflag; - - bc = ch->brdchan; - epcaassert(bc != NULL, "bc out of range"); - - assertgwinon(ch); - ts = tty->termios; - if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ - cmdHead = readw(&bc->rin); - writew(cmdHead, &bc->rout); - cmdHead = readw(&bc->tin); - /* Changing baud in mid-stream transmission can be wonderful */ - /* - * Flush current transmit buffer by setting cmdTail pointer - * (tout) to cmdHead pointer (tin). Hopefully the transmit - * buffer is empty. - */ - fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); - mval = 0; - } else { /* Begin CBAUD not detected */ - /* - * c_cflags have changed but that change had nothing to do with - * BAUD. Propagate the change to the card. - */ - cflag = termios2digi_c(ch, ts->c_cflag); - if (cflag != ch->fepcflag) { - ch->fepcflag = cflag; - /* Set baud rate, char size, stop bits, parity */ - fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); - } - /* - * If the user has not forced CLOCAL and if the device is not a - * CALLOUT device (Which is always CLOCAL) we set flags such - * that the driver will wait on carrier detect. - */ - if (ts->c_cflag & CLOCAL) - clear_bit(ASYNCB_CHECK_CD, &ch->port.flags); - else - set_bit(ASYNCB_CHECK_CD, &ch->port.flags); - mval = ch->m_dtr | ch->m_rts; - } /* End CBAUD not detected */ - iflag = termios2digi_i(ch, ts->c_iflag); - /* Check input mode flags */ - if (iflag != ch->fepiflag) { - ch->fepiflag = iflag; - /* - * Command sets channels iflag structure on the board. Such - * things as input soft flow control, handling of parity - * errors, and break handling are all set here. - * - * break handling, parity handling, input stripping, - * flow control chars - */ - fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); - } - /* - * Set the board mint value for this channel. This will cause hardware - * events to be generated each time the DCD signal (Described in mint) - * changes. - */ - writeb(ch->dcd, &bc->mint); - if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) - if (ch->digiext.digi_flags & DIGI_FORCEDCD) - writeb(0, &bc->mint); - ch->imodem = readb(&bc->mstat); - hflow = termios2digi_h(ch, ts->c_cflag); - if (hflow != ch->hflow) { - ch->hflow = hflow; - /* - * Hard flow control has been selected but the board is not - * using it. Activate hard flow control now. - */ - fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); - } - mval ^= ch->modemfake & (mval ^ ch->modem); - - if (ch->omodem ^ mval) { - ch->omodem = mval; - /* - * The below command sets the DTR and RTS mstat structure. If - * hard flow control is NOT active these changes will drive the - * output of the actual DTR and RTS lines. If hard flow control - * is active, the changes will be saved in the mstat structure - * and only asserted when hard flow control is turned off. - */ - - /* First reset DTR & RTS; then set them */ - fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); - fepcmd(ch, SETMODEM, mval, 0, 0, 1); - } - if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) { - ch->fepstartc = ch->startc; - ch->fepstopc = ch->stopc; - /* - * The XON / XOFF characters have changed; propagate these - * changes to the card. - */ - fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); - } - if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) { - ch->fepstartca = ch->startca; - ch->fepstopca = ch->stopca; - /* - * Similar to the above, this time the auxilarly XON / XOFF - * characters have changed; propagate these changes to the card. - */ - fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); - } -} - -/* Caller holds lock */ -static void receive_data(struct channel *ch, struct tty_struct *tty) -{ - unchar *rptr; - struct ktermios *ts = NULL; - struct board_chan __iomem *bc; - int dataToRead, wrapgap, bytesAvailable; - unsigned int tail, head; - unsigned int wrapmask; - - /* - * This routine is called by doint when a receive data event has taken - * place. - */ - globalwinon(ch); - if (ch->statusflags & RXSTOPPED) - return; - if (tty) - ts = tty->termios; - bc = ch->brdchan; - BUG_ON(!bc); - wrapmask = ch->rxbufsize - 1; - - /* - * Get the head and tail pointers to the receiver queue. Wrap the head - * pointer if it has reached the end of the buffer. - */ - head = readw(&bc->rin); - head &= wrapmask; - tail = readw(&bc->rout) & wrapmask; - - bytesAvailable = (head - tail) & wrapmask; - if (bytesAvailable == 0) - return; - - /* If CREAD bit is off or device not open, set TX tail to head */ - if (!tty || !ts || !(ts->c_cflag & CREAD)) { - writew(head, &bc->rout); - return; - } - - if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0) - return; - - if (readb(&bc->orun)) { - writeb(0, &bc->orun); - printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n", - tty->name); - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } - rxwinon(ch); - while (bytesAvailable > 0) { - /* Begin while there is data on the card */ - wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; - /* - * Even if head has wrapped around only report the amount of - * data to be equal to the size - tail. Remember memcpy can't - * automaticly wrap around the receive buffer. - */ - dataToRead = (wrapgap < bytesAvailable) ? wrapgap - : bytesAvailable; - /* Make sure we don't overflow the buffer */ - dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead); - if (dataToRead == 0) - break; - /* - * Move data read from our card into the line disciplines - * buffer for translation if necessary. - */ - memcpy_fromio(rptr, ch->rxptr + tail, dataToRead); - tail = (tail + dataToRead) & wrapmask; - bytesAvailable -= dataToRead; - } /* End while there is data on the card */ - globalwinon(ch); - writew(tail, &bc->rout); - /* Must be called with global data */ - tty_schedule_flip(tty); -} - -static int info_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case DIGI_GETINFO: - { - struct digi_info di; - int brd; - - if (get_user(brd, (unsigned int __user *)arg)) - return -EFAULT; - if (brd < 0 || brd >= num_cards || num_cards == 0) - return -ENODEV; - - memset(&di, 0, sizeof(di)); - - di.board = brd; - di.status = boards[brd].status; - di.type = boards[brd].type ; - di.numports = boards[brd].numports ; - /* Legacy fixups - just move along nothing to see */ - di.port = (unsigned char *)boards[brd].port ; - di.membase = (unsigned char *)boards[brd].membase ; - - if (copy_to_user((void __user *)arg, &di, sizeof(di))) - return -EFAULT; - break; - - } - - case DIGI_POLLER: - { - int brd = arg & 0xff000000 >> 16; - unsigned char state = arg & 0xff; - - if (brd < 0 || brd >= num_cards) { - printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n"); - return -ENODEV; - } - digi_poller_inhibited = state; - break; - } - - case DIGI_INIT: - { - /* - * This call is made by the apps to complete the - * initialization of the board(s). This routine is - * responsible for setting the card to its initial - * state and setting the drivers control fields to the - * sutianle settings for the card in question. - */ - int crd; - for (crd = 0; crd < num_cards; crd++) - post_fep_init(crd); - break; - } - default: - return -ENOTTY; - } - return 0; -} - -static int pc_tiocmget(struct tty_struct *tty) -{ - struct channel *ch = tty->driver_data; - struct board_chan __iomem *bc; - unsigned int mstat, mflag = 0; - unsigned long flags; - - if (ch) - bc = ch->brdchan; - else - return -EINVAL; - - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - mstat = readb(&bc->mstat); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - - if (mstat & ch->m_dtr) - mflag |= TIOCM_DTR; - if (mstat & ch->m_rts) - mflag |= TIOCM_RTS; - if (mstat & ch->m_cts) - mflag |= TIOCM_CTS; - if (mstat & ch->dsr) - mflag |= TIOCM_DSR; - if (mstat & ch->m_ri) - mflag |= TIOCM_RI; - if (mstat & ch->dcd) - mflag |= TIOCM_CD; - return mflag; -} - -static int pc_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct channel *ch = tty->driver_data; - unsigned long flags; - - if (!ch) - return -EINVAL; - - spin_lock_irqsave(&epca_lock, flags); - /* - * I think this modemfake stuff is broken. It doesn't correctly reflect - * the behaviour desired by the TIOCM* ioctls. Therefore this is - * probably broken. - */ - if (set & TIOCM_RTS) { - ch->modemfake |= ch->m_rts; - ch->modem |= ch->m_rts; - } - if (set & TIOCM_DTR) { - ch->modemfake |= ch->m_dtr; - ch->modem |= ch->m_dtr; - } - if (clear & TIOCM_RTS) { - ch->modemfake |= ch->m_rts; - ch->modem &= ~ch->m_rts; - } - if (clear & TIOCM_DTR) { - ch->modemfake |= ch->m_dtr; - ch->modem &= ~ch->m_dtr; - } - globalwinon(ch); - /* - * The below routine generally sets up parity, baud, flow control - * issues, etc.... It effect both control flags and input flags. - */ - epcaparam(tty, ch); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - return 0; -} - -static int pc_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - digiflow_t dflow; - unsigned long flags; - unsigned int mflag, mstat; - unsigned char startc, stopc; - struct board_chan __iomem *bc; - struct channel *ch = tty->driver_data; - void __user *argp = (void __user *)arg; - - if (ch) - bc = ch->brdchan; - else - return -EINVAL; - switch (cmd) { - case TIOCMODG: - mflag = pc_tiocmget(tty); - if (put_user(mflag, (unsigned long __user *)argp)) - return -EFAULT; - break; - case TIOCMODS: - if (get_user(mstat, (unsigned __user *)argp)) - return -EFAULT; - return pc_tiocmset(tty, mstat, ~mstat); - case TIOCSDTR: - spin_lock_irqsave(&epca_lock, flags); - ch->omodem |= ch->m_dtr; - globalwinon(ch); - fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - break; - - case TIOCCDTR: - spin_lock_irqsave(&epca_lock, flags); - ch->omodem &= ~ch->m_dtr; - globalwinon(ch); - fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - break; - case DIGI_GETA: - if (copy_to_user(argp, &ch->digiext, sizeof(digi_t))) - return -EFAULT; - break; - case DIGI_SETAW: - case DIGI_SETAF: - if (cmd == DIGI_SETAW) { - /* Setup an event to indicate when the transmit - buffer empties */ - spin_lock_irqsave(&epca_lock, flags); - setup_empty_event(tty, ch); - spin_unlock_irqrestore(&epca_lock, flags); - tty_wait_until_sent(tty, 0); - } else { - /* ldisc lock already held in ioctl */ - if (tty->ldisc->ops->flush_buffer) - tty->ldisc->ops->flush_buffer(tty); - } - /* Fall Thru */ - case DIGI_SETA: - if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) - return -EFAULT; - - if (ch->digiext.digi_flags & DIGI_ALTPIN) { - ch->dcd = ch->m_dsr; - ch->dsr = ch->m_dcd; - } else { - ch->dcd = ch->m_dcd; - ch->dsr = ch->m_dsr; - } - - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - - /* - * The below routine generally sets up parity, baud, flow - * control issues, etc.... It effect both control flags and - * input flags. - */ - epcaparam(tty, ch); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - break; - - case DIGI_GETFLOW: - case DIGI_GETAFLOW: - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - if (cmd == DIGI_GETFLOW) { - dflow.startc = readb(&bc->startc); - dflow.stopc = readb(&bc->stopc); - } else { - dflow.startc = readb(&bc->startca); - dflow.stopc = readb(&bc->stopca); - } - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - - if (copy_to_user(argp, &dflow, sizeof(dflow))) - return -EFAULT; - break; - - case DIGI_SETAFLOW: - case DIGI_SETFLOW: - if (cmd == DIGI_SETFLOW) { - startc = ch->startc; - stopc = ch->stopc; - } else { - startc = ch->startca; - stopc = ch->stopca; - } - - if (copy_from_user(&dflow, argp, sizeof(dflow))) - return -EFAULT; - - if (dflow.startc != startc || dflow.stopc != stopc) { - /* Begin if setflow toggled */ - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - - if (cmd == DIGI_SETFLOW) { - ch->fepstartc = ch->startc = dflow.startc; - ch->fepstopc = ch->stopc = dflow.stopc; - fepcmd(ch, SONOFFC, ch->fepstartc, - ch->fepstopc, 0, 1); - } else { - ch->fepstartca = ch->startca = dflow.startc; - ch->fepstopca = ch->stopca = dflow.stopc; - fepcmd(ch, SAUXONOFFC, ch->fepstartca, - ch->fepstopca, 0, 1); - } - - if (ch->statusflags & TXSTOPPED) - pc_start(tty); - - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - } /* End if setflow toggled */ - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct channel *ch; - unsigned long flags; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - - if (ch != NULL) { /* Begin if channel valid */ - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - epcaparam(tty, ch); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - - if ((old_termios->c_cflag & CRTSCTS) && - ((tty->termios->c_cflag & CRTSCTS) == 0)) - tty->hw_stopped = 0; - - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&ch->port.open_wait); - - } /* End if channel valid */ -} - -static void do_softint(struct work_struct *work) -{ - struct channel *ch = container_of(work, struct channel, tqueue); - /* Called in response to a modem change event */ - if (ch && ch->magic == EPCA_MAGIC) { - struct tty_struct *tty = tty_port_tty_get(&ch->port); - - if (tty && tty->driver_data) { - if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { - tty_hangup(tty); - wake_up_interruptible(&ch->port.open_wait); - clear_bit(ASYNCB_NORMAL_ACTIVE, - &ch->port.flags); - } - } - tty_kref_put(tty); - } -} - -/* - * pc_stop and pc_start provide software flow control to the routine and the - * pc_ioctl routine. - */ -static void pc_stop(struct tty_struct *tty) -{ - struct channel *ch; - unsigned long flags; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - spin_lock_irqsave(&epca_lock, flags); - if ((ch->statusflags & TXSTOPPED) == 0) { - /* Begin if transmit stop requested */ - globalwinon(ch); - /* STOP transmitting now !! */ - fepcmd(ch, PAUSETX, 0, 0, 0, 0); - ch->statusflags |= TXSTOPPED; - memoff(ch); - } /* End if transmit stop requested */ - spin_unlock_irqrestore(&epca_lock, flags); - } -} - -static void pc_start(struct tty_struct *tty) -{ - struct channel *ch; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - unsigned long flags; - spin_lock_irqsave(&epca_lock, flags); - /* Just in case output was resumed because of a change - in Digi-flow */ - if (ch->statusflags & TXSTOPPED) { - /* Begin transmit resume requested */ - struct board_chan __iomem *bc; - globalwinon(ch); - bc = ch->brdchan; - if (ch->statusflags & LOWWAIT) - writeb(1, &bc->ilow); - /* Okay, you can start transmitting again... */ - fepcmd(ch, RESUMETX, 0, 0, 0, 0); - ch->statusflags &= ~TXSTOPPED; - memoff(ch); - } /* End transmit resume requested */ - spin_unlock_irqrestore(&epca_lock, flags); - } -} - -/* - * The below routines pc_throttle and pc_unthrottle are used to slow (And - * resume) the receipt of data into the kernels receive buffers. The exact - * occurrence of this depends on the size of the kernels receive buffer and - * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for - * more details. - */ -static void pc_throttle(struct tty_struct *tty) -{ - struct channel *ch; - unsigned long flags; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - spin_lock_irqsave(&epca_lock, flags); - if ((ch->statusflags & RXSTOPPED) == 0) { - globalwinon(ch); - fepcmd(ch, PAUSERX, 0, 0, 0, 0); - ch->statusflags |= RXSTOPPED; - memoff(ch); - } - spin_unlock_irqrestore(&epca_lock, flags); - } -} - -static void pc_unthrottle(struct tty_struct *tty) -{ - struct channel *ch; - unsigned long flags; - /* - * verifyChannel returns the channel from the tty struct if it is - * valid. This serves as a sanity check. - */ - ch = verifyChannel(tty); - if (ch != NULL) { - /* Just in case output was resumed because of a change - in Digi-flow */ - spin_lock_irqsave(&epca_lock, flags); - if (ch->statusflags & RXSTOPPED) { - globalwinon(ch); - fepcmd(ch, RESUMERX, 0, 0, 0, 0); - ch->statusflags &= ~RXSTOPPED; - memoff(ch); - } - spin_unlock_irqrestore(&epca_lock, flags); - } -} - -static int pc_send_break(struct tty_struct *tty, int msec) -{ - struct channel *ch = tty->driver_data; - unsigned long flags; - - if (msec == -1) - msec = 0xFFFF; - else if (msec > 0xFFFE) - msec = 0xFFFE; - else if (msec < 1) - msec = 1; - - spin_lock_irqsave(&epca_lock, flags); - globalwinon(ch); - /* - * Maybe I should send an infinite break here, schedule() for msec - * amount of time, and then stop the break. This way, the user can't - * screw up the FEP by causing digi_send_break() to be called (i.e. via - * an ioctl()) more than once in msec amount of time. - * Try this for now... - */ - fepcmd(ch, SENDBREAK, msec, 0, 10, 0); - memoff(ch); - spin_unlock_irqrestore(&epca_lock, flags); - return 0; -} - -/* Caller MUST hold the lock */ -static void setup_empty_event(struct tty_struct *tty, struct channel *ch) -{ - struct board_chan __iomem *bc = ch->brdchan; - - globalwinon(ch); - ch->statusflags |= EMPTYWAIT; - /* - * When set the iempty flag request a event to be generated when the - * transmit buffer is empty (If there is no BREAK in progress). - */ - writeb(1, &bc->iempty); - memoff(ch); -} - -#ifndef MODULE -static void __init epca_setup(char *str, int *ints) -{ - struct board_info board; - int index, loop, last; - char *temp, *t2; - unsigned len; - - /* - * If this routine looks a little strange it is because it is only - * called if a LILO append command is given to boot the kernel with - * parameters. In this way, we can provide the user a method of - * changing his board configuration without rebuilding the kernel. - */ - if (!liloconfig) - liloconfig = 1; - - memset(&board, 0, sizeof(board)); - - /* Assume the data is int first, later we can change it */ - /* I think that array position 0 of ints holds the number of args */ - for (last = 0, index = 1; index <= ints[0]; index++) - switch (index) { /* Begin parse switch */ - case 1: - board.status = ints[index]; - /* - * We check for 2 (As opposed to 1; because 2 is a flag - * instructing the driver to ignore epcaconfig.) For - * this reason we check for 2. - */ - if (board.status == 2) { - /* Begin ignore epcaconfig as well as lilo cmd line */ - nbdevs = 0; - num_cards = 0; - return; - } /* End ignore epcaconfig as well as lilo cmd line */ - - if (board.status > 2) { - printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", - board.status); - invalid_lilo_config = 1; - setup_error_code |= INVALID_BOARD_STATUS; - return; - } - last = index; - break; - case 2: - board.type = ints[index]; - if (board.type >= PCIXEM) { - printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type); - invalid_lilo_config = 1; - setup_error_code |= INVALID_BOARD_TYPE; - return; - } - last = index; - break; - case 3: - board.altpin = ints[index]; - if (board.altpin > 1) { - printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin); - invalid_lilo_config = 1; - setup_error_code |= INVALID_ALTPIN; - return; - } - last = index; - break; - - case 4: - board.numports = ints[index]; - if (board.numports < 2 || board.numports > 256) { - printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports); - invalid_lilo_config = 1; - setup_error_code |= INVALID_NUM_PORTS; - return; - } - nbdevs += board.numports; - last = index; - break; - - case 5: - board.port = ints[index]; - if (ints[index] <= 0) { - printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); - invalid_lilo_config = 1; - setup_error_code |= INVALID_PORT_BASE; - return; - } - last = index; - break; - - case 6: - board.membase = ints[index]; - if (ints[index] <= 0) { - printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n", - (unsigned int)board.membase); - invalid_lilo_config = 1; - setup_error_code |= INVALID_MEM_BASE; - return; - } - last = index; - break; - - default: - printk(KERN_ERR " - epca_setup: Too many integer parms\n"); - return; - - } /* End parse switch */ - - while (str && *str) { /* Begin while there is a string arg */ - /* find the next comma or terminator */ - temp = str; - /* While string is not null, and a comma hasn't been found */ - while (*temp && (*temp != ',')) - temp++; - if (!*temp) - temp = NULL; - else - *temp++ = 0; - /* Set index to the number of args + 1 */ - index = last + 1; - - switch (index) { - case 1: - len = strlen(str); - if (strncmp("Disable", str, len) == 0) - board.status = 0; - else if (strncmp("Enable", str, len) == 0) - board.status = 1; - else { - printk(KERN_ERR "epca_setup: Invalid status %s\n", str); - invalid_lilo_config = 1; - setup_error_code |= INVALID_BOARD_STATUS; - return; - } - last = index; - break; - - case 2: - for (loop = 0; loop < EPCA_NUM_TYPES; loop++) - if (strcmp(board_desc[loop], str) == 0) - break; - /* - * If the index incremented above refers to a - * legitamate board type set it here. - */ - if (index < EPCA_NUM_TYPES) - board.type = loop; - else { - printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str); - invalid_lilo_config = 1; - setup_error_code |= INVALID_BOARD_TYPE; - return; - } - last = index; - break; - - case 3: - len = strlen(str); - if (strncmp("Disable", str, len) == 0) - board.altpin = 0; - else if (strncmp("Enable", str, len) == 0) - board.altpin = 1; - else { - printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str); - invalid_lilo_config = 1; - setup_error_code |= INVALID_ALTPIN; - return; - } - last = index; - break; - - case 4: - t2 = str; - while (isdigit(*t2)) - t2++; - - if (*t2) { - printk(KERN_ERR "epca_setup: Invalid port count %s\n", str); - invalid_lilo_config = 1; - setup_error_code |= INVALID_NUM_PORTS; - return; - } - - /* - * There is not a man page for simple_strtoul but the - * code can be found in vsprintf.c. The first argument - * is the string to translate (To an unsigned long - * obviously), the second argument can be the address - * of any character variable or a NULL. If a variable - * is given, the end pointer of the string will be - * stored in that variable; if a NULL is given the end - * pointer will not be returned. The last argument is - * the base to use. If a 0 is indicated, the routine - * will attempt to determine the proper base by looking - * at the values prefix (A '0' for octal, a 'x' for - * hex, etc ... If a value is given it will use that - * value as the base. - */ - board.numports = simple_strtoul(str, NULL, 0); - nbdevs += board.numports; - last = index; - break; - - case 5: - t2 = str; - while (isxdigit(*t2)) - t2++; - - if (*t2) { - printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str); - invalid_lilo_config = 1; - setup_error_code |= INVALID_PORT_BASE; - return; - } - - board.port = simple_strtoul(str, NULL, 16); - last = index; - break; - - case 6: - t2 = str; - while (isxdigit(*t2)) - t2++; - - if (*t2) { - printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str); - invalid_lilo_config = 1; - setup_error_code |= INVALID_MEM_BASE; - return; - } - board.membase = simple_strtoul(str, NULL, 16); - last = index; - break; - default: - printk(KERN_ERR "epca: Too many string parms\n"); - return; - } - str = temp; - } /* End while there is a string arg */ - - if (last < 6) { - printk(KERN_ERR "epca: Insufficient parms specified\n"); - return; - } - - /* I should REALLY validate the stuff here */ - /* Copies our local copy of board into boards */ - memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board)); - /* Does this get called once per lilo arg are what ? */ - printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", - num_cards, board_desc[board.type], - board.numports, (int)board.port, (unsigned int) board.membase); - num_cards++; -} - -static int __init epca_real_setup(char *str) -{ - int ints[11]; - - epca_setup(get_options(str, 11, ints), ints); - return 1; -} - -__setup("digiepca", epca_real_setup); -#endif - -enum epic_board_types { - brd_xr = 0, - brd_xem, - brd_cx, - brd_xrj, -}; - -/* indexed directly by epic_board_types enum */ -static struct { - unsigned char board_type; - unsigned bar_idx; /* PCI base address region */ -} epca_info_tbl[] = { - { PCIXR, 0, }, - { PCIXEM, 0, }, - { PCICX, 0, }, - { PCIXRJ, 2, }, -}; - -static int __devinit epca_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - static int board_num = -1; - int board_idx, info_idx = ent->driver_data; - unsigned long addr; - - if (pci_enable_device(pdev)) - return -EIO; - - board_num++; - board_idx = board_num + num_cards; - if (board_idx >= MAXBOARDS) - goto err_out; - - addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx); - if (!addr) { - printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n", - epca_info_tbl[info_idx].bar_idx); - goto err_out; - } - - boards[board_idx].status = ENABLED; - boards[board_idx].type = epca_info_tbl[info_idx].board_type; - boards[board_idx].numports = 0x0; - boards[board_idx].port = addr + PCI_IO_OFFSET; - boards[board_idx].membase = addr; - - if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) { - printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", - 0x200000, addr + PCI_IO_OFFSET); - goto err_out; - } - - boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET, - 0x200000); - if (!boards[board_idx].re_map_port) { - printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", - 0x200000, addr + PCI_IO_OFFSET); - goto err_out_free_pciio; - } - - if (!request_mem_region(addr, 0x200000, "epca")) { - printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", - 0x200000, addr); - goto err_out_free_iounmap; - } - - boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000); - if (!boards[board_idx].re_map_membase) { - printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", - 0x200000, addr + PCI_IO_OFFSET); - goto err_out_free_memregion; - } - - /* - * I don't know what the below does, but the hardware guys say its - * required on everything except PLX (In this case XRJ). - */ - if (info_idx != brd_xrj) { - pci_write_config_byte(pdev, 0x40, 0); - pci_write_config_byte(pdev, 0x46, 0); - } - - return 0; - -err_out_free_memregion: - release_mem_region(addr, 0x200000); -err_out_free_iounmap: - iounmap(boards[board_idx].re_map_port); -err_out_free_pciio: - release_mem_region(addr + PCI_IO_OFFSET, 0x200000); -err_out: - return -ENODEV; -} - - -static struct pci_device_id epca_pci_tbl[] = { - { PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr }, - { PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem }, - { PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx }, - { PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, epca_pci_tbl); - -static int __init init_PCI(void) -{ - memset(&epca_driver, 0, sizeof(epca_driver)); - epca_driver.name = "epca"; - epca_driver.id_table = epca_pci_tbl; - epca_driver.probe = epca_init_one; - - return pci_register_driver(&epca_driver); -} - -MODULE_LICENSE("GPL"); diff --git a/drivers/char/epca.h b/drivers/char/epca.h deleted file mode 100644 index d414bf2dbf7c..000000000000 --- a/drivers/char/epca.h +++ /dev/null @@ -1,158 +0,0 @@ -#define XEMPORTS 0xC02 -#define XEPORTS 0xC22 - -#define MAX_ALLOC 0x100 - -#define MAXBOARDS 12 -#define FEPCODESEG 0x0200L -#define FEPCODE 0x2000L -#define BIOSCODE 0xf800L - -#define MISCGLOBAL 0x0C00L -#define NPORT 0x0C22L -#define MBOX 0x0C40L -#define PORTBASE 0x0C90L - -/* Begin code defines used for epca_setup */ - -#define INVALID_BOARD_TYPE 0x1 -#define INVALID_NUM_PORTS 0x2 -#define INVALID_MEM_BASE 0x4 -#define INVALID_PORT_BASE 0x8 -#define INVALID_BOARD_STATUS 0x10 -#define INVALID_ALTPIN 0x20 - -/* End code defines used for epca_setup */ - - -#define FEPCLR 0x00 -#define FEPMEM 0x02 -#define FEPRST 0x04 -#define FEPINT 0x08 -#define FEPMASK 0x0e -#define FEPWIN 0x80 - -#define PCXE 0 -#define PCXEVE 1 -#define PCXEM 2 -#define EISAXEM 3 -#define PC64XE 4 -#define PCXI 5 -#define PCIXEM 7 -#define PCICX 8 -#define PCIXR 9 -#define PCIXRJ 10 -#define EPCA_NUM_TYPES 6 - - -static char *board_desc[] = -{ - "PC/Xe", - "PC/Xeve", - "PC/Xem", - "EISA/Xem", - "PC/64Xe", - "PC/Xi", - "unknown", - "PCI/Xem", - "PCI/CX", - "PCI/Xr", - "PCI/Xrj", -}; - -#define STARTC 021 -#define STOPC 023 -#define IAIXON 0x2000 - - -#define TXSTOPPED 0x1 -#define LOWWAIT 0x2 -#define EMPTYWAIT 0x4 -#define RXSTOPPED 0x8 -#define TXBUSY 0x10 - -#define DISABLED 0 -#define ENABLED 1 -#define OFF 0 -#define ON 1 - -#define FEPTIMEOUT 200000 -#define SERIAL_TYPE_INFO 3 -#define EPCA_EVENT_HANGUP 1 -#define EPCA_MAGIC 0x5c6df104L - -struct channel -{ - long magic; - struct tty_port port; - unsigned char boardnum; - unsigned char channelnum; - unsigned char omodem; /* FEP output modem status */ - unsigned char imodem; /* FEP input modem status */ - unsigned char modemfake; /* Modem values to be forced */ - unsigned char modem; /* Force values */ - unsigned char hflow; - unsigned char dsr; - unsigned char dcd; - unsigned char m_rts ; /* The bits used in whatever FEP */ - unsigned char m_dcd ; /* is indiginous to this board to */ - unsigned char m_dsr ; /* represent each of the physical */ - unsigned char m_cts ; /* handshake lines */ - unsigned char m_ri ; - unsigned char m_dtr ; - unsigned char stopc; - unsigned char startc; - unsigned char stopca; - unsigned char startca; - unsigned char fepstopc; - unsigned char fepstartc; - unsigned char fepstopca; - unsigned char fepstartca; - unsigned char txwin; - unsigned char rxwin; - unsigned short fepiflag; - unsigned short fepcflag; - unsigned short fepoflag; - unsigned short txbufhead; - unsigned short txbufsize; - unsigned short rxbufhead; - unsigned short rxbufsize; - int close_delay; - unsigned long event; - uint dev; - unsigned long statusflags; - unsigned long c_iflag; - unsigned long c_cflag; - unsigned long c_lflag; - unsigned long c_oflag; - unsigned char __iomem *txptr; - unsigned char __iomem *rxptr; - struct board_info *board; - struct board_chan __iomem *brdchan; - struct digi_struct digiext; - struct work_struct tqueue; - struct global_data __iomem *mailbox; -}; - -struct board_info -{ - unsigned char status; - unsigned char type; - unsigned char altpin; - unsigned short numports; - unsigned long port; - unsigned long membase; - void __iomem *re_map_port; - void __iomem *re_map_membase; - unsigned long memory_seg; - void ( * memwinon ) (struct board_info *, unsigned int) ; - void ( * memwinoff ) (struct board_info *, unsigned int) ; - void ( * globalwinon ) (struct channel *) ; - void ( * txwinon ) (struct channel *) ; - void ( * rxwinon ) (struct channel *) ; - void ( * memoff ) (struct channel *) ; - void ( * assertgwinon ) (struct channel *) ; - void ( * assertmemoff ) (struct channel *) ; - unsigned char poller_inhibited ; -}; - diff --git a/drivers/char/epcaconfig.h b/drivers/char/epcaconfig.h deleted file mode 100644 index 55dec067078e..000000000000 --- a/drivers/char/epcaconfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#define NUMCARDS 0 -#define NBDEVS 0 - -struct board_info static_boards[NUMCARDS]={ -}; - -/* DO NOT HAND EDIT THIS FILE! */ diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile deleted file mode 100644 index 7b78e0dfc5b0..000000000000 --- a/drivers/char/ip2/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Computone IntelliPort Plus Driver -# - -obj-$(CONFIG_COMPUTONE) += ip2.o - -ip2-y := ip2main.o - diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c deleted file mode 100644 index e7af647800b6..000000000000 --- a/drivers/char/ip2/i2cmd.c +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Definition table for In-line and Bypass commands. Applicable -* only when the standard loadware is active. (This is included -* source code, not a separate compilation module.) -* -*******************************************************************************/ - -//------------------------------------------------------------------------------ -// -// Revision History: -// -// 10 October 1991 MAG First Draft -// 7 November 1991 MAG Reflects additional commands. -// 24 February 1992 MAG Additional commands for 1.4.x loadware -// 11 March 1992 MAG Additional commands -// 30 March 1992 MAG Additional command: CMD_DSS_NOW -// 18 May 1992 MAG Discovered commands 39 & 40 must be at the end of a -// packet: affects implementation. -//------------------------------------------------------------------------------ - -//************ -//* Includes * -//************ - -#include "i2cmd.h" /* To get some bit-defines */ - -//------------------------------------------------------------------------------ -// Here is the table of global arrays which represent each type of command -// supported in the IntelliPort standard loadware. See also i2cmd.h -// for a more complete explanation of what is going on. -//------------------------------------------------------------------------------ - -// Here are the various globals: note that the names are not used except through -// the macros defined in i2cmd.h. Also note that although they are character -// arrays here (for extendability) they are cast to structure pointers in the -// i2cmd.h macros. See i2cmd.h for flags definitions. - -// Length Flags Command -static UCHAR ct02[] = { 1, BTH, 0x02 }; // DTR UP -static UCHAR ct03[] = { 1, BTH, 0x03 }; // DTR DN -static UCHAR ct04[] = { 1, BTH, 0x04 }; // RTS UP -static UCHAR ct05[] = { 1, BTH, 0x05 }; // RTS DN -static UCHAR ct06[] = { 1, BYP, 0x06 }; // START FL -static UCHAR ct07[] = { 2, BTH, 0x07,0 }; // BAUD -static UCHAR ct08[] = { 2, BTH, 0x08,0 }; // BITS -static UCHAR ct09[] = { 2, BTH, 0x09,0 }; // STOP -static UCHAR ct10[] = { 2, BTH, 0x0A,0 }; // PARITY -static UCHAR ct11[] = { 2, BTH, 0x0B,0 }; // XON -static UCHAR ct12[] = { 2, BTH, 0x0C,0 }; // XOFF -static UCHAR ct13[] = { 1, BTH, 0x0D }; // STOP FL -static UCHAR ct14[] = { 1, BYP|VIP, 0x0E }; // ACK HOTK -//static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0 }; // IRQ SET -static UCHAR ct16[] = { 2, INL, 0x10,0 }; // IXONOPTS -static UCHAR ct17[] = { 2, INL, 0x11,0 }; // OXONOPTS -static UCHAR ct18[] = { 1, INL, 0x12 }; // CTSENAB -static UCHAR ct19[] = { 1, BTH, 0x13 }; // CTSDSAB -static UCHAR ct20[] = { 1, INL, 0x14 }; // DCDENAB -static UCHAR ct21[] = { 1, BTH, 0x15 }; // DCDDSAB -static UCHAR ct22[] = { 1, BTH, 0x16 }; // DSRENAB -static UCHAR ct23[] = { 1, BTH, 0x17 }; // DSRDSAB -static UCHAR ct24[] = { 1, BTH, 0x18 }; // RIENAB -static UCHAR ct25[] = { 1, BTH, 0x19 }; // RIDSAB -static UCHAR ct26[] = { 2, BTH, 0x1A,0 }; // BRKENAB -static UCHAR ct27[] = { 1, BTH, 0x1B }; // BRKDSAB -//static UCHAR ct28[]={ 2, BTH, 0x1C,0 }; // MAXBLOKSIZE -//static UCHAR ct29[]={ 2, 0, 0x1D,0 }; // reserved -static UCHAR ct30[] = { 1, INL, 0x1E }; // CTSFLOWENAB -static UCHAR ct31[] = { 1, INL, 0x1F }; // CTSFLOWDSAB -static UCHAR ct32[] = { 1, INL, 0x20 }; // RTSFLOWENAB -static UCHAR ct33[] = { 1, INL, 0x21 }; // RTSFLOWDSAB -static UCHAR ct34[] = { 2, BTH, 0x22,0 }; // ISTRIPMODE -static UCHAR ct35[] = { 2, BTH|END, 0x23,0 }; // SENDBREAK -static UCHAR ct36[] = { 2, BTH, 0x24,0 }; // SETERRMODE -//static UCHAR ct36a[]={ 3, INL, 0x24,0,0 }; // SET_REPLACE - -// The following is listed for completeness, but should never be sent directly -// by user-level code. It is sent only by library routines in response to data -// movement. -//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0 }; // FLOW PACKET - -// Back to normal -//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ -//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0 }; // OPOSTON -//static UCHAR ct40[]={ 1, BTH|END, 0x28 }; // OPOSTOFF -static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME -//static UCHAR ct42[]={ 2, BTH, 0x2A,0 }; // TXBAUD -//static UCHAR ct43[]={ 2, BTH, 0x2B,0 }; // RXBAUD -//static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING -//static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB -//static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB -//static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS -//static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB -//static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB -//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB -//static UCHAR ct51[]={ 1, BTH, 0x33 }; // DTRFLOWDSAB -//static UCHAR ct52[]={ 1, BTH, 0x34 }; // BAUDTABRESET -//static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP -static UCHAR ct54[] = { 3, BTH, 0x36,0,0 }; // CUSTOMBAUD1 -static UCHAR ct55[] = { 3, BTH, 0x37,0,0 }; // CUSTOMBAUD2 -static UCHAR ct56[] = { 2, BTH|END, 0x38,0 }; // PAUSE -static UCHAR ct57[] = { 1, BYP, 0x39 }; // SUSPEND -static UCHAR ct58[] = { 1, BYP, 0x3A }; // UNSUSPEND -static UCHAR ct59[] = { 2, BTH, 0x3B,0 }; // PARITYCHK -static UCHAR ct60[] = { 1, INL|VIP, 0x3C }; // BOOKMARKREQ -//static UCHAR ct61[]={ 2, BTH, 0x3D,0 }; // INTERNALLOOP -//static UCHAR ct62[]={ 2, BTH, 0x3E,0 }; // HOTKTIMEOUT -static UCHAR ct63[] = { 2, INL, 0x3F,0 }; // SETTXON -static UCHAR ct64[] = { 2, INL, 0x40,0 }; // SETTXOFF -//static UCHAR ct65[]={ 2, BTH, 0x41,0 }; // SETAUTORTS -//static UCHAR ct66[]={ 2, BTH, 0x42,0 }; // SETHIGHWAT -//static UCHAR ct67[]={ 2, BYP, 0x43,0 }; // STARTSELFL -//static UCHAR ct68[]={ 2, INL, 0x44,0 }; // ENDSELFL -//static UCHAR ct69[]={ 1, BYP, 0x45 }; // HWFLOW_OFF -//static UCHAR ct70[]={ 1, BTH, 0x46 }; // ODSRFL_ENAB -//static UCHAR ct71[]={ 1, BTH, 0x47 }; // ODSRFL_DSAB -//static UCHAR ct72[]={ 1, BTH, 0x48 }; // ODCDFL_ENAB -//static UCHAR ct73[]={ 1, BTH, 0x49 }; // ODCDFL_DSAB -//static UCHAR ct74[]={ 2, BTH, 0x4A,0 }; // LOADLEVEL -//static UCHAR ct75[]={ 2, BTH, 0x4B,0 }; // STATDATA -//static UCHAR ct76[]={ 1, BYP, 0x4C }; // BREAK_ON -//static UCHAR ct77[]={ 1, BYP, 0x4D }; // BREAK_OFF -//static UCHAR ct78[]={ 1, BYP, 0x4E }; // GETFC -static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW -//static UCHAR ct80[]={ 4, BTH, 0x50,0,0,0 }; // DIVISOR_LATCH -//static UCHAR ct81[]={ 1, BYP, 0x51 }; // GET_STATUS -//static UCHAR ct82[]={ 1, BYP, 0x52 }; // GET_TXCNT -//static UCHAR ct83[]={ 1, BYP, 0x53 }; // GET_RXCNT -//static UCHAR ct84[]={ 1, BYP, 0x54 }; // GET_BOXIDS -//static UCHAR ct85[]={10, BYP, 0x55,0,0,0,0,0,0,0,0,0 }; // ENAB_MULT -//static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE -static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST -//static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD -//static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO -//static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break - -// Some composite commands as well -//static UCHAR cc01[]={ 2, BTH, 0x02,0x04 }; // DTR & RTS UP -//static UCHAR cc02[]={ 2, BTH, 0x03,0x05 }; // DTR & RTS DN - -//******** -//* Code * -//******** - -//****************************************************************************** -// Function: i2cmdUnixFlags(iflag, cflag, lflag) -// Parameters: Unix tty flags -// -// Returns: Pointer to command structure -// -// Description: -// -// This routine sets the parameters of command 47 and returns a pointer to the -// appropriate structure. -//****************************************************************************** -#if 0 -cmdSyntaxPtr -i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) -{ - cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47; - - pCM->cmd[1] = (unsigned char) iflag; - pCM->cmd[2] = (unsigned char) (iflag >> 8); - pCM->cmd[3] = (unsigned char) cflag; - pCM->cmd[4] = (unsigned char) (cflag >> 8); - pCM->cmd[5] = (unsigned char) lflag; - pCM->cmd[6] = (unsigned char) (lflag >> 8); - return pCM; -} -#endif /* 0 */ - -//****************************************************************************** -// Function: i2cmdBaudDef(which, rate) -// Parameters: ? -// -// Returns: Pointer to command structure -// -// Description: -// -// This routine sets the parameters of commands 54 or 55 (according to the -// argument which), and returns a pointer to the appropriate structure. -//****************************************************************************** -static cmdSyntaxPtr -i2cmdBaudDef(int which, unsigned short rate) -{ - cmdSyntaxPtr pCM; - - switch(which) - { - case 1: - pCM = (cmdSyntaxPtr) ct54; - break; - default: - case 2: - pCM = (cmdSyntaxPtr) ct55; - break; - } - pCM->cmd[1] = (unsigned char) rate; - pCM->cmd[2] = (unsigned char) (rate >> 8); - return pCM; -} - diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h deleted file mode 100644 index 29277ec6b8ed..000000000000 --- a/drivers/char/ip2/i2cmd.h +++ /dev/null @@ -1,630 +0,0 @@ -/******************************************************************************* -* -* (c) 1999 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Definitions and support for In-line and Bypass commands. -* Applicable only when the standard loadware is active. -* -*******************************************************************************/ -//------------------------------------------------------------------------------ -// Revision History: -// -// 10 October 1991 MAG First Draft -// 7 November 1991 MAG Reflects some new commands -// 20 February 1992 MAG CMD_HOTACK corrected: no argument. -// 24 February 1992 MAG Support added for new commands for 1.4.x loadware. -// 11 March 1992 MAG Additional commands. -// 16 March 1992 MAG Additional commands. -// 30 March 1992 MAG Additional command: CMD_DSS_NOW -// 18 May 1992 MAG Changed CMD_OPOST -// -//------------------------------------------------------------------------------ -#ifndef I2CMD_H // To prevent multiple includes -#define I2CMD_H 1 - -#include "ip2types.h" - -// This module is designed to provide a uniform method of sending commands to -// the board through command packets. The difficulty is, some commands take -// parameters, others do not. Furthermore, it is often useful to send several -// commands to the same channel as part of the same packet. (See also i2pack.h.) -// -// This module is designed so that the caller should not be responsible for -// remembering the exact syntax of each command, or at least so that the -// compiler could check things somewhat. I'll explain as we go... -// -// First, a structure which can embody the syntax of each type of command. -// -typedef struct _cmdSyntax -{ - UCHAR length; // Number of bytes in the command - UCHAR flags; // Information about the command (see below) - - // The command and its parameters, which may be of arbitrary length. Don't - // worry yet how the parameters will be initialized; macros later take care - // of it. Also, don't worry about the arbitrary length issue; this structure - // is never used to allocate space (see i2cmd.c). - UCHAR cmd[2]; -} cmdSyntax, *cmdSyntaxPtr; - -// Bit assignments for flags - -#define INL 1 // Set if suitable for inline commands -#define BYP 2 // Set if suitable for bypass commands -#define BTH (INL|BYP) // suitable for either! -#define END 4 // Set if this must be the last command in a block -#define VIP 8 // Set if this command is special in some way and really - // should only be sent from the library-level and not - // directly from user-level -#define VAR 0x10 // This command is of variable length! - -// Declarations for the global arrays used to bear the commands and their -// arguments. -// -// Note: Since these are globals and the arguments might change, it is important -// that the library routine COPY these into buffers from whence they would be -// sent, rather than merely storing the pointers. In multi-threaded -// environments, important that the copy should obtain before any context switch -// is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND -// MORE THAN ONCE WITH THE SAME PARAMETERS in the same call. -// -static UCHAR ct02[]; -static UCHAR ct03[]; -static UCHAR ct04[]; -static UCHAR ct05[]; -static UCHAR ct06[]; -static UCHAR ct07[]; -static UCHAR ct08[]; -static UCHAR ct09[]; -static UCHAR ct10[]; -static UCHAR ct11[]; -static UCHAR ct12[]; -static UCHAR ct13[]; -static UCHAR ct14[]; -static UCHAR ct15[]; -static UCHAR ct16[]; -static UCHAR ct17[]; -static UCHAR ct18[]; -static UCHAR ct19[]; -static UCHAR ct20[]; -static UCHAR ct21[]; -static UCHAR ct22[]; -static UCHAR ct23[]; -static UCHAR ct24[]; -static UCHAR ct25[]; -static UCHAR ct26[]; -static UCHAR ct27[]; -static UCHAR ct28[]; -static UCHAR ct29[]; -static UCHAR ct30[]; -static UCHAR ct31[]; -static UCHAR ct32[]; -static UCHAR ct33[]; -static UCHAR ct34[]; -static UCHAR ct35[]; -static UCHAR ct36[]; -static UCHAR ct36a[]; -static UCHAR ct41[]; -static UCHAR ct42[]; -static UCHAR ct43[]; -static UCHAR ct44[]; -static UCHAR ct45[]; -static UCHAR ct46[]; -static UCHAR ct48[]; -static UCHAR ct49[]; -static UCHAR ct50[]; -static UCHAR ct51[]; -static UCHAR ct52[]; -static UCHAR ct56[]; -static UCHAR ct57[]; -static UCHAR ct58[]; -static UCHAR ct59[]; -static UCHAR ct60[]; -static UCHAR ct61[]; -static UCHAR ct62[]; -static UCHAR ct63[]; -static UCHAR ct64[]; -static UCHAR ct65[]; -static UCHAR ct66[]; -static UCHAR ct67[]; -static UCHAR ct68[]; -static UCHAR ct69[]; -static UCHAR ct70[]; -static UCHAR ct71[]; -static UCHAR ct72[]; -static UCHAR ct73[]; -static UCHAR ct74[]; -static UCHAR ct75[]; -static UCHAR ct76[]; -static UCHAR ct77[]; -static UCHAR ct78[]; -static UCHAR ct79[]; -static UCHAR ct80[]; -static UCHAR ct81[]; -static UCHAR ct82[]; -static UCHAR ct83[]; -static UCHAR ct84[]; -static UCHAR ct85[]; -static UCHAR ct86[]; -static UCHAR ct87[]; -static UCHAR ct88[]; -static UCHAR ct89[]; -static UCHAR ct90[]; -static UCHAR ct91[]; -static UCHAR cc01[]; -static UCHAR cc02[]; - -// Now, refer to i2cmd.c, and see the character arrays defined there. They are -// cast here to cmdSyntaxPtr. -// -// There are library functions for issuing bypass or inline commands. These -// functions take one or more arguments of the type cmdSyntaxPtr. The routine -// then can figure out how long each command is supposed to be and easily add it -// to the list. -// -// For ease of use, we define manifests which return pointers to appropriate -// cmdSyntaxPtr things. But some commands also take arguments. If a single -// argument is used, we define a macro which performs the single assignment and -// (through the expedient of a comma expression) references the appropriate -// pointer. For commands requiring several arguments, we actually define a -// function to perform the assignments. - -#define CMD_DTRUP (cmdSyntaxPtr)(ct02) // Raise DTR -#define CMD_DTRDN (cmdSyntaxPtr)(ct03) // Lower DTR -#define CMD_RTSUP (cmdSyntaxPtr)(ct04) // Raise RTS -#define CMD_RTSDN (cmdSyntaxPtr)(ct05) // Lower RTS -#define CMD_STARTFL (cmdSyntaxPtr)(ct06) // Start Flushing Data - -#define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01) // Raise DTR and RTS -#define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02) // Lower DTR and RTS - -// Set Baud Rate for transmit and receive -#define CMD_SETBAUD(arg) \ - (((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07)) - -#define CBR_50 1 -#define CBR_75 2 -#define CBR_110 3 -#define CBR_134 4 -#define CBR_150 5 -#define CBR_200 6 -#define CBR_300 7 -#define CBR_600 8 -#define CBR_1200 9 -#define CBR_1800 10 -#define CBR_2400 11 -#define CBR_4800 12 -#define CBR_9600 13 -#define CBR_19200 14 -#define CBR_38400 15 -#define CBR_2000 16 -#define CBR_3600 17 -#define CBR_7200 18 -#define CBR_56000 19 -#define CBR_57600 20 -#define CBR_64000 21 -#define CBR_76800 22 -#define CBR_115200 23 -#define CBR_C1 24 // Custom baud rate 1 -#define CBR_C2 25 // Custom baud rate 2 -#define CBR_153600 26 -#define CBR_230400 27 -#define CBR_307200 28 -#define CBR_460800 29 -#define CBR_921600 30 - -// Set Character size -// -#define CMD_SETBITS(arg) \ - (((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08)) - -#define CSZ_5 0 -#define CSZ_6 1 -#define CSZ_7 2 -#define CSZ_8 3 - -// Set number of stop bits -// -#define CMD_SETSTOP(arg) \ - (((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09)) - -#define CST_1 0 -#define CST_15 1 // 1.5 stop bits -#define CST_2 2 - -// Set parity option -// -#define CMD_SETPAR(arg) \ - (((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10)) - -#define CSP_NP 0 // no parity -#define CSP_OD 1 // odd parity -#define CSP_EV 2 // Even parity -#define CSP_SP 3 // Space parity -#define CSP_MK 4 // Mark parity - -// Define xon char for transmitter flow control -// -#define CMD_DEF_IXON(arg) \ - (((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11)) - -// Define xoff char for transmitter flow control -// -#define CMD_DEF_IXOFF(arg) \ - (((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12)) - -#define CMD_STOPFL (cmdSyntaxPtr)(ct13) // Stop Flushing data - -// Acknowledge receipt of hotkey signal -// -#define CMD_HOTACK (cmdSyntaxPtr)(ct14) - -// Define irq level to use. Should actually be sent by library-level code, not -// directly from user... -// -#define CMDVALUE_IRQ 15 // For library use at initialization. Until this command - // is sent, board processing doesn't really start. -#define CMD_SET_IRQ(arg) \ - (((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15)) - -#define CIR_POLL 0 // No IRQ - Poll -#define CIR_3 3 // IRQ 3 -#define CIR_4 4 // IRQ 4 -#define CIR_5 5 // IRQ 5 -#define CIR_7 7 // IRQ 7 -#define CIR_10 10 // IRQ 10 -#define CIR_11 11 // IRQ 11 -#define CIR_12 12 // IRQ 12 -#define CIR_15 15 // IRQ 15 - -// Select transmit flow xon/xoff options -// -#define CMD_IXON_OPT(arg) \ - (((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16)) - -#define CIX_NONE 0 // Incoming Xon/Xoff characters not special -#define CIX_XON 1 // Xoff disable, Xon enable -#define CIX_XANY 2 // Xoff disable, any key enable - -// Select receive flow xon/xoff options -// -#define CMD_OXON_OPT(arg) \ - (((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17)) - -#define COX_NONE 0 // Don't send Xon/Xoff -#define COX_XON 1 // Send xon/xoff to start/stop incoming data - - -#define CMD_CTS_REP (cmdSyntaxPtr)(ct18) // Enable CTS reporting -#define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting - -#define CMD_DCD_REP (cmdSyntaxPtr)(ct20) // Enable DCD reporting -#define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting - -#define CMD_DSR_REP (cmdSyntaxPtr)(ct22) // Enable DSR reporting -#define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting - -#define CMD_RI_REP (cmdSyntaxPtr)(ct24) // Enable RI reporting -#define CMD_RI_NREP (cmdSyntaxPtr)(ct25) // Disable RI reporting - -// Enable break reporting and select style -// -#define CMD_BRK_REP(arg) \ - (((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26)) - -#define CBK_STAT 0x00 // Report breaks as a status (exception,irq) -#define CBK_NULL 0x01 // Report breaks as a good null -#define CBK_STAT_SEQ 0x02 // Report breaks as a status AND as in-band character - // sequence FFh, 01h, 10h -#define CBK_SEQ 0x03 // Report breaks as the in-band - //sequence FFh, 01h, 10h ONLY. -#define CBK_FLSH 0x04 // if this bit set also flush input data -#define CBK_POSIX 0x08 // if this bit set report as FF,0,0 sequence -#define CBK_SINGLE 0x10 // if this bit set with CBK_SEQ or CBK_STAT_SEQ - //then reports single null instead of triple - -#define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting - -// Specify maximum block size for received data -// -#define CMD_MAX_BLOCK(arg) \ - (((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28)) - -// -- COMMAND 29 is reserved -- - -#define CMD_CTSFL_ENAB (cmdSyntaxPtr)(ct30) // Enable CTS flow control -#define CMD_CTSFL_DSAB (cmdSyntaxPtr)(ct31) // Disable CTS flow control -#define CMD_RTSFL_ENAB (cmdSyntaxPtr)(ct32) // Enable RTS flow control -#define CMD_RTSFL_DSAB (cmdSyntaxPtr)(ct33) // Disable RTS flow control - -// Specify istrip option -// -#define CMD_ISTRIP_OPT(arg) \ - (((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34)) - -#define CIS_NOSTRIP 0 // Strip characters to character size -#define CIS_STRIP 1 // Strip any 8-bit characters to 7 bits - -// Send a break of arg milliseconds -// -#define CMD_SEND_BRK(arg) \ - (((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35)) - -// Set error reporting mode -// -#define CMD_SET_ERROR(arg) \ - (((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36)) - -#define CSE_ESTAT 0 // Report error in a status packet -#define CSE_NOREP 1 // Treat character as though it were good -#define CSE_DROP 2 // Discard the character -#define CSE_NULL 3 // Replace with a null -#define CSE_MARK 4 // Replace with a 3-character sequence (as Unix) - -#define CSE_REPLACE 0x8 // Replace the errored character with the - // replacement character defined here - -#define CSE_STAT_REPLACE 0x18 // Replace the errored character with the - // replacement character defined here AND - // report the error as a status packet (as in - // CSE_ESTAT). - - -// COMMAND 37, to send flow control packets, is handled only by low-level -// library code in response to data movement and shouldn't ever be sent by the -// user code. See i2pack.h and the body of i2lib.c for details. - -// Enable on-board post-processing, using options given in oflag argument. -// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command -// because the loadware does not permit sending back-to-back CMD_OPOST_ON -// commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that -// CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a -// solo packet). This means the caller must specify separately CMD_OPOST_OFF, -// CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure -// each gets a separate packet. Extra CMD_OPOST_OFF's are always ok. -// -#define CMD_OPOST_ON(oflag) \ - (*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \ - (cmdSyntaxPtr)(ct39)) - -#define CMD_OPOST_OFF (cmdSyntaxPtr)(ct40) // Disable on-board post-proc - -#define CMD_RESUME (cmdSyntaxPtr)(ct41) // Resume: behave as though an XON - // were received; - -// Set Transmit baud rate (see command 7 for arguments) -// -#define CMD_SETBAUD_TX(arg) \ - (((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42)) - -// Set Receive baud rate (see command 7 for arguments) -// -#define CMD_SETBAUD_RX(arg) \ - (((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43)) - -// Request interrupt from board each arg milliseconds. Interrupt will specify -// "received data", even though there may be no data present. If arg == 0, -// disables any such interrupts. -// -#define CMD_PING_REQ(arg) \ - (((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44)) - -#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking -#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking - -#if 0 -// COMMAND 47: Send Protocol info via Unix flags: -// iflag = Unix tty t_iflag -// cflag = Unix tty t_cflag -// lflag = Unix tty t_lflag -// See System V Unix/Xenix documentation for the meanings of the bit fields -// within these flags -// -#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag) -#endif /* 0 */ - -#define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl -#define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl -#define CMD_DTRFL_ENAB (cmdSyntaxPtr)(ct50) // Enable DTR flow control -#define CMD_DTRFL_DSAB (cmdSyntaxPtr)(ct51) // Disable DTR flow control -#define CMD_BAUD_RESET (cmdSyntaxPtr)(ct52) // Reset baudrate table - -// COMMAND 54: Define custom rate #1 -// rate = (short) 1/10 of the desired baud rate -// -#define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate) - -// COMMAND 55: Define custom rate #2 -// rate = (short) 1/10 of the desired baud rate -// -#define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate) - -// Pause arg hundredths of seconds. (Note, this is NOT milliseconds.) -// -#define CMD_PAUSE(arg) \ - (((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56)) - -#define CMD_SUSPEND (cmdSyntaxPtr)(ct57) // Suspend output -#define CMD_UNSUSPEND (cmdSyntaxPtr)(ct58) // Un-Suspend output - -// Set parity-checking options -// -#define CMD_PARCHK(arg) \ - (((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59)) - -#define CPK_ENAB 0 // Enable parity checking on input -#define CPK_DSAB 1 // Disable parity checking on input - -#define CMD_BMARK_REQ (cmdSyntaxPtr)(ct60) // Bookmark request - - -// Enable/Disable internal loopback mode -// -#define CMD_INLOOP(arg) \ - (((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61)) - -#define CIN_DISABLE 0 // Normal operation (default) -#define CIN_ENABLE 1 // Internal (local) loopback -#define CIN_REMOTE 2 // Remote loopback - -// Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0 -// --> no timeout: wait forever. -// -#define CMD_HOT_TIME(arg) \ - (((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62)) - - -// Define (outgoing) xon for receive flow control -// -#define CMD_DEF_OXON(arg) \ - (((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63)) - -// Define (outgoing) xoff for receiver flow control -// -#define CMD_DEF_OXOFF(arg) \ - (((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64)) - -// Enable/Disable RTS on transmit (1/2 duplex-style) -// -#define CMD_RTS_XMIT(arg) \ - (((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65)) - -#define CHD_DISABLE 0 -#define CHD_ENABLE 1 - -// Set high-water-mark level (debugging use only) -// -#define CMD_SETHIGHWAT(arg) \ - (((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66)) - -// Start flushing tagged data (tag = 0-14) -// -#define CMD_START_SELFL(tag) \ - (((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67)) - -// End flushing tagged data (tag = 0-14) -// -#define CMD_END_SELFL(tag) \ - (((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68)) - -#define CMD_HWFLOW_OFF (cmdSyntaxPtr)(ct69) // Disable HW TX flow control -#define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c -#define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c -#define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c -#define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c - -// Set transmit interrupt load level. Count should be an even value 2-12 -// -#define CMD_LOADLEVEL(count) \ - (((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74)) - -// If reporting DSS changes, map to character sequence FFh, 2, MSR -// -#define CMD_STATDATA(arg) \ - (((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75)) - -#define CSTD_DISABLE// Report DSS changes as status packets only (default) -#define CSTD_ENABLE // Report DSS changes as in-band data sequence as well as - // by status packet. - -#define CMD_BREAK_ON (cmdSyntaxPtr)(ct76)// Set break and stop xmit -#define CMD_BREAK_OFF (cmdSyntaxPtr)(ct77)// End break and restart xmit -#define CMD_GETFC (cmdSyntaxPtr)(ct78)// Request for flow control packet - // from board. - -// Transmit this character immediately -// -#define CMD_XMIT_NOW(ch) \ - (((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79)) - -// Set baud rate via "divisor latch" -// -#define CMD_DIVISOR_LATCH(which,value) \ - (((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \ - *(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \ - (cmdSyntaxPtr)(ct80)) - -#define CDL_RX 1 // Set receiver rate -#define CDL_TX 2 // Set transmit rate - // (CDL_TX | CDL_RX) Set both rates - -// Request for special diagnostic status pkt from the board. -// -#define CMD_GET_STATUS (cmdSyntaxPtr)(ct81) - -// Request time-stamped transmit character count packet. -// -#define CMD_GET_TXCNT (cmdSyntaxPtr)(ct82) - -// Request time-stamped receive character count packet. -// -#define CMD_GET_RXCNT (cmdSyntaxPtr)(ct83) - -// Request for box/board I.D. packet. -#define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84) - -// Enable or disable multiple channels according to bit-mapped ushorts box 1-4 -// -#define CMD_ENAB_MULT(enable, box1, box2, box3, box4) \ - (((cmdSytaxPtr)(ct85))->cmd[1] = (enable), \ - *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \ - *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \ - *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \ - *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \ - (cmdSyntaxPtr)(ct85)) - -#define CEM_DISABLE 0 -#define CEM_ENABLE 1 - -// Enable or disable receiver or receiver interrupts (default both enabled) -// -#define CMD_RCV_ENABLE(ch) \ - (((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86)) - -#define CRE_OFF 0 // Disable the receiver -#define CRE_ON 1 // Enable the receiver -#define CRE_INTOFF 2 // Disable receiver interrupts (to loadware) -#define CRE_INTON 3 // Enable receiver interrupts (to loadware) - -// Starts up a hardware test process, which runs transparently, and sends a -// STAT_HWFAIL packet in case a hardware failure is detected. -// -#define CMD_HW_TEST (cmdSyntaxPtr)(ct87) - -// Change receiver threshold and timeout value: -// Defaults: timeout = 20mS -// threshold count = 8 when DTRflow not in use, -// threshold count = 5 when DTRflow in use. -// -#define CMD_RCV_THRESHOLD(count,ms) \ - (((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \ - ((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \ - (cmdSyntaxPtr)(ct88)) - -// Makes the loadware report DSS signals for this channel immediately. -// -#define CMD_DSS_NOW (cmdSyntaxPtr)(ct89) - -// Set the receive silo parameters -// timeout is ms idle wait until delivery (~VTIME) -// threshold is max characters cause interrupt (~VMIN) -// -#define CMD_SET_SILO(timeout,threshold) \ - (((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \ - ((cmdSyntaxPtr)(ct90))->cmd[2] = (threshold), \ - (cmdSyntaxPtr)(ct90)) - -// Set timed break in decisecond (1/10s) -// -#define CMD_LBREAK(ds) \ - (((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66)) - - - -#endif // I2CMD_H diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c deleted file mode 100644 index 29db44de399f..000000000000 --- a/drivers/char/ip2/i2ellis.c +++ /dev/null @@ -1,1403 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Low-level interface code for the device driver -* (This is included source code, not a separate compilation -* module.) -* -*******************************************************************************/ -//--------------------------------------------- -// Function declarations private to this module -//--------------------------------------------- -// Functions called only indirectly through i2eBordStr entries. - -static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int); -static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int); -static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int); -static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int); - -static unsigned short iiReadWord16(i2eBordStrPtr); -static unsigned short iiReadWord8(i2eBordStrPtr); -static void iiWriteWord16(i2eBordStrPtr, unsigned short); -static void iiWriteWord8(i2eBordStrPtr, unsigned short); - -static int iiWaitForTxEmptyII(i2eBordStrPtr, int); -static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int); -static int iiTxMailEmptyII(i2eBordStrPtr); -static int iiTxMailEmptyIIEX(i2eBordStrPtr); -static int iiTrySendMailII(i2eBordStrPtr, unsigned char); -static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char); - -static unsigned short iiGetMailII(i2eBordStrPtr); -static unsigned short iiGetMailIIEX(i2eBordStrPtr); - -static void iiEnableMailIrqII(i2eBordStrPtr); -static void iiEnableMailIrqIIEX(i2eBordStrPtr); -static void iiWriteMaskII(i2eBordStrPtr, unsigned char); -static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); - -static void ii2Nop(void); - -//*************** -//* Static Data * -//*************** - -static int ii2Safe; // Safe I/O address for delay routine - -static int iiDelayed; // Set when the iiResetDelay function is - // called. Cleared when ANY board is reset. -static DEFINE_RWLOCK(Dl_spinlock); - -//******** -//* Code * -//******** - -//======================================================= -// Initialization Routines -// -// iiSetAddress -// iiReset -// iiResetDelay -// iiInitialize -//======================================================= - -//****************************************************************************** -// Function: iiSetAddress(pB, address, delay) -// Parameters: pB - pointer to the board structure -// address - the purported I/O address of the board -// delay - pointer to the 1-ms delay function to use -// in this and any future operations to this board -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// This routine (roughly) checks for address validity, sets the i2eValid OK and -// sets the state to II_STATE_COLD which means that we haven't even sent a reset -// yet. -// -//****************************************************************************** -static int -iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay ) -{ - // Should any failure occur before init is finished... - pB->i2eValid = I2E_INCOMPLETE; - - // Cannot check upper limit except extremely: Might be microchannel - // Address must be on an 8-byte boundary - - if ((unsigned int)address <= 0x100 - || (unsigned int)address >= 0xfff8 - || (address & 0x7) - ) - { - I2_COMPLETE(pB, I2EE_BADADDR); - } - - // Initialize accelerators - pB->i2eBase = address; - pB->i2eData = address + FIFO_DATA; - pB->i2eStatus = address + FIFO_STATUS; - pB->i2ePointer = address + FIFO_PTR; - pB->i2eXMail = address + FIFO_MAIL; - pB->i2eXMask = address + FIFO_MASK; - - // Initialize i/o address for ii2DelayIO - ii2Safe = address + FIFO_NOP; - - // Initialize the delay routine - pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop); - - pB->i2eValid = I2E_MAGIC; - pB->i2eState = II_STATE_COLD; - - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiReset(pB) -// Parameters: pB - pointer to the board structure -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Attempts to reset the board (see also i2hw.h). Normally, we would use this to -// reset a board immediately after iiSetAddress(), but it is valid to reset a -// board from any state, say, in order to change or re-load loadware. (Under -// such circumstances, no reason to re-run iiSetAddress(), which is why it is a -// separate routine and not included in this routine. -// -//****************************************************************************** -static int -iiReset(i2eBordStrPtr pB) -{ - // Magic number should be set, else even the address is suspect - if (pB->i2eValid != I2E_MAGIC) - { - I2_COMPLETE(pB, I2EE_BADMAGIC); - } - - outb(0, pB->i2eBase + FIFO_RESET); /* Any data will do */ - iiDelay(pB, 50); // Pause between resets - outb(0, pB->i2eBase + FIFO_RESET); /* Second reset */ - - // We must wait before even attempting to read anything from the FIFO: the - // board's P.O.S.T may actually attempt to read and write its end of the - // FIFO in order to check flags, loop back (where supported), etc. On - // completion of this testing it would reset the FIFO, and on completion - // of all // P.O.S.T., write the message. We must not mistake data which - // might have been sent for testing as part of the reset message. To - // better utilize time, say, when resetting several boards, we allow the - // delay to be performed externally; in this way the caller can reset - // several boards, delay a single time, then call the initialization - // routine for all. - - pB->i2eState = II_STATE_RESET; - - iiDelayed = 0; // i.e., the delay routine hasn't been called since the most - // recent reset. - - // Ensure anything which would have been of use to standard loadware is - // blanked out, since board has now forgotten everything!. - - pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */ - pB->i2eWaitingForEmptyFifo = 0; - pB->i2eOutMailWaiting = 0; - pB->i2eChannelPtr = NULL; - pB->i2eChannelCnt = 0; - - pB->i2eLeadoffWord[0] = 0; - pB->i2eFifoInInts = 0; - pB->i2eFifoOutInts = 0; - pB->i2eFatalTrap = NULL; - pB->i2eFatal = 0; - - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiResetDelay(pB) -// Parameters: pB - pointer to the board structure -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Using the delay defined in board structure, waits two seconds (for board to -// reset). -// -//****************************************************************************** -static int -iiResetDelay(i2eBordStrPtr pB) -{ - if (pB->i2eValid != I2E_MAGIC) { - I2_COMPLETE(pB, I2EE_BADMAGIC); - } - if (pB->i2eState != II_STATE_RESET) { - I2_COMPLETE(pB, I2EE_BADSTATE); - } - iiDelay(pB,2000); /* Now we wait for two seconds. */ - iiDelayed = 1; /* Delay has been called: ok to initialize */ - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiInitialize(pB) -// Parameters: pB - pointer to the board structure -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Attempts to read the Power-on reset message. Initializes any remaining fields -// in the pB structure. -// -// This should be called as the third step of a process beginning with -// iiReset(), then iiResetDelay(). This routine checks to see that the structure -// is "valid" and in the reset state, also confirms that the delay routine has -// been called since the latest reset (to any board! overly strong!). -// -//****************************************************************************** -static int -iiInitialize(i2eBordStrPtr pB) -{ - int itemp; - unsigned char c; - unsigned short utemp; - unsigned int ilimit; - - if (pB->i2eValid != I2E_MAGIC) - { - I2_COMPLETE(pB, I2EE_BADMAGIC); - } - - if (pB->i2eState != II_STATE_RESET || !iiDelayed) - { - I2_COMPLETE(pB, I2EE_BADSTATE); - } - - // In case there is a failure short of our completely reading the power-up - // message. - pB->i2eValid = I2E_INCOMPLETE; - - - // Now attempt to read the message. - - for (itemp = 0; itemp < sizeof(porStr); itemp++) - { - // We expect the entire message is ready. - if (!I2_HAS_INPUT(pB)) { - pB->i2ePomSize = itemp; - I2_COMPLETE(pB, I2EE_PORM_SHORT); - } - - pB->i2ePom.c[itemp] = c = inb(pB->i2eData); - - // We check the magic numbers as soon as they are supposed to be read - // (rather than after) to minimize effect of reading something we - // already suspect can't be "us". - if ( (itemp == POR_1_INDEX && c != POR_MAGIC_1) || - (itemp == POR_2_INDEX && c != POR_MAGIC_2)) - { - pB->i2ePomSize = itemp+1; - I2_COMPLETE(pB, I2EE_BADMAGIC); - } - } - - pB->i2ePomSize = itemp; - - // Ensure that this was all the data... - if (I2_HAS_INPUT(pB)) - I2_COMPLETE(pB, I2EE_PORM_LONG); - - // For now, we'll fail to initialize if P.O.S.T reports bad chip mapper: - // Implying we will not be able to download any code either: That's ok: the - // condition is pretty explicit. - if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER) - { - I2_COMPLETE(pB, I2EE_POSTERR); - } - - // Determine anything which must be done differently depending on the family - // of boards! - switch (pB->i2ePom.e.porID & POR_ID_FAMILY) - { - case POR_ID_FII: // IntelliPort-II - - pB->i2eFifoStyle = FIFO_II; - pB->i2eFifoSize = 512; // 512 bytes, always - pB->i2eDataWidth16 = false; - - pB->i2eMaxIrq = 15; // Because board cannot tell us it is in an 8-bit - // slot, we do allow it to be done (documentation!) - - pB->i2eGoodMap[1] = - pB->i2eGoodMap[2] = - pB->i2eGoodMap[3] = - pB->i2eChannelMap[1] = - pB->i2eChannelMap[2] = - pB->i2eChannelMap[3] = 0; - - switch (pB->i2ePom.e.porID & POR_ID_SIZE) - { - case POR_ID_II_4: - pB->i2eGoodMap[0] = - pB->i2eChannelMap[0] = 0x0f; // four-port - - // Since porPorts1 is based on the Hardware ID register, the numbers - // should always be consistent for IntelliPort-II. Ditto below... - if (pB->i2ePom.e.porPorts1 != 4) - { - I2_COMPLETE(pB, I2EE_INCONSIST); - } - break; - - case POR_ID_II_8: - case POR_ID_II_8R: - pB->i2eGoodMap[0] = - pB->i2eChannelMap[0] = 0xff; // Eight port - if (pB->i2ePom.e.porPorts1 != 8) - { - I2_COMPLETE(pB, I2EE_INCONSIST); - } - break; - - case POR_ID_II_6: - pB->i2eGoodMap[0] = - pB->i2eChannelMap[0] = 0x3f; // Six Port - if (pB->i2ePom.e.porPorts1 != 6) - { - I2_COMPLETE(pB, I2EE_INCONSIST); - } - break; - } - - // Fix up the "good channel list based on any errors reported. - if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1) - { - pB->i2eGoodMap[0] &= ~0x0f; - } - - if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2) - { - pB->i2eGoodMap[0] &= ~0xf0; - } - - break; // POR_ID_FII case - - case POR_ID_FIIEX: // IntelliPort-IIEX - - pB->i2eFifoStyle = FIFO_IIEX; - - itemp = pB->i2ePom.e.porFifoSize; - - // Implicit assumption that fifo would not grow beyond 32k, - // nor would ever be less than 256. - - if (itemp < 8 || itemp > 15) - { - I2_COMPLETE(pB, I2EE_INCONSIST); - } - pB->i2eFifoSize = (1 << itemp); - - // These are based on what P.O.S.T thinks should be there, based on - // box ID registers - ilimit = pB->i2ePom.e.porNumBoxes; - if (ilimit > ABS_MAX_BOXES) - { - ilimit = ABS_MAX_BOXES; - } - - // For as many boxes as EXIST, gives the type of box. - // Added 8/6/93: check for the ISA-4 (asic) which looks like an - // expandable but for whom "8 or 16?" is not the right question. - - utemp = pB->i2ePom.e.porFlags; - if (utemp & POR_CEX4) - { - pB->i2eChannelMap[0] = 0x000f; - } else { - utemp &= POR_BOXES; - for (itemp = 0; itemp < ilimit; itemp++) - { - pB->i2eChannelMap[itemp] = - ((utemp & POR_BOX_16) ? 0xffff : 0x00ff); - utemp >>= 1; - } - } - - // These are based on what P.O.S.T actually found. - - utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1; - - for (itemp = 0; itemp < ilimit; itemp++) - { - pB->i2eGoodMap[itemp] = 0; - if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f; - if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0; - if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00; - if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000; - utemp >>= 4; - } - - // Now determine whether we should transfer in 8 or 16-bit mode. - switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) ) - { - case POR_BUS_SLOT16 | POR_BUS_DIP16: - pB->i2eDataWidth16 = true; - pB->i2eMaxIrq = 15; - break; - - case POR_BUS_SLOT16: - pB->i2eDataWidth16 = false; - pB->i2eMaxIrq = 15; - break; - - case 0: - case POR_BUS_DIP16: // In an 8-bit slot, DIP switch don't care. - default: - pB->i2eDataWidth16 = false; - pB->i2eMaxIrq = 7; - break; - } - break; // POR_ID_FIIEX case - - default: // Unknown type of board - I2_COMPLETE(pB, I2EE_BAD_FAMILY); - break; - } // End the switch based on family - - // Temporarily, claim there is no room in the outbound fifo. - // We will maintain this whenever we check for an empty outbound FIFO. - pB->i2eFifoRemains = 0; - - // Now, based on the bus type, should we expect to be able to re-configure - // interrupts (say, for testing purposes). - switch (pB->i2ePom.e.porBus & POR_BUS_TYPE) - { - case POR_BUS_T_ISA: - case POR_BUS_T_UNK: // If the type of bus is undeclared, assume ok. - case POR_BUS_T_MCA: - case POR_BUS_T_EISA: - break; - default: - I2_COMPLETE(pB, I2EE_BADBUS); - } - - if (pB->i2eDataWidth16) - { - pB->i2eWriteBuf = iiWriteBuf16; - pB->i2eReadBuf = iiReadBuf16; - pB->i2eWriteWord = iiWriteWord16; - pB->i2eReadWord = iiReadWord16; - } else { - pB->i2eWriteBuf = iiWriteBuf8; - pB->i2eReadBuf = iiReadBuf8; - pB->i2eWriteWord = iiWriteWord8; - pB->i2eReadWord = iiReadWord8; - } - - switch(pB->i2eFifoStyle) - { - case FIFO_II: - pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII; - pB->i2eTxMailEmpty = iiTxMailEmptyII; - pB->i2eTrySendMail = iiTrySendMailII; - pB->i2eGetMail = iiGetMailII; - pB->i2eEnableMailIrq = iiEnableMailIrqII; - pB->i2eWriteMask = iiWriteMaskII; - - break; - - case FIFO_IIEX: - pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX; - pB->i2eTxMailEmpty = iiTxMailEmptyIIEX; - pB->i2eTrySendMail = iiTrySendMailIIEX; - pB->i2eGetMail = iiGetMailIIEX; - pB->i2eEnableMailIrq = iiEnableMailIrqIIEX; - pB->i2eWriteMask = iiWriteMaskIIEX; - - break; - - default: - I2_COMPLETE(pB, I2EE_INCONSIST); - } - - // Initialize state information. - pB->i2eState = II_STATE_READY; // Ready to load loadware. - - // Some Final cleanup: - // For some boards, the bootstrap firmware may perform some sort of test - // resulting in a stray character pending in the incoming mailbox. If one is - // there, it should be read and discarded, especially since for the standard - // firmware, it's the mailbox that interrupts the host. - - pB->i2eStartMail = iiGetMail(pB); - - // Throw it away and clear the mailbox structure element - pB->i2eStartMail = NO_MAIL_HERE; - - // Everything is ok now, return with good status/ - - pB->i2eValid = I2E_MAGIC; - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: ii2DelayTimer(mseconds) -// Parameters: mseconds - number of milliseconds to delay -// -// Returns: Nothing -// -// Description: -// -// This routine delays for approximately mseconds milliseconds and is intended -// to be called indirectly through i2Delay field in i2eBordStr. It uses the -// Linux timer_list mechanism. -// -// The Linux timers use a unit called "jiffies" which are 10mS in the Intel -// architecture. This function rounds the delay period up to the next "jiffy". -// In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended -// for Alpha platforms at this time. -// -//****************************************************************************** -static void -ii2DelayTimer(unsigned int mseconds) -{ - msleep_interruptible(mseconds); -} - -#if 0 -//static void ii2DelayIO(unsigned int); -//****************************************************************************** -// !!! Not Used, this is DOS crap, some of you young folks may be interested in -// in how things were done in the stone age of caculating machines !!! -// Function: ii2DelayIO(mseconds) -// Parameters: mseconds - number of milliseconds to delay -// -// Returns: Nothing -// -// Description: -// -// This routine delays for approximately mseconds milliseconds and is intended -// to be called indirectly through i2Delay field in i2eBordStr. It is intended -// for use where a clock-based function is impossible: for example, DOS drivers. -// -// This function uses the IN instruction to place bounds on the timing and -// assumes that ii2Safe has been set. This is because I/O instructions are not -// subject to caching and will therefore take a certain minimum time. To ensure -// the delay is at least long enough on fast machines, it is based on some -// fastest-case calculations. On slower machines this may cause VERY long -// delays. (3 x fastest case). In the fastest case, everything is cached except -// the I/O instruction itself. -// -// Timing calculations: -// The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O -// operation in question is a byte operation to an odd address. For 8-bit -// operations, the architecture generally enforces two wait states. At 10 MHz, a -// single cycle time is 100nS. A read operation at two wait states takes 6 -// cycles for a total time of 600nS. Therefore approximately 1666 iterations -// would be required to generate a single millisecond delay. The worst -// (reasonable) case would be an 8MHz system with no cacheing. In this case, the -// I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code -// fetch of other instructions in the loop would take time (zero wait states, -// however) and would be hard to estimate. This is minimized by using in-line -// assembler for the in inner loop of IN instructions. This consists of just a -// few bytes. So we'll guess about four code fetches per loop. Each code fetch -// should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is -// that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS. -// -// So much for theoretical timings: results using 1666 value on some actual -// machines: -// IBM 286 6MHz 3.15 mS -// Zenith 386 33MHz 2.45 mS -// (brandX) 386 33MHz 1.90 mS (has cache) -// (brandY) 486 33MHz 2.35 mS -// NCR 486 ?? 1.65 mS (microchannel) -// -// For most machines, it is probably safe to scale this number back (remember, -// for robust operation use an actual timed delay if possible), so we are using -// a value of 1190. This yields 1.17 mS for the fastest machine in our sample, -// 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine. -// -// 1/29/93: -// The above timings are too slow. Actual cycle times might be faster. ISA cycle -// times could approach 500 nS, and ... -// The IBM model 77 being microchannel has no wait states for 8-bit reads and -// seems to be accessing the I/O at 440 nS per access (from start of one to -// start of next). This would imply we need 1000/.440 = 2272 iterations to -// guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in -// fact enough. For diagnostics, we keep the level at 1190, but developers note -// this needs tuning. -// -// Safe assumption: 2270 i/o reads = 1 millisecond -// -//****************************************************************************** - - -static int ii2DelValue = 1190; // See timing calculations below - // 1666 for fastest theoretical machine - // 1190 safe for most fast 386 machines - // 1000 for fastest machine tested here - // 540 (sic) for AT286/6Mhz -static void -ii2DelayIO(unsigned int mseconds) -{ - if (!ii2Safe) - return; /* Do nothing if this variable uninitialized */ - - while(mseconds--) { - int i = ii2DelValue; - while ( i-- ) { - inb(ii2Safe); - } - } -} -#endif - -//****************************************************************************** -// Function: ii2Nop() -// Parameters: None -// -// Returns: Nothing -// -// Description: -// -// iiInitialize will set i2eDelay to this if the delay parameter is NULL. This -// saves checking for a NULL pointer at every call. -//****************************************************************************** -static void -ii2Nop(void) -{ - return; // no mystery here -} - -//======================================================= -// Routines which are available in 8/16-bit versions, or -// in different fifo styles. These are ALL called -// indirectly through the board structure. -//======================================================= - -//****************************************************************************** -// Function: iiWriteBuf16(pB, address, count) -// Parameters: pB - pointer to board structure -// address - address of data to write -// count - number of data bytes to write -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Writes 'count' bytes from 'address' to the data fifo specified by the board -// structure pointer pB. Should count happen to be odd, an extra pad byte is -// sent (identity unknown...). Uses 16-bit (word) operations. Is called -// indirectly through pB->i2eWriteBuf. -// -//****************************************************************************** -static int -iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count) -{ - // Rudimentary sanity checking here. - if (pB->i2eValid != I2E_MAGIC) - I2_COMPLETE(pB, I2EE_INVALID); - - I2_OUTSW(pB->i2eData, address, count); - - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiWriteBuf8(pB, address, count) -// Parameters: pB - pointer to board structure -// address - address of data to write -// count - number of data bytes to write -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Writes 'count' bytes from 'address' to the data fifo specified by the board -// structure pointer pB. Should count happen to be odd, an extra pad byte is -// sent (identity unknown...). This is to be consistent with the 16-bit version. -// Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf. -// -//****************************************************************************** -static int -iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count) -{ - /* Rudimentary sanity checking here */ - if (pB->i2eValid != I2E_MAGIC) - I2_COMPLETE(pB, I2EE_INVALID); - - I2_OUTSB(pB->i2eData, address, count); - - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiReadBuf16(pB, address, count) -// Parameters: pB - pointer to board structure -// address - address to put data read -// count - number of data bytes to read -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Reads 'count' bytes into 'address' from the data fifo specified by the board -// structure pointer pB. Should count happen to be odd, an extra pad byte is -// received (identity unknown...). Uses 16-bit (word) operations. Is called -// indirectly through pB->i2eReadBuf. -// -//****************************************************************************** -static int -iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count) -{ - // Rudimentary sanity checking here. - if (pB->i2eValid != I2E_MAGIC) - I2_COMPLETE(pB, I2EE_INVALID); - - I2_INSW(pB->i2eData, address, count); - - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiReadBuf8(pB, address, count) -// Parameters: pB - pointer to board structure -// address - address to put data read -// count - number of data bytes to read -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Reads 'count' bytes into 'address' from the data fifo specified by the board -// structure pointer pB. Should count happen to be odd, an extra pad byte is -// received (identity unknown...). This to match the 16-bit behaviour. Uses -// 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf. -// -//****************************************************************************** -static int -iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count) -{ - // Rudimentary sanity checking here. - if (pB->i2eValid != I2E_MAGIC) - I2_COMPLETE(pB, I2EE_INVALID); - - I2_INSB(pB->i2eData, address, count); - - I2_COMPLETE(pB, I2EE_GOOD); -} - -//****************************************************************************** -// Function: iiReadWord16(pB) -// Parameters: pB - pointer to board structure -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Returns the word read from the data fifo specified by the board-structure -// pointer pB. Uses a 16-bit operation. Is called indirectly through -// pB->i2eReadWord. -// -//****************************************************************************** -static unsigned short -iiReadWord16(i2eBordStrPtr pB) -{ - return inw(pB->i2eData); -} - -//****************************************************************************** -// Function: iiReadWord8(pB) -// Parameters: pB - pointer to board structure -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Returns the word read from the data fifo specified by the board-structure -// pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is -// called indirectly through pB->i2eReadWord. -// -//****************************************************************************** -static unsigned short -iiReadWord8(i2eBordStrPtr pB) -{ - unsigned short urs; - - urs = inb(pB->i2eData); - - return (inb(pB->i2eData) << 8) | urs; -} - -//****************************************************************************** -// Function: iiWriteWord16(pB, value) -// Parameters: pB - pointer to board structure -// value - data to write -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Writes the word 'value' to the data fifo specified by the board-structure -// pointer pB. Uses 16-bit operation. Is called indirectly through -// pB->i2eWriteWord. -// -//****************************************************************************** -static void -iiWriteWord16(i2eBordStrPtr pB, unsigned short value) -{ - outw((int)value, pB->i2eData); -} - -//****************************************************************************** -// Function: iiWriteWord8(pB, value) -// Parameters: pB - pointer to board structure -// value - data to write -// -// Returns: True if everything appears copacetic. -// False if there is any error: the pB->i2eError field has the error -// -// Description: -// -// Writes the word 'value' to the data fifo specified by the board-structure -// pointer pB. Uses two 8-bit operations (writes LSB first). Is called -// indirectly through pB->i2eWriteWord. -// -//****************************************************************************** -static void -iiWriteWord8(i2eBordStrPtr pB, unsigned short value) -{ - outb((char)value, pB->i2eData); - outb((char)(value >> 8), pB->i2eData); -} - -//****************************************************************************** -// Function: iiWaitForTxEmptyII(pB, mSdelay) -// Parameters: pB - pointer to board structure -// mSdelay - period to wait before returning -// -// Returns: True if the FIFO is empty. -// False if it not empty in the required time: the pB->i2eError -// field has the error. -// -// Description: -// -// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if -// not empty by the required time, returns false and error in pB->i2eError, -// otherwise returns true. -// -// mSdelay == 0 is taken to mean must be empty on the first test. -// -// This version operates on IntelliPort-II - style FIFO's -// -// Note this routine is organized so that if status is ok there is no delay at -// all called either before or after the test. Is called indirectly through -// pB->i2eWaitForTxEmpty. -// -//****************************************************************************** -static int -iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay) -{ - unsigned long flags; - int itemp; - - for (;;) - { - // This routine hinges on being able to see the "other" status register - // (as seen by the local processor). His incoming fifo is our outgoing - // FIFO. - // - // By the nature of this routine, you would be using this as part of a - // larger atomic context: i.e., you would use this routine to ensure the - // fifo empty, then act on this information. Between these two halves, - // you will generally not want to service interrupts or in any way - // disrupt the assumptions implicit in the larger context. - // - // Even worse, however, this routine "shifts" the status register to - // point to the local status register which is not the usual situation. - // Therefore for extra safety, we force the critical section to be - // completely atomic, and pick up after ourselves before allowing any - // interrupts of any kind. - - - write_lock_irqsave(&Dl_spinlock, flags); - outb(SEL_COMMAND, pB->i2ePointer); - outb(SEL_CMD_SH, pB->i2ePointer); - - itemp = inb(pB->i2eStatus); - - outb(SEL_COMMAND, pB->i2ePointer); - outb(SEL_CMD_UNSH, pB->i2ePointer); - - if (itemp & ST_IN_EMPTY) - { - I2_UPDATE_FIFO_ROOM(pB); - write_unlock_irqrestore(&Dl_spinlock, flags); - I2_COMPLETE(pB, I2EE_GOOD); - } - - write_unlock_irqrestore(&Dl_spinlock, flags); - - if (mSdelay-- == 0) - break; - - iiDelay(pB, 1); /* 1 mS granularity on checking condition */ - } - I2_COMPLETE(pB, I2EE_TXE_TIME); -} - -//****************************************************************************** -// Function: iiWaitForTxEmptyIIEX(pB, mSdelay) -// Parameters: pB - pointer to board structure -// mSdelay - period to wait before returning -// -// Returns: True if the FIFO is empty. -// False if it not empty in the required time: the pB->i2eError -// field has the error. -// -// Description: -// -// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if -// not empty by the required time, returns false and error in pB->i2eError, -// otherwise returns true. -// -// mSdelay == 0 is taken to mean must be empty on the first test. -// -// This version operates on IntelliPort-IIEX - style FIFO's -// -// Note this routine is organized so that if status is ok there is no delay at -// all called either before or after the test. Is called indirectly through -// pB->i2eWaitForTxEmpty. -// -//****************************************************************************** -static int -iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay) -{ - unsigned long flags; - - for (;;) - { - // By the nature of this routine, you would be using this as part of a - // larger atomic context: i.e., you would use this routine to ensure the - // fifo empty, then act on this information. Between these two halves, - // you will generally not want to service interrupts or in any way - // disrupt the assumptions implicit in the larger context. - - write_lock_irqsave(&Dl_spinlock, flags); - - if (inb(pB->i2eStatus) & STE_OUT_MT) { - I2_UPDATE_FIFO_ROOM(pB); - write_unlock_irqrestore(&Dl_spinlock, flags); - I2_COMPLETE(pB, I2EE_GOOD); - } - write_unlock_irqrestore(&Dl_spinlock, flags); - - if (mSdelay-- == 0) - break; - - iiDelay(pB, 1); // 1 mS granularity on checking condition - } - I2_COMPLETE(pB, I2EE_TXE_TIME); -} - -//****************************************************************************** -// Function: iiTxMailEmptyII(pB) -// Parameters: pB - pointer to board structure -// -// Returns: True if the transmit mailbox is empty. -// False if it not empty. -// -// Description: -// -// Returns true or false according to whether the transmit mailbox is empty (and -// therefore able to accept more mail) -// -// This version operates on IntelliPort-II - style FIFO's -// -//****************************************************************************** -static int -iiTxMailEmptyII(i2eBordStrPtr pB) -{ - int port = pB->i2ePointer; - outb(SEL_OUTMAIL, port); - return inb(port) == 0; -} - -//****************************************************************************** -// Function: iiTxMailEmptyIIEX(pB) -// Parameters: pB - pointer to board structure -// -// Returns: True if the transmit mailbox is empty. -// False if it not empty. -// -// Description: -// -// Returns true or false according to whether the transmit mailbox is empty (and -// therefore able to accept more mail) -// -// This version operates on IntelliPort-IIEX - style FIFO's -// -//****************************************************************************** -static int -iiTxMailEmptyIIEX(i2eBordStrPtr pB) -{ - return !(inb(pB->i2eStatus) & STE_OUT_MAIL); -} - -//****************************************************************************** -// Function: iiTrySendMailII(pB,mail) -// Parameters: pB - pointer to board structure -// mail - value to write to mailbox -// -// Returns: True if the transmit mailbox is empty, and mail is sent. -// False if it not empty. -// -// Description: -// -// If outgoing mailbox is empty, sends mail and returns true. If outgoing -// mailbox is not empty, returns false. -// -// This version operates on IntelliPort-II - style FIFO's -// -//****************************************************************************** -static int -iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail) -{ - int port = pB->i2ePointer; - - outb(SEL_OUTMAIL, port); - if (inb(port) == 0) { - outb(SEL_OUTMAIL, port); - outb(mail, port); - return 1; - } - return 0; -} - -//****************************************************************************** -// Function: iiTrySendMailIIEX(pB,mail) -// Parameters: pB - pointer to board structure -// mail - value to write to mailbox -// -// Returns: True if the transmit mailbox is empty, and mail is sent. -// False if it not empty. -// -// Description: -// -// If outgoing mailbox is empty, sends mail and returns true. If outgoing -// mailbox is not empty, returns false. -// -// This version operates on IntelliPort-IIEX - style FIFO's -// -//****************************************************************************** -static int -iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail) -{ - if (inb(pB->i2eStatus) & STE_OUT_MAIL) - return 0; - outb(mail, pB->i2eXMail); - return 1; -} - -//****************************************************************************** -// Function: iiGetMailII(pB,mail) -// Parameters: pB - pointer to board structure -// -// Returns: Mailbox data or NO_MAIL_HERE. -// -// Description: -// -// If no mail available, returns NO_MAIL_HERE otherwise returns the data from -// the mailbox, which is guaranteed != NO_MAIL_HERE. -// -// This version operates on IntelliPort-II - style FIFO's -// -//****************************************************************************** -static unsigned short -iiGetMailII(i2eBordStrPtr pB) -{ - if (I2_HAS_MAIL(pB)) { - outb(SEL_INMAIL, pB->i2ePointer); - return inb(pB->i2ePointer); - } else { - return NO_MAIL_HERE; - } -} - -//****************************************************************************** -// Function: iiGetMailIIEX(pB,mail) -// Parameters: pB - pointer to board structure -// -// Returns: Mailbox data or NO_MAIL_HERE. -// -// Description: -// -// If no mail available, returns NO_MAIL_HERE otherwise returns the data from -// the mailbox, which is guaranteed != NO_MAIL_HERE. -// -// This version operates on IntelliPort-IIEX - style FIFO's -// -//****************************************************************************** -static unsigned short -iiGetMailIIEX(i2eBordStrPtr pB) -{ - if (I2_HAS_MAIL(pB)) - return inb(pB->i2eXMail); - else - return NO_MAIL_HERE; -} - -//****************************************************************************** -// Function: iiEnableMailIrqII(pB) -// Parameters: pB - pointer to board structure -// -// Returns: Nothing -// -// Description: -// -// Enables board to interrupt host (only) by writing to host's in-bound mailbox. -// -// This version operates on IntelliPort-II - style FIFO's -// -//****************************************************************************** -static void -iiEnableMailIrqII(i2eBordStrPtr pB) -{ - outb(SEL_MASK, pB->i2ePointer); - outb(ST_IN_MAIL, pB->i2ePointer); -} - -//****************************************************************************** -// Function: iiEnableMailIrqIIEX(pB) -// Parameters: pB - pointer to board structure -// -// Returns: Nothing -// -// Description: -// -// Enables board to interrupt host (only) by writing to host's in-bound mailbox. -// -// This version operates on IntelliPort-IIEX - style FIFO's -// -//****************************************************************************** -static void -iiEnableMailIrqIIEX(i2eBordStrPtr pB) -{ - outb(MX_IN_MAIL, pB->i2eXMask); -} - -//****************************************************************************** -// Function: iiWriteMaskII(pB) -// Parameters: pB - pointer to board structure -// -// Returns: Nothing -// -// Description: -// -// Writes arbitrary value to the mask register. -// -// This version operates on IntelliPort-II - style FIFO's -// -//****************************************************************************** -static void -iiWriteMaskII(i2eBordStrPtr pB, unsigned char value) -{ - outb(SEL_MASK, pB->i2ePointer); - outb(value, pB->i2ePointer); -} - -//****************************************************************************** -// Function: iiWriteMaskIIEX(pB) -// Parameters: pB - pointer to board structure -// -// Returns: Nothing -// -// Description: -// -// Writes arbitrary value to the mask register. -// -// This version operates on IntelliPort-IIEX - style FIFO's -// -//****************************************************************************** -static void -iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value) -{ - outb(value, pB->i2eXMask); -} - -//****************************************************************************** -// Function: iiDownloadBlock(pB, pSource, isStandard) -// Parameters: pB - pointer to board structure -// pSource - loadware block to download -// isStandard - True if "standard" loadware, else false. -// -// Returns: Success or Failure -// -// Description: -// -// Downloads a single block (at pSource)to the board referenced by pB. Caller -// sets isStandard to true/false according to whether the "standard" loadware is -// what's being loaded. The normal process, then, is to perform an iiInitialize -// to the board, then perform some number of iiDownloadBlocks using the returned -// state to determine when download is complete. -// -// Possible return values: (see I2ELLIS.H) -// II_DOWN_BADVALID -// II_DOWN_BADFILE -// II_DOWN_CONTINUING -// II_DOWN_GOOD -// II_DOWN_BAD -// II_DOWN_BADSTATE -// II_DOWN_TIMEOUT -// -// Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to -// determine whether this is the first block, whether to check for magic -// numbers, how many blocks there are to go... -// -//****************************************************************************** -static int -iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard) -{ - int itemp; - int loadedFirst; - - if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID; - - switch(pB->i2eState) - { - case II_STATE_READY: - - // Loading the first block after reset. Must check the magic number of the - // loadfile, store the number of blocks we expect to load. - if (pSource->e.loadMagic != MAGIC_LOADFILE) - { - return II_DOWN_BADFILE; - } - - // Next we store the total number of blocks to load, including this one. - pB->i2eToLoad = 1 + pSource->e.loadBlocksMore; - - // Set the state, store the version numbers. ('Cause this may have come - // from a file - we might want to report these versions and revisions in - // case of an error! - pB->i2eState = II_STATE_LOADING; - pB->i2eLVersion = pSource->e.loadVersion; - pB->i2eLRevision = pSource->e.loadRevision; - pB->i2eLSub = pSource->e.loadSubRevision; - - // The time and date of compilation is also available but don't bother - // storing it for normal purposes. - loadedFirst = 1; - break; - - case II_STATE_LOADING: - loadedFirst = 0; - break; - - default: - return II_DOWN_BADSTATE; - } - - // Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad - // must be positive still, because otherwise we would have cleaned up last - // time and set the state to II_STATE_LOADED. - if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { - return II_DOWN_TIMEOUT; - } - - if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) { - return II_DOWN_BADVALID; - } - - // If we just loaded the first block, wait for the fifo to empty an extra - // long time to allow for any special startup code in the firmware, like - // sending status messages to the LCD's. - - if (loadedFirst) { - if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) { - return II_DOWN_TIMEOUT; - } - } - - // Determine whether this was our last block! - if (--(pB->i2eToLoad)) { - return II_DOWN_CONTINUING; // more to come... - } - - // It WAS our last block: Clean up operations... - // ...Wait for last buffer to drain from the board... - if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { - return II_DOWN_TIMEOUT; - } - // If there were only a single block written, this would come back - // immediately and be harmless, though not strictly necessary. - itemp = MAX_DLOAD_ACK_TIME/10; - while (--itemp) { - if (I2_HAS_INPUT(pB)) { - switch (inb(pB->i2eData)) { - case LOADWARE_OK: - pB->i2eState = - isStandard ? II_STATE_STDLOADED :II_STATE_LOADED; - - // Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2) - // will, // if there is a debug port attached, require some - // time to send information to the debug port now. It will do - // this before // executing any of the code we just downloaded. - // It may take up to 700 milliseconds. - if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) { - iiDelay(pB, 700); - } - - return II_DOWN_GOOD; - - case LOADWARE_BAD: - default: - return II_DOWN_BAD; - } - } - - iiDelay(pB, 10); // 10 mS granularity on checking condition - } - - // Drop-through --> timed out waiting for firmware confirmation - - pB->i2eState = II_STATE_BADLOAD; - return II_DOWN_TIMEOUT; -} - -//****************************************************************************** -// Function: iiDownloadAll(pB, pSource, isStandard, size) -// Parameters: pB - pointer to board structure -// pSource - loadware block to download -// isStandard - True if "standard" loadware, else false. -// size - size of data to download (in bytes) -// -// Returns: Success or Failure -// -// Description: -// -// Given a pointer to a board structure, a pointer to the beginning of some -// loadware, whether it is considered the "standard loadware", and the size of -// the array in bytes loads the entire array to the board as loadware. -// -// Assumes the board has been freshly reset and the power-up reset message read. -// (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be -// too much or too little data to load, or if iiDownloadBlock complains. -//****************************************************************************** -static int -iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size) -{ - int status; - - // We know (from context) board should be ready for the first block of - // download. Complain if not. - if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE; - - while (size > 0) { - size -= LOADWARE_BLOCK_SIZE; // How much data should there be left to - // load after the following operation ? - - // Note we just bump pSource by "one", because its size is actually that - // of an entire block, same as LOADWARE_BLOCK_SIZE. - status = iiDownloadBlock(pB, pSource++, isStandard); - - switch(status) - { - case II_DOWN_GOOD: - return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD); - - case II_DOWN_CONTINUING: - break; - - default: - return status; - } - } - - // We shouldn't drop out: it means "while" caught us with nothing left to - // download, yet the previous DownloadBlock did not return complete. Ergo, - // not enough data to match the size byte in the header. - return II_DOWN_UNDER; -} diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h deleted file mode 100644 index fb6df2456018..000000000000 --- a/drivers/char/ip2/i2ellis.h +++ /dev/null @@ -1,566 +0,0 @@ -/******************************************************************************* -* -* (c) 1999 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Mainline code for the device driver -* -*******************************************************************************/ -//------------------------------------------------------------------------------ -// i2ellis.h -// -// IntelliPort-II and IntelliPort-IIEX -// -// Extremely -// Low -// Level -// Interface -// Services -// -// Structure Definitions and declarations for "ELLIS" service routines found in -// i2ellis.c -// -// These routines are based on properties of the IntelliPort-II and -IIEX -// hardware and bootstrap firmware, and are not sensitive to particular -// conventions of any particular loadware. -// -// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material -// here and in i2ellis.c is intended to provice a useful, but not required, -// layer of insulation from the hardware specifics. -//------------------------------------------------------------------------------ -#ifndef I2ELLIS_H /* To prevent multiple includes */ -#define I2ELLIS_H 1 -//------------------------------------------------ -// Revision History: -// -// 30 September 1991 MAG First Draft Started -// 12 October 1991 ...continued... -// -// 20 December 1996 AKM Linux version -//------------------------------------------------- - -//---------------------- -// Mandatory Includes: -//---------------------- -#include "ip2types.h" -#include "i2hw.h" // The hardware definitions - -//------------------------------------------ -// STAT_BOXIDS packets -//------------------------------------------ -#define MAX_BOX 4 - -typedef struct _bidStat -{ - unsigned char bid_value[MAX_BOX]; -} bidStat, *bidStatPtr; - -// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX -// boards, reports the hardware-specific "asynchronous resource register" on -// each expansion box. Boxes not present report 0xff. For -II boards, the first -// element contains 0x80 for 8-port, 0x40 for 4-port boards. - -// Box IDs aka ARR or Async Resource Register (more than you want to know) -// 7 6 5 4 3 2 1 0 -// F F N N L S S S -// ============================= -// F F - Product Family Designator -// =====+++++++++++++++++++++++++++++++ -// 0 0 - Intelliport II EX / ISA-8 -// 1 0 - IntelliServer -// 0 1 - SAC - Port Device (Intelliport III ??? ) -// =====+++++++++++++++++++++++++++++++++++++++ -// N N - Number of Ports -// 0 0 - 8 (eight) -// 0 1 - 4 (four) -// 1 0 - 12 (twelve) -// 1 1 - 16 (sixteen) -// =++++++++++++++++++++++++++++++++++ -// L - LCD Display Module Present -// 0 - No -// 1 - LCD module present -// =========+++++++++++++++++++++++++++++++++++++ -// S S S - Async Signals Supported Designator -// 0 0 0 - 8dss, Mod DCE DB25 Female -// 0 0 1 - 6dss, RJ-45 -// 0 1 0 - RS-232/422 dss, DB25 Female -// 0 1 1 - RS-232/422 dss, separate 232/422 DB25 Female -// 1 0 0 - 6dss, 921.6 I/F with ST654's -// 1 0 1 - RS-423/232 8dss, RJ-45 10Pin -// 1 1 0 - 6dss, Mod DCE DB25 Female -// 1 1 1 - NO BOX PRESENT - -#define FF(c) ((c & 0xC0) >> 6) -#define NN(c) ((c & 0x30) >> 4) -#define L(c) ((c & 0x08) >> 3) -#define SSS(c) (c & 0x07) - -#define BID_HAS_654(x) (SSS(x) == 0x04) -#define BID_NO_BOX 0xff /* no box */ -#define BID_8PORT 0x80 /* IP2-8 port */ -#define BID_4PORT 0x81 /* IP2-4 port */ -#define BID_EXP_MASK 0x30 /* IP2-EX */ -#define BID_EXP_8PORT 0x00 /* 8, */ -#define BID_EXP_4PORT 0x10 /* 4, */ -#define BID_EXP_UNDEF 0x20 /* UNDEF, */ -#define BID_EXP_16PORT 0x30 /* 16, */ -#define BID_LCD_CTRL 0x08 /* LCD Controller */ -#define BID_LCD_NONE 0x00 /* - no controller present */ -#define BID_LCD_PRES 0x08 /* - controller present */ -#define BID_CON_MASK 0x07 /* - connector pinouts */ -#define BID_CON_DB25 0x00 /* - DB-25 F */ -#define BID_CON_RJ45 0x01 /* - rj45 */ - -//------------------------------------------------------------------------------ -// i2eBordStr -// -// This structure contains all the information the ELLIS routines require in -// dealing with a particular board. -//------------------------------------------------------------------------------ -// There are some queues here which are guaranteed to never contain the entry -// for a single channel twice. So they must be slightly larger to allow -// unambiguous full/empty management -// -#define CH_QUEUE_SIZE ABS_MOST_PORTS+2 - -typedef struct _i2eBordStr -{ - porStr i2ePom; // Structure containing the power-on message. - - unsigned short i2ePomSize; - // The number of bytes actually read if - // different from sizeof i2ePom, indicates - // there is an error! - - unsigned short i2eStartMail; - // Contains whatever inbound mailbox data - // present at startup. NO_MAIL_HERE indicates - // nothing was present. No special - // significance as of this writing, but may be - // useful for diagnostic reasons. - - unsigned short i2eValid; - // Indicates validity of the structure; if - // i2eValid == I2E_MAGIC, then we can trust - // the other fields. Some (especially - // initialization) functions are good about - // checking for validity. Many functions do - // not, it being assumed that the larger - // context assures we are using a valid - // i2eBordStrPtr. - - unsigned short i2eError; - // Used for returning an error condition from - // several functions which use i2eBordStrPtr - // as an argument. - - // Accelerators to characterize separate features of a board, derived from a - // number of sources. - - unsigned short i2eFifoSize; - // Always, the size of the FIFO. For - // IntelliPort-II, always the same, for -IIEX - // taken from the Power-On reset message. - - volatile - unsigned short i2eFifoRemains; - // Used during normal operation to indicate a - // lower bound on the amount of data which - // might be in the outbound fifo. - - unsigned char i2eFifoStyle; - // Accelerator which tells which style (-II or - // -IIEX) FIFO we are using. - - unsigned char i2eDataWidth16; - // Accelerator which tells whether we should - // do 8 or 16-bit data transfers. - - unsigned char i2eMaxIrq; - // The highest allowable IRQ, based on the - // slot size. - - // Accelerators for various addresses on the board - int i2eBase; // I/O Address of the Board - int i2eData; // From here data transfers happen - int i2eStatus; // From here status reads happen - int i2ePointer; // (IntelliPort-II: pointer/commands) - int i2eXMail; // (IntelliPOrt-IIEX: mailboxes - int i2eXMask; // (IntelliPort-IIEX: mask write - - //------------------------------------------------------- - // Information presented in a common format across boards - // For each box, bit map of the channels present. Box closest to - // the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable) - // is taken to be box 0. These are derived from product i.d. registers. - - unsigned short i2eChannelMap[ABS_MAX_BOXES]; - - // Same as above, except each is derived from firmware attempting to detect - // the uart presence (by reading a valid GFRCR register). If bits are set in - // i2eChannelMap and not in i2eGoodMap, there is a potential problem. - - unsigned short i2eGoodMap[ABS_MAX_BOXES]; - - // --------------------------- - // For indirect function calls - - // Routine to cause an N-millisecond delay: Patched by the ii2Initialize - // function. - - void (*i2eDelay)(unsigned int); - - // Routine to write N bytes to the board through the FIFO. Returns true if - // all copacetic, otherwise returns false and error is in i2eError field. - // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. - - int (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int); - - // Routine to read N bytes from the board through the FIFO. Returns true if - // copacetic, otherwise returns false and error in i2eError. - // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. - - int (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int); - - // Returns a word from FIFO. Will use 2 byte operations if needed. - - unsigned short (*i2eReadWord)(struct _i2eBordStr *); - - // Writes a word to FIFO. Will use 2 byte operations if needed. - - void (*i2eWriteWord)(struct _i2eBordStr *, unsigned short); - - // Waits specified time for the Transmit FIFO to go empty. Returns true if - // ok, otherwise returns false and error in i2eError. - - int (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int); - - // Returns true or false according to whether the outgoing mailbox is empty. - - int (*i2eTxMailEmpty)(struct _i2eBordStr *); - - // Checks whether outgoing mailbox is empty. If so, sends mail and returns - // true. Otherwise returns false. - - int (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char); - - // If no mail available, returns NO_MAIL_HERE, else returns the value in the - // mailbox (guaranteed can't be NO_MAIL_HERE). - - unsigned short (*i2eGetMail)(struct _i2eBordStr *); - - // Enables the board to interrupt the host when it writes to the mailbox. - // Irqs will not occur, however, until the loadware separately enables - // interrupt generation to the host. The standard loadware does this in - // response to a command packet sent by the host. (Also, disables - // any other potential interrupt sources from the board -- other than the - // inbound mailbox). - - void (*i2eEnableMailIrq)(struct _i2eBordStr *); - - // Writes an arbitrary value to the mask register. - - void (*i2eWriteMask)(struct _i2eBordStr *, unsigned char); - - - // State information - - // During downloading, indicates the number of blocks remaining to download - // to the board. - - short i2eToLoad; - - // State of board (see manifests below) (e.g., whether in reset condition, - // whether standard loadware is installed, etc. - - unsigned char i2eState; - - // These three fields are only valid when there is loadware running on the - // board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED ) - - unsigned char i2eLVersion; // Loadware version - unsigned char i2eLRevision; // Loadware revision - unsigned char i2eLSub; // Loadware subrevision - - // Flags which only have meaning in the context of the standard loadware. - // Somewhat violates the layering concept, but there is so little additional - // needed at the board level (while much additional at the channel level), - // that this beats maintaining two different per-board structures. - - // Indicates which IRQ the board has been initialized (from software) to use - // For MicroChannel boards, any value different from IRQ_UNDEFINED means - // that the software command has been sent to enable interrupts (or specify - // they are disabled). Special value: IRQ_UNDEFINED indicates that the - // software command to select the interrupt has not yet been sent, therefore - // (since the standard loadware insists that it be sent before any other - // packets are sent) no other packets should be sent yet. - - unsigned short i2eUsingIrq; - - // This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us - // putting more in the mailbox until an appropriate mailbox message is - // received. - - unsigned char i2eWaitingForEmptyFifo; - - // Any mailbox bits waiting to be sent to the board are OR'ed in here. - - unsigned char i2eOutMailWaiting; - - // The head of any incoming packet is read into here, is then examined and - // we dispatch accordingly. - - unsigned short i2eLeadoffWord[1]; - - // Running counter of interrupts where the mailbox indicated incoming data. - - unsigned short i2eFifoInInts; - - // Running counter of interrupts where the mailbox indicated outgoing data - // had been stripped. - - unsigned short i2eFifoOutInts; - - // If not void, gives the address of a routine to call if fatal board error - // is found (only applies to standard l/w). - - void (*i2eFatalTrap)(struct _i2eBordStr *); - - // Will point to an array of some sort of channel structures (whose format - // is unknown at this level, being a function of what loadware is - // installed and the code configuration (max sizes of buffers, etc.)). - - void *i2eChannelPtr; - - // Set indicates that the board has gone fatal. - - unsigned short i2eFatal; - - // The number of elements pointed to by i2eChannelPtr. - - unsigned short i2eChannelCnt; - - // Ring-buffers of channel structures whose channels have particular needs. - - rwlock_t Fbuf_spinlock; - volatile - unsigned short i2Fbuf_strip; // Strip index - volatile - unsigned short i2Fbuf_stuff; // Stuff index - void *i2Fbuf[CH_QUEUE_SIZE]; // An array of channel pointers - // of channels who need to send - // flow control packets. - rwlock_t Dbuf_spinlock; - volatile - unsigned short i2Dbuf_strip; // Strip index - volatile - unsigned short i2Dbuf_stuff; // Stuff index - void *i2Dbuf[CH_QUEUE_SIZE]; // An array of channel pointers - // of channels who need to send - // data or in-line command packets. - rwlock_t Bbuf_spinlock; - volatile - unsigned short i2Bbuf_strip; // Strip index - volatile - unsigned short i2Bbuf_stuff; // Stuff index - void *i2Bbuf[CH_QUEUE_SIZE]; // An array of channel pointers - // of channels who need to send - // bypass command packets. - - /* - * A set of flags to indicate that certain events have occurred on at least - * one of the ports on this board. We use this to decide whether to spin - * through the channels looking for breaks, etc. - */ - int got_input; - int status_change; - bidStat channelBtypes; - - /* - * Debugging counters, etc. - */ - unsigned long debugFlowQueued; - unsigned long debugInlineQueued; - unsigned long debugDataQueued; - unsigned long debugBypassQueued; - unsigned long debugFlowCount; - unsigned long debugInlineCount; - unsigned long debugBypassCount; - - rwlock_t read_fifo_spinlock; - rwlock_t write_fifo_spinlock; - -// For queuing interrupt bottom half handlers. /\/\|=mhw=|\/\/ - struct work_struct tqueue_interrupt; - - struct timer_list SendPendingTimer; // Used by iiSendPending - unsigned int SendPendingRetry; -} i2eBordStr, *i2eBordStrPtr; - -//------------------------------------------------------------------- -// Macro Definitions for the indirect calls defined in the i2eBordStr -//------------------------------------------------------------------- -// -#define iiDelay(a,b) (*(a)->i2eDelay)(b) -#define iiWriteBuf(a,b,c) (*(a)->i2eWriteBuf)(a,b,c) -#define iiReadBuf(a,b,c) (*(a)->i2eReadBuf)(a,b,c) - -#define iiWriteWord(a,b) (*(a)->i2eWriteWord)(a,b) -#define iiReadWord(a) (*(a)->i2eReadWord)(a) - -#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b) - -#define iiTxMailEmpty(a) (*(a)->i2eTxMailEmpty)(a) -#define iiTrySendMail(a,b) (*(a)->i2eTrySendMail)(a,b) - -#define iiGetMail(a) (*(a)->i2eGetMail)(a) -#define iiEnableMailIrq(a) (*(a)->i2eEnableMailIrq)(a) -#define iiDisableMailIrq(a) (*(a)->i2eWriteMask)(a,0) -#define iiWriteMask(a,b) (*(a)->i2eWriteMask)(a,b) - -//------------------------------------------- -// Manifests for i2eBordStr: -//------------------------------------------- - -typedef void (*delayFunc_t)(unsigned int); - -// i2eValid -// -#define I2E_MAGIC 0x4251 // Structure is valid. -#define I2E_INCOMPLETE 0x1122 // Structure failed during init. - - -// i2eError -// -#define I2EE_GOOD 0 // Operation successful -#define I2EE_BADADDR 1 // Address out of range -#define I2EE_BADSTATE 2 // Attempt to perform a function when the board - // structure was in the incorrect state -#define I2EE_BADMAGIC 3 // Bad magic number from Power On test (i2ePomSize - // reflects what was read -#define I2EE_PORM_SHORT 4 // Power On message too short -#define I2EE_PORM_LONG 5 // Power On message too long -#define I2EE_BAD_FAMILY 6 // Un-supported board family type -#define I2EE_INCONSIST 7 // Firmware reports something impossible, - // e.g. unexpected number of ports... Almost no - // excuse other than bad FIFO... -#define I2EE_POSTERR 8 // Power-On self test reported a bad error -#define I2EE_BADBUS 9 // Unknown Bus type declared in message -#define I2EE_TXE_TIME 10 // Timed out waiting for TX Fifo to empty -#define I2EE_INVALID 11 // i2eValid field does not indicate a valid and - // complete board structure (for functions which - // require this be so.) -#define I2EE_BAD_PORT 12 // Discrepancy between channels actually found and - // what the product is supposed to have. Check - // i2eGoodMap vs i2eChannelMap for details. -#define I2EE_BAD_IRQ 13 // Someone specified an unsupported IRQ -#define I2EE_NOCHANNELS 14 // No channel structures have been defined (for - // functions requiring this). - -// i2eFifoStyle -// -#define FIFO_II 0 /* IntelliPort-II style: see also i2hw.h */ -#define FIFO_IIEX 1 /* IntelliPort-IIEX style */ - -// i2eGetMail -// -#define NO_MAIL_HERE 0x1111 // Since mail is unsigned char, cannot possibly - // promote to 0x1111. -// i2eState -// -#define II_STATE_COLD 0 // Addresses have been defined, but board not even - // reset yet. -#define II_STATE_RESET 1 // Board,if it exists, has just been reset -#define II_STATE_READY 2 // Board ready for its first block -#define II_STATE_LOADING 3 // Board continuing load -#define II_STATE_LOADED 4 // Board has finished load: status ok -#define II_STATE_BADLOAD 5 // Board has finished load: failed! -#define II_STATE_STDLOADED 6 // Board has finished load: standard firmware - -// i2eUsingIrq -// -#define I2_IRQ_UNDEFINED 0x1352 /* No valid irq (or polling = 0) can - * ever promote to this! */ -//------------------------------------------ -// Handy Macros for i2ellis.c and others -// Note these are common to -II and -IIEX -//------------------------------------------ - -// Given a pointer to the board structure, does the input FIFO have any data or -// not? -// -#define I2_HAS_INPUT(pB) !(inb(pB->i2eStatus) & ST_IN_EMPTY) - -// Given a pointer to the board structure, is there anything in the incoming -// mailbox? -// -#define I2_HAS_MAIL(pB) (inb(pB->i2eStatus) & ST_IN_MAIL) - -#define I2_UPDATE_FIFO_ROOM(pB) ((pB)->i2eFifoRemains = (pB)->i2eFifoSize) - -//------------------------------------------ -// Function Declarations for i2ellis.c -//------------------------------------------ -// -// Functions called directly -// -// Initialization of a board & structure is in four (five!) parts: -// -// 1) iiSetAddress() - Define the board address & delay function for a board. -// 2) iiReset() - Reset the board (provided it exists) -// -- Note you may do this to several boards -- -// 3) iiResetDelay() - Delay for 2 seconds (once for all boards) -// 4) iiInitialize() - Attempt to read Power-up message; further initialize -// accelerators -// -// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write -// loadware. To change loadware, you must begin again with step 2, resetting -// the board again (step 1 not needed). - -static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t ); -static int iiReset(i2eBordStrPtr); -static int iiResetDelay(i2eBordStrPtr); -static int iiInitialize(i2eBordStrPtr); - -// Routine to validate that all channels expected are there. -// -extern int iiValidateChannels(i2eBordStrPtr); - -// Routine used to download a block of loadware. -// -static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int); - -// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile: -// -#define II_DOWN_BADVALID 0 // board structure is invalid -#define II_DOWN_CONTINUING 1 // So far, so good, firmware expects more -#define II_DOWN_GOOD 2 // Download complete, CRC good -#define II_DOWN_BAD 3 // Download complete, but CRC bad -#define II_DOWN_BADFILE 4 // Bad magic number in loadware file -#define II_DOWN_BADSTATE 5 // Board is in an inappropriate state for - // downloading loadware. (see i2eState) -#define II_DOWN_TIMEOUT 6 // Timeout waiting for firmware -#define II_DOWN_OVER 7 // Too much data -#define II_DOWN_UNDER 8 // Not enough data -#define II_DOWN_NOFILE 9 // Loadware file not found - -// Routine to download an entire loadware module: Return values are a subset of -// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING -// -static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int); - -// Many functions defined here return True if good, False otherwise, with an -// error code in i2eError field. Here is a handy macro for setting the error -// code and returning. -// -#define I2_COMPLETE(pB,code) do { \ - pB->i2eError = code; \ - return (code == I2EE_GOOD);\ - } while (0) - -#endif // I2ELLIS_H diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h deleted file mode 100644 index c0ba6c05f0cd..000000000000 --- a/drivers/char/ip2/i2hw.h +++ /dev/null @@ -1,652 +0,0 @@ -/******************************************************************************* -* -* (c) 1999 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Definitions limited to properties of the hardware or the -* bootstrap firmware. As such, they are applicable regardless of -* operating system or loadware (standard or diagnostic). -* -*******************************************************************************/ -#ifndef I2HW_H -#define I2HW_H 1 -//------------------------------------------------------------------------------ -// Revision History: -// -// 23 September 1991 MAG First Draft Started...through... -// 11 October 1991 ... Continuing development... -// 6 August 1993 Added support for ISA-4 (asic) which is architected -// as an ISA-CEX with a single 4-port box. -// -// 20 December 1996 AKM Version for Linux -// -//------------------------------------------------------------------------------ -/*------------------------------------------------------------------------------ - -HARDWARE DESCRIPTION: - -Introduction: - -The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8) -addresses in the host's I/O space. - -Some addresses are used to transfer data to/from the board, some to transfer -so-called "mailbox" messages, and some to read bit-mapped status information. -While all the products in the line are functionally similar, some use a 16-bit -data path to transfer data while others use an 8-bit path. Also, the use of -command /status/mailbox registers differs slightly between the II and IIEX -branches of the family. - -The host determines what type of board it is dealing with by reading a string of -sixteen characters from the board. These characters are always placed in the -fifo by the board's local processor whenever the board is reset (either from -power-on or under software control) and are known as the "Power-on Reset -Message." In order that this message can be read from either type of board, the -hardware registers used in reading this message are the same. Once this message -has been read by the host, then it has the information required to operate. - -General Differences between boards: - -The greatest structural difference is between the -II and -IIEX families of -product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support -the data path, mailbox registers, and status registers. This chip contains some -features which are not used in the IntelliPort-II products; a description of -these is omitted here. Because of these many features, it contains many -registers, too many to access directly within a small address space. They are -accessed by first writing a value to a "pointer" register. This value selects -the register to be accessed. The next read or write to that address accesses -the selected register rather than the pointer register. - -The -IIEX boards use a proprietary design similar to the Am4701 in function. But -because of a simpler, more streamlined design it doesn't require so many -registers. This means they can be accessed directly in single operations rather -than through a pointer register. - -Besides these differences, there are differences in whether 8-bit or 16-bit -transfers are used to move data to the board. - -The -II boards are capable only of 8-bit data transfers, while the -IIEX boards -may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP -switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit -transfers are supported (and will be expected by the standard loadware). The -on-board firmware can determine the position of the switch, and whether the -board is installed in a 16-bit slot; it supplies this information to the host as -part of the power-up reset message. - -The configuration switch (#8) and slot selection do not directly configure the -hardware. It is up to the on-board loadware and host-based drivers to act -according to the selected options. That is, loadware and drivers could be -written to perform 8-bit transfers regardless of the state of the DIP switch or -slot (and in a diagnostic environment might well do so). Likewise, 16-bit -transfers could be performed as long as the card is in a 16-bit slot. - -Note the slot selection and DIP switch selection are provided separately: a -board running in 8-bit mode in a 16-bit slot has a greater range of possible -interrupts to choose from; information of potential use to the host. - -All 8-bit data transfers are done in the same way, regardless of whether on a --II board or a -IIEX board. - -The host must consider two things then: 1) whether a -II or -IIEX product is -being used, and 2) whether an 8-bit or 16-bit data path is used. - -A further difference is that -II boards always have a 512-byte fifo operating in -each direction. -IIEX boards may use fifos of varying size; this size is -reported as part of the power-up message. - -I/O Map Of IntelliPort-II and IntelliPort-IIEX boards: -(Relative to the chosen base address) - -Addr R/W IntelliPort-II IntelliPort-IIEX ----- --- -------------- ---------------- -0 R/W Data Port (byte) Data Port (byte or word) -1 R/W (Not used) (MSB of word-wide data written to Data Port) -2 R Status Register Status Register -2 W Pointer Register Interrupt Mask Register -3 R/W (Not used) Mailbox Registers (6 bits: 11111100) -4,5 -- Reserved for future products -6 -- Reserved for future products -7 R Guaranteed to have no effect -7 W Hardware reset of board. - - -Rules: -All data transfers are performed using the even i/o address. If byte-wide data -transfers are being used, do INB/OUTB operations on the data port. If word-wide -transfers are used, do INW/OUTW operations. In some circumstances (such as -reading the power-up message) you will do INB from the data port, but in this -case the MSB of each word read is lost. When accessing all other unreserved -registers, use byte operations only. -------------------------------------------------------------------------------*/ - -//------------------------------------------------ -// Mandatory Includes: -//------------------------------------------------ -// -#include "ip2types.h" - -//------------------------------------------------------------------------- -// Manifests for the I/O map: -//------------------------------------------------------------------------- -// R/W: Data port (byte) for IntelliPort-II, -// R/W: Data port (byte or word) for IntelliPort-IIEX -// Incoming or outgoing data passes through a FIFO, the status of which is -// available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is -// the primary means of transferring data, commands, flow-control, and status -// information between the host and board. -// -#define FIFO_DATA 0 - -// Another way of passing information between the board and the host is -// through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of -// data. Writing data to the mailbox causes a status bit to be set, and -// potentially interrupting the intended receiver. The sender has some way to -// determine whether the data has been read yet; as soon as it has, it may send -// more. The mailboxes are handled differently on -II and -IIEX products, as -// suggested below. -//------------------------------------------------------------------------------ -// Read: Status Register for IntelliPort-II or -IIEX -// The presence of any bit set here will cause an interrupt to the host, -// provided the corresponding bit has been unmasked in the interrupt mask -// register. Furthermore, interrupts to the host are disabled globally until the -// loadware selects the irq line to use. With the exception of STN_MR, the bits -// remain set so long as the associated condition is true. -// -#define FIFO_STATUS 2 - -// Bit map of status bits which are identical for -II and -IIEX -// -#define ST_OUT_FULL 0x40 // Outbound FIFO full -#define ST_IN_EMPTY 0x20 // Inbound FIFO empty -#define ST_IN_MAIL 0x04 // Inbound Mailbox full - -// The following exists only on the Intelliport-IIEX, and indicates that the -// board has not read the last outgoing mailbox data yet. In the IntelliPort-II, -// the outgoing mailbox may be read back: a zero indicates the board has read -// the data. -// -#define STE_OUT_MAIL 0x80 // Outbound mailbox full (!) - -// The following bits are defined differently for -II and -IIEX boards. Code -// which relies on these bits will need to be functionally different for the two -// types of boards and should be generally avoided because of the additional -// complexity this creates: - -// Bit map of status bits only on -II - -// Fifo has been RESET (cleared when the status register is read). Note that -// this condition cannot be masked and would always interrupt the host, except -// that the hardware reset also disables interrupts globally from the board -// until re-enabled by loadware. This could also arise from the -// Am4701-supported command to reset the chip, but this command is generally not -// used here. -// -#define STN_MR 0x80 - -// See the AMD Am4701 data sheet for details on the following four bits. They -// are not presently used by Computone drivers. -// -#define STN_OUT_AF 0x10 // Outbound FIFO almost full (programmable) -#define STN_IN_AE 0x08 // Inbound FIFO almost empty (programmable) -#define STN_BD 0x02 // Inbound byte detected -#define STN_PE 0x01 // Parity/Framing condition detected - -// Bit-map of status bits only on -IIEX -// -#define STE_OUT_HF 0x10 // Outbound FIFO half full -#define STE_IN_HF 0x08 // Inbound FIFO half full -#define STE_IN_FULL 0x02 // Inbound FIFO full -#define STE_OUT_MT 0x01 // Outbound FIFO empty - -//------------------------------------------------------------------------------ - -// Intelliport-II -- Write Only: the pointer register. -// Values are written to this register to select the Am4701 internal register to -// be accessed on the next operation. -// -#define FIFO_PTR 0x02 - -// Values for the pointer register -// -#define SEL_COMMAND 0x1 // Selects the Am4701 command register - -// Some possible commands: -// -#define SEL_CMD_MR 0x80 // Am4701 command to reset the chip -#define SEL_CMD_SH 0x40 // Am4701 command to map the "other" port into the - // status register. -#define SEL_CMD_UNSH 0 // Am4701 command to "unshift": port maps into its - // own status register. -#define SEL_MASK 0x2 // Selects the Am4701 interrupt mask register. The - // interrupt mask register is bit-mapped to match - // the status register (FIFO_STATUS) except for - // STN_MR. (See above.) -#define SEL_BYTE_DET 0x3 // Selects the Am4701 byte-detect register. (Not - // normally used except in diagnostics.) -#define SEL_OUTMAIL 0x4 // Selects the outbound mailbox (R/W). Reading back - // a value of zero indicates that the mailbox has - // been read by the board and is available for more - // data./ Writing to the mailbox optionally - // interrupts the board, depending on the loadware's - // setting of its interrupt mask register. -#define SEL_AEAF 0x5 // Selects AE/AF threshold register. -#define SEL_INMAIL 0x6 // Selects the inbound mailbox (Read) - -//------------------------------------------------------------------------------ -// IntelliPort-IIEX -- Write Only: interrupt mask (and misc flags) register: -// Unlike IntelliPort-II, bit assignments do NOT match those of the status -// register. -// -#define FIFO_MASK 0x2 - -// Mailbox readback select: -// If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If -// clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox. -// This is the normal situation. The clearing of a mailbox is determined on -// -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback -// capability is provided for diagnostic purposes only. -// -#define MX_OUTMAIL_RSEL 0x80 - -#define MX_IN_MAIL 0x40 // Enables interrupts when incoming mailbox goes - // full (ST_IN_MAIL set). -#define MX_IN_FULL 0x20 // Enables interrupts when incoming FIFO goes full - // (STE_IN_FULL). -#define MX_IN_MT 0x08 // Enables interrupts when incoming FIFO goes empty - // (ST_IN_MT). -#define MX_OUT_FULL 0x04 // Enables interrupts when outgoing FIFO goes full - // (ST_OUT_FULL). -#define MX_OUT_MT 0x01 // Enables interrupts when outgoing FIFO goes empty - // (STE_OUT_MT). - -// Any remaining bits are reserved, and should be written to ZERO for -// compatibility with future Computone products. - -//------------------------------------------------------------------------------ -// IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two -// bits always read back 0). -// Read: One of the mailboxes, usually Inbound. -// Inbound Mailbox (MX_OUTMAIL_RSEL = 0) -// Outbound Mailbox (MX_OUTMAIL_RSEL = 1) -// Write: Outbound Mailbox -// For the IntelliPort-II boards, the outbound mailbox is read back to determine -// whether the board has read the data (0 --> data has been read). For the -// IntelliPort-IIEX, this is done by reading a status register. To determine -// whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit -// in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by -// setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the -// case with the -II boards. For this reason, FIFO_MAIL is normally used to read -// the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for -// MX_OUTMAIL_RSEL description.) -// -#define FIFO_MAIL 0x3 - -//------------------------------------------------------------------------------ -// WRITE ONLY: Resets the board. (Data doesn't matter). -// -#define FIFO_RESET 0x7 - -//------------------------------------------------------------------------------ -// READ ONLY: Will have no effect. (Data is undefined.) -// Actually, there will be an effect, in that the operation is sure to generate -// a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short -// delays when no comparable time constant is available. -// -#define FIFO_NOP 0x7 - -//------------------------------------------------------------------------------ -// RESET & POWER-ON RESET MESSAGE -/*------------------------------------------------------------------------------ -RESET: - -The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel -reset, and via a write to the reset register described above. For products using -the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses, -the Power-up and channel reset sources cause additional hardware initialization -which should only occur at system startup time. - -The third type of reset, called a "command reset", is done by writing any data -to the FIFO_RESET address described above. This resets the on-board processor, -FIFO, UARTS, and associated hardware. - -This passes control of the board to the bootstrap firmware, which performs a -Power-On Self Test and which detects its current configuration. For example, --IIEX products determine the size of FIFO which has been installed, and the -number and type of expansion boxes attached. - -This and other information is then written to the FIFO in a 16-byte data block -to be read by the host. This block is guaranteed to be present within two (2) -seconds of having received the command reset. The firmware is now ready to -receive loadware from the host. - -It is good practice to perform a command reset to the board explicitly as part -of your software initialization. This allows your code to properly restart from -a soft boot. (Many systems do not issue channel reset on soft boot). - -Because of a hardware reset problem on some of the Cirrus Logic 1400's which are -used on the product, it is recommended that you reset the board twice, separated -by an approximately 50 milliseconds delay. (VERY approximately: probably ok to -be off by a factor of five. The important point is that the first command reset -in fact generates a reset pulse on the board. This pulse is guaranteed to last -less than 10 milliseconds. The additional delay ensures the 1400 has had the -chance to respond sufficiently to the first reset. Why not a longer delay? Much -more than 50 milliseconds gets to be noticable, but the board would still work. - -Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap -firmware is ready to receive loadware. - -Note on Power-on Reset Message format: -The various fields have been designed with future expansion in view. -Combinations of bitfields and values have been defined which define products -which may not currently exist. This has been done to allow drivers to anticipate -the possible introduction of products in a systematic fashion. This is not -intended to suggest that each potential product is actually under consideration. -------------------------------------------------------------------------------*/ - -//---------------------------------------- -// Format of Power-on Reset Message -//---------------------------------------- - -typedef union _porStr // "por" stands for Power On Reset -{ - unsigned char c[16]; // array used when considering the message as a - // string of undifferentiated characters - - struct // Elements used when considering values - { - // The first two bytes out of the FIFO are two magic numbers. These are - // intended to establish that there is indeed a member of the - // IntelliPort-II(EX) family present. The remaining bytes may be - // expected // to be valid. When reading the Power-on Reset message, - // if the magic numbers do not match it is probably best to stop - // reading immediately. You are certainly not reading our board (unless - // hardware is faulty), and may in fact be reading some other piece of - // hardware. - - unsigned char porMagic1; // magic number: first byte == POR_MAGIC_1 - unsigned char porMagic2; // magic number: second byte == POR_MAGIC_2 - - // The Version, Revision, and Subrevision are stored as absolute numbers - // and would normally be displayed in the format V.R.S (e.g. 1.0.2) - - unsigned char porVersion; // Bootstrap firmware version number - unsigned char porRevision; // Bootstrap firmware revision number - unsigned char porSubRev; // Bootstrap firmware sub-revision number - - unsigned char porID; // Product ID: Bit-mapped according to - // conventions described below. Among other - // things, this allows us to distinguish - // IntelliPort-II boards from IntelliPort-IIEX - // boards. - - unsigned char porBus; // IntelliPort-II: Unused - // IntelliPort-IIEX: Bus Information: - // Bit-mapped below - - unsigned char porMemory; // On-board DRAM size: in 32k blocks - - // porPorts1 (and porPorts2) are used to determine the ports which are - // available to the board. For non-expandable product, a single number - // is sufficient. For expandable product, the board may be connected - // to as many as four boxes. Each box may be (so far) either a 16-port - // or an 8-port size. Whenever an 8-port box is used, the remaining 8 - // ports leave gaps between existing channels. For that reason, - // expandable products must report a MAP of available channels. Since - // each UART supports four ports, we represent each UART found by a - // single bit. Using two bytes to supply the mapping information we - // report the presense or absense of up to 16 UARTS, or 64 ports in - // steps of 4 ports. For -IIEX products, the ports are numbered - // starting at the box closest to the controller in the "chain". - - // Interpreted Differently for IntelliPort-II and -IIEX. - // -II: Number of ports (Derived actually from product ID). See - // Diag1&2 to indicate if uart was actually detected. - // -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This - // bitmap is based on detecting the uarts themselves; - // see porFlags for information from the box i.d's. - unsigned char porPorts1; - - unsigned char porDiag1; // Results of on-board P.O.S.T, 1st byte - unsigned char porDiag2; // Results of on-board P.O.S.T, 2nd byte - unsigned char porSpeed; // Speed of local CPU: given as MHz x10 - // e.g., 16.0 MHz CPU is reported as 160 - unsigned char porFlags; // Misc information (see manifests below) - // Bit-mapped: CPU type, UART's present - - unsigned char porPorts2; // -II: Undefined - // -IIEX: Bit-map of UARTS found, MSB (see - // above for LSB) - - // IntelliPort-II: undefined - // IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the - // host interface FIFO, in each direction. When running the -IIEX in - // 8-bit mode, fifo capacity is halved. The bootstrap firmware will - // have already accounted for this fact in generating this number. - unsigned char porFifoSize; - - // IntelliPort-II: undefined - // IntelliPort-IIEX: The number of boxes connected. (Presently 1-4) - unsigned char porNumBoxes; - } e; -} porStr, *porStrPtr; - -//-------------------------- -// Values for porStr fields -//-------------------------- - -//--------------------- -// porMagic1, porMagic2 -//---------------------- -// -#define POR_MAGIC_1 0x96 // The only valid value for porMagic1 -#define POR_MAGIC_2 0x35 // The only valid value for porMagic2 -#define POR_1_INDEX 0 // Byte position of POR_MAGIC_1 -#define POR_2_INDEX 1 // Ditto for POR_MAGIC_2 - -//---------------------- -// porID -//---------------------- -// -#define POR_ID_FAMILY 0xc0 // These bits indicate the general family of - // product. -#define POR_ID_FII 0x00 // Family is "IntelliPort-II" -#define POR_ID_FIIEX 0x40 // Family is "IntelliPort-IIEX" - -// These bits are reserved, presently zero. May be used at a later date to -// convey other product information. -// -#define POR_ID_RESERVED 0x3c - -#define POR_ID_SIZE 0x03 // Remaining bits indicate number of ports & - // Connector information. -#define POR_ID_II_8 0x00 // For IntelliPort-II, indicates 8-port using - // standard brick. -#define POR_ID_II_8R 0x01 // For IntelliPort-II, indicates 8-port using - // RJ11's (no CTS) -#define POR_ID_II_6 0x02 // For IntelliPort-II, indicates 6-port using - // RJ45's -#define POR_ID_II_4 0x03 // For IntelliPort-II, indicates 4-port using - // 4xRJ45 connectors -#define POR_ID_EX 0x00 // For IntelliPort-IIEX, indicates standard - // expandable controller (other values reserved) - -//---------------------- -// porBus -//---------------------- - -// IntelliPort-IIEX only: Board is installed in a 16-bit slot -// -#define POR_BUS_SLOT16 0x20 - -// IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface -// operation. -// -#define POR_BUS_DIP16 0x10 - -// Bits 0-2 indicate type of bus: This information is stored in the bootstrap -// loadware, different loadware being used on different products for different -// buses. For most situations, the drivers do not need this information; but it -// is handy in a diagnostic environment. For example, on microchannel boards, -// you would not want to try to test several interrupts, only the one for which -// you were configured. -// -#define POR_BUS_TYPE 0x07 - -// Unknown: this product doesn't know what bus it is running in. (e.g. if same -// bootstrap firmware were wanted for two different buses.) -// -#define POR_BUS_T_UNK 0 - -// Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK -// state, since the same bootstrap firmware is used for each. - -#define POR_BUS_T_MCA 1 // MCA BUS */ -#define POR_BUS_T_EISA 2 // EISA BUS */ -#define POR_BUS_T_ISA 3 // ISA BUS */ - -// Values 4-7 Reserved - -// Remaining bits are reserved - -//---------------------- -// porDiag1 -//---------------------- - -#define POR_BAD_MAPPER 0x80 // HW failure on P.O.S.T: Chip mapper failed - -// These two bits valid only for the IntelliPort-II -// -#define POR_BAD_UART1 0x01 // First 1400 bad -#define POR_BAD_UART2 0x02 // Second 1400 bad - -//---------------------- -// porDiag2 -//---------------------- - -#define POR_DEBUG_PORT 0x80 // debug port was detected by the P.O.S.T -#define POR_DIAG_OK 0x00 // Indicates passage: Failure codes not yet - // available. - // Other bits undefined. -//---------------------- -// porFlags -//---------------------- - -#define POR_CPU 0x03 // These bits indicate supposed CPU type -#define POR_CPU_8 0x01 // Board uses an 80188 (no such thing yet) -#define POR_CPU_6 0x02 // Board uses an 80186 (all existing products) -#define POR_CEX4 0x04 // If set, this is an ISA-CEX/4: An ISA-4 (asic) - // which is architected like an ISA-CEX connected - // to a (hitherto impossible) 4-port box. -#define POR_BOXES 0xf0 // Valid for IntelliPort-IIEX only: Map of Box - // sizes based on box I.D. -#define POR_BOX_16 0x10 // Set indicates 16-port, clear 8-port - -//------------------------------------- -// LOADWARE and DOWNLOADING CODE -//------------------------------------- - -/* -Loadware may be sent to the board in two ways: -1) It may be read from a (binary image) data file block by block as each block - is sent to the board. This is only possible when the initialization is - performed by code which can access your file system. This is most suitable - for diagnostics and appications which use the interface library directly. - -2) It may be hard-coded into your source by including a .h file (typically - supplied by Computone), which declares a data array and initializes every - element. This achieves the same result as if an entire loadware file had - been read into the array. - - This requires more data space in your program, but access to the file system - is not required. This method is more suited to driver code, which typically - is running at a level too low to access the file system directly. - -At present, loadware can only be generated at Computone. - -All Loadware begins with a header area which has a particular format. This -includes a magic number which identifies the file as being (purportedly) -loadware, CRC (for the loader), and version information. -*/ - - -//----------------------------------------------------------------------------- -// Format of loadware block -// -// This is defined as a union so we can pass a pointer to one of these items -// and (if it is the first block) pick out the version information, etc. -// -// Otherwise, to deal with this as a simple character array -//------------------------------------------------------------------------------ - -#define LOADWARE_BLOCK_SIZE 512 // Number of bytes in each block of loadware - -typedef union _loadHdrStr -{ - unsigned char c[LOADWARE_BLOCK_SIZE]; // Valid for every block - - struct // These fields are valid for only the first block of loadware. - { - unsigned char loadMagic; // Magic number: see below - unsigned char loadBlocksMore; // How many more blocks? - unsigned char loadCRC[2]; // Two CRC bytes: used by loader - unsigned char loadVersion; // Version number - unsigned char loadRevision; // Revision number - unsigned char loadSubRevision; // Sub-revision number - unsigned char loadSpares[9]; // Presently unused - unsigned char loadDates[32]; // Null-terminated string which can give - // date and time of compilation - } e; -} loadHdrStr, *loadHdrStrPtr; - -//------------------------------------ -// Defines for downloading code: -//------------------------------------ - -// The loadMagic field in the first block of the loadfile must be this, else the -// file is not valid. -// -#define MAGIC_LOADFILE 0x3c - -// How do we know the load was successful? On completion of the load, the -// bootstrap firmware returns a code to indicate whether it thought the download -// was valid and intends to execute it. These are the only possible valid codes: -// -#define LOADWARE_OK 0xc3 // Download was ok -#define LOADWARE_BAD 0x5a // Download was bad (CRC error) - -// Constants applicable to writing blocks of loadware: -// The first block of loadware might take 600 mS to load, in extreme cases. -// (Expandable board: worst case for sending startup messages to the LCD's). -// The 600mS figure is not really a calculation, but a conservative -// guess/guarantee. Usually this will be within 100 mS, like subsequent blocks. -// -#define MAX_DLOAD_START_TIME 1000 // 1000 mS -#define MAX_DLOAD_READ_TIME 100 // 100 mS - -// Firmware should respond with status (see above) within this long of host -// having sent the final block. -// -#define MAX_DLOAD_ACK_TIME 100 // 100 mS, again! - -//------------------------------------------------------ -// MAXIMUM NUMBER OF PORTS PER BOARD: -// This is fixed for now (with the expandable), but may -// be expanding according to even newer products. -//------------------------------------------------------ -// -#define ABS_MAX_BOXES 4 // Absolute most boxes per board -#define ABS_BIGGEST_BOX 16 // Absolute the most ports per box -#define ABS_MOST_PORTS (ABS_MAX_BOXES * ABS_BIGGEST_BOX) - -#define I2_OUTSW(port, addr, count) outsw((port), (addr), (((count)+1)/2)) -#define I2_OUTSB(port, addr, count) outsb((port), (addr), (((count)+1))&-2) -#define I2_INSW(port, addr, count) insw((port), (addr), (((count)+1)/2)) -#define I2_INSB(port, addr, count) insb((port), (addr), (((count)+1))&-2) - -#endif // I2HW_H - diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c deleted file mode 100644 index 0d10b89218ed..000000000000 --- a/drivers/char/ip2/i2lib.c +++ /dev/null @@ -1,2214 +0,0 @@ -/******************************************************************************* -* -* (c) 1999 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport -* serial I/O controllers. -* -* DESCRIPTION: High-level interface code for the device driver. Uses the -* Extremely Low Level Interface Support (i2ellis.c). Provides an -* interface to the standard loadware, to support drivers or -* application code. (This is included source code, not a separate -* compilation module.) -* -*******************************************************************************/ -//------------------------------------------------------------------------------ -// Note on Strategy: -// Once the board has been initialized, it will interrupt us when: -// 1) It has something in the fifo for us to read (incoming data, flow control -// packets, or whatever). -// 2) It has stripped whatever we have sent last time in the FIFO (and -// consequently is ready for more). -// -// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This -// worsens performance considerably, but is done so that a great many channels -// might use only a little memory. -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -// Revision History: -// -// 0.00 - 4/16/91 --- First Draft -// 0.01 - 4/29/91 --- 1st beta release -// 0.02 - 6/14/91 --- Changes to allow small model compilation -// 0.03 - 6/17/91 MAG Break reporting protected from interrupts routines with -// in-line asm added for moving data to/from ring buffers, -// replacing a variety of methods used previously. -// 0.04 - 6/21/91 MAG Initial flow-control packets not queued until -// i2_enable_interrupts time. Former versions would enqueue -// them at i2_init_channel time, before we knew how many -// channels were supposed to exist! -// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now; -// supports new 16-bit protocol and expandable boards. -// - 10/24/91 MAG Most changes in place and stable. -// 0.06 - 2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no -// argument. -// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt -// level (mostly responses to specific commands.) -// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet -// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE -// turning on the interrupt. -// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check -// some incoming. -// -// 1.1 - 12/25/96 AKM Linux version. -// - 10/09/98 DMC Revised Linux version. -//------------------------------------------------------------------------------ - -//************ -//* Includes * -//************ - -#include -#include "i2lib.h" - - -//*********************** -//* Function Prototypes * -//*********************** -static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int); -static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int ); -static void i2StripFifo(i2eBordStrPtr); -static void i2StuffFifoBypass(i2eBordStrPtr); -static void i2StuffFifoFlow(i2eBordStrPtr); -static void i2StuffFifoInline(i2eBordStrPtr); -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 void serviceOutgoingFifo(i2eBordStrPtr); - -// Functions defined in ip2.c as part of interrupt handling -static void do_input(struct work_struct *); -static void do_status(struct work_struct *); - -//*************** -//* Debug Data * -//*************** -#ifdef DEBUG_FIFO - -unsigned char DBGBuf[0x4000]; -unsigned short I = 0; - -static void -WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) -{ - char *p = src; - - // XXX: We need a spin lock here if we ever use this again - - while (*s) { // copy label - DBGBuf[I] = *s++; - I = I++ & 0x3fff; - } - while (n--) { // copy data - DBGBuf[I] = *p++; - I = I++ & 0x3fff; - } -} - -static void -fatality(i2eBordStrPtr pB ) -{ - int i; - - for (i=0;i= ' ' && DBGBuf[i] <= '~') { - printk(" %c ",DBGBuf[i]); - } else { - printk(" . "); - } - } - printk("\n"); - printk("Last index %x\n",I); -} -#endif /* DEBUG_FIFO */ - -//******** -//* Code * -//******** - -static inline int -i2Validate ( i2ChanStrPtr pCh ) -{ - //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity, - // (CHANNEL_MAGIC | CHANNEL_SUPPORT)); - return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) - == (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 -// Returns: Nothing -// -// Description: -// If any outgoing mail bits are set and there is outgoing mailbox is empty, -// send the mail and clear the bits. -//****************************************************************************** -static void -iiSendPendingMail(i2eBordStrPtr pB) -{ - if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) ) - { - if (iiTrySendMail(pB, pB->i2eOutMailWaiting)) - { - /* If we were already waiting for fifo to empty, - * or just sent MB_OUT_STUFFED, then we are - * still waiting for it to empty, until we should - * receive an MB_IN_STRIPPED from the board. - */ - pB->i2eWaitingForEmptyFifo |= - (pB->i2eOutMailWaiting & MB_OUT_STUFFED); - pB->i2eOutMailWaiting = 0; - pB->SendPendingRetry = 0; - } else { -/* The only time we hit this area is when "iiTrySendMail" has - failed. That only occurs when the outbound mailbox is - still busy with the last message. We take a short breather - to let the board catch up with itself and then try again. - 16 Retries is the limit - then we got a borked board. - /\/\|=mhw=|\/\/ */ - - if( ++pB->SendPendingRetry < 16 ) { - 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" ); - } - } - } -} - -//****************************************************************************** -// Function: i2InitChannels(pB, nChannels, pCh) -// Parameters: Pointer to Ellis Board structure -// Number of channels to initialize -// Pointer to first element in an array of channel structures -// Returns: Success or failure -// -// Description: -// -// This function patches pointers, back-pointers, and initializes all the -// elements in the channel structure array. -// -// This should be run after the board structure is initialized, through having -// loaded the standard loadware (otherwise it complains). -// -// In any case, it must be done before any serious work begins initializing the -// irq's or sending commands... -// -//****************************************************************************** -static int -i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) -{ - int index, stuffIndex; - i2ChanStrPtr *ppCh; - - if (pB->i2eValid != I2E_MAGIC) { - I2_COMPLETE(pB, I2EE_BADMAGIC); - } - if (pB->i2eState != II_STATE_STDLOADED) { - I2_COMPLETE(pB, I2EE_BADSTATE); - } - - rwlock_init(&pB->read_fifo_spinlock); - rwlock_init(&pB->write_fifo_spinlock); - rwlock_init(&pB->Dbuf_spinlock); - rwlock_init(&pB->Bbuf_spinlock); - rwlock_init(&pB->Fbuf_spinlock); - - // NO LOCK needed yet - this is init - - pB->i2eChannelPtr = pCh; - pB->i2eChannelCnt = nChannels; - - pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0; - pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0; - pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0; - - pB->SendPendingRetry = 0; - - memset ( pCh, 0, sizeof (i2ChanStr) * nChannels ); - - for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf); - nChannels && index < ABS_MOST_PORTS; - index++) - { - if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) { - continue; - } - rwlock_init(&pCh->Ibuf_spinlock); - rwlock_init(&pCh->Obuf_spinlock); - rwlock_init(&pCh->Cbuf_spinlock); - rwlock_init(&pCh->Pbuf_spinlock); - // NO LOCK needed yet - this is init - // Set up validity flag according to support level - if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) { - pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT; - } else { - pCh->validity = CHANNEL_MAGIC; - } - pCh->pMyBord = pB; /* Back-pointer */ - - // Prepare an outgoing flow-control packet to send as soon as the chance - // occurs. - if ( pCh->validity & CHANNEL_SUPPORT ) { - pCh->infl.hd.i2sChannel = index; - pCh->infl.hd.i2sCount = 5; - pCh->infl.hd.i2sType = PTYPE_BYPASS; - pCh->infl.fcmd = 37; - pCh->infl.asof = 0; - pCh->infl.room = IBUF_SIZE - 1; - - pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full - - // The following is similar to calling i2QueueNeeds, except that this - // is done in longhand, since we are setting up initial conditions on - // many channels at once. - pCh->channelNeeds = NEED_FLOW; // Since starting from scratch - pCh->sinceLastFlow = 0; // No bytes received since last flow - // control packet was queued - stuffIndex++; - *ppCh++ = pCh; // List this channel as needing - // initial flow control packet sent - } - - // Don't allow anything to be sent until the status packets come in from - // the board. - - pCh->outfl.asof = 0; - pCh->outfl.room = 0; - - // Initialize all the ring buffers - - pCh->Ibuf_stuff = pCh->Ibuf_strip = 0; - pCh->Obuf_stuff = pCh->Obuf_strip = 0; - pCh->Cbuf_stuff = pCh->Cbuf_strip = 0; - - memset( &pCh->icount, 0, sizeof (struct async_icount) ); - pCh->hotKeyIn = HOT_CLEAR; - pCh->channelOptions = 0; - pCh->bookMarks = 0; - init_waitqueue_head(&pCh->pBookmarkWait); - - init_waitqueue_head(&pCh->open_wait); - init_waitqueue_head(&pCh->close_wait); - init_waitqueue_head(&pCh->delta_msr_wait); - - // Set base and divisor so default custom rate is 9600 - pCh->BaudBase = 921600; // MAX for ST654, changed after we get - pCh->BaudDivisor = 96; // the boxids (UART types) later - - pCh->dataSetIn = 0; - pCh->dataSetOut = 0; - - pCh->wopen = 0; - pCh->throttled = 0; - - pCh->speed = CBR_9600; - - pCh->flags = 0; - - pCh->ClosingDelay = 5*HZ/10; - pCh->ClosingWaitTime = 30*HZ; - - // Initialize task queue objects - INIT_WORK(&pCh->tqueue_input, do_input); - INIT_WORK(&pCh->tqueue_status, do_status); - -#ifdef IP2DEBUG_TRACE - pCh->trace = ip2trace; -#endif - - ++pCh; - --nChannels; - } - // No need to check for wrap here; this is initialization. - pB->i2Fbuf_stuff = stuffIndex; - I2_COMPLETE(pB, I2EE_GOOD); - -} - -//****************************************************************************** -// Function: i2DeQueueNeeds(pB, type) -// Parameters: Pointer to a board structure -// type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW -// Returns: -// Pointer to a channel structure -// -// Description: Returns pointer struct of next channel that needs service of -// the type specified. Otherwise returns a NULL reference. -// -//****************************************************************************** -static i2ChanStrPtr -i2DeQueueNeeds(i2eBordStrPtr pB, int type) -{ - unsigned short queueIndex; - unsigned long flags; - - i2ChanStrPtr pCh = NULL; - - switch(type) { - - case NEED_INLINE: - - write_lock_irqsave(&pB->Dbuf_spinlock, flags); - if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip) - { - queueIndex = pB->i2Dbuf_strip; - pCh = pB->i2Dbuf[queueIndex]; - queueIndex++; - if (queueIndex >= CH_QUEUE_SIZE) { - queueIndex = 0; - } - pB->i2Dbuf_strip = queueIndex; - pCh->channelNeeds &= ~NEED_INLINE; - } - write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); - break; - - case NEED_BYPASS: - - write_lock_irqsave(&pB->Bbuf_spinlock, flags); - if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip) - { - queueIndex = pB->i2Bbuf_strip; - pCh = pB->i2Bbuf[queueIndex]; - queueIndex++; - if (queueIndex >= CH_QUEUE_SIZE) { - queueIndex = 0; - } - pB->i2Bbuf_strip = queueIndex; - pCh->channelNeeds &= ~NEED_BYPASS; - } - write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); - break; - - case NEED_FLOW: - - write_lock_irqsave(&pB->Fbuf_spinlock, flags); - if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip) - { - queueIndex = pB->i2Fbuf_strip; - pCh = pB->i2Fbuf[queueIndex]; - queueIndex++; - if (queueIndex >= CH_QUEUE_SIZE) { - queueIndex = 0; - } - pB->i2Fbuf_strip = queueIndex; - pCh->channelNeeds &= ~NEED_FLOW; - } - write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); - break; - default: - printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type); - break; - } - return pCh; -} - -//****************************************************************************** -// Function: i2QueueNeeds(pB, pCh, type) -// Parameters: Pointer to a board structure -// Pointer to a channel structure -// type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW -// Returns: Nothing -// -// Description: -// For each type of need selected, if the given channel is not already in the -// queue, adds it, and sets the flag indicating it is in the queue. -//****************************************************************************** -static void -i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type) -{ - unsigned short queueIndex; - unsigned long flags; - - // We turn off all the interrupts during this brief process, since the - // interrupt-level code might want to put things on the queue as well. - - switch (type) { - - case NEED_INLINE: - - write_lock_irqsave(&pB->Dbuf_spinlock, flags); - if ( !(pCh->channelNeeds & NEED_INLINE) ) - { - pCh->channelNeeds |= NEED_INLINE; - queueIndex = pB->i2Dbuf_stuff; - pB->i2Dbuf[queueIndex++] = pCh; - if (queueIndex >= CH_QUEUE_SIZE) - queueIndex = 0; - pB->i2Dbuf_stuff = queueIndex; - } - write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); - break; - - case NEED_BYPASS: - - write_lock_irqsave(&pB->Bbuf_spinlock, flags); - if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS)) - { - pCh->channelNeeds |= NEED_BYPASS; - queueIndex = pB->i2Bbuf_stuff; - pB->i2Bbuf[queueIndex++] = pCh; - if (queueIndex >= CH_QUEUE_SIZE) - queueIndex = 0; - pB->i2Bbuf_stuff = queueIndex; - } - write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); - break; - - case NEED_FLOW: - - write_lock_irqsave(&pB->Fbuf_spinlock, flags); - if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW)) - { - pCh->channelNeeds |= NEED_FLOW; - queueIndex = pB->i2Fbuf_stuff; - pB->i2Fbuf[queueIndex++] = pCh; - if (queueIndex >= CH_QUEUE_SIZE) - queueIndex = 0; - pB->i2Fbuf_stuff = queueIndex; - } - write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); - break; - - case NEED_CREDIT: - pCh->channelNeeds |= NEED_CREDIT; - break; - default: - printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type); - break; - } - return; -} - -//****************************************************************************** -// Function: i2QueueCommands(type, pCh, timeout, nCommands, pCs,...) -// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE -// pointer to the channel structure -// maximum period to wait -// number of commands (n) -// n commands -// Returns: Number of commands sent, or -1 for error -// -// get board lock before calling -// -// Description: -// Queues up some commands to be sent to a channel. To send possibly several -// bypass or inline commands to the given channel. The timeout parameter -// indicates how many HUNDREDTHS OF SECONDS to wait until there is room: -// 0 = return immediately if no room, -ive = wait forever, +ive = number of -// 1/100 seconds to wait. Return values: -// -1 Some kind of nasty error: bad channel structure or invalid arguments. -// 0 No room to send all the commands -// (+) Number of commands sent -//****************************************************************************** -static int -i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands, - cmdSyntaxPtr pCs0,...) -{ - int totalsize = 0; - int blocksize; - int lastended; - cmdSyntaxPtr *ppCs; - cmdSyntaxPtr pCs; - int count; - int flag; - i2eBordStrPtr pB; - - unsigned short maxBlock; - unsigned short maxBuff; - short bufroom; - unsigned short stuffIndex; - unsigned char *pBuf; - unsigned char *pInsert; - unsigned char *pDest, *pSource; - unsigned short channel; - int cnt; - unsigned long flags = 0; - rwlock_t *lock_var_p = NULL; - - // Make sure the channel exists, otherwise do nothing - if ( !i2Validate ( pCh ) ) { - return -1; - } - - ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 ); - - pB = pCh->pMyBord; - - // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT - if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED) - return -2; - // If the board has gone fatal, return bad, and also hit the trap routine if - // it exists. - if (pB->i2eFatal) { - if ( pB->i2eFatalTrap ) { - (*(pB)->i2eFatalTrap)(pB); - } - return -3; - } - // Set up some variables, Which buffers are we using? How big are they? - switch(type) - { - case PTYPE_INLINE: - flag = INL; - maxBlock = MAX_OBUF_BLOCK; - maxBuff = OBUF_SIZE; - pBuf = pCh->Obuf; - break; - case PTYPE_BYPASS: - flag = BYP; - maxBlock = MAX_CBUF_BLOCK; - maxBuff = CBUF_SIZE; - pBuf = pCh->Cbuf; - break; - default: - return -4; - } - // Determine the total size required for all the commands - totalsize = blocksize = sizeof(i2CmdHeader); - lastended = 0; - ppCs = &pCs0; - for ( count = nCommands; count; count--, ppCs++) - { - pCs = *ppCs; - cnt = pCs->length; - // Will a new block be needed for this one? - // Two possible reasons: too - // big or previous command has to be at the end of a packet. - if ((blocksize + cnt > maxBlock) || lastended) { - blocksize = sizeof(i2CmdHeader); - totalsize += sizeof(i2CmdHeader); - } - totalsize += cnt; - blocksize += cnt; - - // If this command had to end a block, then we will make sure to - // account for it should there be any more blocks. - lastended = pCs->flags & END; - } - for (;;) { - // Make sure any pending flush commands go out before we add more data. - if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) { - // How much room (this time through) ? - switch(type) { - case PTYPE_INLINE: - lock_var_p = &pCh->Obuf_spinlock; - write_lock_irqsave(lock_var_p, flags); - stuffIndex = pCh->Obuf_stuff; - bufroom = pCh->Obuf_strip - stuffIndex; - break; - case PTYPE_BYPASS: - lock_var_p = &pCh->Cbuf_spinlock; - write_lock_irqsave(lock_var_p, flags); - stuffIndex = pCh->Cbuf_stuff; - bufroom = pCh->Cbuf_strip - stuffIndex; - break; - default: - return -5; - } - if (--bufroom < 0) { - bufroom += maxBuff; - } - - ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom ); - - // Check for overflow - if (totalsize <= bufroom) { - // Normal Expected path - We still hold LOCK - break; /* from for()- Enough room: goto proceed */ - } - ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); - write_unlock_irqrestore(lock_var_p, flags); - } else - ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); - - /* Prepare to wait for buffers to empty */ - serviceOutgoingFifo(pB); // Dump what we got - - if (timeout == 0) { - return 0; // Tired of waiting - } - if (timeout > 0) - timeout--; // So negative values == forever - - if (!in_interrupt()) { - schedule_timeout_interruptible(1); // short nap - } else { - // we cannot sched/sleep in interrupt silly - return 0; - } - if (signal_pending(current)) { - return 0; // Wake up! Time to die!!! - } - - ip2trace (CHANN, ITRC_QUEUE, 4, 0 ); - - } // end of for(;;) - - // At this point we have room and the lock - stick them in. - channel = pCh->infl.hd.i2sChannel; - pInsert = &pBuf[stuffIndex]; // Pointer to start of packet - pDest = CMD_OF(pInsert); // Pointer to start of command - - // When we start counting, the block is the size of the header - for (blocksize = sizeof(i2CmdHeader), count = nCommands, - lastended = 0, ppCs = &pCs0; - count; - count--, ppCs++) - { - pCs = *ppCs; // Points to command protocol structure - - // If this is a bookmark request command, post the fact that a bookmark - // request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ - // has no parameters! The more general solution would be to reference - // pCs->cmd[0]. - if (pCs == CMD_BMARK_REQ) { - pCh->bookMarks++; - - ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks ); - - } - cnt = pCs->length; - - // If this command would put us over the maximum block size or - // if the last command had to be at the end of a block, we end - // the existing block here and start a new one. - if ((blocksize + cnt > maxBlock) || lastended) { - - ip2trace (CHANN, ITRC_QUEUE, 5, 0 ); - - PTYPE_OF(pInsert) = type; - CHANNEL_OF(pInsert) = channel; - // count here does not include the header - CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); - stuffIndex += blocksize; - if(stuffIndex >= maxBuff) { - stuffIndex = 0; - pInsert = pBuf; - } - pInsert = &pBuf[stuffIndex]; // Pointer to start of next pkt - pDest = CMD_OF(pInsert); - blocksize = sizeof(i2CmdHeader); - } - // Now we know there is room for this one in the current block - - blocksize += cnt; // Total bytes in this command - pSource = pCs->cmd; // Copy the command into the buffer - while (cnt--) { - *pDest++ = *pSource++; - } - // If this command had to end a block, then we will make sure to account - // for it should there be any more blocks. - lastended = pCs->flags & END; - } // end for - // Clean up the final block by writing header, etc - - PTYPE_OF(pInsert) = type; - CHANNEL_OF(pInsert) = channel; - // count here does not include the header - CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); - stuffIndex += blocksize; - if(stuffIndex >= maxBuff) { - stuffIndex = 0; - pInsert = pBuf; - } - // Updates the index, and post the need for service. When adding these to - // the queue of channels, we turn off the interrupt while doing so, - // because at interrupt level we might want to push a channel back to the - // end of the queue. - switch(type) - { - case PTYPE_INLINE: - pCh->Obuf_stuff = stuffIndex; // Store buffer pointer - write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); - - pB->debugInlineQueued++; - // Add the channel pointer to list of channels needing service (first - // come...), if it's not already there. - i2QueueNeeds(pB, pCh, NEED_INLINE); - break; - - case PTYPE_BYPASS: - pCh->Cbuf_stuff = stuffIndex; // Store buffer pointer - write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); - - pB->debugBypassQueued++; - // Add the channel pointer to list of channels needing service (first - // come...), if it's not already there. - i2QueueNeeds(pB, pCh, NEED_BYPASS); - break; - } - - ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands ); - - return nCommands; // Good status: number of commands sent -} - -//****************************************************************************** -// Function: i2GetStatus(pCh,resetBits) -// Parameters: Pointer to a channel structure -// Bit map of status bits to clear -// Returns: Bit map of current status bits -// -// Description: -// Returns the state of data set signals, and whether a break has been received, -// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status -// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared -// AFTER the condition is passed. If pCh does not point to a valid channel, -// returns -1 (which would be impossible otherwise. -//****************************************************************************** -static int -i2GetStatus(i2ChanStrPtr pCh, int resetBits) -{ - unsigned short status; - i2eBordStrPtr pB; - - ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits ); - - // Make sure the channel exists, otherwise do nothing */ - if ( !i2Validate ( pCh ) ) - return -1; - - pB = pCh->pMyBord; - - status = pCh->dataSetIn; - - // Clear any specified error bits: but note that only actual error bits can - // be cleared, regardless of the value passed. - if (resetBits) - { - pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR)); - pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI); - } - - ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn ); - - return status; -} - -//****************************************************************************** -// Function: i2Input(pChpDest,count) -// Parameters: Pointer to a channel structure -// Pointer to data buffer -// Number of bytes to read -// Returns: Number of bytes read, or -1 for error -// -// Description: -// Strips data from the input buffer and writes it to pDest. If there is a -// collosal blunder, (invalid structure pointers or the like), returns -1. -// Otherwise, returns the number of bytes read. -//****************************************************************************** -static int -i2Input(i2ChanStrPtr pCh) -{ - int amountToMove; - unsigned short stripIndex; - int count; - unsigned long flags = 0; - - ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0); - - // Ensure channel structure seems real - if ( !i2Validate( pCh ) ) { - count = -1; - goto i2Input_exit; - } - write_lock_irqsave(&pCh->Ibuf_spinlock, flags); - - // initialize some accelerators and private copies - stripIndex = pCh->Ibuf_strip; - - count = pCh->Ibuf_stuff - stripIndex; - - // If buffer is empty or requested data count was 0, (trivial case) return - // without any further thought. - if ( count == 0 ) { - write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - goto i2Input_exit; - } - // Adjust for buffer wrap - if ( count < 0 ) { - count += IBUF_SIZE; - } - // Don't give more than can be taken by the line discipline - amountToMove = pCh->pTTY->receive_room; - if (count > amountToMove) { - count = amountToMove; - } - // How much could we copy without a wrap? - amountToMove = IBUF_SIZE - stripIndex; - - if (amountToMove > count) { - amountToMove = count; - } - // Move the first block - pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, - &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); - // If we needed to wrap, do the second data move - if (count > amountToMove) { - pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, - pCh->Ibuf, NULL, count - amountToMove ); - } - // Bump and wrap the stripIndex all at once by the amount of data read. This - // method is good regardless of whether the data was in one or two pieces. - stripIndex += count; - if (stripIndex >= IBUF_SIZE) { - stripIndex -= IBUF_SIZE; - } - pCh->Ibuf_strip = stripIndex; - - // Update our flow control information and possibly queue ourselves to send - // it, depending on how much data has been stripped since the last time a - // packet was sent. - pCh->infl.asof += count; - - if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) { - pCh->sinceLastFlow -= pCh->whenSendFlow; - write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); - } else { - write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - } - -i2Input_exit: - - ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count); - - return count; -} - -//****************************************************************************** -// Function: i2InputFlush(pCh) -// Parameters: Pointer to a channel structure -// Returns: Number of bytes stripped, or -1 for error -// -// Description: -// Strips any data from the input buffer. If there is a collosal blunder, -// (invalid structure pointers or the like), returns -1. Otherwise, returns the -// number of bytes stripped. -//****************************************************************************** -static int -i2InputFlush(i2ChanStrPtr pCh) -{ - int count; - unsigned long flags; - - // Ensure channel structure seems real - if ( !i2Validate ( pCh ) ) - return -1; - - ip2trace (CHANN, ITRC_INPUT, 10, 0); - - write_lock_irqsave(&pCh->Ibuf_spinlock, flags); - count = pCh->Ibuf_stuff - pCh->Ibuf_strip; - - // Adjust for buffer wrap - if (count < 0) { - count += IBUF_SIZE; - } - - // Expedient way to zero out the buffer - pCh->Ibuf_strip = pCh->Ibuf_stuff; - - - // Update our flow control information and possibly queue ourselves to send - // it, depending on how much data has been stripped since the last time a - // packet was sent. - - pCh->infl.asof += count; - - if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow ) - { - pCh->sinceLastFlow -= pCh->whenSendFlow; - write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); - } else { - write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - } - - ip2trace (CHANN, ITRC_INPUT, 19, 1, count); - - return count; -} - -//****************************************************************************** -// Function: i2InputAvailable(pCh) -// Parameters: Pointer to a channel structure -// Returns: Number of bytes available, or -1 for error -// -// Description: -// If there is a collosal blunder, (invalid structure pointers or the like), -// returns -1. Otherwise, returns the number of bytes stripped. Otherwise, -// returns the number of bytes available in the buffer. -//****************************************************************************** -#if 0 -static int -i2InputAvailable(i2ChanStrPtr pCh) -{ - int count; - - // Ensure channel structure seems real - if ( !i2Validate ( pCh ) ) return -1; - - - // initialize some accelerators and private copies - read_lock_irqsave(&pCh->Ibuf_spinlock, flags); - count = pCh->Ibuf_stuff - pCh->Ibuf_strip; - read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - - // Adjust for buffer wrap - if (count < 0) - { - count += IBUF_SIZE; - } - - return count; -} -#endif - -//****************************************************************************** -// Function: i2Output(pCh, pSource, count) -// Parameters: Pointer to channel structure -// Pointer to source data -// Number of bytes to send -// Returns: Number of bytes sent, or -1 for error -// -// Description: -// Queues the data at pSource to be sent as data packets to the board. If there -// is a collosal blunder, (invalid structure pointers or the like), returns -1. -// Otherwise, returns the number of bytes written. What if there is not enough -// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then -// we transfer as many characters as we can now, then return. If this bit is -// clear (default), routine will spin along until all the data is buffered. -// Should this occur, the 1-ms delay routine is called while waiting to avoid -// applications that one cannot break out of. -//****************************************************************************** -static int -i2Output(i2ChanStrPtr pCh, const char *pSource, int count) -{ - i2eBordStrPtr pB; - unsigned char *pInsert; - int amountToMove; - int countOriginal = count; - unsigned short channel; - unsigned short stuffIndex; - unsigned long flags; - - int bailout = 10; - - ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 ); - - // Ensure channel structure seems real - if ( !i2Validate ( pCh ) ) - return -1; - - // initialize some accelerators and private copies - pB = pCh->pMyBord; - channel = pCh->infl.hd.i2sChannel; - - // If the board has gone fatal, return bad, and also hit the trap routine if - // it exists. - if (pB->i2eFatal) { - if (pB->i2eFatalTrap) { - (*(pB)->i2eFatalTrap)(pB); - } - return -1; - } - // Proceed as though we would do everything - while ( count > 0 ) { - - // How much room in output buffer is there? - read_lock_irqsave(&pCh->Obuf_spinlock, flags); - amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; - read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); - if (amountToMove < 0) { - amountToMove += OBUF_SIZE; - } - // Subtract off the headers size and see how much room there is for real - // data. If this is negative, we will discover later. - amountToMove -= sizeof (i2DataHeader); - - // Don't move more (now) than can go in a single packet - if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) { - amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader); - } - // Don't move more than the count we were given - if (amountToMove > count) { - amountToMove = count; - } - // Now we know how much we must move: NB because the ring buffers have - // an overflow area at the end, we needn't worry about wrapping in the - // middle of a packet. - -// Small WINDOW here with no LOCK but I can't call Flush with LOCK -// We would be flushing (or ending flush) anyway - - ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove ); - - if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) - && amountToMove > 0 ) - { - write_lock_irqsave(&pCh->Obuf_spinlock, flags); - stuffIndex = pCh->Obuf_stuff; - - // Had room to move some data: don't know whether the block size, - // buffer space, or what was the limiting factor... - pInsert = &(pCh->Obuf[stuffIndex]); - - // Set up the header - CHANNEL_OF(pInsert) = channel; - PTYPE_OF(pInsert) = PTYPE_DATA; - TAG_OF(pInsert) = 0; - ID_OF(pInsert) = ID_ORDINARY_DATA; - DATA_COUNT_OF(pInsert) = amountToMove; - - // Move the data - memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); - // Adjust pointers and indices - pSource += amountToMove; - pCh->Obuf_char_count += amountToMove; - stuffIndex += amountToMove + sizeof(i2DataHeader); - count -= amountToMove; - - if (stuffIndex >= OBUF_SIZE) { - stuffIndex = 0; - } - pCh->Obuf_stuff = stuffIndex; - - write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); - - ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex ); - - } else { - - // Cannot move data - // becuz we need to stuff a flush - // or amount to move is <= 0 - - ip2trace(CHANN, ITRC_OUTPUT, 14, 3, - amountToMove, pB->i2eFifoRemains, - pB->i2eWaitingForEmptyFifo ); - - // Put this channel back on queue - // this ultimatly gets more data or wakes write output - i2QueueNeeds(pB, pCh, NEED_INLINE); - - if ( pB->i2eWaitingForEmptyFifo ) { - - ip2trace (CHANN, ITRC_OUTPUT, 16, 0 ); - - // or schedule - if (!in_interrupt()) { - - ip2trace (CHANN, ITRC_OUTPUT, 61, 0 ); - - schedule_timeout_interruptible(2); - if (signal_pending(current)) { - break; - } - continue; - } else { - - ip2trace (CHANN, ITRC_OUTPUT, 62, 0 ); - - // let interrupt in = WAS restore_flags() - // We hold no lock nor is irq off anymore??? - - break; - } - break; // from while(count) - } - else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) ) - { - ip2trace (CHANN, ITRC_OUTPUT, 19, 2, - pB->i2eFifoRemains, - pB->i2eTxMailEmpty ); - - break; // from while(count) - } else if ( pCh->channelNeeds & NEED_CREDIT ) { - - ip2trace (CHANN, ITRC_OUTPUT, 22, 0 ); - - break; // from while(count) - } else if ( --bailout) { - - // Try to throw more things (maybe not us) in the fifo if we're - // not already waiting for it. - - ip2trace (CHANN, ITRC_OUTPUT, 20, 0 ); - - serviceOutgoingFifo(pB); - //break; CONTINUE; - } else { - ip2trace (CHANN, ITRC_OUTPUT, 21, 3, - pB->i2eFifoRemains, - pB->i2eOutMailWaiting, - pB->i2eWaitingForEmptyFifo ); - - break; // from while(count) - } - } - } // End of while(count) - - i2QueueNeeds(pB, pCh, NEED_INLINE); - - // We drop through either when the count expires, or when there is some - // count left, but there was a non-blocking write. - if (countOriginal > count) { - - ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count ); - - serviceOutgoingFifo( pB ); - } - - ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count ); - - return countOriginal - count; -} - -//****************************************************************************** -// Function: i2FlushOutput(pCh) -// Parameters: Pointer to a channel structure -// Returns: Nothing -// -// Description: -// Sends bypass command to start flushing (waiting possibly forever until there -// is room), then sends inline command to stop flushing output, (again waiting -// possibly forever). -//****************************************************************************** -static inline void -i2FlushOutput(i2ChanStrPtr pCh) -{ - - ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags ); - - if (pCh->flush_flags) - return; - - if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { - pCh->flush_flags = STARTFL_FLAG; // Failed - flag for later - - ip2trace (CHANN, ITRC_FLUSH, 2, 0 ); - - } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) { - pCh->flush_flags = STOPFL_FLAG; // Failed - flag for later - - ip2trace (CHANN, ITRC_FLUSH, 3, 0 ); - } -} - -static int -i2RetryFlushOutput(i2ChanStrPtr pCh) -{ - int old_flags = pCh->flush_flags; - - ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags ); - - pCh->flush_flags = 0; // Clear flag so we can avoid recursion - // and queue the commands - - if ( old_flags & STARTFL_FLAG ) { - if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { - old_flags = STOPFL_FLAG; //Success - send stop flush - } else { - old_flags = STARTFL_FLAG; //Failure - Flag for retry later - } - - ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags ); - - } - if ( old_flags & STOPFL_FLAG ) { - if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) { - old_flags = 0; // Success - clear flags - } - - ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags ); - } - pCh->flush_flags = old_flags; - - ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags ); - - return old_flags; -} - -//****************************************************************************** -// Function: i2DrainOutput(pCh,timeout) -// Parameters: Pointer to a channel structure -// Maximum period to wait -// Returns: ? -// -// Description: -// Uses the bookmark request command to ask the board to send a bookmark back as -// soon as all the data is completely sent. -//****************************************************************************** -static void -i2DrainWakeup(unsigned long d) -{ - i2ChanStrPtr pCh = (i2ChanStrPtr)d; - - ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); - - pCh->BookmarkTimer.expires = 0; - wake_up_interruptible( &pCh->pBookmarkWait ); -} - -static void -i2DrainOutput(i2ChanStrPtr pCh, int timeout) -{ - wait_queue_t wait; - i2eBordStrPtr pB; - - ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires); - - pB = pCh->pMyBord; - // If the board has gone fatal, return bad, - // and also hit the trap routine if it exists. - if (pB->i2eFatal) { - if (pB->i2eFatalTrap) { - (*(pB)->i2eFatalTrap)(pB); - } - return; - } - if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { - // One per customer (channel) - setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, - (unsigned long)pCh); - - ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); - - mod_timer(&pCh->BookmarkTimer, jiffies + timeout); - } - - i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); - - init_waitqueue_entry(&wait, current); - add_wait_queue(&(pCh->pBookmarkWait), &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - serviceOutgoingFifo( pB ); - - schedule(); // Now we take our interruptible sleep on - - // Clean up the queue - set_current_state( TASK_RUNNING ); - remove_wait_queue(&(pCh->pBookmarkWait), &wait); - - // if expires == 0 then timer poped, then do not need to del_timer - if ((timeout > 0) && pCh->BookmarkTimer.expires && - time_before(jiffies, pCh->BookmarkTimer.expires)) { - del_timer( &(pCh->BookmarkTimer) ); - pCh->BookmarkTimer.expires = 0; - - ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires ); - - } - ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires ); - return; -} - -//****************************************************************************** -// Function: i2OutputFree(pCh) -// Parameters: Pointer to a channel structure -// Returns: Space in output buffer -// -// Description: -// Returns -1 if very gross error. Otherwise returns the amount of bytes still -// free in the output buffer. -//****************************************************************************** -static int -i2OutputFree(i2ChanStrPtr pCh) -{ - int amountToMove; - unsigned long flags; - - // Ensure channel structure seems real - if ( !i2Validate ( pCh ) ) { - return -1; - } - read_lock_irqsave(&pCh->Obuf_spinlock, flags); - amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; - read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); - - if (amountToMove < 0) { - amountToMove += OBUF_SIZE; - } - // If this is negative, we will discover later - amountToMove -= sizeof(i2DataHeader); - - return (amountToMove < 0) ? 0 : amountToMove; -} -static void - -ip2_owake( PTTY tp) -{ - i2ChanStrPtr pCh; - - if (tp == NULL) return; - - pCh = tp->driver_data; - - ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, - (1 << TTY_DO_WRITE_WAKEUP) ); - - tty_wakeup(tp); -} - -static inline void -set_baud_params(i2eBordStrPtr pB) -{ - int i,j; - i2ChanStrPtr *pCh; - - pCh = (i2ChanStrPtr *) pB->i2eChannelPtr; - - for (i = 0; i < ABS_MAX_BOXES; i++) { - if (pB->channelBtypes.bid_value[i]) { - if (BID_HAS_654(pB->channelBtypes.bid_value[i])) { - for (j = 0; j < ABS_BIGGEST_BOX; j++) { - if (pCh[i*16+j] == NULL) - break; - (pCh[i*16+j])->BaudBase = 921600; // MAX for ST654 - (pCh[i*16+j])->BaudDivisor = 96; - } - } else { // has cirrus cd1400 - for (j = 0; j < ABS_BIGGEST_BOX; j++) { - if (pCh[i*16+j] == NULL) - break; - (pCh[i*16+j])->BaudBase = 115200; // MAX for CD1400 - (pCh[i*16+j])->BaudDivisor = 12; - } - } - } - } -} - -//****************************************************************************** -// Function: i2StripFifo(pB) -// Parameters: Pointer to a board structure -// Returns: ? -// -// Description: -// Strips all the available data from the incoming FIFO, identifies the type of -// packet, and either buffers the data or does what needs to be done. -// -// Note there is no overflow checking here: if the board sends more data than it -// ought to, we will not detect it here, but blindly overflow... -//****************************************************************************** - -// A buffer for reading in blocks for unknown channels -static unsigned char junkBuffer[IBUF_SIZE]; - -// A buffer to read in a status packet. Because of the size of the count field -// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE -static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4]; - -// This table changes the bit order from MSR order given by STAT_MODEM packet to -// status bits used in our library. -static char xlatDss[16] = { -0 | 0 | 0 | 0 , -0 | 0 | 0 | I2_CTS , -0 | 0 | I2_DSR | 0 , -0 | 0 | I2_DSR | I2_CTS , -0 | I2_RI | 0 | 0 , -0 | I2_RI | 0 | I2_CTS , -0 | I2_RI | I2_DSR | 0 , -0 | I2_RI | I2_DSR | I2_CTS , -I2_DCD | 0 | 0 | 0 , -I2_DCD | 0 | 0 | I2_CTS , -I2_DCD | 0 | I2_DSR | 0 , -I2_DCD | 0 | I2_DSR | I2_CTS , -I2_DCD | I2_RI | 0 | 0 , -I2_DCD | I2_RI | 0 | I2_CTS , -I2_DCD | I2_RI | I2_DSR | 0 , -I2_DCD | I2_RI | I2_DSR | I2_CTS }; - -static inline void -i2StripFifo(i2eBordStrPtr pB) -{ - i2ChanStrPtr pCh; - int channel; - int count; - unsigned short stuffIndex; - int amountToRead; - unsigned char *pc, *pcLimit; - unsigned char uc; - unsigned char dss_change; - unsigned long bflags,cflags; - -// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 ); - - while (I2_HAS_INPUT(pB)) { -// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 ); - - // Process packet from fifo a one atomic unit - write_lock_irqsave(&pB->read_fifo_spinlock, bflags); - - // The first word (or two bytes) will have channel number and type of - // packet, possibly other information - pB->i2eLeadoffWord[0] = iiReadWord(pB); - - switch(PTYPE_OF(pB->i2eLeadoffWord)) - { - case PTYPE_DATA: - pB->got_input = 1; - -// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 ); - - channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */ - count = iiReadWord(pB); /* Count is in the next word */ - -// NEW: Check the count for sanity! Should the hardware fail, our death -// is more pleasant. While an oversize channel is acceptable (just more -// than the driver supports), an over-length count clearly means we are -// sick! - if ( ((unsigned int)count) > IBUF_SIZE ) { - pB->i2eFatal = 2; - write_unlock_irqrestore(&pB->read_fifo_spinlock, - bflags); - return; /* Bail out ASAP */ - } - // Channel is illegally big ? - if ((channel >= pB->i2eChannelCnt) || - (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel]))) - { - iiReadBuf(pB, junkBuffer, count); - write_unlock_irqrestore(&pB->read_fifo_spinlock, - bflags); - break; /* From switch: ready for next packet */ - } - - // Channel should be valid, then - - // If this is a hot-key, merely post its receipt for now. These are - // always supposed to be 1-byte packets, so we won't even check the - // count. Also we will post an acknowledgement to the board so that - // more data can be forthcoming. Note that we are not trying to use - // these sequences in this driver, merely to robustly ignore them. - if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY) - { - pCh->hotKeyIn = iiReadWord(pB) & 0xff; - write_unlock_irqrestore(&pB->read_fifo_spinlock, - bflags); - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK); - break; /* From the switch: ready for next packet */ - } - - // Normal data! We crudely assume there is room for the data in our - // buffer because the board wouldn't have exceeded his credit limit. - write_lock_irqsave(&pCh->Ibuf_spinlock, cflags); - // We have 2 locks now - stuffIndex = pCh->Ibuf_stuff; - amountToRead = IBUF_SIZE - stuffIndex; - if (amountToRead > count) - amountToRead = count; - - // stuffIndex would have been already adjusted so there would - // always be room for at least one, and count is always at least - // one. - - iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); - pCh->icount.rx += amountToRead; - - // Update the stuffIndex by the amount of data moved. Note we could - // never ask for more data than would just fit. However, we might - // have read in one more byte than we wanted because the read - // rounds up to even bytes. If this byte is on the end of the - // packet, and is padding, we ignore it. If the byte is part of - // the actual data, we need to move it. - - stuffIndex += amountToRead; - - if (stuffIndex >= IBUF_SIZE) { - if ((amountToRead & 1) && (count > amountToRead)) { - pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE]; - amountToRead++; - stuffIndex = 1; - } else { - stuffIndex = 0; - } - } - - // If there is anything left over, read it as well - if (count > amountToRead) { - amountToRead = count - amountToRead; - iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); - pCh->icount.rx += amountToRead; - stuffIndex += amountToRead; - } - - // Update stuff index - pCh->Ibuf_stuff = stuffIndex; - write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags); - write_unlock_irqrestore(&pB->read_fifo_spinlock, - bflags); - -#ifdef USE_IQ - schedule_work(&pCh->tqueue_input); -#else - do_input(&pCh->tqueue_input); -#endif - - // Note we do not need to maintain any flow-control credits at this - // time: if we were to increment .asof and decrement .room, there - // would be no net effect. Instead, when we strip data, we will - // increment .asof and leave .room unchanged. - - break; // From switch: ready for next packet - - case PTYPE_STATUS: - ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 ); - - count = CMD_COUNT_OF(pB->i2eLeadoffWord); - - iiReadBuf(pB, cmdBuffer, count); - // We can release early with buffer grab - write_unlock_irqrestore(&pB->read_fifo_spinlock, - bflags); - - pc = cmdBuffer; - pcLimit = &(cmdBuffer[count]); - - while (pc < pcLimit) { - channel = *pc++; - - ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc ); - - /* check for valid channel */ - if (channel < pB->i2eChannelCnt - && - (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL - ) - { - dss_change = 0; - - switch (uc = *pc++) - { - /* Breaks and modem signals are easy: just update status */ - case STAT_CTS_UP: - if ( !(pCh->dataSetIn & I2_CTS) ) - { - pCh->dataSetIn |= I2_DCTS; - pCh->icount.cts++; - dss_change = 1; - } - pCh->dataSetIn |= I2_CTS; - break; - - case STAT_CTS_DN: - if ( pCh->dataSetIn & I2_CTS ) - { - pCh->dataSetIn |= I2_DCTS; - pCh->icount.cts++; - dss_change = 1; - } - pCh->dataSetIn &= ~I2_CTS; - break; - - case STAT_DCD_UP: - ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn ); - - if ( !(pCh->dataSetIn & I2_DCD) ) - { - ip2trace (CHANN, ITRC_MODEM, 2, 0 ); - pCh->dataSetIn |= I2_DDCD; - pCh->icount.dcd++; - dss_change = 1; - } - pCh->dataSetIn |= I2_DCD; - - ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn ); - break; - - case STAT_DCD_DN: - ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn ); - if ( pCh->dataSetIn & I2_DCD ) - { - ip2trace (channel, ITRC_MODEM, 5, 0 ); - pCh->dataSetIn |= I2_DDCD; - pCh->icount.dcd++; - dss_change = 1; - } - pCh->dataSetIn &= ~I2_DCD; - - ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn ); - break; - - case STAT_DSR_UP: - if ( !(pCh->dataSetIn & I2_DSR) ) - { - pCh->dataSetIn |= I2_DDSR; - pCh->icount.dsr++; - dss_change = 1; - } - pCh->dataSetIn |= I2_DSR; - break; - - case STAT_DSR_DN: - if ( pCh->dataSetIn & I2_DSR ) - { - pCh->dataSetIn |= I2_DDSR; - pCh->icount.dsr++; - dss_change = 1; - } - pCh->dataSetIn &= ~I2_DSR; - break; - - case STAT_RI_UP: - if ( !(pCh->dataSetIn & I2_RI) ) - { - pCh->dataSetIn |= I2_DRI; - pCh->icount.rng++; - dss_change = 1; - } - pCh->dataSetIn |= I2_RI ; - break; - - case STAT_RI_DN: - // to be compat with serial.c - //if ( pCh->dataSetIn & I2_RI ) - //{ - // pCh->dataSetIn |= I2_DRI; - // pCh->icount.rng++; - // dss_change = 1; - //} - pCh->dataSetIn &= ~I2_RI ; - break; - - case STAT_BRK_DET: - pCh->dataSetIn |= I2_BRK; - pCh->icount.brk++; - dss_change = 1; - break; - - // Bookmarks? one less request we're waiting for - case STAT_BMARK: - pCh->bookMarks--; - if (pCh->bookMarks <= 0 ) { - pCh->bookMarks = 0; - wake_up_interruptible( &pCh->pBookmarkWait ); - - ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires ); - } - break; - - // Flow control packets? Update the new credits, and if - // someone was waiting for output, queue him up again. - case STAT_FLOW: - pCh->outfl.room = - ((flowStatPtr)pc)->room - - (pCh->outfl.asof - ((flowStatPtr)pc)->asof); - - ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room ); - - if (pCh->channelNeeds & NEED_CREDIT) - { - ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds); - - pCh->channelNeeds &= ~NEED_CREDIT; - i2QueueNeeds(pB, pCh, NEED_INLINE); - if ( pCh->pTTY ) - ip2_owake(pCh->pTTY); - } - - ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds); - - pc += sizeof(flowStat); - break; - - /* Special packets: */ - /* Just copy the information into the channel structure */ - - case STAT_STATUS: - - pCh->channelStatus = *((debugStatPtr)pc); - pc += sizeof(debugStat); - break; - - case STAT_TXCNT: - - pCh->channelTcount = *((cntStatPtr)pc); - pc += sizeof(cntStat); - break; - - case STAT_RXCNT: - - pCh->channelRcount = *((cntStatPtr)pc); - pc += sizeof(cntStat); - break; - - case STAT_BOXIDS: - pB->channelBtypes = *((bidStatPtr)pc); - pc += sizeof(bidStat); - set_baud_params(pB); - break; - - case STAT_HWFAIL: - i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST); - pCh->channelFail = *((failStatPtr)pc); - pc += sizeof(failStat); - break; - - /* No explicit match? then - * Might be an error packet... - */ - default: - switch (uc & STAT_MOD_ERROR) - { - case STAT_ERROR: - if (uc & STAT_E_PARITY) { - pCh->dataSetIn |= I2_PAR; - pCh->icount.parity++; - } - if (uc & STAT_E_FRAMING){ - pCh->dataSetIn |= I2_FRA; - pCh->icount.frame++; - } - if (uc & STAT_E_OVERRUN){ - pCh->dataSetIn |= I2_OVR; - pCh->icount.overrun++; - } - break; - - case STAT_MODEM: - // the answer to DSS_NOW request (not change) - pCh->dataSetIn = (pCh->dataSetIn - & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) ) - | xlatDss[uc & 0xf]; - wake_up_interruptible ( &pCh->dss_now_wait ); - default: - break; - } - } /* End of switch on status type */ - if (dss_change) { -#ifdef USE_IQ - schedule_work(&pCh->tqueue_status); -#else - do_status(&pCh->tqueue_status); -#endif - } - } - else /* Or else, channel is invalid */ - { - // Even though the channel is invalid, we must test the - // status to see how much additional data it has (to be - // skipped) - switch (*pc++) - { - case STAT_FLOW: - pc += 4; /* Skip the data */ - break; - - default: - break; - } - } - } // End of while (there is still some status packet left) - break; - - default: // Neither packet? should be impossible - ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1, - PTYPE_OF(pB->i2eLeadoffWord) ); - write_unlock_irqrestore(&pB->read_fifo_spinlock, - bflags); - - break; - } // End of switch on type of packets - } /*while(board I2_HAS_INPUT)*/ - - ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 ); - - // Send acknowledgement to the board even if there was no data! - pB->i2eOutMailWaiting |= MB_IN_STRIPPED; - return; -} - -//****************************************************************************** -// Function: i2Write2Fifo(pB,address,count) -// Parameters: Pointer to a board structure, source address, byte count -// Returns: bytes written -// -// Description: -// Writes count bytes to board io address(implied) from source -// Adjusts count, leaves reserve for next time around bypass cmds -//****************************************************************************** -static int -i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve) -{ - int rc = 0; - unsigned long flags; - write_lock_irqsave(&pB->write_fifo_spinlock, flags); - if (!pB->i2eWaitingForEmptyFifo) { - if (pB->i2eFifoRemains > (count+reserve)) { - pB->i2eFifoRemains -= count; - iiWriteBuf(pB, source, count); - pB->i2eOutMailWaiting |= MB_OUT_STUFFED; - rc = count; - } - } - write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); - return rc; -} -//****************************************************************************** -// Function: i2StuffFifoBypass(pB) -// Parameters: Pointer to a board structure -// Returns: Nothing -// -// Description: -// Stuffs as many bypass commands into the fifo as possible. This is simpler -// than stuffing data or inline commands to fifo, since we do not have -// flow-control to deal with. -//****************************************************************************** -static inline void -i2StuffFifoBypass(i2eBordStrPtr pB) -{ - i2ChanStrPtr pCh; - unsigned char *pRemove; - unsigned short stripIndex; - unsigned short packetSize; - unsigned short paddedSize; - unsigned short notClogged = 1; - unsigned long flags; - - int bailout = 1000; - - // Continue processing so long as there are entries, or there is room in the - // fifo. Each entry represents a channel with something to do. - while ( --bailout && notClogged && - (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS)))) - { - write_lock_irqsave(&pCh->Cbuf_spinlock, flags); - stripIndex = pCh->Cbuf_strip; - - // as long as there are packets for this channel... - - while (stripIndex != pCh->Cbuf_stuff) { - pRemove = &(pCh->Cbuf[stripIndex]); - packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader); - paddedSize = roundup(packetSize, 2); - - if (paddedSize > 0) { - if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) { - notClogged = 0; /* fifo full */ - i2QueueNeeds(pB, pCh, NEED_BYPASS); // Put back on queue - break; // Break from the channel - } - } -#ifdef DEBUG_FIFO -WriteDBGBuf("BYPS", pRemove, paddedSize); -#endif /* DEBUG_FIFO */ - pB->debugBypassCount++; - - pRemove += packetSize; - stripIndex += packetSize; - if (stripIndex >= CBUF_SIZE) { - stripIndex = 0; - pRemove = pCh->Cbuf; - } - } - // Done with this channel. Move to next, removing this one from - // the queue of channels if we cleaned it out (i.e., didn't get clogged. - pCh->Cbuf_strip = stripIndex; - write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); - } // Either clogged or finished all the work - -#ifdef IP2DEBUG_TRACE - if ( !bailout ) { - ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 ); - } -#endif -} - -//****************************************************************************** -// Function: i2StuffFifoFlow(pB) -// Parameters: Pointer to a board structure -// Returns: Nothing -// -// Description: -// Stuffs as many flow control packets into the fifo as possible. This is easier -// even than doing normal bypass commands, because there is always at most one -// packet, already assembled, for each channel. -//****************************************************************************** -static inline void -i2StuffFifoFlow(i2eBordStrPtr pB) -{ - i2ChanStrPtr pCh; - unsigned short paddedSize = roundup(sizeof(flowIn), 2); - - ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2, - pB->i2eFifoRemains, paddedSize ); - - // Continue processing so long as there are entries, or there is room in the - // fifo. Each entry represents a channel with something to do. - while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) { - pB->debugFlowCount++; - - // NO Chan LOCK needed ??? - if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) { - break; - } -#ifdef DEBUG_FIFO - WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize); -#endif /* DEBUG_FIFO */ - - } // Either clogged or finished all the work - - ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 ); -} - -//****************************************************************************** -// Function: i2StuffFifoInline(pB) -// Parameters: Pointer to a board structure -// Returns: Nothing -// -// Description: -// Stuffs as much data and inline commands into the fifo as possible. This is -// the most complex fifo-stuffing operation, since there if now the channel -// flow-control issue to deal with. -//****************************************************************************** -static inline void -i2StuffFifoInline(i2eBordStrPtr pB) -{ - i2ChanStrPtr pCh; - unsigned char *pRemove; - unsigned short stripIndex; - unsigned short packetSize; - unsigned short paddedSize; - unsigned short notClogged = 1; - unsigned short flowsize; - unsigned long flags; - - int bailout = 1000; - int bailout2; - - ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, - pB->i2Dbuf_strip, pB->i2Dbuf_stuff ); - - // Continue processing so long as there are entries, or there is room in the - // fifo. Each entry represents a channel with something to do. - while ( --bailout && notClogged && - (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) ) - { - write_lock_irqsave(&pCh->Obuf_spinlock, flags); - stripIndex = pCh->Obuf_strip; - - ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff ); - - // as long as there are packets for this channel... - bailout2 = 1000; - while ( --bailout2 && stripIndex != pCh->Obuf_stuff) { - pRemove = &(pCh->Obuf[stripIndex]); - - // Must determine whether this be a data or command packet to - // calculate correctly the header size and the amount of - // flow-control credit this type of packet will use. - if (PTYPE_OF(pRemove) == PTYPE_DATA) { - flowsize = DATA_COUNT_OF(pRemove); - packetSize = flowsize + sizeof(i2DataHeader); - } else { - flowsize = CMD_COUNT_OF(pRemove); - packetSize = flowsize + sizeof(i2CmdHeader); - } - flowsize = CREDIT_USAGE(flowsize); - paddedSize = roundup(packetSize, 2); - - ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize ); - - // If we don't have enough credits from the board to send the data, - // flag the channel that we are waiting for flow control credit, and - // break out. This will clean up this channel and remove us from the - // queue of hot things to do. - - ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize ); - - if (pCh->outfl.room <= flowsize) { - // Do Not have the credits to send this packet. - i2QueueNeeds(pB, pCh, NEED_CREDIT); - notClogged = 0; - break; // So to do next channel - } - if ( (paddedSize > 0) - && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) { - // Do Not have room in fifo to send this packet. - notClogged = 0; - i2QueueNeeds(pB, pCh, NEED_INLINE); - break; // Break from the channel - } -#ifdef DEBUG_FIFO -WriteDBGBuf("DATA", pRemove, paddedSize); -#endif /* DEBUG_FIFO */ - pB->debugInlineCount++; - - pCh->icount.tx += flowsize; - // Update current credits - pCh->outfl.room -= flowsize; - pCh->outfl.asof += flowsize; - if (PTYPE_OF(pRemove) == PTYPE_DATA) { - pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove); - } - pRemove += packetSize; - stripIndex += packetSize; - - ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip); - - if (stripIndex >= OBUF_SIZE) { - stripIndex = 0; - pRemove = pCh->Obuf; - - ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex ); - - } - } /* while */ - if ( !bailout2 ) { - ip2trace (CHANN, ITRC_ERROR, 3, 0 ); - } - // Done with this channel. Move to next, removing this one from the - // queue of channels if we cleaned it out (i.e., didn't get clogged. - pCh->Obuf_strip = stripIndex; - write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); - if ( notClogged ) - { - - ip2trace (CHANN, ITRC_SICMD, 8, 0 ); - - if ( pCh->pTTY ) { - ip2_owake(pCh->pTTY); - } - } - } // Either clogged or finished all the work - - if ( !bailout ) { - ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 ); - } - - ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip); -} - -//****************************************************************************** -// Function: serviceOutgoingFifo(pB) -// Parameters: Pointer to a board structure -// Returns: Nothing -// -// Description: -// Helper routine to put data in the outgoing fifo, if we aren't already waiting -// for something to be there. If the fifo has only room for a very little data, -// go head and hit the board with a mailbox hit immediately. Otherwise, it will -// have to happen later in the interrupt processing. Since this routine may be -// called both at interrupt and foreground time, we must turn off interrupts -// during the entire process. -//****************************************************************************** -static void -serviceOutgoingFifo(i2eBordStrPtr pB) -{ - // If we aren't currently waiting for the board to empty our fifo, service - // everything that is pending, in priority order (especially, Bypass before - // Inline). - if ( ! pB->i2eWaitingForEmptyFifo ) - { - i2StuffFifoFlow(pB); - i2StuffFifoBypass(pB); - i2StuffFifoInline(pB); - - iiSendPendingMail(pB); - } -} - -//****************************************************************************** -// Function: i2ServiceBoard(pB) -// Parameters: Pointer to a board structure -// Returns: Nothing -// -// Description: -// Normally this is called from interrupt level, but there is deliberately -// nothing in here specific to being called from interrupt level. All the -// hardware-specific, interrupt-specific things happen at the outer levels. -// -// For example, a timer interrupt could drive this routine for some sort of -// polled operation. The only requirement is that the programmer deal with any -// atomiticity/concurrency issues that result. -// -// This routine responds to the board's having sent mailbox information to the -// host (which would normally cause an interrupt). This routine reads the -// incoming mailbox. If there is no data in it, this board did not create the -// interrupt and/or has nothing to be done to it. (Except, if we have been -// waiting to write mailbox data to it, we may do so. -// -// Based on the value in the mailbox, we may take various actions. -// -// No checking here of pB validity: after all, it shouldn't have been called by -// the handler unless pB were on the list. -//****************************************************************************** -static inline int -i2ServiceBoard ( i2eBordStrPtr pB ) -{ - unsigned inmail; - unsigned long flags; - - - /* This should be atomic because of the way we are called... */ - if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) { - inmail = iiGetMail(pB); - } - pB->i2eStartMail = NO_MAIL_HERE; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail ); - - if (inmail != NO_MAIL_HERE) { - // If the board has gone fatal, nothing to do but hit a bit that will - // alert foreground tasks to protest! - if ( inmail & MB_FATAL_ERROR ) { - pB->i2eFatal = 1; - goto exit_i2ServiceBoard; - } - - /* Assuming no fatal condition, we proceed to do work */ - if ( inmail & MB_IN_STUFFED ) { - pB->i2eFifoInInts++; - i2StripFifo(pB); /* There might be incoming packets */ - } - - if (inmail & MB_OUT_STRIPPED) { - pB->i2eFifoOutInts++; - write_lock_irqsave(&pB->write_fifo_spinlock, flags); - pB->i2eFifoRemains = pB->i2eFifoSize; - pB->i2eWaitingForEmptyFifo = 0; - write_unlock_irqrestore(&pB->write_fifo_spinlock, - flags); - - ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains ); - - } - serviceOutgoingFifo(pB); - } - - ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 ); - -exit_i2ServiceBoard: - - return 0; -} diff --git a/drivers/char/ip2/i2lib.h b/drivers/char/ip2/i2lib.h deleted file mode 100644 index e559e9bac06d..000000000000 --- a/drivers/char/ip2/i2lib.h +++ /dev/null @@ -1,351 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Header file for high level library functions -* -*******************************************************************************/ -#ifndef I2LIB_H -#define I2LIB_H 1 -//------------------------------------------------------------------------------ -// I2LIB.H -// -// IntelliPort-II and IntelliPort-IIEX -// -// Defines, structure definitions, and external declarations for i2lib.c -//------------------------------------------------------------------------------ -//-------------------------------------- -// Mandatory Includes: -//-------------------------------------- -#include "ip2types.h" -#include "i2ellis.h" -#include "i2pack.h" -#include "i2cmd.h" -#include - -//------------------------------------------------------------------------------ -// i2ChanStr -- Channel Structure: -// Used to track per-channel information for the library routines using standard -// loadware. Note also, a pointer to an array of these structures is patched -// into the i2eBordStr (see i2ellis.h) -//------------------------------------------------------------------------------ -// -// If we make some limits on the maximum block sizes, we can avoid dealing with -// buffer wrap. The wrapping of the buffer is based on where the start of the -// packet is. Then there is always room for the packet contiguously. -// -// Maximum total length of an outgoing data or in-line command block. The limit -// of 36 on data is quite arbitrary and based more on DOS memory limitations -// than the board interface. However, for commands, the maximum packet length is -// MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits -// (see I2PACK.H) in such packets. For data packets, the count field size is not -// the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE, -// but be careful if wanting to modify either. -// -#define MAX_OBUF_BLOCK 36 - -// Another note on maximum block sizes: we are buffering packets here. Data is -// put into the buffer (if there is room) regardless of the credits from the -// board. The board sends new credits whenever it has removed from his buffers a -// number of characters equal to 80% of total buffer size. (Of course, the total -// buffer size is what is reported when the very first set of flow control -// status packets are received from the board. Therefore, to be robust, you must -// always fill the board to at least 80% of the current credit limit, else you -// might not give it enough to trigger a new report. These conditions are -// obtained here so long as the maximum output block size is less than 20% the -// size of the board's output buffers. This is true at present by "coincidence" -// or "infernal knowledge": the board's output buffers are at least 700 bytes -// long (20% = 140 bytes, at least). The 80% figure is "official", so the safest -// strategy might be to trap the first flow control report and guarantee that -// the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first -// reported buffer credit. -// -#define MAX_CBUF_BLOCK 6 // Maximum total length of a bypass command block - -#define IBUF_SIZE 512 // character capacity of input buffer per channel -#define OBUF_SIZE 1024// character capacity of output buffer per channel -#define CBUF_SIZE 10 // character capacity of output bypass buffer - -typedef struct _i2ChanStr -{ - // First, back-pointers so that given a pointer to this structure, you can - // determine the correct board and channel number to reference, (say, when - // issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.) - - int port_index; // Index of port in channel structure array attached - // to board structure. - PTTY pTTY; // Pointer to tty structure for port (OS specific) - USHORT validity; // Indicates whether the given channel has been - // initialized, really exists (or is a missing - // channel, e.g. channel 9 on an 8-port box.) - - i2eBordStrPtr pMyBord; // Back-pointer to this channel's board structure - - int wopen; // waiting fer carrier - - int throttled; // Set if upper layer can take no data - - int flags; // Defined in tty.h - - PWAITQ open_wait; // Pointer for OS sleep function. - PWAITQ close_wait; // Pointer for OS sleep function. - PWAITQ delta_msr_wait;// Pointer for OS sleep function. - PWAITQ dss_now_wait; // Pointer for OS sleep function. - - struct timer_list BookmarkTimer; // Used by i2DrainOutput - wait_queue_head_t pBookmarkWait; // Used by i2DrainOutput - - int BaudBase; - int BaudDivisor; - - USHORT ClosingDelay; - USHORT ClosingWaitTime; - - volatile - flowIn infl; // This structure is initialized as a completely - // formed flow-control command packet, and as such - // has the channel number, also the capacity and - // "as-of" data needed continuously. - - USHORT sinceLastFlow; // Counts the number of characters read from input - // buffers, since the last time flow control info - // was sent. - - USHORT whenSendFlow; // Determines when new flow control is to be sent to - // the board. Note unlike earlier manifestations of - // the driver, these packets can be sent from - // in-place. - - USHORT channelNeeds; // Bit map of important things which must be done - // for this channel. (See bits below ) - - volatile - flowStat outfl; // Same type of structure is used to hold current - // flow control information used to control our - // output. "asof" is kept updated as data is sent, - // and "room" never goes to zero. - - // The incoming ring buffer - // Unlike the outgoing buffers, this holds raw data, not packets. The two - // extra bytes are used to hold the byte-padding when there is room for an - // odd number of bytes before we must wrap. - // - UCHAR Ibuf[IBUF_SIZE + 2]; - volatile - USHORT Ibuf_stuff; // Stuffing index - volatile - USHORT Ibuf_strip; // Stripping index - - // The outgoing ring-buffer: Holds Data and command packets. N.B., even - // though these are in the channel structure, the channel is also written - // here, the easier to send it to the fifo when ready. HOWEVER, individual - // packets here are NOT padded to even length: the routines for writing - // blocks to the fifo will pad to even byte counts. - // - UCHAR Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4]; - volatile - USHORT Obuf_stuff; // Stuffing index - volatile - USHORT Obuf_strip; // Stripping index - int Obuf_char_count; - - // The outgoing bypass-command buffer. Unlike earlier manifestations, the - // flow control packets are sent directly from the structures. As above, the - // channel number is included in the packet, but they are NOT padded to even - // size. - // - UCHAR Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2]; - volatile - USHORT Cbuf_stuff; // Stuffing index - volatile - USHORT Cbuf_strip; // Stripping index - - // The temporary buffer for the Linux tty driver PutChar entry. - // - UCHAR Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)]; - volatile - USHORT Pbuf_stuff; // Stuffing index - - // The state of incoming data-set signals - // - USHORT dataSetIn; // Bit-mapped according to below. Also indicates - // whether a break has been detected since last - // inquiry. - - // The state of outcoming data-set signals (as far as we can tell!) - // - USHORT dataSetOut; // Bit-mapped according to below. - - // Most recent hot-key identifier detected - // - USHORT hotKeyIn; // Hot key as sent by the board, HOT_CLEAR indicates - // no hot key detected since last examined. - - // Counter of outstanding requests for bookmarks - // - short bookMarks; // Number of outstanding bookmark requests, (+ive - // whenever a bookmark request if queued up, -ive - // whenever a bookmark is received). - - // Misc options - // - USHORT channelOptions; // See below - - // To store various incoming special packets - // - debugStat channelStatus; - cntStat channelRcount; - cntStat channelTcount; - failStat channelFail; - - // To store the last values for line characteristics we sent to the board. - // - int speed; - - int flush_flags; - - void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...); - - /* - * Kernel counters for the 4 input interrupts - */ - struct async_icount icount; - - /* - * Task queues for processing input packets from the board. - */ - struct work_struct tqueue_input; - struct work_struct tqueue_status; - struct work_struct tqueue_hangup; - - rwlock_t Ibuf_spinlock; - rwlock_t Obuf_spinlock; - rwlock_t Cbuf_spinlock; - rwlock_t Pbuf_spinlock; - -} i2ChanStr, *i2ChanStrPtr; - -//--------------------------------------------------- -// Manifests and bit-maps for elements in i2ChanStr -//--------------------------------------------------- -// -// flush flags -// -#define STARTFL_FLAG 1 -#define STOPFL_FLAG 2 - -// validity -// -#define CHANNEL_MAGIC_BITS 0xff00 -#define CHANNEL_MAGIC 0x5300 // (validity & CHANNEL_MAGIC_BITS) == - // CHANNEL_MAGIC --> structure good - -#define CHANNEL_SUPPORT 0x0001 // Indicates channel is supported, exists, - // and passed P.O.S.T. - -// channelNeeds -// -#define NEED_FLOW 1 // Indicates flow control has been queued -#define NEED_INLINE 2 // Indicates inline commands or data queued -#define NEED_BYPASS 4 // Indicates bypass commands queued -#define NEED_CREDIT 8 // Indicates would be sending except has not sufficient - // credit. The data is still in the channel structure, - // but the channel is not enqueued in the board - // structure again until there is a credit received from - // the board. - -// dataSetIn (Also the bits for i2GetStatus return value) -// -#define I2_DCD 1 -#define I2_CTS 2 -#define I2_DSR 4 -#define I2_RI 8 - -// dataSetOut (Also the bits for i2GetStatus return value) -// -#define I2_DTR 1 -#define I2_RTS 2 - -// i2GetStatus() can optionally clear these bits -// -#define I2_BRK 0x10 // A break was detected -#define I2_PAR 0x20 // A parity error was received -#define I2_FRA 0x40 // A framing error was received -#define I2_OVR 0x80 // An overrun error was received - -// i2GetStatus() automatically clears these bits */ -// -#define I2_DDCD 0x100 // DCD changed from its former value -#define I2_DCTS 0x200 // CTS changed from its former value -#define I2_DDSR 0x400 // DSR changed from its former value -#define I2_DRI 0x800 // RI changed from its former value - -// hotKeyIn -// -#define HOT_CLEAR 0x1322 // Indicates that no hot-key has been detected - -// channelOptions -// -#define CO_NBLOCK_WRITE 1 // Writes don't block waiting for buffer. (Default - // is, they do wait.) - -// fcmodes -// -#define I2_OUTFLOW_CTS 0x0001 -#define I2_INFLOW_RTS 0x0002 -#define I2_INFLOW_DSR 0x0004 -#define I2_INFLOW_DTR 0x0008 -#define I2_OUTFLOW_DSR 0x0010 -#define I2_OUTFLOW_DTR 0x0020 -#define I2_OUTFLOW_XON 0x0040 -#define I2_OUTFLOW_XANY 0x0080 -#define I2_INFLOW_XON 0x0100 - -#define I2_CRTSCTS (I2_OUTFLOW_CTS|I2_INFLOW_RTS) -#define I2_IXANY_MODE (I2_OUTFLOW_XON|I2_OUTFLOW_XANY) - -//------------------------------------------- -// Macros used from user level like functions -//------------------------------------------- - -// Macros to set and clear channel options -// -#define i2SetOption(pCh, option) pCh->channelOptions |= option -#define i2ClrOption(pCh, option) pCh->channelOptions &= ~option - -// Macro to set fatal-error trap -// -#define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine - -//-------------------------------------------- -// Declarations and prototypes for i2lib.c -//-------------------------------------------- -// -static int i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr); -static int i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...); -static int i2GetStatus(i2ChanStrPtr, int); -static int i2Input(i2ChanStrPtr); -static int i2InputFlush(i2ChanStrPtr); -static int i2Output(i2ChanStrPtr, const char *, int); -static int i2OutputFree(i2ChanStrPtr); -static int i2ServiceBoard(i2eBordStrPtr); -static void i2DrainOutput(i2ChanStrPtr, int); - -#ifdef IP2DEBUG_TRACE -void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...); -#else -#define ip2trace(a,b,c,d...) do {} while (0) -#endif - -// Argument to i2QueueCommands -// -#define C_IN_LINE 1 -#define C_BYPASS 0 - -#endif // I2LIB_H diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h deleted file mode 100644 index 00342a677c90..000000000000 --- a/drivers/char/ip2/i2pack.h +++ /dev/null @@ -1,364 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Definitions of the packets used to transfer data and commands -* Host <--> Board. Information provided here is only applicable -* when the standard loadware is active. -* -*******************************************************************************/ -#ifndef I2PACK_H -#define I2PACK_H 1 - -//----------------------------------------------- -// Revision History: -// -// 10 October 1991 MAG First draft -// 24 February 1992 MAG Additions for 1.4.x loadware -// 11 March 1992 MAG New status packets -// -//----------------------------------------------- - -//------------------------------------------------------------------------------ -// Packet Formats: -// -// Information passes between the host and board through the FIFO in packets. -// These have headers which indicate the type of packet. Because the fifo data -// path may be 16-bits wide, the protocol is constrained such that each packet -// is always padded to an even byte count. (The lower-level interface routines -// -- i2ellis.c -- are designed to do this). -// -// The sender (be it host or board) must place some number of complete packets -// in the fifo, then place a message in the mailbox that packets are available. -// Placing such a message interrupts the "receiver" (be it board or host), who -// reads the mailbox message and determines that there are incoming packets -// ready. Since there are no partial packets, and the length of a packet is -// given in the header, the remainder of the packet can be read without checking -// for FIFO empty condition. The process is repeated, packet by packet, until -// the incoming FIFO is empty. Then the receiver uses the outbound mailbox to -// signal the board that it has read the data. Only then can the sender place -// additional data in the fifo. -//------------------------------------------------------------------------------ -// -//------------------------------------------------ -// Definition of Packet Header Area -//------------------------------------------------ -// -// Caution: these only define header areas. In actual use the data runs off -// beyond the end of these structures. -// -// Since these structures are based on sequences of bytes which go to the board, -// there cannot be ANY padding between the elements. -#pragma pack(1) - -//---------------------------- -// DATA PACKETS -//---------------------------- - -typedef struct _i2DataHeader -{ - unsigned char i2sChannel; /* The channel number: 0-255 */ - - // -- Bitfields are allocated LSB first -- - - // For incoming data, indicates whether this is an ordinary packet or a - // special one (e.g., hot key hit). - unsigned i2sId : 2 __attribute__ ((__packed__)); - - // For tagging data packets. There are flush commands which flush only data - // packets bearing a particular tag. (used in implementing IntelliView and - // IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has - // meaning internally to the loadware). - unsigned i2sTag : 4; - - // These two bits determine the type of packet sent/received. - unsigned i2sType : 2; - - // The count of data to follow: does not include the possible additional - // padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0. - unsigned short i2sCount; - -} i2DataHeader, *i2DataHeaderPtr; - -// Structure is immediately followed by the data, proper. - -//---------------------------- -// NON-DATA PACKETS -//---------------------------- - -typedef struct _i2CmdHeader -{ - unsigned char i2sChannel; // The channel number: 0-255 (Except where noted - // - see below - - // Number of bytes of commands, status or whatever to follow - unsigned i2sCount : 6; - - // These two bits determine the type of packet sent/received. - unsigned i2sType : 2; - -} i2CmdHeader, *i2CmdHeaderPtr; - -// Structure is immediately followed by the applicable data. - -//--------------------------------------- -// Flow Control Packets (Outbound) -//--------------------------------------- - -// One type of outbound command packet is so important that the entire structure -// is explicitly defined here. That is the flow-control packet. This is never -// sent by user-level code (as would be the commands to raise/lower DTR, for -// example). These are only sent by the library routines in response to reading -// incoming data into the buffers. -// -// The parameters inside the command block are maintained in place, then the -// block is sent at the appropriate time. - -typedef struct _flowIn -{ - i2CmdHeader hd; // Channel #, count, type (see above) - unsigned char fcmd; // The flow control command (37) - unsigned short asof; // As of byte number "asof" (LSB first!) I have room - // for "room" bytes - unsigned short room; -} flowIn, *flowInPtr; - -//---------------------------------------- -// (Incoming) Status Packets -//---------------------------------------- - -// Incoming packets which are non-data packets are status packets. In this case, -// the channel number in the header is unimportant. What follows are one or more -// sub-packets, the first word of which consists of the channel (first or low -// byte) and the status indicator (second or high byte), followed by possibly -// more data. - -#define STAT_CTS_UP 0 /* CTS raised (no other bytes) */ -#define STAT_CTS_DN 1 /* CTS dropped (no other bytes) */ -#define STAT_DCD_UP 2 /* DCD raised (no other bytes) */ -#define STAT_DCD_DN 3 /* DCD dropped (no other bytes) */ -#define STAT_DSR_UP 4 /* DSR raised (no other bytes) */ -#define STAT_DSR_DN 5 /* DSR dropped (no other bytes) */ -#define STAT_RI_UP 6 /* RI raised (no other bytes) */ -#define STAT_RI_DN 7 /* RI dropped (no other bytes) */ -#define STAT_BRK_DET 8 /* BRK detect (no other bytes) */ -#define STAT_FLOW 9 /* Flow control(-- more: see below */ -#define STAT_BMARK 10 /* Bookmark (no other bytes) - * Bookmark is sent as a response to - * a command 60: request for bookmark - */ -#define STAT_STATUS 11 /* Special packet: see below */ -#define STAT_TXCNT 12 /* Special packet: see below */ -#define STAT_RXCNT 13 /* Special packet: see below */ -#define STAT_BOXIDS 14 /* Special packet: see below */ -#define STAT_HWFAIL 15 /* Special packet: see below */ - -#define STAT_MOD_ERROR 0xc0 -#define STAT_MODEM 0xc0/* If status & STAT_MOD_ERROR: - * == STAT_MODEM, then this is a modem - * status packet, given in response to a - * CMD_DSS_NOW command. - * The low nibble has each data signal: - */ -#define STAT_MOD_DCD 0x8 -#define STAT_MOD_RI 0x4 -#define STAT_MOD_DSR 0x2 -#define STAT_MOD_CTS 0x1 - -#define STAT_ERROR 0x80/* If status & STAT_MOD_ERROR - * == STAT_ERROR, then - * sort of error on the channel. - * The remaining seven bits indicate - * what sort of error it is. - */ -/* The low three bits indicate parity, framing, or overrun errors */ - -#define STAT_E_PARITY 4 /* Parity error */ -#define STAT_E_FRAMING 2 /* Framing error */ -#define STAT_E_OVERRUN 1 /* (uxart) overrun error */ - -//--------------------------------------- -// STAT_FLOW packets -//--------------------------------------- - -typedef struct _flowStat -{ - unsigned short asof; - unsigned short room; -}flowStat, *flowStatPtr; - -// flowStat packets are received from the board to regulate the flow of outgoing -// data. A local copy of this structure is also kept to track the amount of -// credits used and credits remaining. "room" is the amount of space in the -// board's buffers, "as of" having received a certain byte number. When sending -// data to the fifo, you must calculate how much buffer space your packet will -// use. Add this to the current "asof" and subtract it from the current "room". -// -// The calculation for the board's buffer is given by CREDIT_USAGE, where size -// is the un-rounded count of either data characters or command characters. -// (Which is to say, the count rounded up, plus two). - -#define CREDIT_USAGE(size) (((size) + 3) & ~1) - -//--------------------------------------- -// STAT_STATUS packets -//--------------------------------------- - -typedef struct _debugStat -{ - unsigned char d_ccsr; - unsigned char d_txinh; - unsigned char d_stat1; - unsigned char d_stat2; -} debugStat, *debugStatPtr; - -// debugStat packets are sent to the host in response to a CMD_GET_STATUS -// command. Each byte is bit-mapped as described below: - -#define D_CCSR_XON 2 /* Has received XON, ready to transmit */ -#define D_CCSR_XOFF 4 /* Has received XOFF, not transmitting */ -#define D_CCSR_TXENAB 8 /* Transmitter is enabled */ -#define D_CCSR_RXENAB 0x80 /* Receiver is enabled */ - -#define D_TXINH_BREAK 1 /* We are sending a break */ -#define D_TXINH_EMPTY 2 /* No data to send */ -#define D_TXINH_SUSP 4 /* Output suspended via command 57 */ -#define D_TXINH_CMD 8 /* We are processing an in-line command */ -#define D_TXINH_LCD 0x10 /* LCD diagnostics are running */ -#define D_TXINH_PAUSE 0x20 /* We are processing a PAUSE command */ -#define D_TXINH_DCD 0x40 /* DCD is low, preventing transmission */ -#define D_TXINH_DSR 0x80 /* DSR is low, preventing transmission */ - -#define D_STAT1_TXEN 1 /* Transmit INTERRUPTS enabled */ -#define D_STAT1_RXEN 2 /* Receiver INTERRUPTS enabled */ -#define D_STAT1_MDEN 4 /* Modem (data set sigs) interrupts enabled */ -#define D_STAT1_RLM 8 /* Remote loopback mode selected */ -#define D_STAT1_LLM 0x10 /* Local internal loopback mode selected */ -#define D_STAT1_CTS 0x20 /* CTS is low, preventing transmission */ -#define D_STAT1_DTR 0x40 /* DTR is low, to stop remote transmission */ -#define D_STAT1_RTS 0x80 /* RTS is low, to stop remote transmission */ - -#define D_STAT2_TXMT 1 /* Transmit buffers are all empty */ -#define D_STAT2_RXMT 2 /* Receive buffers are all empty */ -#define D_STAT2_RXINH 4 /* Loadware has tried to inhibit remote - * transmission: dropped DTR, sent XOFF, - * whatever... - */ -#define D_STAT2_RXFLO 8 /* Loadware can send no more data to host - * until it receives a flow-control packet - */ -//----------------------------------------- -// STAT_TXCNT and STAT_RXCNT packets -//---------------------------------------- - -typedef struct _cntStat -{ - unsigned short cs_time; // (Assumes host is little-endian!) - unsigned short cs_count; -} cntStat, *cntStatPtr; - -// These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT -// bypass command. cs_time is a running 1 Millisecond counter which acts as a -// time stamp. cs_count is a running counter of data sent or received from the -// uxarts. (Not including data added by the chip itself, as with CRLF -// processing). -//------------------------------------------ -// STAT_HWFAIL packets -//------------------------------------------ - -typedef struct _failStat -{ - unsigned char fs_written; - unsigned char fs_read; - unsigned short fs_address; -} failStat, *failStatPtr; - -// This packet is sent whenever the on-board diagnostic process detects an -// error. At startup, this process is dormant. The host can wake it up by -// issuing the bypass command CMD_HW_TEST. The process runs at low priority and -// performs continuous hardware verification; writing data to certain on-board -// registers, reading it back, and comparing. If it detects an error, this -// packet is sent to the host, and the process goes dormant again until the host -// sends another CMD_HW_TEST. It then continues with the next register to be -// tested. - -//------------------------------------------------------------------------------ -// Macros to deal with the headers more easily! Note that these are defined so -// they may be used as "left" as well as "right" expressions. -//------------------------------------------------------------------------------ - -// Given a pointer to the packet, reference the channel number -// -#define CHANNEL_OF(pP) ((i2DataHeaderPtr)(pP))->i2sChannel - -// Given a pointer to the packet, reference the Packet type -// -#define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType - -// The possible types of packets -// -#define PTYPE_DATA 0 /* Host <--> Board */ -#define PTYPE_BYPASS 1 /* Host ---> Board */ -#define PTYPE_INLINE 2 /* Host ---> Board */ -#define PTYPE_STATUS 2 /* Host <--- Board */ - -// Given a pointer to a Data packet, reference the Tag -// -#define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag - -// Given a pointer to a Data packet, reference the data i.d. -// -#define ID_OF(pP) ((i2DataHeaderPtr)(pP))->i2sId - -// The possible types of ID's -// -#define ID_ORDINARY_DATA 0 -#define ID_HOT_KEY 1 - -// Given a pointer to a Data packet, reference the count -// -#define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount - -// Given a pointer to a Data packet, reference the beginning of data -// -#define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header - -// Given a pointer to a Non-Data packet, reference the count -// -#define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount - -#define MAX_CMD_PACK_SIZE 62 // Maximum size of such a count - -// Given a pointer to a Non-Data packet, reference the beginning of data -// -#define CMD_OF(pP) &((unsigned char *)(pP))[2] // 2 = size of header - -//-------------------------------- -// MailBox Bits: -//-------------------------------- - -//-------------------------- -// Outgoing (host to board) -//-------------------------- -// -#define MB_OUT_STUFFED 0x80 // Host has placed output in fifo -#define MB_IN_STRIPPED 0x40 // Host has read in all input from fifo - -//-------------------------- -// Incoming (board to host) -//-------------------------- -// -#define MB_IN_STUFFED 0x80 // Board has placed input in fifo -#define MB_OUT_STRIPPED 0x40 // Board has read all output from fifo -#define MB_FATAL_ERROR 0x20 // Board has encountered a fatal error - -#pragma pack() // Reset padding to command-line default - -#endif // I2PACK_H - diff --git a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h deleted file mode 100644 index 936ccc533949..000000000000 --- a/drivers/char/ip2/ip2.h +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Driver constants for configuration and tuning -* -* NOTES: -* -*******************************************************************************/ -#ifndef IP2_H -#define IP2_H - -#include "ip2types.h" -#include "i2cmd.h" - -/*************/ -/* Constants */ -/*************/ - -/* Device major numbers - since version 2.0.26. */ -#define IP2_TTY_MAJOR 71 -#define IP2_CALLOUT_MAJOR 72 -#define IP2_IPL_MAJOR 73 - -/* Board configuration array. - * This array defines the hardware irq and address for up to IP2_MAX_BOARDS - * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified, - * PCI and EISA boards are probed for and automagicly configed - * iff the addresses are set to 1 and 2 respectivily. - * 0x0100 - 0x03f0 == ISA - * 1 == PCI - * 2 == EISA - * 0 == (skip this board) - * This array defines the hardware addresses for them. Special - * addresses are EISA and PCI which go sniffing for boards. - - * In a multiboard system the position in the array determines which port - * devices are assigned to each board: - * board 0 is assigned ttyF0.. to ttyF63, - * board 1 is assigned ttyF64 to ttyF127, - * board 2 is assigned ttyF128 to ttyF191, - * board 3 is assigned ttyF192 to ttyF255. - * - * In PCI and EISA bus systems each range is mapped to card in - * monotonically increasing slot number order, ISA position is as specified - * here. - - * If the irqs are ALL set to 0,0,0,0 all boards operate in - * polled mode. For interrupt operation ISA boards require that the IRQ be - * specified, while PCI and EISA boards any nonzero entry - * will enable interrupts using the BIOS configured irq for the board. - * An invalid irq entry will default to polled mode for that card and print - * console warning. - - * When the driver is loaded as a module these setting can be overridden on the - * modprobe command line or on an option line in /etc/modprobe.conf. - * If the driver is built-in the configuration must be - * set here for ISA cards and address set to 1 and 2 for PCI and EISA. - * - * Here is an example that shows most if not all possibe combinations: - - *static ip2config_t ip2config = - *{ - * {11,1,0,0}, // irqs - * { // Addresses - * 0x0308, // Board 0, ttyF0 - ttyF63// ISA card at io=0x308, irq=11 - * 0x0001, // Board 1, ttyF64 - ttyF127//PCI card configured by BIOS - * 0x0000, // Board 2, ttyF128 - ttyF191// Slot skipped - * 0x0002 // Board 3, ttyF192 - ttyF255//EISA card configured by BIOS - * // but polled not irq driven - * } - *}; - */ - - /* this structure is zeroed out because the suggested method is to configure - * the driver as a module, set up the parameters with an options line in - * /etc/modprobe.conf and load with modprobe or kmod, the kernel - * module loader - */ - - /* This structure is NOW always initialized when the driver is initialized. - * Compiled in defaults MUST be added to the io and irq arrays in - * ip2.c. Those values are configurable from insmod parameters in the - * case of modules or from command line parameters (ip2=io,irq) when - * compiled in. - */ - -static ip2config_t ip2config = -{ - {0,0,0,0}, // irqs - { // Addresses - /* Do NOT set compile time defaults HERE! Use the arrays in - ip2.c! These WILL be overwritten! =mhw= */ - 0x0000, // Board 0, ttyF0 - ttyF63 - 0x0000, // Board 1, ttyF64 - ttyF127 - 0x0000, // Board 2, ttyF128 - ttyF191 - 0x0000 // Board 3, ttyF192 - ttyF255 - } -}; - -#endif diff --git a/drivers/char/ip2/ip2ioctl.h b/drivers/char/ip2/ip2ioctl.h deleted file mode 100644 index aa0a9da85e05..000000000000 --- a/drivers/char/ip2/ip2ioctl.h +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Driver constants for configuration and tuning -* -* NOTES: -* -*******************************************************************************/ - -#ifndef IP2IOCTL_H -#define IP2IOCTL_H - -//************* -//* Constants * -//************* - -// High baud rates (if not defined elsewhere. -#ifndef B153600 -# define B153600 0010005 -#endif -#ifndef B307200 -# define B307200 0010006 -#endif -#ifndef B921600 -# define B921600 0010007 -#endif - -#endif diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c deleted file mode 100644 index ea7a8fb08283..000000000000 --- a/drivers/char/ip2/ip2main.c +++ /dev/null @@ -1,3234 +0,0 @@ -/* -* -* (c) 1999 by Computone Corporation -* -******************************************************************************** -* -* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Mainline code for the device driver -* -*******************************************************************************/ -// ToDo: -// -// Fix the immediate DSS_NOW problem. -// Work over the channel stats return logic in ip2_ipl_ioctl so they -// make sense for all 256 possible channels and so the user space -// utilities will compile and work properly. -// -// Done: -// -// 1.2.14 /\/\|=mhw=|\/\/ -// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. -// Changed the definition of ip2trace to be more consistent with kernel style -// Thanks to Andreas Dilger for these updates -// -// 1.2.13 /\/\|=mhw=|\/\/ -// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform -// to agreed devfs serial device naming convention. -// -// 1.2.12 /\/\|=mhw=|\/\/ -// Cleaned up some remove queue cut and paste errors -// -// 1.2.11 /\/\|=mhw=|\/\/ -// Clean up potential NULL pointer dereferences -// Clean up devfs registration -// Add kernel command line parsing for io and irq -// Compile defaults for io and irq are now set in ip2.c not ip2.h! -// Reworked poll_only hack for explicit parameter setting -// You must now EXPLICITLY set poll_only = 1 or set all irqs to 0 -// Merged ip2_loadmain and old_ip2_init -// Converted all instances of interruptible_sleep_on into queue calls -// Most of these had no race conditions but better to clean up now -// -// 1.2.10 /\/\|=mhw=|\/\/ -// Fixed the bottom half interrupt handler and enabled USE_IQI -// to split the interrupt handler into a formal top-half / bottom-half -// Fixed timing window on high speed processors that queued messages to -// the outbound mail fifo faster than the board could handle. -// -// 1.2.9 -// Four box EX was barfing on >128k kmalloc, made structure smaller by -// reducing output buffer size -// -// 1.2.8 -// Device file system support (MHW) -// -// 1.2.7 -// Fixed -// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules -// -// 1.2.6 -//Fixes DCD problems -// DCD was not reported when CLOCAL was set on call to TIOCMGET -// -//Enhancements: -// TIOCMGET requests and waits for status return -// No DSS interrupts enabled except for DCD when needed -// -// For internal use only -// -//#define IP2DEBUG_INIT -//#define IP2DEBUG_OPEN -//#define IP2DEBUG_WRITE -//#define IP2DEBUG_READ -//#define IP2DEBUG_IOCTL -//#define IP2DEBUG_IPL - -//#define IP2DEBUG_TRACE -//#define DEBUG_FIFO - -/************/ -/* Includes */ -/************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include "ip2types.h" -#include "ip2trace.h" -#include "ip2ioctl.h" -#include "ip2.h" -#include "i2ellis.h" -#include "i2lib.h" - -/***************** - * /proc/ip2mem * - *****************/ - -#include -#include - -static DEFINE_MUTEX(ip2_mutex); -static const struct file_operations ip2mem_proc_fops; -static const struct file_operations ip2_proc_fops; - -/********************/ -/* Type Definitions */ -/********************/ - -/*************/ -/* Constants */ -/*************/ - -/* String constants to identify ourselves */ -static const char pcName[] = "Computone IntelliPort Plus multiport driver"; -static const char pcVersion[] = "1.2.14"; - -/* String constants for port names */ -static const char pcDriver_name[] = "ip2"; -static const char pcIpl[] = "ip2ipl"; - -/***********************/ -/* Function Prototypes */ -/***********************/ - -/* Global module entry functions */ - -/* Private (static) functions */ -static int ip2_open(PTTY, struct file *); -static void ip2_close(PTTY, struct file *); -static int ip2_write(PTTY, const unsigned char *, int); -static int ip2_putchar(PTTY, unsigned char); -static void ip2_flush_chars(PTTY); -static int ip2_write_room(PTTY); -static int ip2_chars_in_buf(PTTY); -static void ip2_flush_buffer(PTTY); -static int ip2_ioctl(PTTY, UINT, ULONG); -static void ip2_set_termios(PTTY, struct ktermios *); -static void ip2_set_line_discipline(PTTY); -static void ip2_throttle(PTTY); -static void ip2_unthrottle(PTTY); -static void ip2_stop(PTTY); -static void ip2_start(PTTY); -static void ip2_hangup(PTTY); -static int ip2_tiocmget(struct tty_struct *tty); -static int ip2_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear); -static int ip2_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); - -static void set_irq(int, int); -static void ip2_interrupt_bh(struct work_struct *work); -static irqreturn_t ip2_interrupt(int irq, void *dev_id); -static void ip2_poll(unsigned long arg); -static inline void service_all_boards(void); -static void do_input(struct work_struct *); -static void do_status(struct work_struct *); - -static void ip2_wait_until_sent(PTTY,int); - -static void set_params (i2ChanStrPtr, struct ktermios *); -static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); -static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); - -static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); -static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); -static long ip2_ipl_ioctl(struct file *, UINT, ULONG); -static int ip2_ipl_open(struct inode *, struct file *); - -static int DumpTraceBuffer(char __user *, int); -static int DumpFifoBuffer( char __user *, int); - -static void ip2_init_board(int, const struct firmware *); -static unsigned short find_eisa_board(int); -static int ip2_setup(char *str); - -/***************/ -/* Static Data */ -/***************/ - -static struct tty_driver *ip2_tty_driver; - -/* Here, then is a table of board pointers which the interrupt routine should - * scan through to determine who it must service. - */ -static unsigned short i2nBoards; // Number of boards here - -static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS]; - -static i2ChanStrPtr DevTable[IP2_MAX_PORTS]; -//DevTableMem just used to save addresses for kfree -static void *DevTableMem[IP2_MAX_BOARDS]; - -/* This is the driver descriptor for the ip2ipl device, which is used to - * download the loadware to the boards. - */ -static const struct file_operations ip2_ipl = { - .owner = THIS_MODULE, - .read = ip2_ipl_read, - .write = ip2_ipl_write, - .unlocked_ioctl = ip2_ipl_ioctl, - .open = ip2_ipl_open, - .llseek = noop_llseek, -}; - -static unsigned long irq_counter; -static unsigned long bh_counter; - -// Use immediate queue to service interrupts -#define USE_IQI -//#define USE_IQ // PCI&2.2 needs work - -/* The timer_list entry for our poll routine. If interrupt operation is not - * selected, the board is serviced periodically to see if anything needs doing. - */ -#define POLL_TIMEOUT (jiffies + 1) -static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); - -#ifdef IP2DEBUG_TRACE -/* Trace (debug) buffer data */ -#define TRACEMAX 1000 -static unsigned long tracebuf[TRACEMAX]; -static int tracestuff; -static int tracestrip; -static int tracewrap; -#endif - -/**********/ -/* Macros */ -/**********/ - -#ifdef IP2DEBUG_OPEN -#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ - tty->name,(pCh->flags), \ - tty->count,/*GET_USE_COUNT(module)*/0,s) -#else -#define DBG_CNT(s) -#endif - -/********/ -/* Code */ -/********/ - -#include "i2ellis.c" /* Extremely low-level interface services */ -#include "i2cmd.c" /* Standard loadware command definitions */ -#include "i2lib.c" /* High level interface services */ - -/* Configuration area for modprobe */ - -MODULE_AUTHOR("Doug McNash"); -MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); -MODULE_LICENSE("GPL"); - -#define MAX_CMD_STR 50 - -static int poll_only; -static char cmd[MAX_CMD_STR]; - -static int Eisa_irq; -static int Eisa_slot; - -static int iindx; -static char rirqs[IP2_MAX_BOARDS]; -static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; - -/* Note: Add compiled in defaults to these arrays, not to the structure - in ip2.h any longer. That structure WILL get overridden - by these values, or command line values, or insmod values!!! =mhw= -*/ -static int io[IP2_MAX_BOARDS]; -static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; - -MODULE_AUTHOR("Doug McNash"); -MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); -module_param_array(irq, int, NULL, 0); -MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards"); -module_param_array(io, int, NULL, 0); -MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); -module_param(poll_only, bool, 0); -MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); -module_param_string(ip2, cmd, MAX_CMD_STR, 0); -MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); - -/* for sysfs class support */ -static struct class *ip2_class; - -/* Some functions to keep track of what irqs we have */ - -static int __init is_valid_irq(int irq) -{ - int *i = Valid_Irqs; - - while (*i != 0 && *i != irq) - i++; - - return *i; -} - -static void __init mark_requested_irq(char irq) -{ - rirqs[iindx++] = irq; -} - -static int __exit clear_requested_irq(char irq) -{ - int i; - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - if (rirqs[i] == irq) { - rirqs[i] = 0; - return 1; - } - } - return 0; -} - -static int have_requested_irq(char irq) -{ - /* array init to zeros so 0 irq will not be requested as a side - * effect */ - int i; - for (i = 0; i < IP2_MAX_BOARDS; ++i) - if (rirqs[i] == irq) - return 1; - return 0; -} - -/******************************************************************************/ -/* Function: cleanup_module() */ -/* Parameters: None */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This is a required entry point for an installable module. It has to return */ -/* the device and the driver to a passive state. It should not be necessary */ -/* to reset the board fully, especially as the loadware is downloaded */ -/* externally rather than in the driver. We just want to disable the board */ -/* and clear the loadware to a reset state. To allow this there has to be a */ -/* way to detect whether the board has the loadware running at init time to */ -/* handle subsequent installations of the driver. All memory allocated by the */ -/* driver should be returned since it may be unloaded from memory. */ -/******************************************************************************/ -static void __exit ip2_cleanup_module(void) -{ - int err; - int i; - - del_timer_sync(&PollTimer); - - /* Reset the boards we have. */ - for (i = 0; i < IP2_MAX_BOARDS; i++) - if (i2BoardPtrTable[i]) - iiReset(i2BoardPtrTable[i]); - - /* The following is done at most once, if any boards were installed. */ - for (i = 0; i < IP2_MAX_BOARDS; i++) { - if (i2BoardPtrTable[i]) { - iiResetDelay(i2BoardPtrTable[i]); - /* free io addresses and Tibet */ - release_region(ip2config.addr[i], 8); - device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); - device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, - 4 * i + 1)); - } - /* Disable and remove interrupt handler. */ - if (ip2config.irq[i] > 0 && - have_requested_irq(ip2config.irq[i])) { - free_irq(ip2config.irq[i], (void *)&pcName); - clear_requested_irq(ip2config.irq[i]); - } - } - class_destroy(ip2_class); - err = tty_unregister_driver(ip2_tty_driver); - if (err) - printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", - err); - put_tty_driver(ip2_tty_driver); - unregister_chrdev(IP2_IPL_MAJOR, pcIpl); - remove_proc_entry("ip2mem", NULL); - - /* free memory */ - for (i = 0; i < IP2_MAX_BOARDS; i++) { - void *pB; -#ifdef CONFIG_PCI - if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { - pci_disable_device(ip2config.pci_dev[i]); - pci_dev_put(ip2config.pci_dev[i]); - ip2config.pci_dev[i] = NULL; - } -#endif - pB = i2BoardPtrTable[i]; - if (pB != NULL) { - kfree(pB); - i2BoardPtrTable[i] = NULL; - } - if (DevTableMem[i] != NULL) { - kfree(DevTableMem[i]); - DevTableMem[i] = NULL; - } - } -} -module_exit(ip2_cleanup_module); - -static const struct tty_operations ip2_ops = { - .open = ip2_open, - .close = ip2_close, - .write = ip2_write, - .put_char = ip2_putchar, - .flush_chars = ip2_flush_chars, - .write_room = ip2_write_room, - .chars_in_buffer = ip2_chars_in_buf, - .flush_buffer = ip2_flush_buffer, - .ioctl = ip2_ioctl, - .throttle = ip2_throttle, - .unthrottle = ip2_unthrottle, - .set_termios = ip2_set_termios, - .set_ldisc = ip2_set_line_discipline, - .stop = ip2_stop, - .start = ip2_start, - .hangup = ip2_hangup, - .tiocmget = ip2_tiocmget, - .tiocmset = ip2_tiocmset, - .get_icount = ip2_get_icount, - .proc_fops = &ip2_proc_fops, -}; - -/******************************************************************************/ -/* Function: ip2_loadmain() */ -/* Parameters: irq, io from command line of insmod et. al. */ -/* pointer to fip firmware and firmware size for boards */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This was the required entry point for all drivers (now in ip2.c) */ -/* It performs all */ -/* initialisation of the devices and driver structures, and registers itself */ -/* with the relevant kernel modules. */ -/******************************************************************************/ -/* IRQF_DISABLED - if set blocks all interrupts else only this line */ -/* IRQF_SHARED - for shared irq PCI or maybe EISA only */ -/* SA_RANDOM - can be source for cert. random number generators */ -#define IP2_SA_FLAGS 0 - - -static const struct firmware *ip2_request_firmware(void) -{ - struct platform_device *pdev; - const struct firmware *fw; - - pdev = platform_device_register_simple("ip2", 0, NULL, 0); - if (IS_ERR(pdev)) { - printk(KERN_ERR "Failed to register platform device for ip2\n"); - return NULL; - } - if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) { - printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n"); - fw = NULL; - } - platform_device_unregister(pdev); - return fw; -} - -/****************************************************************************** - * ip2_setup: - * str: kernel command line string - * - * Can't autoprobe the boards so user must specify configuration on - * kernel command line. Sane people build it modular but the others - * come here. - * - * Alternating pairs of io,irq for up to 4 boards. - * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 - * - * io=0 => No board - * io=1 => PCI - * io=2 => EISA - * else => ISA I/O address - * - * irq=0 or invalid for ISA will revert to polling mode - * - * Any value = -1, do not overwrite compiled in value. - * - ******************************************************************************/ -static int __init ip2_setup(char *str) -{ - int j, ints[10]; /* 4 boards, 2 parameters + 2 */ - unsigned int i; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - for (i = 0, j = 1; i < 4; i++) { - if (j > ints[0]) - break; - if (ints[j] >= 0) - io[i] = ints[j]; - j++; - if (j > ints[0]) - break; - if (ints[j] >= 0) - irq[i] = ints[j]; - j++; - } - return 1; -} -__setup("ip2=", ip2_setup); - -static int __init ip2_loadmain(void) -{ - int i, j, box; - int err = 0; - i2eBordStrPtr pB = NULL; - int rc = -1; - const struct firmware *fw = NULL; - char *str; - - str = cmd; - - if (poll_only) { - /* Hard lock the interrupts to zero */ - irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; - } - - /* Check module parameter with 'ip2=' has been passed or not */ - if (!poll_only && (!strncmp(str, "ip2=", 4))) - ip2_setup(str); - - ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); - - /* process command line arguments to modprobe or - insmod i.e. iop & irqp */ - /* irqp and iop should ALWAYS be specified now... But we check - them individually just to be sure, anyways... */ - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - ip2config.addr[i] = io[i]; - if (irq[i] >= 0) - ip2config.irq[i] = irq[i]; - else - ip2config.irq[i] = 0; - /* This is a little bit of a hack. If poll_only=1 on command - line back in ip2.c OR all IRQs on all specified boards are - explicitly set to 0, then drop to poll only mode and override - PCI or EISA interrupts. This superceeds the old hack of - triggering if all interrupts were zero (like da default). - Still a hack but less prone to random acts of terrorism. - - What we really should do, now that the IRQ default is set - to -1, is to use 0 as a hard coded, do not probe. - - /\/\|=mhw=|\/\/ - */ - poll_only |= irq[i]; - } - poll_only = !poll_only; - - /* Announce our presence */ - printk(KERN_INFO "%s version %s\n", pcName, pcVersion); - - ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); - if (!ip2_tty_driver) - return -ENOMEM; - - /* Initialise all the boards we can find (up to the maximum). */ - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - switch (ip2config.addr[i]) { - case 0: /* skip this slot even if card is present */ - break; - default: /* ISA */ - /* ISA address must be specified */ - if (ip2config.addr[i] < 0x100 || - ip2config.addr[i] > 0x3f8) { - printk(KERN_ERR "IP2: Bad ISA board %d " - "address %x\n", i, - ip2config.addr[i]); - ip2config.addr[i] = 0; - break; - } - ip2config.type[i] = ISA; - - /* Check for valid irq argument, set for polling if - * invalid */ - if (ip2config.irq[i] && - !is_valid_irq(ip2config.irq[i])) { - printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n", - ip2config.irq[i]); - /* 0 is polling and is valid in that sense */ - ip2config.irq[i] = 0; - } - break; - case PCI: -#ifdef CONFIG_PCI - { - struct pci_dev *pdev = NULL; - u32 addr; - int status; - - pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE, - PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev); - if (pdev == NULL) { - ip2config.addr[i] = 0; - printk(KERN_ERR "IP2: PCI board %d not " - "found\n", i); - break; - } - - if (pci_enable_device(pdev)) { - dev_err(&pdev->dev, "can't enable device\n"); - goto out; - } - ip2config.type[i] = PCI; - ip2config.pci_dev[i] = pci_dev_get(pdev); - status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, - &addr); - if (addr & 1) - ip2config.addr[i] = (USHORT)(addr & 0xfffe); - else - dev_err(&pdev->dev, "I/O address error\n"); - - ip2config.irq[i] = pdev->irq; -out: - pci_dev_put(pdev); - } -#else - printk(KERN_ERR "IP2: PCI card specified but PCI " - "support not enabled.\n"); - printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI " - "defined!\n"); -#endif /* CONFIG_PCI */ - break; - case EISA: - ip2config.addr[i] = find_eisa_board(Eisa_slot + 1); - if (ip2config.addr[i] != 0) { - /* Eisa_irq set as side effect, boo */ - ip2config.type[i] = EISA; - } - ip2config.irq[i] = Eisa_irq; - break; - } /* switch */ - } /* for */ - - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - if (ip2config.addr[i]) { - pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); - if (pB) { - i2BoardPtrTable[i] = pB; - iiSetAddress(pB, ip2config.addr[i], - ii2DelayTimer); - iiReset(pB); - } else - printk(KERN_ERR "IP2: board memory allocation " - "error\n"); - } - } - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - pB = i2BoardPtrTable[i]; - if (pB != NULL) { - iiResetDelay(pB); - break; - } - } - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - /* We don't want to request the firmware unless we have at - least one board */ - if (i2BoardPtrTable[i] != NULL) { - if (!fw) - fw = ip2_request_firmware(); - if (!fw) - break; - ip2_init_board(i, fw); - } - } - if (fw) - release_firmware(fw); - - ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0); - - ip2_tty_driver->owner = THIS_MODULE; - ip2_tty_driver->name = "ttyF"; - ip2_tty_driver->driver_name = pcDriver_name; - ip2_tty_driver->major = IP2_TTY_MAJOR; - ip2_tty_driver->minor_start = 0; - ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; - ip2_tty_driver->init_termios = tty_std_termios; - ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; - ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV; - tty_set_operations(ip2_tty_driver, &ip2_ops); - - ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0); - - err = tty_register_driver(ip2_tty_driver); - if (err) { - printk(KERN_ERR "IP2: failed to register tty driver\n"); - put_tty_driver(ip2_tty_driver); - return err; /* leaking resources */ - } - - err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl); - if (err) { - printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", - err); - } else { - /* create the sysfs class */ - ip2_class = class_create(THIS_MODULE, "ip2"); - if (IS_ERR(ip2_class)) { - err = PTR_ERR(ip2_class); - goto out_chrdev; - } - } - /* Register the read_procmem thing */ - if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { - printk(KERN_ERR "IP2: failed to register read_procmem\n"); - return -EIO; /* leaking resources */ - } - - ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0); - /* Register the interrupt handler or poll handler, depending upon the - * specified interrupt. - */ - - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - if (ip2config.addr[i] == 0) - continue; - - pB = i2BoardPtrTable[i]; - if (pB != NULL) { - device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i), - NULL, "ipl%d", i); - device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i + 1), - NULL, "stat%d", i); - - for (box = 0; box < ABS_MAX_BOXES; box++) - for (j = 0; j < ABS_BIGGEST_BOX; j++) - if (pB->i2eChannelMap[box] & (1 << j)) - tty_register_device( - ip2_tty_driver, - j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES), - NULL); - } - - if (poll_only) { - /* Poll only forces driver to only use polling and - to ignore the probed PCI or EISA interrupts. */ - ip2config.irq[i] = CIR_POLL; - } - if (ip2config.irq[i] == CIR_POLL) { -retry: - if (!timer_pending(&PollTimer)) { - mod_timer(&PollTimer, POLL_TIMEOUT); - printk(KERN_INFO "IP2: polling\n"); - } - } else { - if (have_requested_irq(ip2config.irq[i])) - continue; - rc = request_irq(ip2config.irq[i], ip2_interrupt, - IP2_SA_FLAGS | - (ip2config.type[i] == PCI ? IRQF_SHARED : 0), - pcName, i2BoardPtrTable[i]); - if (rc) { - printk(KERN_ERR "IP2: request_irq failed: " - "error %d\n", rc); - ip2config.irq[i] = CIR_POLL; - printk(KERN_INFO "IP2: Polling %ld/sec.\n", - (POLL_TIMEOUT - jiffies)); - goto retry; - } - mark_requested_irq(ip2config.irq[i]); - /* Initialise the interrupt handler bottom half - * (aka slih). */ - } - } - - for (i = 0; i < IP2_MAX_BOARDS; ++i) { - if (i2BoardPtrTable[i]) { - /* set and enable board interrupt */ - set_irq(i, ip2config.irq[i]); - } - } - - ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0); - - return 0; - -out_chrdev: - unregister_chrdev(IP2_IPL_MAJOR, "ip2"); - /* unregister and put tty here */ - return err; -} -module_init(ip2_loadmain); - -/******************************************************************************/ -/* Function: ip2_init_board() */ -/* Parameters: Index of board in configuration structure */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This function initializes the specified board. The loadware is copied to */ -/* the board, the channel structures are initialized, and the board details */ -/* are reported on the console. */ -/******************************************************************************/ -static void -ip2_init_board(int boardnum, const struct firmware *fw) -{ - int i; - int nports = 0, nboxes = 0; - i2ChanStrPtr pCh; - i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; - - if ( !iiInitialize ( pB ) ) { - printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", - pB->i2eBase, pB->i2eError ); - goto err_initialize; - } - printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, - ip2config.addr[boardnum], ip2config.irq[boardnum] ); - - if (!request_region( ip2config.addr[boardnum], 8, pcName )) { - printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]); - goto err_initialize; - } - - if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size ) - != II_DOWN_GOOD ) { - printk ( KERN_ERR "IP2: failed to download loadware\n" ); - goto err_release_region; - } else { - printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", - pB->i2ePom.e.porVersion, - pB->i2ePom.e.porRevision, - pB->i2ePom.e.porSubRev, pB->i2eLVersion, - pB->i2eLRevision, pB->i2eLSub ); - } - - switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { - - default: - printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", - pB->i2ePom.e.porID ); - nports = 0; - goto err_release_region; - break; - - case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ - printk ( KERN_INFO "IP2: ISA-4\n" ); - nports = 4; - break; - - case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ - printk ( KERN_INFO "IP2: ISA-8 std\n" ); - nports = 8; - break; - - case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ - printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); - nports = 8; - break; - - case POR_ID_FIIEX: /* IntelliPort IIEX */ - { - int portnum = IP2_PORTS_PER_BOARD * boardnum; - int box; - - for( box = 0; box < ABS_MAX_BOXES; ++box ) { - if ( pB->i2eChannelMap[box] != 0 ) { - ++nboxes; - } - for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { - if ( pB->i2eChannelMap[box] & 1<< i ) { - ++nports; - } - } - } - DevTableMem[boardnum] = pCh = - kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); - if ( !pCh ) { - printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); - goto err_release_region; - } - if ( !i2InitChannels( pB, nports, pCh ) ) { - printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); - kfree ( pCh ); - goto err_release_region; - } - pB->i2eChannelPtr = &DevTable[portnum]; - pB->i2eChannelCnt = ABS_MOST_PORTS; - - for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { - for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { - if ( pB->i2eChannelMap[box] & (1 << i) ) { - DevTable[portnum + i] = pCh; - pCh->port_index = portnum + i; - pCh++; - } - } - } - printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", - nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); - } - goto ex_exit; - } - DevTableMem[boardnum] = pCh = - kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); - if ( !pCh ) { - printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); - goto err_release_region; - } - pB->i2eChannelPtr = pCh; - pB->i2eChannelCnt = nports; - if ( !i2InitChannels( pB, nports, pCh ) ) { - printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); - kfree ( pCh ); - goto err_release_region; - } - pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; - - for( i = 0; i < pB->i2eChannelCnt; ++i ) { - DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; - pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; - pCh++; - } -ex_exit: - INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); - return; - -err_release_region: - release_region(ip2config.addr[boardnum], 8); -err_initialize: - kfree ( pB ); - i2BoardPtrTable[boardnum] = NULL; - return; -} - -/******************************************************************************/ -/* Function: find_eisa_board ( int start_slot ) */ -/* Parameters: First slot to check */ -/* Returns: Address of EISA IntelliPort II controller */ -/* */ -/* Description: */ -/* This function searches for an EISA IntelliPort controller, starting */ -/* from the specified slot number. If the motherboard is not identified as an */ -/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ -/* it returns the base address of the controller. */ -/******************************************************************************/ -static unsigned short -find_eisa_board( int start_slot ) -{ - int i, j; - unsigned int idm = 0; - unsigned int idp = 0; - unsigned int base = 0; - unsigned int value; - int setup_address; - int setup_irq; - int ismine = 0; - - /* - * First a check for an EISA motherboard, which we do by comparing the - * EISA ID registers for the system board and the first couple of slots. - * No slot ID should match the system board ID, but on an ISA or PCI - * machine the odds are that an empty bus will return similar values for - * each slot. - */ - i = 0x0c80; - value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); - for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { - j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); - if ( value == j ) - return 0; - } - - /* - * OK, so we are inclined to believe that this is an EISA machine. Find - * an IntelliPort controller. - */ - for( i = start_slot; i < 16; i++ ) { - base = i << 12; - idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); - idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); - ismine = 0; - if ( idm == 0x0e8e ) { - if ( idp == 0x0281 || idp == 0x0218 ) { - ismine = 1; - } else if ( idp == 0x0282 || idp == 0x0283 ) { - ismine = 3; /* Can do edge-trigger */ - } - if ( ismine ) { - Eisa_slot = i; - break; - } - } - } - if ( !ismine ) - return 0; - - /* It's some sort of EISA card, but at what address is it configured? */ - - setup_address = base + 0xc88; - value = inb(base + 0xc86); - setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; - - if ( (ismine & 2) && !(value & 0x10) ) { - ismine = 1; /* Could be edging, but not */ - } - - if ( Eisa_irq == 0 ) { - Eisa_irq = setup_irq; - } else if ( Eisa_irq != setup_irq ) { - printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); - } - -#ifdef IP2DEBUG_INIT -printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", - base >> 12, idm, idp, setup_address); - if ( Eisa_irq ) { - printk(KERN_DEBUG ", Interrupt %d %s\n", - setup_irq, (ismine & 2) ? "(edge)" : "(level)"); - } else { - printk(KERN_DEBUG ", (polled)\n"); - } -#endif - return setup_address; -} - -/******************************************************************************/ -/* Function: set_irq() */ -/* Parameters: index to board in board table */ -/* IRQ to use */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/******************************************************************************/ -static void -set_irq( int boardnum, int boardIrq ) -{ - unsigned char tempCommand[16]; - i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; - unsigned long flags; - - /* - * Notify the boards they may generate interrupts. This is done by - * sending an in-line command to channel 0 on each board. This is why - * the channels have to be defined already. For each board, if the - * interrupt has never been defined, we must do so NOW, directly, since - * board will not send flow control or even give an interrupt until this - * is done. If polling we must send 0 as the interrupt parameter. - */ - - // We will get an interrupt here at the end of this function - - iiDisableMailIrq(pB); - - /* We build up the entire packet header. */ - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_INLINE; - CMD_COUNT_OF(tempCommand) = 2; - (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ; - (CMD_OF(tempCommand))[1] = boardIrq; - /* - * Write to FIFO; don't bother to adjust fifo capacity for this, since - * board will respond almost immediately after SendMail hit. - */ - write_lock_irqsave(&pB->write_fifo_spinlock, flags); - iiWriteBuf(pB, tempCommand, 4); - write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); - pB->i2eUsingIrq = boardIrq; - pB->i2eOutMailWaiting |= MB_OUT_STUFFED; - - /* Need to update number of boards before you enable mailbox int */ - ++i2nBoards; - - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_BYPASS; - CMD_COUNT_OF(tempCommand) = 6; - (CMD_OF(tempCommand))[0] = 88; // SILO - (CMD_OF(tempCommand))[1] = 64; // chars - (CMD_OF(tempCommand))[2] = 32; // ms - - (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK - (CMD_OF(tempCommand))[4] = 64; // chars - - (CMD_OF(tempCommand))[5] = 87; // HW_TEST - write_lock_irqsave(&pB->write_fifo_spinlock, flags); - iiWriteBuf(pB, tempCommand, 8); - write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); - - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_BYPASS; - CMD_COUNT_OF(tempCommand) = 1; - (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ - iiWriteBuf(pB, tempCommand, 3); - -#ifdef XXX - // enable heartbeat for test porpoises - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_BYPASS; - CMD_COUNT_OF(tempCommand) = 2; - (CMD_OF(tempCommand))[0] = 44; /* get ping */ - (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ - write_lock_irqsave(&pB->write_fifo_spinlock, flags); - iiWriteBuf(pB, tempCommand, 4); - write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); -#endif - - iiEnableMailIrq(pB); - iiSendPendingMail(pB); -} - -/******************************************************************************/ -/* Interrupt Handler Section */ -/******************************************************************************/ - -static inline void -service_all_boards(void) -{ - int i; - i2eBordStrPtr pB; - - /* Service every board on the list */ - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - pB = i2BoardPtrTable[i]; - if ( pB ) { - i2ServiceBoard( pB ); - } - } -} - - -/******************************************************************************/ -/* Function: ip2_interrupt_bh(work) */ -/* Parameters: work - pointer to the board structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* Service the board in a bottom half interrupt handler and then */ -/* reenable the board's interrupts if it has an IRQ number */ -/* */ -/******************************************************************************/ -static void -ip2_interrupt_bh(struct work_struct *work) -{ - i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); -// pB better well be set or we have a problem! We can only get -// here from the IMMEDIATE queue. Here, we process the boards. -// Checking pB doesn't cost much and it saves us from the sanity checkers. - - bh_counter++; - - if ( pB ) { - i2ServiceBoard( pB ); - if( pB->i2eUsingIrq ) { -// Re-enable his interrupts - iiEnableMailIrq(pB); - } - } -} - - -/******************************************************************************/ -/* Function: ip2_interrupt(int irq, void *dev_id) */ -/* Parameters: irq - interrupt number */ -/* pointer to optional device ID structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* Our task here is simply to identify each board which needs servicing. */ -/* If we are queuing then, queue it to be serviced, and disable its irq */ -/* mask otherwise process the board directly. */ -/* */ -/* We could queue by IRQ but that just complicates things on both ends */ -/* with very little gain in performance (how many instructions does */ -/* it take to iterate on the immediate queue). */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_irq_work(i2eBordStrPtr pB) -{ -#ifdef USE_IQI - if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { -// Disable his interrupt (will be enabled when serviced) -// This is mostly to protect from reentrancy. - iiDisableMailIrq(pB); - -// Park the board on the immediate queue for processing. - schedule_work(&pB->tqueue_interrupt); - -// Make sure the immediate queue is flagged to fire. - } -#else - -// We are using immediate servicing here. This sucks and can -// cause all sorts of havoc with ppp and others. The failsafe -// check on iiSendPendingMail could also throw a hairball. - - i2ServiceBoard( pB ); - -#endif /* USE_IQI */ -} - -static void -ip2_polled_interrupt(void) -{ - int i; - i2eBordStrPtr pB; - - ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0); - - /* Service just the boards on the list using this irq */ - for( i = 0; i < i2nBoards; ++i ) { - pB = i2BoardPtrTable[i]; - -// Only process those boards which match our IRQ. -// IRQ = 0 for polled boards, we won't poll "IRQ" boards - - if (pB && pB->i2eUsingIrq == 0) - ip2_irq_work(pB); - } - - ++irq_counter; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); -} - -static irqreturn_t -ip2_interrupt(int irq, void *dev_id) -{ - i2eBordStrPtr pB = dev_id; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq ); - - ip2_irq_work(pB); - - ++irq_counter; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); - return IRQ_HANDLED; -} - -/******************************************************************************/ -/* Function: ip2_poll(unsigned long arg) */ -/* Parameters: ? */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This function calls the library routine i2ServiceBoard for each board in */ -/* the board table. This is used instead of the interrupt routine when polled */ -/* mode is specified. */ -/******************************************************************************/ -static void -ip2_poll(unsigned long arg) -{ - ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); - - // Just polled boards, IRQ = 0 will hit all non-interrupt boards. - // It will NOT poll boards handled by hard interrupts. - // The issue of queued BH interrupts is handled in ip2_interrupt(). - ip2_polled_interrupt(); - - mod_timer(&PollTimer, POLL_TIMEOUT); - - ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); -} - -static void do_input(struct work_struct *work) -{ - i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); - unsigned long flags; - - ip2trace(CHANN, ITRC_INPUT, 21, 0 ); - - // Data input - if ( pCh->pTTY != NULL ) { - read_lock_irqsave(&pCh->Ibuf_spinlock, flags); - if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { - read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - i2Input( pCh ); - } else - read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); - } else { - ip2trace(CHANN, ITRC_INPUT, 22, 0 ); - - i2InputFlush( pCh ); - } -} - -// code duplicated from n_tty (ldisc) -static inline void isig(int sig, struct tty_struct *tty, int flush) -{ - /* FIXME: This is completely bogus */ - if (tty->pgrp) - kill_pgrp(tty->pgrp, sig, 1); - if (flush || !L_NOFLSH(tty)) { - if ( tty->ldisc->ops->flush_buffer ) - tty->ldisc->ops->flush_buffer(tty); - i2InputFlush( tty->driver_data ); - } -} - -static void do_status(struct work_struct *work) -{ - i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); - int status; - - status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); - - ip2trace (CHANN, ITRC_STATUS, 21, 1, status ); - - if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { - if ( (status & I2_BRK) ) { - // code duplicated from n_tty (ldisc) - if (I_IGNBRK(pCh->pTTY)) - goto skip_this; - if (I_BRKINT(pCh->pTTY)) { - isig(SIGINT, pCh->pTTY, 1); - goto skip_this; - } - wake_up_interruptible(&pCh->pTTY->read_wait); - } -#ifdef NEVER_HAPPENS_AS_SETUP_XXX - // and can't work because we don't know the_char - // as the_char is reported on a separate path - // The intelligent board does this stuff as setup - { - char brkf = TTY_NORMAL; - unsigned char brkc = '\0'; - unsigned char tmp; - if ( (status & I2_BRK) ) { - brkf = TTY_BREAK; - brkc = '\0'; - } - else if (status & I2_PAR) { - brkf = TTY_PARITY; - brkc = the_char; - } else if (status & I2_FRA) { - brkf = TTY_FRAME; - brkc = the_char; - } else if (status & I2_OVR) { - brkf = TTY_OVERRUN; - brkc = the_char; - } - tmp = pCh->pTTY->real_raw; - pCh->pTTY->real_raw = 0; - pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); - pCh->pTTY->real_raw = tmp; - } -#endif /* NEVER_HAPPENS_AS_SETUP_XXX */ - } -skip_this: - - if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { - wake_up_interruptible(&pCh->delta_msr_wait); - - if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { - if ( status & I2_DCD ) { - if ( pCh->wopen ) { - wake_up_interruptible ( &pCh->open_wait ); - } - } else { - if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { - tty_hangup( pCh->pTTY ); - } - } - } - } - - ip2trace (CHANN, ITRC_STATUS, 26, 0 ); -} - -/******************************************************************************/ -/* Device Open/Close/Ioctl Entry Point Section */ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: open_sanity_check() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* Verifies the structure magic numbers and cross links. */ -/******************************************************************************/ -#ifdef IP2DEBUG_OPEN -static void -open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ) -{ - if ( pBrd->i2eValid != I2E_MAGIC ) { - printk(KERN_ERR "IP2: invalid board structure\n" ); - } else if ( pBrd != pCh->pMyBord ) { - printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", - pCh->pMyBord ); - } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { - printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); - } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { - } else { - printk(KERN_INFO "IP2: all pointers check out!\n" ); - } -} -#endif - - -/******************************************************************************/ -/* Function: ip2_open() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Returns: Success or failure */ -/* */ -/* Description: (MANDATORY) */ -/* A successful device open has to run a gauntlet of checks before it */ -/* completes. After some sanity checking and pointer setup, the function */ -/* blocks until all conditions are satisfied. It then initialises the port to */ -/* the default characteristics and returns. */ -/******************************************************************************/ -static int -ip2_open( PTTY tty, struct file *pFile ) -{ - wait_queue_t wait; - int rc = 0; - int do_clocal = 0; - i2ChanStrPtr pCh = DevTable[tty->index]; - - ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 ); - - if ( pCh == NULL ) { - return -ENODEV; - } - /* Setup pointer links in device and tty structures */ - pCh->pTTY = tty; - tty->driver_data = pCh; - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG \ - "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n", - tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index); - open_sanity_check ( pCh, pCh->pMyBord ); -#endif - - i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); - pCh->dataSetOut |= (I2_DTR | I2_RTS); - serviceOutgoingFifo( pCh->pMyBord ); - - /* Block here until the port is ready (per serial and istallion) */ - /* - * 1. If the port is in the middle of closing wait for the completion - * and then return the appropriate error. - */ - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->close_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { - if ( pCh->flags & ASYNC_CLOSING ) { - tty_unlock(); - schedule(); - tty_lock(); - } - if ( tty_hung_up_p(pFile) ) { - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->close_wait, &wait); - return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; - } - } - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->close_wait, &wait); - - /* - * 3. Handle a non-blocking open of a normal port. - */ - if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<flags |= ASYNC_NORMAL_ACTIVE; - goto noblock; - } - /* - * 4. Now loop waiting for the port to be free and carrier present - * (if required). - */ - if ( tty->termios->c_cflag & CLOCAL ) - do_clocal = 1; - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal); -#endif - - ++pCh->wopen; - - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->open_wait, &wait); - - for(;;) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); - pCh->dataSetOut |= (I2_DTR | I2_RTS); - set_current_state( TASK_INTERRUPTIBLE ); - serviceOutgoingFifo( pCh->pMyBord ); - if ( tty_hung_up_p(pFile) ) { - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->open_wait, &wait); - return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; - } - if (!(pCh->flags & ASYNC_CLOSING) && - (do_clocal || (pCh->dataSetIn & I2_DCD) )) { - rc = 0; - break; - } - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", - (pCh->flags & ASYNC_CLOSING)?"True":"False"); - printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n"); -#endif - ip2trace (CHANN, ITRC_OPEN, 3, 2, 0, - (pCh->flags & ASYNC_CLOSING) ); - /* check for signal */ - if (signal_pending(current)) { - rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); - break; - } - tty_unlock(); - schedule(); - tty_lock(); - } - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->open_wait, &wait); - - --pCh->wopen; //why count? - - ip2trace (CHANN, ITRC_OPEN, 4, 0 ); - - if (rc != 0 ) { - return rc; - } - pCh->flags |= ASYNC_NORMAL_ACTIVE; - -noblock: - - /* first open - Assign termios structure to port */ - if ( tty->count == 1 ) { - i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); - /* Now we must send the termios settings to the loadware */ - set_params( pCh, NULL ); - } - - /* - * Now set any i2lib options. These may go away if the i2lib code ends - * up rolled into the mainline. - */ - pCh->channelOptions |= CO_NBLOCK_WRITE; - -#ifdef IP2DEBUG_OPEN - printk (KERN_DEBUG "IP2: open completed\n" ); -#endif - serviceOutgoingFifo( pCh->pMyBord ); - - ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); - - return 0; -} - -/******************************************************************************/ -/* Function: ip2_close() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_close( PTTY tty, struct file *pFile ) -{ - i2ChanStrPtr pCh = tty->driver_data; - - if ( !pCh ) { - return; - } - - ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 ); - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG "IP2:close %s:\n",tty->name); -#endif - - if ( tty_hung_up_p ( pFile ) ) { - - ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); - - return; - } - if ( tty->count > 1 ) { /* not the last close */ - - ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); - - return; - } - pCh->flags |= ASYNC_CLOSING; // last close actually - - tty->closing = 1; - - if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { - /* - * Before we drop DTR, make sure the transmitter has completely drained. - * This uses an timeout, after which the close - * completes. - */ - ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); - } - /* - * At this point we stop accepting input. Here we flush the channel - * input buffer which will allow the board to send up more data. Any - * additional input is tossed at interrupt/poll time. - */ - i2InputFlush( pCh ); - - /* disable DSS reporting */ - i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, - CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - if (tty->termios->c_cflag & HUPCL) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); - pCh->dataSetOut &= ~(I2_DTR | I2_RTS); - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); - } - - serviceOutgoingFifo ( pCh->pMyBord ); - - tty_ldisc_flush(tty); - tty_driver_flush_buffer(tty); - tty->closing = 0; - - pCh->pTTY = NULL; - - if (pCh->wopen) { - if (pCh->ClosingDelay) { - msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); - } - wake_up_interruptible(&pCh->open_wait); - } - - pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&pCh->close_wait); - -#ifdef IP2DEBUG_OPEN - DBG_CNT("ip2_close: after wakeups--"); -#endif - - - ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); - - return; -} - -/******************************************************************************/ -/* Function: ip2_hangup() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_hangup ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - - if( !pCh ) { - return; - } - - ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); - - ip2_flush_buffer(tty); - - /* disable DSS reporting */ - - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); - i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); - if ( (tty->termios->c_cflag & HUPCL) ) { - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); - pCh->dataSetOut &= ~(I2_DTR | I2_RTS); - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); - } - i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, - CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - serviceOutgoingFifo ( pCh->pMyBord ); - - wake_up_interruptible ( &pCh->delta_msr_wait ); - - pCh->flags &= ~ASYNC_NORMAL_ACTIVE; - pCh->pTTY = NULL; - wake_up_interruptible ( &pCh->open_wait ); - - ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 ); -} - -/******************************************************************************/ -/******************************************************************************/ -/* Device Output Section */ -/******************************************************************************/ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: ip2_write() */ -/* Parameters: Pointer to tty structure */ -/* Flag denoting data is in user (1) or kernel (0) space */ -/* Pointer to data */ -/* Number of bytes to write */ -/* Returns: Number of bytes actually written */ -/* */ -/* Description: (MANDATORY) */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_write( PTTY tty, const unsigned char *pData, int count) -{ - i2ChanStrPtr pCh = tty->driver_data; - int bytesSent = 0; - unsigned long flags; - - ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); - - /* Flush out any buffered data left over from ip2_putchar() calls. */ - ip2_flush_chars( tty ); - - /* This is the actual move bit. Make sure it does what we need!!!!! */ - write_lock_irqsave(&pCh->Pbuf_spinlock, flags); - bytesSent = i2Output( pCh, pData, count); - write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); - - ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); - - return bytesSent > 0 ? bytesSent : 0; -} - -/******************************************************************************/ -/* Function: ip2_putchar() */ -/* Parameters: Pointer to tty structure */ -/* Character to write */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_putchar( PTTY tty, unsigned char ch ) -{ - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - -// ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); - - write_lock_irqsave(&pCh->Pbuf_spinlock, flags); - pCh->Pbuf[pCh->Pbuf_stuff++] = ch; - if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { - write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); - ip2_flush_chars( tty ); - } else - write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); - return 1; - -// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); -} - -/******************************************************************************/ -/* Function: ip2_flush_chars() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/******************************************************************************/ -static void -ip2_flush_chars( PTTY tty ) -{ - int strip; - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - - write_lock_irqsave(&pCh->Pbuf_spinlock, flags); - if ( pCh->Pbuf_stuff ) { - -// ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); - - // - // We may need to restart i2Output if it does not fullfill this request - // - strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff); - if ( strip != pCh->Pbuf_stuff ) { - memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); - } - pCh->Pbuf_stuff -= strip; - } - write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); -} - -/******************************************************************************/ -/* Function: ip2_write_room() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Number of bytes that the driver can accept */ -/* */ -/* Description: */ -/* */ -/******************************************************************************/ -static int -ip2_write_room ( PTTY tty ) -{ - int bytesFree; - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - - read_lock_irqsave(&pCh->Pbuf_spinlock, flags); - bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; - read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); - - ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); - - return ((bytesFree > 0) ? bytesFree : 0); -} - -/******************************************************************************/ -/* Function: ip2_chars_in_buf() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Number of bytes queued for transmission */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_chars_in_buf ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - int rc; - unsigned long flags; - - ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff ); - -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", - pCh->Obuf_char_count + pCh->Pbuf_stuff, - pCh->Obuf_char_count, pCh->Pbuf_stuff ); -#endif - read_lock_irqsave(&pCh->Obuf_spinlock, flags); - rc = pCh->Obuf_char_count; - read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); - read_lock_irqsave(&pCh->Pbuf_spinlock, flags); - rc += pCh->Pbuf_stuff; - read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); - return rc; -} - -/******************************************************************************/ -/* Function: ip2_flush_buffer() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_flush_buffer( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - - ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 ); - -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: flush buffer\n" ); -#endif - write_lock_irqsave(&pCh->Pbuf_spinlock, flags); - pCh->Pbuf_stuff = 0; - write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); - i2FlushOutput( pCh ); - ip2_owake(tty); - - ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 ); - -} - -/******************************************************************************/ -/* Function: ip2_wait_until_sent() */ -/* Parameters: Pointer to tty structure */ -/* Timeout for wait. */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This function is used in place of the normal tty_wait_until_sent, which */ -/* only waits for the driver buffers to be empty (or rather, those buffers */ -/* reported by chars_in_buffer) which doesn't work for IP2 due to the */ -/* indeterminate number of bytes buffered on the board. */ -/******************************************************************************/ -static void -ip2_wait_until_sent ( PTTY tty, int timeout ) -{ - int i = jiffies; - i2ChanStrPtr pCh = tty->driver_data; - - tty_wait_until_sent(tty, timeout ); - if ( (i = timeout - (jiffies -i)) > 0) - i2DrainOutput( pCh, i ); -} - -/******************************************************************************/ -/******************************************************************************/ -/* Device Input Section */ -/******************************************************************************/ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: ip2_throttle() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_throttle ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - -#ifdef IP2DEBUG_READ - printk (KERN_DEBUG "IP2: throttle\n" ); -#endif - /* - * Signal the poll/interrupt handlers not to forward incoming data to - * the line discipline. This will cause the buffers to fill up in the - * library and thus cause the library routines to send the flow control - * stuff. - */ - pCh->throttled = 1; -} - -/******************************************************************************/ -/* Function: ip2_unthrottle() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_unthrottle ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - -#ifdef IP2DEBUG_READ - printk (KERN_DEBUG "IP2: unthrottle\n" ); -#endif - - /* Pass incoming data up to the line discipline again. */ - pCh->throttled = 0; - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); - serviceOutgoingFifo( pCh->pMyBord ); - read_lock_irqsave(&pCh->Ibuf_spinlock, flags); - if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) { - read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); -#ifdef IP2DEBUG_READ - printk (KERN_DEBUG "i2Input called from unthrottle\n" ); -#endif - i2Input( pCh ); - } else - read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); -} - -static void -ip2_start ( PTTY tty ) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND); - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME); -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: start tx\n" ); -#endif -} - -static void -ip2_stop ( PTTY tty ) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND); -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: stop tx\n" ); -#endif -} - -/******************************************************************************/ -/* Device Ioctl Section */ -/******************************************************************************/ - -static int ip2_tiocmget(struct tty_struct *tty) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; -#ifdef ENABLE_DSSNOW - wait_queue_t wait; -#endif - - if (pCh == NULL) - return -ENODEV; - -/* - FIXME - the following code is causing a NULL pointer dereference in - 2.3.51 in an interrupt handler. It's suppose to prompt the board - to return the DSS signal status immediately. Why doesn't it do - the same thing in 2.2.14? -*/ - -/* This thing is still busted in the 1.2.12 driver on 2.4.x - and even hoses the serial console so the oops can be trapped. - /\/\|=mhw=|\/\/ */ - -#ifdef ENABLE_DSSNOW - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); - - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->dss_now_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - serviceOutgoingFifo( pCh->pMyBord ); - - schedule(); - - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->dss_now_wait, &wait); - - if (signal_pending(current)) { - return -EINTR; - } -#endif - return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) - | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) - | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) - | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) - | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) - | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); -} - -static int ip2_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - - if (pCh == NULL) - return -ENODEV; - - if (set & TIOCM_RTS) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); - pCh->dataSetOut |= I2_RTS; - } - if (set & TIOCM_DTR) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); - pCh->dataSetOut |= I2_DTR; - } - - if (clear & TIOCM_RTS) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); - pCh->dataSetOut &= ~I2_RTS; - } - if (clear & TIOCM_DTR) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); - pCh->dataSetOut &= ~I2_DTR; - } - serviceOutgoingFifo( pCh->pMyBord ); - return 0; -} - -/******************************************************************************/ -/* Function: ip2_ioctl() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Command */ -/* Argument */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg ) -{ - wait_queue_t wait; - i2ChanStrPtr pCh = DevTable[tty->index]; - i2eBordStrPtr pB; - struct async_icount cprev, cnow; /* kernel counter temps */ - int rc = 0; - unsigned long flags; - void __user *argp = (void __user *)arg; - - if ( pCh == NULL ) - return -ENODEV; - - pB = pCh->pMyBord; - - ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg ); - -#ifdef IP2DEBUG_IOCTL - printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg ); -#endif - - switch(cmd) { - case TIOCGSERIAL: - - ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc ); - - rc = get_serial_info(pCh, argp); - if (rc) - return rc; - break; - - case TIOCSSERIAL: - - ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc ); - - rc = set_serial_info(pCh, argp); - if (rc) - return rc; - break; - - case TCXONC: - rc = tty_check_change(tty); - if (rc) - return rc; - switch (arg) { - case TCOOFF: - //return -ENOIOCTLCMD; - break; - case TCOON: - //return -ENOIOCTLCMD; - break; - case TCIOFF: - if (STOP_CHAR(tty) != __DISABLED_CHAR) { - i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, - CMD_XMIT_NOW(STOP_CHAR(tty))); - } - break; - case TCION: - if (START_CHAR(tty) != __DISABLED_CHAR) { - i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, - CMD_XMIT_NOW(START_CHAR(tty))); - } - break; - default: - return -EINVAL; - } - return 0; - - case TCSBRK: /* SVID version: non-zero arg --> no break */ - rc = tty_check_change(tty); - - ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc ); - - if (!rc) { - ip2_wait_until_sent(tty,0); - if (!arg) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250)); - serviceOutgoingFifo( pCh->pMyBord ); - } - } - break; - - case TCSBRKP: /* support for POSIX tcsendbreak() */ - rc = tty_check_change(tty); - - ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc ); - - if (!rc) { - ip2_wait_until_sent(tty,0); - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, - CMD_SEND_BRK(arg ? arg*100 : 250)); - serviceOutgoingFifo ( pCh->pMyBord ); - } - break; - - case TIOCGSOFTCAR: - - ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); - - rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); - if (rc) - return rc; - break; - - case TIOCSSOFTCAR: - - ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); - - rc = get_user(arg,(unsigned long __user *) argp); - if (rc) - return rc; - tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) - | (arg ? CLOCAL : 0)); - - break; - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask - * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS - * for masking). Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - write_lock_irqsave(&pB->read_fifo_spinlock, flags); - cprev = pCh->icount; /* note the counters on entry */ - write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, - CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP); - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->delta_msr_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - serviceOutgoingFifo( pCh->pMyBord ); - for(;;) { - ip2trace (CHANN, ITRC_IOCTL, 10, 0 ); - - schedule(); - - ip2trace (CHANN, ITRC_IOCTL, 11, 0 ); - - /* see if a signal did it */ - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - write_lock_irqsave(&pB->read_fifo_spinlock, flags); - cnow = pCh->icount; /* atomic copy */ - write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - rc = -EIO; /* no change => rc */ - break; - } - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - rc = 0; - break; - } - cprev = cnow; - } - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->delta_msr_wait, &wait); - - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, - CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - if ( ! (pCh->flags & ASYNC_CHECK_CD)) { - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP); - } - serviceOutgoingFifo( pCh->pMyBord ); - return rc; - break; - - /* - * The rest are not supported by this driver. By returning -ENOIOCTLCMD they - * will be passed to the line discipline for it to handle. - */ - case TIOCSERCONFIG: - case TIOCSERGWILD: - case TIOCSERGETLSR: - case TIOCSERSWILD: - case TIOCSERGSTRUCT: - case TIOCSERGETMULTI: - case TIOCSERSETMULTI: - - default: - ip2trace (CHANN, ITRC_IOCTL, 12, 0 ); - - rc = -ENOIOCTLCMD; - break; - } - - ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 ); - - return rc; -} - -static int ip2_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - i2eBordStrPtr pB; - struct async_icount cnow; /* kernel counter temp */ - unsigned long flags; - - if ( pCh == NULL ) - return -ENODEV; - - pB = pCh->pMyBord; - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for RI where - * only 0->1 is counted. The controller is quite capable of counting - * both, but this done to preserve compatibility with the standard - * serial driver. - */ - - write_lock_irqsave(&pB->read_fifo_spinlock, flags); - cnow = pCh->icount; - write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - return 0; -} - -/******************************************************************************/ -/* Function: GetSerialInfo() */ -/* Parameters: Pointer to channel structure */ -/* Pointer to old termios structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This is to support the setserial command, and requires processing of the */ -/* standard Linux serial structure. */ -/******************************************************************************/ -static int -get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo ) -{ - struct serial_struct tmp; - - memset ( &tmp, 0, sizeof(tmp) ); - tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16]; - if (BID_HAS_654(tmp.type)) { - tmp.type = PORT_16650; - } else { - tmp.type = PORT_CIRRUS; - } - tmp.line = pCh->port_index; - tmp.port = pCh->pMyBord->i2eBase; - tmp.irq = ip2config.irq[pCh->port_index/64]; - tmp.flags = pCh->flags; - tmp.baud_base = pCh->BaudBase; - tmp.close_delay = pCh->ClosingDelay; - tmp.closing_wait = pCh->ClosingWaitTime; - tmp.custom_divisor = pCh->BaudDivisor; - return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); -} - -/******************************************************************************/ -/* Function: SetSerialInfo() */ -/* Parameters: Pointer to channel structure */ -/* Pointer to old termios structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This function provides support for setserial, which uses the TIOCSSERIAL */ -/* ioctl. Not all setserial parameters are relevant. If the user attempts to */ -/* change the IRQ, address or type of the port the ioctl fails. */ -/******************************************************************************/ -static int -set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) -{ - struct serial_struct ns; - int old_flags, old_baud_divisor; - - if (copy_from_user(&ns, new_info, sizeof (ns))) - return -EFAULT; - - /* - * We don't allow setserial to change IRQ, board address, type or baud - * base. Also line nunber as such is meaningless but we use it for our - * array index so it is fixed also. - */ - if ( (ns.irq != ip2config.irq[pCh->port_index]) - || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) - || (ns.baud_base != pCh->BaudBase) - || (ns.line != pCh->port_index) ) { - return -EINVAL; - } - - old_flags = pCh->flags; - old_baud_divisor = pCh->BaudDivisor; - - if ( !capable(CAP_SYS_ADMIN) ) { - if ( ( ns.close_delay != pCh->ClosingDelay ) || - ( (ns.flags & ~ASYNC_USR_MASK) != - (pCh->flags & ~ASYNC_USR_MASK) ) ) { - return -EPERM; - } - - pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) | - (ns.flags & ASYNC_USR_MASK); - pCh->BaudDivisor = ns.custom_divisor; - } else { - pCh->flags = (pCh->flags & ~ASYNC_FLAGS) | - (ns.flags & ASYNC_FLAGS); - pCh->BaudDivisor = ns.custom_divisor; - pCh->ClosingDelay = ns.close_delay * HZ/100; - pCh->ClosingWaitTime = ns.closing_wait * HZ/100; - } - - if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) ) - || (old_baud_divisor != pCh->BaudDivisor) ) { - // Invalidate speed and reset parameters - set_params( pCh, NULL ); - } - - return 0; -} - -/******************************************************************************/ -/* Function: ip2_set_termios() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to old termios structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_set_termios( PTTY tty, struct ktermios *old_termios ) -{ - i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; - -#ifdef IP2DEBUG_IOCTL - printk (KERN_DEBUG "IP2: set termios %p\n", old_termios ); -#endif - - set_params( pCh, old_termios ); -} - -/******************************************************************************/ -/* Function: ip2_set_line_discipline() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: Does nothing */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_set_line_discipline ( PTTY tty ) -{ -#ifdef IP2DEBUG_IOCTL - printk (KERN_DEBUG "IP2: set line discipline\n" ); -#endif - - ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 ); - -} - -/******************************************************************************/ -/* Function: SetLine Characteristics() */ -/* Parameters: Pointer to channel structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This routine is called to update the channel structure with the new line */ -/* characteristics, and send the appropriate commands to the board when they */ -/* change. */ -/******************************************************************************/ -static void -set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) -{ - tcflag_t cflag, iflag, lflag; - char stop_char, start_char; - struct ktermios dummy; - - lflag = pCh->pTTY->termios->c_lflag; - cflag = pCh->pTTY->termios->c_cflag; - iflag = pCh->pTTY->termios->c_iflag; - - if (o_tios == NULL) { - dummy.c_lflag = ~lflag; - dummy.c_cflag = ~cflag; - dummy.c_iflag = ~iflag; - o_tios = &dummy; - } - - { - switch ( cflag & CBAUD ) { - case B0: - i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); - pCh->dataSetOut &= ~(I2_DTR | I2_RTS); - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); - pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag); - goto service_it; - break; - case B38400: - /* - * This is the speed that is overloaded with all the other high - * speeds, depending upon the flag settings. - */ - if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) { - pCh->speed = CBR_57600; - } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) { - pCh->speed = CBR_115200; - } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) { - pCh->speed = CBR_C1; - } else { - pCh->speed = CBR_38400; - } - break; - case B50: pCh->speed = CBR_50; break; - case B75: pCh->speed = CBR_75; break; - case B110: pCh->speed = CBR_110; break; - case B134: pCh->speed = CBR_134; break; - case B150: pCh->speed = CBR_150; break; - case B200: pCh->speed = CBR_200; break; - case B300: pCh->speed = CBR_300; break; - case B600: pCh->speed = CBR_600; break; - case B1200: pCh->speed = CBR_1200; break; - case B1800: pCh->speed = CBR_1800; break; - case B2400: pCh->speed = CBR_2400; break; - case B4800: pCh->speed = CBR_4800; break; - case B9600: pCh->speed = CBR_9600; break; - case B19200: pCh->speed = CBR_19200; break; - case B57600: pCh->speed = CBR_57600; break; - case B115200: pCh->speed = CBR_115200; break; - case B153600: pCh->speed = CBR_153600; break; - case B230400: pCh->speed = CBR_230400; break; - case B307200: pCh->speed = CBR_307200; break; - case B460800: pCh->speed = CBR_460800; break; - case B921600: pCh->speed = CBR_921600; break; - default: pCh->speed = CBR_9600; break; - } - if ( pCh->speed == CBR_C1 ) { - // Process the custom speed parameters. - int bps = pCh->BaudBase / pCh->BaudDivisor; - if ( bps == 921600 ) { - pCh->speed = CBR_921600; - } else { - bps = bps/10; - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) ); - } - } - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed)); - - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); - pCh->dataSetOut |= (I2_DTR | I2_RTS); - } - if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) - { - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, - CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1)); - } - if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) - { - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, - CMD_SETPAR( - (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP) - ) - ); - } - /* byte size and parity */ - if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) - { - int datasize; - switch ( cflag & CSIZE ) { - case CS5: datasize = CSZ_5; break; - case CS6: datasize = CSZ_6; break; - case CS7: datasize = CSZ_7; break; - case CS8: datasize = CSZ_8; break; - default: datasize = CSZ_5; break; /* as per serial.c */ - } - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) ); - } - /* Process CTS flow control flag setting */ - if ( (cflag & CRTSCTS) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, - 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB); - } else { - i2QueueCommands(PTYPE_INLINE, pCh, 100, - 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); - } - // - // Process XON/XOFF flow control flags settings - // - stop_char = STOP_CHAR(pCh->pTTY); - start_char = START_CHAR(pCh->pTTY); - - //////////// can't be \000 - if (stop_char == __DISABLED_CHAR ) - { - stop_char = ~__DISABLED_CHAR; - } - if (start_char == __DISABLED_CHAR ) - { - start_char = ~__DISABLED_CHAR; - } - ///////////////////////////////// - - if ( o_tios->c_cc[VSTART] != start_char ) - { - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char)); - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char)); - } - if ( o_tios->c_cc[VSTOP] != stop_char ) - { - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char)); - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char)); - } - if (stop_char == __DISABLED_CHAR ) - { - stop_char = ~__DISABLED_CHAR; //TEST123 - goto no_xoff; - } - if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) - { - if ( iflag & IXOFF ) { // Enable XOFF output flow control - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON)); - } else { // Disable XOFF output flow control -no_xoff: - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE)); - } - } - if (start_char == __DISABLED_CHAR ) - { - goto no_xon; - } - if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) - { - if ( iflag & IXON ) { - if ( iflag & IXANY ) { // Enable XON/XANY output flow control - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY)); - } else { // Enable XON output flow control - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON)); - } - } else { // Disable XON output flow control -no_xon: - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE)); - } - } - if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) - { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, - CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0))); - } - if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) - { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, - CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB)); - } - - if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) - ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) - { - char brkrpt = 0; - char parrpt = 0; - - if ( iflag & IGNBRK ) { /* Ignore breaks altogether */ - /* Ignore breaks altogether */ - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP); - } else { - if ( iflag & BRKINT ) { - if ( iflag & PARMRK ) { - brkrpt = 0x0a; // exception an inline triple - } else { - brkrpt = 0x1a; // exception and NULL - } - brkrpt |= 0x04; // flush input - } else { - if ( iflag & PARMRK ) { - brkrpt = 0x0b; //POSIX triple \0377 \0 \0 - } else { - brkrpt = 0x01; // Null only - } - } - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt)); - } - - if (iflag & IGNPAR) { - parrpt = 0x20; - /* would be 2 for not cirrus bug */ - /* would be 0x20 cept for cirrus bug */ - } else { - if ( iflag & PARMRK ) { - /* - * Replace error characters with 3-byte sequence (\0377,\0,char) - */ - parrpt = 0x04 ; - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0)); - } else { - parrpt = 0x03; - } - } - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt)); - } - if (cflag & CLOCAL) { - // Status reporting fails for DCD if this is off - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP); - pCh->flags &= ~ASYNC_CHECK_CD; - } else { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP); - pCh->flags |= ASYNC_CHECK_CD; - } - -service_it: - i2DrainOutput( pCh, 100 ); -} - -/******************************************************************************/ -/* IPL Device Section */ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: ip2_ipl_read() */ -/* Parameters: Pointer to device inode */ -/* Pointer to file structure */ -/* Pointer to data */ -/* Number of bytes to read */ -/* Returns: Success or failure */ -/* */ -/* Description: Ugly */ -/* */ -/* */ -/******************************************************************************/ - -static -ssize_t -ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) -{ - unsigned int minor = iminor(pFile->f_path.dentry->d_inode); - int rc = 0; - -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count ); -#endif - - switch( minor ) { - case 0: // IPL device - rc = -EINVAL; - break; - case 1: // Status dump - rc = -EINVAL; - break; - case 2: // Ping device - rc = -EINVAL; - break; - case 3: // Trace device - rc = DumpTraceBuffer ( pData, count ); - break; - case 4: // Trace device - rc = DumpFifoBuffer ( pData, count ); - break; - default: - rc = -ENODEV; - break; - } - return rc; -} - -static int -DumpFifoBuffer ( char __user *pData, int count ) -{ -#ifdef DEBUG_FIFO - int rc; - rc = copy_to_user(pData, DBGBuf, count); - - printk(KERN_DEBUG "Last index %d\n", I ); - - return count; -#endif /* DEBUG_FIFO */ - return 0; -} - -static int -DumpTraceBuffer ( char __user *pData, int count ) -{ -#ifdef IP2DEBUG_TRACE - int rc; - int dumpcount; - int chunk; - int *pIndex = (int __user *)pData; - - if ( count < (sizeof(int) * 6) ) { - return -EIO; - } - rc = put_user(tracewrap, pIndex ); - rc = put_user(TRACEMAX, ++pIndex ); - rc = put_user(tracestrip, ++pIndex ); - rc = put_user(tracestuff, ++pIndex ); - pData += sizeof(int) * 6; - count -= sizeof(int) * 6; - - dumpcount = tracestuff - tracestrip; - if ( dumpcount < 0 ) { - dumpcount += TRACEMAX; - } - if ( dumpcount > count ) { - dumpcount = count; - } - chunk = TRACEMAX - tracestrip; - if ( dumpcount > chunk ) { - rc = copy_to_user(pData, &tracebuf[tracestrip], - chunk * sizeof(tracebuf[0]) ); - pData += chunk * sizeof(tracebuf[0]); - tracestrip = 0; - chunk = dumpcount - chunk; - } else { - chunk = dumpcount; - } - rc = copy_to_user(pData, &tracebuf[tracestrip], - chunk * sizeof(tracebuf[0]) ); - tracestrip += chunk; - tracewrap = 0; - - rc = put_user(tracestrip, ++pIndex ); - rc = put_user(tracestuff, ++pIndex ); - - return dumpcount; -#else - return 0; -#endif -} - -/******************************************************************************/ -/* Function: ip2_ipl_write() */ -/* Parameters: */ -/* Pointer to file structure */ -/* Pointer to data */ -/* Number of bytes to write */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static ssize_t -ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off) -{ -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count ); -#endif - return 0; -} - -/******************************************************************************/ -/* Function: ip2_ipl_ioctl() */ -/* Parameters: Pointer to device inode */ -/* Pointer to file structure */ -/* Command */ -/* Argument */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static long -ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) -{ - unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); - int rc = 0; - void __user *argp = (void __user *)arg; - ULONG __user *pIndex = argp; - i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4]; - i2ChanStrPtr pCh; - -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); -#endif - - mutex_lock(&ip2_mutex); - - switch ( iplminor ) { - case 0: // IPL device - rc = -EINVAL; - break; - case 1: // Status dump - case 5: - case 9: - case 13: - switch ( cmd ) { - case 64: /* Driver - ip2stat */ - rc = put_user(-1, pIndex++ ); - rc = put_user(irq_counter, pIndex++ ); - rc = put_user(bh_counter, pIndex++ ); - break; - - case 65: /* Board - ip2stat */ - if ( pB ) { - rc = copy_to_user(argp, pB, sizeof(i2eBordStr)); - rc = put_user(inb(pB->i2eStatus), - (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); - } else { - rc = -ENODEV; - } - break; - - default: - if (cmd < IP2_MAX_PORTS) { - pCh = DevTable[cmd]; - if ( pCh ) - { - rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); - if (rc) - rc = -EFAULT; - } else { - rc = -ENODEV; - } - } else { - rc = -EINVAL; - } - } - break; - - case 2: // Ping device - rc = -EINVAL; - break; - case 3: // Trace device - /* - * akpm: This used to write a whole bunch of function addresses - * to userspace, which generated lots of put_user() warnings. - * I killed it all. Just return "success" and don't do - * anything. - */ - if (cmd == 1) - rc = 0; - else - rc = -EINVAL; - break; - - default: - rc = -ENODEV; - break; - } - mutex_unlock(&ip2_mutex); - return rc; -} - -/******************************************************************************/ -/* Function: ip2_ipl_open() */ -/* Parameters: Pointer to device inode */ -/* Pointer to file structure */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_ipl_open( struct inode *pInode, struct file *pFile ) -{ - -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: open\n" ); -#endif - return 0; -} - -static int -proc_ip2mem_show(struct seq_file *m, void *v) -{ - i2eBordStrPtr pB; - i2ChanStrPtr pCh; - PTTY tty; - int i; - -#define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n" -#define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n" -#define FMTLIN3 " 0x%04x 0x%04x rc flow\n" - - seq_printf(m,"\n"); - - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - pB = i2BoardPtrTable[i]; - if ( pB ) { - seq_printf(m,"board %d:\n",i); - seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n", - pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting); - } - } - - seq_printf(m,"#: tty flags, port flags, cflags, iflags\n"); - for (i=0; i < IP2_MAX_PORTS; i++) { - pCh = DevTable[i]; - if (pCh) { - tty = pCh->pTTY; - if (tty && tty->count) { - seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags, - tty->termios->c_cflag,tty->termios->c_iflag); - - seq_printf(m,FMTLIN2, - pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds); - seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room); - } - } - } - return 0; -} - -static int proc_ip2mem_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_ip2mem_show, NULL); -} - -static const struct file_operations ip2mem_proc_fops = { - .owner = THIS_MODULE, - .open = proc_ip2mem_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * This is the handler for /proc/tty/driver/ip2 - * - * This stretch of code has been largely plagerized from at least three - * different sources including ip2mkdev.c and a couple of other drivers. - * The bugs are all mine. :-) =mhw= - */ -static int ip2_proc_show(struct seq_file *m, void *v) -{ - int i, j, box; - int boxes = 0; - int ports = 0; - int tports = 0; - i2eBordStrPtr pB; - char *sep; - - seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); - seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", - IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, - IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); - - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - /* This need to be reset for a board by board count... */ - boxes = 0; - pB = i2BoardPtrTable[i]; - if( pB ) { - switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) - { - case POR_ID_FIIEX: - seq_printf(m, "Board %d: EX ports=", i); - sep = ""; - for( box = 0; box < ABS_MAX_BOXES; ++box ) - { - ports = 0; - - if( pB->i2eChannelMap[box] != 0 ) ++boxes; - for( j = 0; j < ABS_BIGGEST_BOX; ++j ) - { - if( pB->i2eChannelMap[box] & 1<< j ) { - ++ports; - } - } - seq_printf(m, "%s%d", sep, ports); - sep = ","; - tports += ports; - } - seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); - break; - - case POR_ID_II_4: - seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); - tports = ports = 4; - break; - - case POR_ID_II_8: - seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); - tports = ports = 8; - break; - - case POR_ID_II_8R: - seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); - tports = ports = 8; - break; - - default: - seq_printf(m, "Board %d: unknown", i); - /* Don't try and probe for minor numbers */ - tports = ports = 0; - } - - } else { - /* Don't try and probe for minor numbers */ - seq_printf(m, "Board %d: vacant", i); - tports = ports = 0; - } - - if( tports ) { - seq_puts(m, " minors="); - sep = ""; - for ( box = 0; box < ABS_MAX_BOXES; ++box ) - { - for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) - { - if ( pB->i2eChannelMap[box] & (1 << j) ) - { - seq_printf(m, "%s%d", sep, - j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES)); - sep = ","; - } - } - } - } - seq_putc(m, '\n'); - } - return 0; - } - -static int ip2_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, ip2_proc_show, NULL); -} - -static const struct file_operations ip2_proc_fops = { - .owner = THIS_MODULE, - .open = ip2_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/******************************************************************************/ -/* Function: ip2trace() */ -/* Parameters: Value to add to trace buffer */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -#ifdef IP2DEBUG_TRACE -void -ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...) -{ - long flags; - unsigned long *pCode = &codes; - union ip2breadcrumb bc; - i2ChanStrPtr pCh; - - - tracebuf[tracestuff++] = jiffies; - if ( tracestuff == TRACEMAX ) { - tracestuff = 0; - } - if ( tracestuff == tracestrip ) { - if ( ++tracestrip == TRACEMAX ) { - tracestrip = 0; - } - ++tracewrap; - } - - bc.hdr.port = 0xff & pn; - bc.hdr.cat = cat; - bc.hdr.codes = (unsigned char)( codes & 0xff ); - bc.hdr.label = label; - tracebuf[tracestuff++] = bc.value; - - for (;;) { - if ( tracestuff == TRACEMAX ) { - tracestuff = 0; - } - if ( tracestuff == tracestrip ) { - if ( ++tracestrip == TRACEMAX ) { - tracestrip = 0; - } - ++tracewrap; - } - - if ( !codes-- ) - break; - - tracebuf[tracestuff++] = *++pCode; - } -} -#endif - - -MODULE_LICENSE("GPL"); - -static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = { - { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) }, - { } -}; - -MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); - -MODULE_FIRMWARE("intelliport2.bin"); diff --git a/drivers/char/ip2/ip2trace.h b/drivers/char/ip2/ip2trace.h deleted file mode 100644 index da20435dc8a6..000000000000 --- a/drivers/char/ip2/ip2trace.h +++ /dev/null @@ -1,42 +0,0 @@ - -// -union ip2breadcrumb -{ - struct { - unsigned char port, cat, codes, label; - } __attribute__ ((packed)) hdr; - unsigned long value; -}; - -#define ITRC_NO_PORT 0xFF -#define CHANN (pCh->port_index) - -#define ITRC_ERROR '!' -#define ITRC_INIT 'A' -#define ITRC_OPEN 'B' -#define ITRC_CLOSE 'C' -#define ITRC_DRAIN 'D' -#define ITRC_IOCTL 'E' -#define ITRC_FLUSH 'F' -#define ITRC_STATUS 'G' -#define ITRC_HANGUP 'H' -#define ITRC_INTR 'I' -#define ITRC_SFLOW 'J' -#define ITRC_SBCMD 'K' -#define ITRC_SICMD 'L' -#define ITRC_MODEM 'M' -#define ITRC_INPUT 'N' -#define ITRC_OUTPUT 'O' -#define ITRC_PUTC 'P' -#define ITRC_QUEUE 'Q' -#define ITRC_STFLW 'R' -#define ITRC_SFIFO 'S' -#define ITRC_VERIFY 'V' -#define ITRC_WRITE 'W' - -#define ITRC_ENTER 0x00 -#define ITRC_RETURN 0xFF - -#define ITRC_QUEUE_ROOM 2 -#define ITRC_QUEUE_CMD 6 - diff --git a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h deleted file mode 100644 index 9d67b260b2f6..000000000000 --- a/drivers/char/ip2/ip2types.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* -* -* (c) 1998 by Computone Corporation -* -******************************************************************************** -* -* -* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Driver constants and type definitions. -* -* NOTES: -* -*******************************************************************************/ -#ifndef IP2TYPES_H -#define IP2TYPES_H - -//************* -//* Constants * -//************* - -// Define some limits for this driver. Ports per board is a hardware limitation -// that will not change. Current hardware limits this to 64 ports per board. -// Boards per driver is a self-imposed limit. -// -#define IP2_MAX_BOARDS 4 -#define IP2_PORTS_PER_BOARD ABS_MOST_PORTS -#define IP2_MAX_PORTS (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD) - -#define ISA 0 -#define PCI 1 -#define EISA 2 - -//******************** -//* Type Definitions * -//******************** - -typedef struct tty_struct * PTTY; -typedef wait_queue_head_t PWAITQ; - -typedef unsigned char UCHAR; -typedef unsigned int UINT; -typedef unsigned short USHORT; -typedef unsigned long ULONG; - -typedef struct -{ - short irq[IP2_MAX_BOARDS]; - unsigned short addr[IP2_MAX_BOARDS]; - int type[IP2_MAX_BOARDS]; -#ifdef CONFIG_PCI - struct pci_dev *pci_dev[IP2_MAX_BOARDS]; -#endif -} ip2config_t; - -#endif diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c deleted file mode 100644 index 0b266272cccd..000000000000 --- a/drivers/char/istallion.c +++ /dev/null @@ -1,4507 +0,0 @@ -/*****************************************************************************/ - -/* - * istallion.c -- stallion intelligent multiport serial driver. - * - * Copyright (C) 1996-1999 Stallion Technologies - * Copyright (C) 1994-1996 Greg Ungerer. - * - * This code is loosely based on the Linux serial driver, written by - * Linus Torvalds, Theodore T'so and others. - * - * 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. - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -/*****************************************************************************/ - -/* - * Define different board types. Not all of the following board types - * are supported by this driver. But I will use the standard "assigned" - * board numbers. Currently supported boards are abbreviated as: - * ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and - * STAL = Stallion. - */ -#define BRD_UNKNOWN 0 -#define BRD_STALLION 1 -#define BRD_BRUMBY4 2 -#define BRD_ONBOARD2 3 -#define BRD_ONBOARD 4 -#define BRD_ONBOARDE 7 -#define BRD_ECP 23 -#define BRD_ECPE 24 -#define BRD_ECPMC 25 -#define BRD_ECPPCI 29 - -#define BRD_BRUMBY BRD_BRUMBY4 - -/* - * Define a configuration structure to hold the board configuration. - * Need to set this up in the code (for now) with the boards that are - * to be configured into the system. This is what needs to be modified - * when adding/removing/modifying boards. Each line entry in the - * stli_brdconf[] array is a board. Each line contains io/irq/memory - * ranges for that board (as well as what type of board it is). - * Some examples: - * { BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 }, - * This line will configure an EasyConnection 8/64 at io address 2a0, - * and shared memory address of cc000. Multiple EasyConnection 8/64 - * boards can share the same shared memory address space. No interrupt - * is required for this board type. - * Another example: - * { BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 }, - * This line will configure an EasyConnection 8/64 EISA in slot 5 and - * shared memory address of 0x80000000 (2 GByte). Multiple - * EasyConnection 8/64 EISA boards can share the same shared memory - * address space. No interrupt is required for this board type. - * Another example: - * { BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 }, - * This line will configure an ONboard (ISA type) at io address 240, - * and shared memory address of d0000. Multiple ONboards can share - * the same shared memory address space. No interrupt required. - * Another example: - * { BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 }, - * This line will configure a Brumby board (any number of ports!) at - * io address 360 and shared memory address of c8000. All Brumby boards - * configured into a system must have their own separate io and memory - * addresses. No interrupt is required. - * Another example: - * { BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 }, - * This line will configure an original Stallion board at io address 330 - * and shared memory address d0000 (this would only be valid for a "V4.0" - * or Rev.O Stallion board). All Stallion boards configured into the - * system must have their own separate io and memory addresses. No - * interrupt is required. - */ - -struct stlconf { - int brdtype; - int ioaddr1; - int ioaddr2; - unsigned long memaddr; - int irq; - int irqtype; -}; - -static unsigned int stli_nrbrds; - -/* stli_lock must NOT be taken holding brd_lock */ -static spinlock_t stli_lock; /* TTY logic lock */ -static spinlock_t brd_lock; /* Board logic lock */ - -/* - * There is some experimental EISA board detection code in this driver. - * By default it is disabled, but for those that want to try it out, - * then set the define below to be 1. - */ -#define STLI_EISAPROBE 0 - -/*****************************************************************************/ - -/* - * Define some important driver characteristics. Device major numbers - * allocated as per Linux Device Registry. - */ -#ifndef STL_SIOMEMMAJOR -#define STL_SIOMEMMAJOR 28 -#endif -#ifndef STL_SERIALMAJOR -#define STL_SERIALMAJOR 24 -#endif -#ifndef STL_CALLOUTMAJOR -#define STL_CALLOUTMAJOR 25 -#endif - -/*****************************************************************************/ - -/* - * Define our local driver identity first. Set up stuff to deal with - * all the local structures required by a serial tty driver. - */ -static char *stli_drvtitle = "Stallion Intelligent Multiport Serial Driver"; -static char *stli_drvname = "istallion"; -static char *stli_drvversion = "5.6.0"; -static char *stli_serialname = "ttyE"; - -static struct tty_driver *stli_serial; -static const struct tty_port_operations stli_port_ops; - -#define STLI_TXBUFSIZE 4096 - -/* - * Use a fast local buffer for cooked characters. Typically a whole - * bunch of cooked characters come in for a port, 1 at a time. So we - * save those up into a local buffer, then write out the whole lot - * with a large memcpy. Just use 1 buffer for all ports, since its - * use it is only need for short periods of time by each port. - */ -static char *stli_txcookbuf; -static int stli_txcooksize; -static int stli_txcookrealsize; -static struct tty_struct *stli_txcooktty; - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. Basically all it defines is a raw port - * at 9600 baud, 8 data bits, no parity, 1 stop bit. - */ -static struct ktermios stli_deftermios = { - .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), - .c_cc = INIT_C_CC, - .c_ispeed = 9600, - .c_ospeed = 9600, -}; - -/* - * Define global stats structures. Not used often, and can be - * re-used for each stats call. - */ -static comstats_t stli_comstats; -static combrd_t stli_brdstats; -static struct asystats stli_cdkstats; - -/*****************************************************************************/ - -static DEFINE_MUTEX(stli_brdslock); -static struct stlibrd *stli_brds[STL_MAXBRDS]; - -static int stli_shared; - -/* - * Per board state flags. Used with the state field of the board struct. - * Not really much here... All we need to do is keep track of whether - * the board has been detected, and whether it is actually running a slave - * or not. - */ -#define BST_FOUND 0 -#define BST_STARTED 1 -#define BST_PROBED 2 - -/* - * Define the set of port state flags. These are marked for internal - * state purposes only, usually to do with the state of communications - * with the slave. Most of them need to be updated atomically, so always - * use the bit setting operations (unless protected by cli/sti). - */ -#define ST_OPENING 2 -#define ST_CLOSING 3 -#define ST_CMDING 4 -#define ST_TXBUSY 5 -#define ST_RXING 6 -#define ST_DOFLUSHRX 7 -#define ST_DOFLUSHTX 8 -#define ST_DOSIGS 9 -#define ST_RXSTOP 10 -#define ST_GETSIGS 11 - -/* - * Define an array of board names as printable strings. Handy for - * referencing boards when printing trace and stuff. - */ -static char *stli_brdnames[] = { - "Unknown", - "Stallion", - "Brumby", - "ONboard-MC", - "ONboard", - "Brumby", - "Brumby", - "ONboard-EI", - NULL, - "ONboard", - "ONboard-MC", - "ONboard-MC", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "EasyIO", - "EC8/32-AT", - "EC8/32-MC", - "EC8/64-AT", - "EC8/64-EI", - "EC8/64-MC", - "EC8/32-PCI", - "EC8/64-PCI", - "EasyIO-PCI", - "EC/RA-PCI", -}; - -/*****************************************************************************/ - -/* - * Define some string labels for arguments passed from the module - * load line. These allow for easy board definitions, and easy - * modification of the io, memory and irq resoucres. - */ - -static char *board0[8]; -static char *board1[8]; -static char *board2[8]; -static char *board3[8]; - -static char **stli_brdsp[] = { - (char **) &board0, - (char **) &board1, - (char **) &board2, - (char **) &board3 -}; - -/* - * Define a set of common board names, and types. This is used to - * parse any module arguments. - */ - -static struct stlibrdtype { - char *name; - int type; -} stli_brdstr[] = { - { "stallion", BRD_STALLION }, - { "1", BRD_STALLION }, - { "brumby", BRD_BRUMBY }, - { "brumby4", BRD_BRUMBY }, - { "brumby/4", BRD_BRUMBY }, - { "brumby-4", BRD_BRUMBY }, - { "brumby8", BRD_BRUMBY }, - { "brumby/8", BRD_BRUMBY }, - { "brumby-8", BRD_BRUMBY }, - { "brumby16", BRD_BRUMBY }, - { "brumby/16", BRD_BRUMBY }, - { "brumby-16", BRD_BRUMBY }, - { "2", BRD_BRUMBY }, - { "onboard2", BRD_ONBOARD2 }, - { "onboard-2", BRD_ONBOARD2 }, - { "onboard/2", BRD_ONBOARD2 }, - { "onboard-mc", BRD_ONBOARD2 }, - { "onboard/mc", BRD_ONBOARD2 }, - { "onboard-mca", BRD_ONBOARD2 }, - { "onboard/mca", BRD_ONBOARD2 }, - { "3", BRD_ONBOARD2 }, - { "onboard", BRD_ONBOARD }, - { "onboardat", BRD_ONBOARD }, - { "4", BRD_ONBOARD }, - { "onboarde", BRD_ONBOARDE }, - { "onboard-e", BRD_ONBOARDE }, - { "onboard/e", BRD_ONBOARDE }, - { "onboard-ei", BRD_ONBOARDE }, - { "onboard/ei", BRD_ONBOARDE }, - { "7", BRD_ONBOARDE }, - { "ecp", BRD_ECP }, - { "ecpat", BRD_ECP }, - { "ec8/64", BRD_ECP }, - { "ec8/64-at", BRD_ECP }, - { "ec8/64-isa", BRD_ECP }, - { "23", BRD_ECP }, - { "ecpe", BRD_ECPE }, - { "ecpei", BRD_ECPE }, - { "ec8/64-e", BRD_ECPE }, - { "ec8/64-ei", BRD_ECPE }, - { "24", BRD_ECPE }, - { "ecpmc", BRD_ECPMC }, - { "ec8/64-mc", BRD_ECPMC }, - { "ec8/64-mca", BRD_ECPMC }, - { "25", BRD_ECPMC }, - { "ecppci", BRD_ECPPCI }, - { "ec/ra", BRD_ECPPCI }, - { "ec/ra-pc", BRD_ECPPCI }, - { "ec/ra-pci", BRD_ECPPCI }, - { "29", BRD_ECPPCI }, -}; - -/* - * Define the module agruments. - */ -MODULE_AUTHOR("Greg Ungerer"); -MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver"); -MODULE_LICENSE("GPL"); - - -module_param_array(board0, charp, NULL, 0); -MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]"); -module_param_array(board1, charp, NULL, 0); -MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]"); -module_param_array(board2, charp, NULL, 0); -MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); -module_param_array(board3, charp, NULL, 0); -MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); - -#if STLI_EISAPROBE != 0 -/* - * Set up a default memory address table for EISA board probing. - * The default addresses are all bellow 1Mbyte, which has to be the - * case anyway. They should be safe, since we only read values from - * them, and interrupts are disabled while we do it. If the higher - * memory support is compiled in then we also try probing around - * the 1Gb, 2Gb and 3Gb areas as well... - */ -static unsigned long stli_eisamemprobeaddrs[] = { - 0xc0000, 0xd0000, 0xe0000, 0xf0000, - 0x80000000, 0x80010000, 0x80020000, 0x80030000, - 0x40000000, 0x40010000, 0x40020000, 0x40030000, - 0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000, - 0xff000000, 0xff010000, 0xff020000, 0xff030000, -}; - -static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs); -#endif - -/* - * Define the Stallion PCI vendor and device IDs. - */ -#ifndef PCI_DEVICE_ID_ECRA -#define PCI_DEVICE_ID_ECRA 0x0004 -#endif - -static struct pci_device_id istallion_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); - -static struct pci_driver stli_pcidriver; - -/*****************************************************************************/ - -/* - * Hardware configuration info for ECP boards. These defines apply - * to the directly accessible io ports of the ECP. There is a set of - * defines for each ECP board type, ISA, EISA, MCA and PCI. - */ -#define ECP_IOSIZE 4 - -#define ECP_MEMSIZE (128 * 1024) -#define ECP_PCIMEMSIZE (256 * 1024) - -#define ECP_ATPAGESIZE (4 * 1024) -#define ECP_MCPAGESIZE (4 * 1024) -#define ECP_EIPAGESIZE (64 * 1024) -#define ECP_PCIPAGESIZE (64 * 1024) - -#define STL_EISAID 0x8c4e - -/* - * Important defines for the ISA class of ECP board. - */ -#define ECP_ATIREG 0 -#define ECP_ATCONFR 1 -#define ECP_ATMEMAR 2 -#define ECP_ATMEMPR 3 -#define ECP_ATSTOP 0x1 -#define ECP_ATINTENAB 0x10 -#define ECP_ATENABLE 0x20 -#define ECP_ATDISABLE 0x00 -#define ECP_ATADDRMASK 0x3f000 -#define ECP_ATADDRSHFT 12 - -/* - * Important defines for the EISA class of ECP board. - */ -#define ECP_EIIREG 0 -#define ECP_EIMEMARL 1 -#define ECP_EICONFR 2 -#define ECP_EIMEMARH 3 -#define ECP_EIENABLE 0x1 -#define ECP_EIDISABLE 0x0 -#define ECP_EISTOP 0x4 -#define ECP_EIEDGE 0x00 -#define ECP_EILEVEL 0x80 -#define ECP_EIADDRMASKL 0x00ff0000 -#define ECP_EIADDRSHFTL 16 -#define ECP_EIADDRMASKH 0xff000000 -#define ECP_EIADDRSHFTH 24 -#define ECP_EIBRDENAB 0xc84 - -#define ECP_EISAID 0x4 - -/* - * Important defines for the Micro-channel class of ECP board. - * (It has a lot in common with the ISA boards.) - */ -#define ECP_MCIREG 0 -#define ECP_MCCONFR 1 -#define ECP_MCSTOP 0x20 -#define ECP_MCENABLE 0x80 -#define ECP_MCDISABLE 0x00 - -/* - * Important defines for the PCI class of ECP board. - * (It has a lot in common with the other ECP boards.) - */ -#define ECP_PCIIREG 0 -#define ECP_PCICONFR 1 -#define ECP_PCISTOP 0x01 - -/* - * Hardware configuration info for ONboard and Brumby boards. These - * defines apply to the directly accessible io ports of these boards. - */ -#define ONB_IOSIZE 16 -#define ONB_MEMSIZE (64 * 1024) -#define ONB_ATPAGESIZE (64 * 1024) -#define ONB_MCPAGESIZE (64 * 1024) -#define ONB_EIMEMSIZE (128 * 1024) -#define ONB_EIPAGESIZE (64 * 1024) - -/* - * Important defines for the ISA class of ONboard board. - */ -#define ONB_ATIREG 0 -#define ONB_ATMEMAR 1 -#define ONB_ATCONFR 2 -#define ONB_ATSTOP 0x4 -#define ONB_ATENABLE 0x01 -#define ONB_ATDISABLE 0x00 -#define ONB_ATADDRMASK 0xff0000 -#define ONB_ATADDRSHFT 16 - -#define ONB_MEMENABLO 0 -#define ONB_MEMENABHI 0x02 - -/* - * Important defines for the EISA class of ONboard board. - */ -#define ONB_EIIREG 0 -#define ONB_EIMEMARL 1 -#define ONB_EICONFR 2 -#define ONB_EIMEMARH 3 -#define ONB_EIENABLE 0x1 -#define ONB_EIDISABLE 0x0 -#define ONB_EISTOP 0x4 -#define ONB_EIEDGE 0x00 -#define ONB_EILEVEL 0x80 -#define ONB_EIADDRMASKL 0x00ff0000 -#define ONB_EIADDRSHFTL 16 -#define ONB_EIADDRMASKH 0xff000000 -#define ONB_EIADDRSHFTH 24 -#define ONB_EIBRDENAB 0xc84 - -#define ONB_EISAID 0x1 - -/* - * Important defines for the Brumby boards. They are pretty simple, - * there is not much that is programmably configurable. - */ -#define BBY_IOSIZE 16 -#define BBY_MEMSIZE (64 * 1024) -#define BBY_PAGESIZE (16 * 1024) - -#define BBY_ATIREG 0 -#define BBY_ATCONFR 1 -#define BBY_ATSTOP 0x4 - -/* - * Important defines for the Stallion boards. They are pretty simple, - * there is not much that is programmably configurable. - */ -#define STAL_IOSIZE 16 -#define STAL_MEMSIZE (64 * 1024) -#define STAL_PAGESIZE (64 * 1024) - -/* - * Define the set of status register values for EasyConnection panels. - * The signature will return with the status value for each panel. From - * this we can determine what is attached to the board - before we have - * actually down loaded any code to it. - */ -#define ECH_PNLSTATUS 2 -#define ECH_PNL16PORT 0x20 -#define ECH_PNLIDMASK 0x07 -#define ECH_PNLXPID 0x40 -#define ECH_PNLINTRPEND 0x80 - -/* - * Define some macros to do things to the board. Even those these boards - * are somewhat related there is often significantly different ways of - * doing some operation on it (like enable, paging, reset, etc). So each - * board class has a set of functions which do the commonly required - * operations. The macros below basically just call these functions, - * generally checking for a NULL function - which means that the board - * needs nothing done to it to achieve this operation! - */ -#define EBRDINIT(brdp) \ - if (brdp->init != NULL) \ - (* brdp->init)(brdp) - -#define EBRDENABLE(brdp) \ - if (brdp->enable != NULL) \ - (* brdp->enable)(brdp); - -#define EBRDDISABLE(brdp) \ - if (brdp->disable != NULL) \ - (* brdp->disable)(brdp); - -#define EBRDINTR(brdp) \ - if (brdp->intr != NULL) \ - (* brdp->intr)(brdp); - -#define EBRDRESET(brdp) \ - if (brdp->reset != NULL) \ - (* brdp->reset)(brdp); - -#define EBRDGETMEMPTR(brdp,offset) \ - (* brdp->getmemptr)(brdp, offset, __LINE__) - -/* - * Define the maximal baud rate, and the default baud base for ports. - */ -#define STL_MAXBAUD 460800 -#define STL_BAUDBASE 115200 -#define STL_CLOSEDELAY (5 * HZ / 10) - -/*****************************************************************************/ - -/* - * Define macros to extract a brd or port number from a minor number. - */ -#define MINOR2BRD(min) (((min) & 0xc0) >> 6) -#define MINOR2PORT(min) ((min) & 0x3f) - -/*****************************************************************************/ - -/* - * Prototype all functions in this driver! - */ - -static int stli_parsebrd(struct stlconf *confp, char **argp); -static int stli_open(struct tty_struct *tty, struct file *filp); -static void stli_close(struct tty_struct *tty, struct file *filp); -static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); -static int stli_putchar(struct tty_struct *tty, unsigned char ch); -static void stli_flushchars(struct tty_struct *tty); -static int stli_writeroom(struct tty_struct *tty); -static int stli_charsinbuffer(struct tty_struct *tty); -static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static void stli_settermios(struct tty_struct *tty, struct ktermios *old); -static void stli_throttle(struct tty_struct *tty); -static void stli_unthrottle(struct tty_struct *tty); -static void stli_stop(struct tty_struct *tty); -static void stli_start(struct tty_struct *tty); -static void stli_flushbuffer(struct tty_struct *tty); -static int stli_breakctl(struct tty_struct *tty, int state); -static void stli_waituntilsent(struct tty_struct *tty, int timeout); -static void stli_sendxchar(struct tty_struct *tty, char ch); -static void stli_hangup(struct tty_struct *tty); - -static int stli_brdinit(struct stlibrd *brdp); -static int stli_startbrd(struct stlibrd *brdp); -static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); -static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); -static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); -static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); -static void stli_poll(unsigned long arg); -static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); -static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); -static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); -static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); -static int stli_setport(struct tty_struct *tty); -static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); -static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); -static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); -static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); -static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); -static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); -static long stli_mktiocm(unsigned long sigvalue); -static void stli_read(struct stlibrd *brdp, struct stliport *portp); -static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); -static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp); -static int stli_getbrdstats(combrd_t __user *bp); -static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp); -static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp); -static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); -static int stli_getportstruct(struct stliport __user *arg); -static int stli_getbrdstruct(struct stlibrd __user *arg); -static struct stlibrd *stli_allocbrd(void); - -static void stli_ecpinit(struct stlibrd *brdp); -static void stli_ecpenable(struct stlibrd *brdp); -static void stli_ecpdisable(struct stlibrd *brdp); -static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_ecpreset(struct stlibrd *brdp); -static void stli_ecpintr(struct stlibrd *brdp); -static void stli_ecpeiinit(struct stlibrd *brdp); -static void stli_ecpeienable(struct stlibrd *brdp); -static void stli_ecpeidisable(struct stlibrd *brdp); -static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_ecpeireset(struct stlibrd *brdp); -static void stli_ecpmcenable(struct stlibrd *brdp); -static void stli_ecpmcdisable(struct stlibrd *brdp); -static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_ecpmcreset(struct stlibrd *brdp); -static void stli_ecppciinit(struct stlibrd *brdp); -static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_ecppcireset(struct stlibrd *brdp); - -static void stli_onbinit(struct stlibrd *brdp); -static void stli_onbenable(struct stlibrd *brdp); -static void stli_onbdisable(struct stlibrd *brdp); -static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_onbreset(struct stlibrd *brdp); -static void stli_onbeinit(struct stlibrd *brdp); -static void stli_onbeenable(struct stlibrd *brdp); -static void stli_onbedisable(struct stlibrd *brdp); -static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_onbereset(struct stlibrd *brdp); -static void stli_bbyinit(struct stlibrd *brdp); -static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_bbyreset(struct stlibrd *brdp); -static void stli_stalinit(struct stlibrd *brdp); -static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); -static void stli_stalreset(struct stlibrd *brdp); - -static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr); - -static int stli_initecp(struct stlibrd *brdp); -static int stli_initonb(struct stlibrd *brdp); -#if STLI_EISAPROBE != 0 -static int stli_eisamemprobe(struct stlibrd *brdp); -#endif -static int stli_initports(struct stlibrd *brdp); - -/*****************************************************************************/ - -/* - * Define the driver info for a user level shared memory device. This - * device will work sort of like the /dev/kmem device - except that it - * will give access to the shared memory on the Stallion intelligent - * board. This is also a very useful debugging tool. - */ -static const struct file_operations stli_fsiomem = { - .owner = THIS_MODULE, - .read = stli_memread, - .write = stli_memwrite, - .unlocked_ioctl = stli_memioctl, - .llseek = default_llseek, -}; - -/*****************************************************************************/ - -/* - * Define a timer_list entry for our poll routine. The slave board - * is polled every so often to see if anything needs doing. This is - * much cheaper on host cpu than using interrupts. It turns out to - * not increase character latency by much either... - */ -static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0); - -static int stli_timeron; - -/* - * Define the calculation for the timeout routine. - */ -#define STLI_TIMEOUT (jiffies + 1) - -/*****************************************************************************/ - -static struct class *istallion_class; - -static void stli_cleanup_ports(struct stlibrd *brdp) -{ - struct stliport *portp; - unsigned int j; - struct tty_struct *tty; - - for (j = 0; j < STL_MAXPORTS; j++) { - portp = brdp->ports[j]; - if (portp != NULL) { - tty = tty_port_tty_get(&portp->port); - if (tty != NULL) { - tty_hangup(tty); - tty_kref_put(tty); - } - kfree(portp); - } - } -} - -/*****************************************************************************/ - -/* - * Parse the supplied argument string, into the board conf struct. - */ - -static int stli_parsebrd(struct stlconf *confp, char **argp) -{ - unsigned int i; - char *sp; - - if (argp[0] == NULL || *argp[0] == 0) - return 0; - - for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) - *sp = tolower(*sp); - - for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) { - if (strcmp(stli_brdstr[i].name, argp[0]) == 0) - break; - } - if (i == ARRAY_SIZE(stli_brdstr)) { - printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]); - return 0; - } - - confp->brdtype = stli_brdstr[i].type; - if (argp[1] != NULL && *argp[1] != 0) - confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0); - if (argp[2] != NULL && *argp[2] != 0) - confp->memaddr = simple_strtoul(argp[2], NULL, 0); - return(1); -} - -/*****************************************************************************/ - -/* - * On the first open of the device setup the port hardware, and - * initialize the per port data structure. Since initializing the port - * requires several commands to the board we will need to wait for any - * other open that is already initializing the port. - * - * Locking: protected by the port mutex. - */ - -static int stli_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct stliport *portp = container_of(port, struct stliport, port); - struct stlibrd *brdp = stli_brds[portp->brdnr]; - int rc; - - if ((rc = stli_initopen(tty, brdp, portp)) >= 0) - clear_bit(TTY_IO_ERROR, &tty->flags); - wake_up_interruptible(&portp->raw_wait); - return rc; -} - -static int stli_open(struct tty_struct *tty, struct file *filp) -{ - struct stlibrd *brdp; - struct stliport *portp; - unsigned int minordev, brdnr, portnr; - - minordev = tty->index; - brdnr = MINOR2BRD(minordev); - if (brdnr >= stli_nrbrds) - return -ENODEV; - brdp = stli_brds[brdnr]; - if (brdp == NULL) - return -ENODEV; - if (!test_bit(BST_STARTED, &brdp->state)) - return -ENODEV; - portnr = MINOR2PORT(minordev); - if (portnr > brdp->nrports) - return -ENODEV; - - portp = brdp->ports[portnr]; - if (portp == NULL) - return -ENODEV; - if (portp->devnr < 1) - return -ENODEV; - - tty->driver_data = portp; - return tty_port_open(&portp->port, tty, filp); -} - - -/*****************************************************************************/ - -static void stli_shutdown(struct tty_port *port) -{ - struct stlibrd *brdp; - unsigned long ftype; - unsigned long flags; - struct stliport *portp = container_of(port, struct stliport, port); - - if (portp->brdnr >= stli_nrbrds) - return; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return; - - /* - * May want to wait for data to drain before closing. The BUSY - * flag keeps track of whether we are still transmitting or not. - * It is updated by messages from the slave - indicating when all - * chars really have drained. - */ - - if (!test_bit(ST_CLOSING, &portp->state)) - stli_rawclose(brdp, portp, 0, 0); - - spin_lock_irqsave(&stli_lock, flags); - clear_bit(ST_TXBUSY, &portp->state); - clear_bit(ST_RXSTOP, &portp->state); - spin_unlock_irqrestore(&stli_lock, flags); - - ftype = FLUSHTX | FLUSHRX; - stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); -} - -static void stli_close(struct tty_struct *tty, struct file *filp) -{ - struct stliport *portp = tty->driver_data; - unsigned long flags; - if (portp == NULL) - return; - spin_lock_irqsave(&stli_lock, flags); - /* Flush any internal buffering out first */ - if (tty == stli_txcooktty) - stli_flushchars(tty); - spin_unlock_irqrestore(&stli_lock, flags); - tty_port_close(&portp->port, tty, filp); -} - -/*****************************************************************************/ - -/* - * Carry out first open operations on a port. This involves a number of - * commands to be sent to the slave. We need to open the port, set the - * notification events, set the initial port settings, get and set the - * initial signal values. We sleep and wait in between each one. But - * this still all happens pretty quickly. - */ - -static int stli_initopen(struct tty_struct *tty, - struct stlibrd *brdp, struct stliport *portp) -{ - asynotify_t nt; - asyport_t aport; - int rc; - - if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0) - return rc; - - memset(&nt, 0, sizeof(asynotify_t)); - nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK); - nt.signal = SG_DCD; - if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt, - sizeof(asynotify_t), 0)) < 0) - return rc; - - stli_mkasyport(tty, portp, &aport, tty->termios); - if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, - sizeof(asyport_t), 0)) < 0) - return rc; - - set_bit(ST_GETSIGS, &portp->state); - if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig, - sizeof(asysigs_t), 1)) < 0) - return rc; - if (test_and_clear_bit(ST_GETSIGS, &portp->state)) - portp->sigs = stli_mktiocm(portp->asig.sigvalue); - stli_mkasysigs(&portp->asig, 1, 1); - if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, - sizeof(asysigs_t), 0)) < 0) - return rc; - - return 0; -} - -/*****************************************************************************/ - -/* - * Send an open message to the slave. This will sleep waiting for the - * acknowledgement, so must have user context. We need to co-ordinate - * with close events here, since we don't want open and close events - * to overlap. - */ - -static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) -{ - cdkhdr_t __iomem *hdrp; - cdkctrl_t __iomem *cp; - unsigned char __iomem *bits; - unsigned long flags; - int rc; - -/* - * Send a message to the slave to open this port. - */ - -/* - * Slave is already closing this port. This can happen if a hangup - * occurs on this port. So we must wait until it is complete. The - * order of opens and closes may not be preserved across shared - * memory, so we must wait until it is complete. - */ - wait_event_interruptible_tty(portp->raw_wait, - !test_bit(ST_CLOSING, &portp->state)); - if (signal_pending(current)) { - return -ERESTARTSYS; - } - -/* - * Everything is ready now, so write the open message into shared - * memory. Once the message is in set the service bits to say that - * this port wants service. - */ - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; - writel(arg, &cp->openarg); - writeb(1, &cp->open); - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + - portp->portidx; - writeb(readb(bits) | portp->portbit, bits); - EBRDDISABLE(brdp); - - if (wait == 0) { - spin_unlock_irqrestore(&brd_lock, flags); - return 0; - } - -/* - * Slave is in action, so now we must wait for the open acknowledgment - * to come back. - */ - rc = 0; - set_bit(ST_OPENING, &portp->state); - spin_unlock_irqrestore(&brd_lock, flags); - - wait_event_interruptible_tty(portp->raw_wait, - !test_bit(ST_OPENING, &portp->state)); - if (signal_pending(current)) - rc = -ERESTARTSYS; - - if ((rc == 0) && (portp->rc != 0)) - rc = -EIO; - return rc; -} - -/*****************************************************************************/ - -/* - * Send a close message to the slave. Normally this will sleep waiting - * for the acknowledgement, but if wait parameter is 0 it will not. If - * wait is true then must have user context (to sleep). - */ - -static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) -{ - cdkhdr_t __iomem *hdrp; - cdkctrl_t __iomem *cp; - unsigned char __iomem *bits; - unsigned long flags; - int rc; - -/* - * Slave is already closing this port. This can happen if a hangup - * occurs on this port. - */ - if (wait) { - wait_event_interruptible_tty(portp->raw_wait, - !test_bit(ST_CLOSING, &portp->state)); - if (signal_pending(current)) { - return -ERESTARTSYS; - } - } - -/* - * Write the close command into shared memory. - */ - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; - writel(arg, &cp->closearg); - writeb(1, &cp->close); - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + - portp->portidx; - writeb(readb(bits) |portp->portbit, bits); - EBRDDISABLE(brdp); - - set_bit(ST_CLOSING, &portp->state); - spin_unlock_irqrestore(&brd_lock, flags); - - if (wait == 0) - return 0; - -/* - * Slave is in action, so now we must wait for the open acknowledgment - * to come back. - */ - rc = 0; - wait_event_interruptible_tty(portp->raw_wait, - !test_bit(ST_CLOSING, &portp->state)); - if (signal_pending(current)) - rc = -ERESTARTSYS; - - if ((rc == 0) && (portp->rc != 0)) - rc = -EIO; - return rc; -} - -/*****************************************************************************/ - -/* - * Send a command to the slave and wait for the response. This must - * have user context (it sleeps). This routine is generic in that it - * can send any type of command. Its purpose is to wait for that command - * to complete (as opposed to initiating the command then returning). - */ - -static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) -{ - /* - * no need for wait_event_tty because clearing ST_CMDING cannot block - * on BTM - */ - wait_event_interruptible(portp->raw_wait, - !test_bit(ST_CMDING, &portp->state)); - if (signal_pending(current)) - return -ERESTARTSYS; - - stli_sendcmd(brdp, portp, cmd, arg, size, copyback); - - wait_event_interruptible(portp->raw_wait, - !test_bit(ST_CMDING, &portp->state)); - if (signal_pending(current)) - return -ERESTARTSYS; - - if (portp->rc != 0) - return -EIO; - return 0; -} - -/*****************************************************************************/ - -/* - * Send the termios settings for this port to the slave. This sleeps - * waiting for the command to complete - so must have user context. - */ - -static int stli_setport(struct tty_struct *tty) -{ - struct stliport *portp = tty->driver_data; - struct stlibrd *brdp; - asyport_t aport; - - if (portp == NULL) - return -ENODEV; - if (portp->brdnr >= stli_nrbrds) - return -ENODEV; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return -ENODEV; - - stli_mkasyport(tty, portp, &aport, tty->termios); - return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0)); -} - -/*****************************************************************************/ - -static int stli_carrier_raised(struct tty_port *port) -{ - struct stliport *portp = container_of(port, struct stliport, port); - return (portp->sigs & TIOCM_CD) ? 1 : 0; -} - -static void stli_dtr_rts(struct tty_port *port, int on) -{ - struct stliport *portp = container_of(port, struct stliport, port); - struct stlibrd *brdp = stli_brds[portp->brdnr]; - stli_mkasysigs(&portp->asig, on, on); - if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, - sizeof(asysigs_t), 0) < 0) - printk(KERN_WARNING "istallion: dtr set failed.\n"); -} - - -/*****************************************************************************/ - -/* - * Write routine. Take the data and put it in the shared memory ring - * queue. If port is not already sending chars then need to mark the - * service bits for this port. - */ - -static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - cdkasy_t __iomem *ap; - cdkhdr_t __iomem *hdrp; - unsigned char __iomem *bits; - unsigned char __iomem *shbuf; - unsigned char *chbuf; - struct stliport *portp; - struct stlibrd *brdp; - unsigned int len, stlen, head, tail, size; - unsigned long flags; - - if (tty == stli_txcooktty) - stli_flushchars(tty); - portp = tty->driver_data; - if (portp == NULL) - return 0; - if (portp->brdnr >= stli_nrbrds) - return 0; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return 0; - chbuf = (unsigned char *) buf; - -/* - * All data is now local, shove as much as possible into shared memory. - */ - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); - head = (unsigned int) readw(&ap->txq.head); - tail = (unsigned int) readw(&ap->txq.tail); - if (tail != ((unsigned int) readw(&ap->txq.tail))) - tail = (unsigned int) readw(&ap->txq.tail); - size = portp->txsize; - if (head >= tail) { - len = size - (head - tail) - 1; - stlen = size - head; - } else { - len = tail - head - 1; - stlen = len; - } - - len = min(len, (unsigned int)count); - count = 0; - shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset); - - while (len > 0) { - stlen = min(len, stlen); - memcpy_toio(shbuf + head, chbuf, stlen); - chbuf += stlen; - len -= stlen; - count += stlen; - head += stlen; - if (head >= size) { - head = 0; - stlen = tail; - } - } - - ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); - writew(head, &ap->txq.head); - if (test_bit(ST_TXBUSY, &portp->state)) { - if (readl(&ap->changed.data) & DT_TXEMPTY) - writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data); - } - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + - portp->portidx; - writeb(readb(bits) | portp->portbit, bits); - set_bit(ST_TXBUSY, &portp->state); - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); - - return(count); -} - -/*****************************************************************************/ - -/* - * Output a single character. We put it into a temporary local buffer - * (for speed) then write out that buffer when the flushchars routine - * is called. There is a safety catch here so that if some other port - * writes chars before the current buffer has been, then we write them - * first them do the new ports. - */ - -static int stli_putchar(struct tty_struct *tty, unsigned char ch) -{ - if (tty != stli_txcooktty) { - if (stli_txcooktty != NULL) - stli_flushchars(stli_txcooktty); - stli_txcooktty = tty; - } - - stli_txcookbuf[stli_txcooksize++] = ch; - return 0; -} - -/*****************************************************************************/ - -/* - * Transfer characters from the local TX cooking buffer to the board. - * We sort of ignore the tty that gets passed in here. We rely on the - * info stored with the TX cook buffer to tell us which port to flush - * the data on. In any case we clean out the TX cook buffer, for re-use - * by someone else. - */ - -static void stli_flushchars(struct tty_struct *tty) -{ - cdkhdr_t __iomem *hdrp; - unsigned char __iomem *bits; - cdkasy_t __iomem *ap; - struct tty_struct *cooktty; - struct stliport *portp; - struct stlibrd *brdp; - unsigned int len, stlen, head, tail, size, count, cooksize; - unsigned char *buf; - unsigned char __iomem *shbuf; - unsigned long flags; - - cooksize = stli_txcooksize; - cooktty = stli_txcooktty; - stli_txcooksize = 0; - stli_txcookrealsize = 0; - stli_txcooktty = NULL; - - if (cooktty == NULL) - return; - if (tty != cooktty) - tty = cooktty; - if (cooksize == 0) - return; - - portp = tty->driver_data; - if (portp == NULL) - return; - if (portp->brdnr >= stli_nrbrds) - return; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - - ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); - head = (unsigned int) readw(&ap->txq.head); - tail = (unsigned int) readw(&ap->txq.tail); - if (tail != ((unsigned int) readw(&ap->txq.tail))) - tail = (unsigned int) readw(&ap->txq.tail); - size = portp->txsize; - if (head >= tail) { - len = size - (head - tail) - 1; - stlen = size - head; - } else { - len = tail - head - 1; - stlen = len; - } - - len = min(len, cooksize); - count = 0; - shbuf = EBRDGETMEMPTR(brdp, portp->txoffset); - buf = stli_txcookbuf; - - while (len > 0) { - stlen = min(len, stlen); - memcpy_toio(shbuf + head, buf, stlen); - buf += stlen; - len -= stlen; - count += stlen; - head += stlen; - if (head >= size) { - head = 0; - stlen = tail; - } - } - - ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); - writew(head, &ap->txq.head); - - if (test_bit(ST_TXBUSY, &portp->state)) { - if (readl(&ap->changed.data) & DT_TXEMPTY) - writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data); - } - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + - portp->portidx; - writeb(readb(bits) | portp->portbit, bits); - set_bit(ST_TXBUSY, &portp->state); - - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -static int stli_writeroom(struct tty_struct *tty) -{ - cdkasyrq_t __iomem *rp; - struct stliport *portp; - struct stlibrd *brdp; - unsigned int head, tail, len; - unsigned long flags; - - if (tty == stli_txcooktty) { - if (stli_txcookrealsize != 0) { - len = stli_txcookrealsize - stli_txcooksize; - return len; - } - } - - portp = tty->driver_data; - if (portp == NULL) - return 0; - if (portp->brdnr >= stli_nrbrds) - return 0; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return 0; - - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq; - head = (unsigned int) readw(&rp->head); - tail = (unsigned int) readw(&rp->tail); - if (tail != ((unsigned int) readw(&rp->tail))) - tail = (unsigned int) readw(&rp->tail); - len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head); - len--; - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); - - if (tty == stli_txcooktty) { - stli_txcookrealsize = len; - len -= stli_txcooksize; - } - return len; -} - -/*****************************************************************************/ - -/* - * Return the number of characters in the transmit buffer. Normally we - * will return the number of chars in the shared memory ring queue. - * We need to kludge around the case where the shared memory buffer is - * empty but not all characters have drained yet, for this case just - * return that there is 1 character in the buffer! - */ - -static int stli_charsinbuffer(struct tty_struct *tty) -{ - cdkasyrq_t __iomem *rp; - struct stliport *portp; - struct stlibrd *brdp; - unsigned int head, tail, len; - unsigned long flags; - - if (tty == stli_txcooktty) - stli_flushchars(tty); - portp = tty->driver_data; - if (portp == NULL) - return 0; - if (portp->brdnr >= stli_nrbrds) - return 0; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return 0; - - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq; - head = (unsigned int) readw(&rp->head); - tail = (unsigned int) readw(&rp->tail); - if (tail != ((unsigned int) readw(&rp->tail))) - tail = (unsigned int) readw(&rp->tail); - len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head)); - if ((len == 0) && test_bit(ST_TXBUSY, &portp->state)) - len = 1; - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); - - return len; -} - -/*****************************************************************************/ - -/* - * Generate the serial struct info. - */ - -static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp) -{ - struct serial_struct sio; - struct stlibrd *brdp; - - memset(&sio, 0, sizeof(struct serial_struct)); - sio.type = PORT_UNKNOWN; - sio.line = portp->portnr; - sio.irq = 0; - sio.flags = portp->port.flags; - sio.baud_base = portp->baud_base; - sio.close_delay = portp->port.close_delay; - sio.closing_wait = portp->closing_wait; - sio.custom_divisor = portp->custom_divisor; - sio.xmit_fifo_size = 0; - sio.hub6 = 0; - - brdp = stli_brds[portp->brdnr]; - if (brdp != NULL) - sio.port = brdp->iobase; - - return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? - -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Set port according to the serial struct info. - * At this point we do not do any auto-configure stuff, so we will - * just quietly ignore any requests to change irq, etc. - */ - -static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp) -{ - struct serial_struct sio; - int rc; - struct stliport *portp = tty->driver_data; - - if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) - return -EFAULT; - if (!capable(CAP_SYS_ADMIN)) { - if ((sio.baud_base != portp->baud_base) || - (sio.close_delay != portp->port.close_delay) || - ((sio.flags & ~ASYNC_USR_MASK) != - (portp->port.flags & ~ASYNC_USR_MASK))) - return -EPERM; - } - - portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | - (sio.flags & ASYNC_USR_MASK); - portp->baud_base = sio.baud_base; - portp->port.close_delay = sio.close_delay; - portp->closing_wait = sio.closing_wait; - portp->custom_divisor = sio.custom_divisor; - - if ((rc = stli_setport(tty)) < 0) - return rc; - return 0; -} - -/*****************************************************************************/ - -static int stli_tiocmget(struct tty_struct *tty) -{ - struct stliport *portp = tty->driver_data; - struct stlibrd *brdp; - int rc; - - if (portp == NULL) - return -ENODEV; - if (portp->brdnr >= stli_nrbrds) - return 0; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return 0; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, - &portp->asig, sizeof(asysigs_t), 1)) < 0) - return rc; - - return stli_mktiocm(portp->asig.sigvalue); -} - -static int stli_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct stliport *portp = tty->driver_data; - struct stlibrd *brdp; - int rts = -1, dtr = -1; - - if (portp == NULL) - return -ENODEV; - if (portp->brdnr >= stli_nrbrds) - return 0; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return 0; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - if (set & TIOCM_RTS) - rts = 1; - if (set & TIOCM_DTR) - dtr = 1; - if (clear & TIOCM_RTS) - rts = 0; - if (clear & TIOCM_DTR) - dtr = 0; - - stli_mkasysigs(&portp->asig, dtr, rts); - - return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, - sizeof(asysigs_t), 0); -} - -static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) -{ - struct stliport *portp; - struct stlibrd *brdp; - int rc; - void __user *argp = (void __user *)arg; - - portp = tty->driver_data; - if (portp == NULL) - return -ENODEV; - if (portp->brdnr >= stli_nrbrds) - return 0; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return 0; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - rc = 0; - - switch (cmd) { - case TIOCGSERIAL: - rc = stli_getserial(portp, argp); - break; - case TIOCSSERIAL: - rc = stli_setserial(tty, argp); - break; - case STL_GETPFLAG: - rc = put_user(portp->pflag, (unsigned __user *)argp); - break; - case STL_SETPFLAG: - if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0) - stli_setport(tty); - break; - case COM_GETPORTSTATS: - rc = stli_getportstats(tty, portp, argp); - break; - case COM_CLRPORTSTATS: - rc = stli_clrportstats(portp, argp); - break; - case TIOCSERCONFIG: - case TIOCSERGWILD: - case TIOCSERSWILD: - case TIOCSERGETLSR: - case TIOCSERGSTRUCT: - case TIOCSERGETMULTI: - case TIOCSERSETMULTI: - default: - rc = -ENOIOCTLCMD; - break; - } - - return rc; -} - -/*****************************************************************************/ - -/* - * This routine assumes that we have user context and can sleep. - * Looks like it is true for the current ttys implementation..!! - */ - -static void stli_settermios(struct tty_struct *tty, struct ktermios *old) -{ - struct stliport *portp; - struct stlibrd *brdp; - struct ktermios *tiosp; - asyport_t aport; - - portp = tty->driver_data; - if (portp == NULL) - return; - if (portp->brdnr >= stli_nrbrds) - return; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return; - - tiosp = tty->termios; - - stli_mkasyport(tty, portp, &aport, tiosp); - stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); - stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1); - stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, - sizeof(asysigs_t), 0); - if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) - tty->hw_stopped = 0; - if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) - wake_up_interruptible(&portp->port.open_wait); -} - -/*****************************************************************************/ - -/* - * Attempt to flow control who ever is sending us data. We won't really - * do any flow control action here. We can't directly, and even if we - * wanted to we would have to send a command to the slave. The slave - * knows how to flow control, and will do so when its buffers reach its - * internal high water marks. So what we will do is set a local state - * bit that will stop us sending any RX data up from the poll routine - * (which is the place where RX data from the slave is handled). - */ - -static void stli_throttle(struct tty_struct *tty) -{ - struct stliport *portp = tty->driver_data; - if (portp == NULL) - return; - set_bit(ST_RXSTOP, &portp->state); -} - -/*****************************************************************************/ - -/* - * Unflow control the device sending us data... That means that all - * we have to do is clear the RXSTOP state bit. The next poll call - * will then be able to pass the RX data back up. - */ - -static void stli_unthrottle(struct tty_struct *tty) -{ - struct stliport *portp = tty->driver_data; - if (portp == NULL) - return; - clear_bit(ST_RXSTOP, &portp->state); -} - -/*****************************************************************************/ - -/* - * Stop the transmitter. - */ - -static void stli_stop(struct tty_struct *tty) -{ -} - -/*****************************************************************************/ - -/* - * Start the transmitter again. - */ - -static void stli_start(struct tty_struct *tty) -{ -} - -/*****************************************************************************/ - - -/* - * Hangup this port. This is pretty much like closing the port, only - * a little more brutal. No waiting for data to drain. Shutdown the - * port and maybe drop signals. This is rather tricky really. We want - * to close the port as well. - */ - -static void stli_hangup(struct tty_struct *tty) -{ - struct stliport *portp = tty->driver_data; - tty_port_hangup(&portp->port); -} - -/*****************************************************************************/ - -/* - * Flush characters from the lower buffer. We may not have user context - * so we cannot sleep waiting for it to complete. Also we need to check - * if there is chars for this port in the TX cook buffer, and flush them - * as well. - */ - -static void stli_flushbuffer(struct tty_struct *tty) -{ - struct stliport *portp; - struct stlibrd *brdp; - unsigned long ftype, flags; - - portp = tty->driver_data; - if (portp == NULL) - return; - if (portp->brdnr >= stli_nrbrds) - return; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - if (tty == stli_txcooktty) { - stli_txcooktty = NULL; - stli_txcooksize = 0; - stli_txcookrealsize = 0; - } - if (test_bit(ST_CMDING, &portp->state)) { - set_bit(ST_DOFLUSHTX, &portp->state); - } else { - ftype = FLUSHTX; - if (test_bit(ST_DOFLUSHRX, &portp->state)) { - ftype |= FLUSHRX; - clear_bit(ST_DOFLUSHRX, &portp->state); - } - __stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); - } - spin_unlock_irqrestore(&brd_lock, flags); - tty_wakeup(tty); -} - -/*****************************************************************************/ - -static int stli_breakctl(struct tty_struct *tty, int state) -{ - struct stlibrd *brdp; - struct stliport *portp; - long arg; - - portp = tty->driver_data; - if (portp == NULL) - return -EINVAL; - if (portp->brdnr >= stli_nrbrds) - return -EINVAL; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return -EINVAL; - - arg = (state == -1) ? BREAKON : BREAKOFF; - stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); - return 0; -} - -/*****************************************************************************/ - -static void stli_waituntilsent(struct tty_struct *tty, int timeout) -{ - struct stliport *portp; - unsigned long tend; - - portp = tty->driver_data; - if (portp == NULL) - return; - - if (timeout == 0) - timeout = HZ; - tend = jiffies + timeout; - - while (test_bit(ST_TXBUSY, &portp->state)) { - if (signal_pending(current)) - break; - msleep_interruptible(20); - if (time_after_eq(jiffies, tend)) - break; - } -} - -/*****************************************************************************/ - -static void stli_sendxchar(struct tty_struct *tty, char ch) -{ - struct stlibrd *brdp; - struct stliport *portp; - asyctrl_t actrl; - - portp = tty->driver_data; - if (portp == NULL) - return; - if (portp->brdnr >= stli_nrbrds) - return; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return; - - memset(&actrl, 0, sizeof(asyctrl_t)); - if (ch == STOP_CHAR(tty)) { - actrl.rxctrl = CT_STOPFLOW; - } else if (ch == START_CHAR(tty)) { - actrl.rxctrl = CT_STARTFLOW; - } else { - actrl.txctrl = CT_SENDCHR; - actrl.tximdch = ch; - } - stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); -} - -static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr) -{ - char *uart; - int rc; - - rc = stli_portcmdstats(NULL, portp); - - uart = "UNKNOWN"; - if (test_bit(BST_STARTED, &brdp->state)) { - switch (stli_comstats.hwid) { - case 0: uart = "2681"; break; - case 1: uart = "SC26198"; break; - default:uart = "CD1400"; break; - } - } - seq_printf(m, "%d: uart:%s ", portnr, uart); - - if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) { - char sep; - - seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, - (int) stli_comstats.rxtotal); - - if (stli_comstats.rxframing) - seq_printf(m, " fe:%d", - (int) stli_comstats.rxframing); - if (stli_comstats.rxparity) - seq_printf(m, " pe:%d", - (int) stli_comstats.rxparity); - if (stli_comstats.rxbreaks) - seq_printf(m, " brk:%d", - (int) stli_comstats.rxbreaks); - if (stli_comstats.rxoverrun) - seq_printf(m, " oe:%d", - (int) stli_comstats.rxoverrun); - - sep = ' '; - if (stli_comstats.signals & TIOCM_RTS) { - seq_printf(m, "%c%s", sep, "RTS"); - sep = '|'; - } - if (stli_comstats.signals & TIOCM_CTS) { - seq_printf(m, "%c%s", sep, "CTS"); - sep = '|'; - } - if (stli_comstats.signals & TIOCM_DTR) { - seq_printf(m, "%c%s", sep, "DTR"); - sep = '|'; - } - if (stli_comstats.signals & TIOCM_CD) { - seq_printf(m, "%c%s", sep, "DCD"); - sep = '|'; - } - if (stli_comstats.signals & TIOCM_DSR) { - seq_printf(m, "%c%s", sep, "DSR"); - sep = '|'; - } - } - seq_putc(m, '\n'); -} - -/*****************************************************************************/ - -/* - * Port info, read from the /proc file system. - */ - -static int stli_proc_show(struct seq_file *m, void *v) -{ - struct stlibrd *brdp; - struct stliport *portp; - unsigned int brdnr, portnr, totalport; - - totalport = 0; - - seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion); - -/* - * We scan through for each board, panel and port. The offset is - * calculated on the fly, and irrelevant ports are skipped. - */ - for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) { - brdp = stli_brds[brdnr]; - if (brdp == NULL) - continue; - if (brdp->state == 0) - continue; - - totalport = brdnr * STL_MAXPORTS; - for (portnr = 0; (portnr < brdp->nrports); portnr++, - totalport++) { - portp = brdp->ports[portnr]; - if (portp == NULL) - continue; - stli_portinfo(m, brdp, portp, totalport); - } - } - return 0; -} - -static int stli_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, stli_proc_show, NULL); -} - -static const struct file_operations stli_proc_fops = { - .owner = THIS_MODULE, - .open = stli_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/*****************************************************************************/ - -/* - * Generic send command routine. This will send a message to the slave, - * of the specified type with the specified argument. Must be very - * careful of data that will be copied out from shared memory - - * containing command results. The command completion is all done from - * a poll routine that does not have user context. Therefore you cannot - * copy back directly into user space, or to the kernel stack of a - * process. This routine does not sleep, so can be called from anywhere. - * - * The caller must hold the brd_lock (see also stli_sendcmd the usual - * entry point) - */ - -static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) -{ - cdkhdr_t __iomem *hdrp; - cdkctrl_t __iomem *cp; - unsigned char __iomem *bits; - - if (test_bit(ST_CMDING, &portp->state)) { - printk(KERN_ERR "istallion: command already busy, cmd=%x!\n", - (int) cmd); - return; - } - - EBRDENABLE(brdp); - cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; - if (size > 0) { - memcpy_toio((void __iomem *) &(cp->args[0]), arg, size); - if (copyback) { - portp->argp = arg; - portp->argsize = size; - } - } - writel(0, &cp->status); - writel(cmd, &cp->cmd); - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + - portp->portidx; - writeb(readb(bits) | portp->portbit, bits); - set_bit(ST_CMDING, &portp->state); - EBRDDISABLE(brdp); -} - -static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) -{ - unsigned long flags; - - spin_lock_irqsave(&brd_lock, flags); - __stli_sendcmd(brdp, portp, cmd, arg, size, copyback); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Read data from shared memory. This assumes that the shared memory - * is enabled and that interrupts are off. Basically we just empty out - * the shared memory buffer into the tty buffer. Must be careful to - * handle the case where we fill up the tty buffer, but still have - * more chars to unload. - */ - -static void stli_read(struct stlibrd *brdp, struct stliport *portp) -{ - cdkasyrq_t __iomem *rp; - char __iomem *shbuf; - struct tty_struct *tty; - unsigned int head, tail, size; - unsigned int len, stlen; - - if (test_bit(ST_RXSTOP, &portp->state)) - return; - tty = tty_port_tty_get(&portp->port); - if (tty == NULL) - return; - - rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq; - head = (unsigned int) readw(&rp->head); - if (head != ((unsigned int) readw(&rp->head))) - head = (unsigned int) readw(&rp->head); - tail = (unsigned int) readw(&rp->tail); - size = portp->rxsize; - if (head >= tail) { - len = head - tail; - stlen = len; - } else { - len = size - (tail - head); - stlen = size - tail; - } - - len = tty_buffer_request_room(tty, len); - - shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset); - - while (len > 0) { - unsigned char *cptr; - - stlen = min(len, stlen); - tty_prepare_flip_string(tty, &cptr, stlen); - memcpy_fromio(cptr, shbuf + tail, stlen); - len -= stlen; - tail += stlen; - if (tail >= size) { - tail = 0; - stlen = head; - } - } - rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq; - writew(tail, &rp->tail); - - if (head != tail) - set_bit(ST_RXING, &portp->state); - - tty_schedule_flip(tty); - tty_kref_put(tty); -} - -/*****************************************************************************/ - -/* - * Set up and carry out any delayed commands. There is only a small set - * of slave commands that can be done "off-level". So it is not too - * difficult to deal with them here. - */ - -static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp) -{ - int cmd; - - if (test_bit(ST_DOSIGS, &portp->state)) { - if (test_bit(ST_DOFLUSHTX, &portp->state) && - test_bit(ST_DOFLUSHRX, &portp->state)) - cmd = A_SETSIGNALSF; - else if (test_bit(ST_DOFLUSHTX, &portp->state)) - cmd = A_SETSIGNALSFTX; - else if (test_bit(ST_DOFLUSHRX, &portp->state)) - cmd = A_SETSIGNALSFRX; - else - cmd = A_SETSIGNALS; - clear_bit(ST_DOFLUSHTX, &portp->state); - clear_bit(ST_DOFLUSHRX, &portp->state); - clear_bit(ST_DOSIGS, &portp->state); - memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig, - sizeof(asysigs_t)); - writel(0, &cp->status); - writel(cmd, &cp->cmd); - set_bit(ST_CMDING, &portp->state); - } else if (test_bit(ST_DOFLUSHTX, &portp->state) || - test_bit(ST_DOFLUSHRX, &portp->state)) { - cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0); - cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0); - clear_bit(ST_DOFLUSHTX, &portp->state); - clear_bit(ST_DOFLUSHRX, &portp->state); - memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int)); - writel(0, &cp->status); - writel(A_FLUSH, &cp->cmd); - set_bit(ST_CMDING, &portp->state); - } -} - -/*****************************************************************************/ - -/* - * Host command service checking. This handles commands or messages - * coming from the slave to the host. Must have board shared memory - * enabled and interrupts off when called. Notice that by servicing the - * read data last we don't need to change the shared memory pointer - * during processing (which is a slow IO operation). - * Return value indicates if this port is still awaiting actions from - * the slave (like open, command, or even TX data being sent). If 0 - * then port is still busy, otherwise no longer busy. - */ - -static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) -{ - cdkasy_t __iomem *ap; - cdkctrl_t __iomem *cp; - struct tty_struct *tty; - asynotify_t nt; - unsigned long oldsigs; - int rc, donerx; - - ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); - cp = &ap->ctrl; - -/* - * Check if we are waiting for an open completion message. - */ - if (test_bit(ST_OPENING, &portp->state)) { - rc = readl(&cp->openarg); - if (readb(&cp->open) == 0 && rc != 0) { - if (rc > 0) - rc--; - writel(0, &cp->openarg); - portp->rc = rc; - clear_bit(ST_OPENING, &portp->state); - wake_up_interruptible(&portp->raw_wait); - } - } - -/* - * Check if we are waiting for a close completion message. - */ - if (test_bit(ST_CLOSING, &portp->state)) { - rc = (int) readl(&cp->closearg); - if (readb(&cp->close) == 0 && rc != 0) { - if (rc > 0) - rc--; - writel(0, &cp->closearg); - portp->rc = rc; - clear_bit(ST_CLOSING, &portp->state); - wake_up_interruptible(&portp->raw_wait); - } - } - -/* - * Check if we are waiting for a command completion message. We may - * need to copy out the command results associated with this command. - */ - if (test_bit(ST_CMDING, &portp->state)) { - rc = readl(&cp->status); - if (readl(&cp->cmd) == 0 && rc != 0) { - if (rc > 0) - rc--; - if (portp->argp != NULL) { - memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]), - portp->argsize); - portp->argp = NULL; - } - writel(0, &cp->status); - portp->rc = rc; - clear_bit(ST_CMDING, &portp->state); - stli_dodelaycmd(portp, cp); - wake_up_interruptible(&portp->raw_wait); - } - } - -/* - * Check for any notification messages ready. This includes lots of - * different types of events - RX chars ready, RX break received, - * TX data low or empty in the slave, modem signals changed state. - */ - donerx = 0; - - if (ap->notify) { - nt = ap->changed; - ap->notify = 0; - tty = tty_port_tty_get(&portp->port); - - if (nt.signal & SG_DCD) { - oldsigs = portp->sigs; - portp->sigs = stli_mktiocm(nt.sigvalue); - clear_bit(ST_GETSIGS, &portp->state); - if ((portp->sigs & TIOCM_CD) && - ((oldsigs & TIOCM_CD) == 0)) - wake_up_interruptible(&portp->port.open_wait); - if ((oldsigs & TIOCM_CD) && - ((portp->sigs & TIOCM_CD) == 0)) { - if (portp->port.flags & ASYNC_CHECK_CD) { - if (tty) - tty_hangup(tty); - } - } - } - - if (nt.data & DT_TXEMPTY) - clear_bit(ST_TXBUSY, &portp->state); - if (nt.data & (DT_TXEMPTY | DT_TXLOW)) { - if (tty != NULL) { - tty_wakeup(tty); - EBRDENABLE(brdp); - } - } - - if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) { - if (tty != NULL) { - tty_insert_flip_char(tty, 0, TTY_BREAK); - if (portp->port.flags & ASYNC_SAK) { - do_SAK(tty); - EBRDENABLE(brdp); - } - tty_schedule_flip(tty); - } - } - tty_kref_put(tty); - - if (nt.data & DT_RXBUSY) { - donerx++; - stli_read(brdp, portp); - } - } - -/* - * It might seem odd that we are checking for more RX chars here. - * But, we need to handle the case where the tty buffer was previously - * filled, but we had more characters to pass up. The slave will not - * send any more RX notify messages until the RX buffer has been emptied. - * But it will leave the service bits on (since the buffer is not empty). - * So from here we can try to process more RX chars. - */ - if ((!donerx) && test_bit(ST_RXING, &portp->state)) { - clear_bit(ST_RXING, &portp->state); - stli_read(brdp, portp); - } - - return((test_bit(ST_OPENING, &portp->state) || - test_bit(ST_CLOSING, &portp->state) || - test_bit(ST_CMDING, &portp->state) || - test_bit(ST_TXBUSY, &portp->state) || - test_bit(ST_RXING, &portp->state)) ? 0 : 1); -} - -/*****************************************************************************/ - -/* - * Service all ports on a particular board. Assumes that the boards - * shared memory is enabled, and that the page pointer is pointed - * at the cdk header structure. - */ - -static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp) -{ - struct stliport *portp; - unsigned char hostbits[(STL_MAXCHANS / 8) + 1]; - unsigned char slavebits[(STL_MAXCHANS / 8) + 1]; - unsigned char __iomem *slavep; - int bitpos, bitat, bitsize; - int channr, nrdevs, slavebitchange; - - bitsize = brdp->bitsize; - nrdevs = brdp->nrdevs; - -/* - * Check if slave wants any service. Basically we try to do as - * little work as possible here. There are 2 levels of service - * bits. So if there is nothing to do we bail early. We check - * 8 service bits at a time in the inner loop, so we can bypass - * the lot if none of them want service. - */ - memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset), - bitsize); - - memset(&slavebits[0], 0, bitsize); - slavebitchange = 0; - - for (bitpos = 0; (bitpos < bitsize); bitpos++) { - if (hostbits[bitpos] == 0) - continue; - channr = bitpos * 8; - for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) { - if (hostbits[bitpos] & bitat) { - portp = brdp->ports[(channr - 1)]; - if (stli_hostcmd(brdp, portp)) { - slavebitchange++; - slavebits[bitpos] |= bitat; - } - } - } - } - -/* - * If any of the ports are no longer busy then update them in the - * slave request bits. We need to do this after, since a host port - * service may initiate more slave requests. - */ - if (slavebitchange) { - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset; - for (bitpos = 0; (bitpos < bitsize); bitpos++) { - if (readb(slavebits + bitpos)) - writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos); - } - } -} - -/*****************************************************************************/ - -/* - * Driver poll routine. This routine polls the boards in use and passes - * messages back up to host when necessary. This is actually very - * CPU efficient, since we will always have the kernel poll clock, it - * adds only a few cycles when idle (since board service can be - * determined very easily), but when loaded generates no interrupts - * (with their expensive associated context change). - */ - -static void stli_poll(unsigned long arg) -{ - cdkhdr_t __iomem *hdrp; - struct stlibrd *brdp; - unsigned int brdnr; - - mod_timer(&stli_timerlist, STLI_TIMEOUT); - -/* - * Check each board and do any servicing required. - */ - for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) { - brdp = stli_brds[brdnr]; - if (brdp == NULL) - continue; - if (!test_bit(BST_STARTED, &brdp->state)) - continue; - - spin_lock(&brd_lock); - EBRDENABLE(brdp); - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - if (readb(&hdrp->hostreq)) - stli_brdpoll(brdp, hdrp); - EBRDDISABLE(brdp); - spin_unlock(&brd_lock); - } -} - -/*****************************************************************************/ - -/* - * Translate the termios settings into the port setting structure of - * the slave. - */ - -static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, - asyport_t *pp, struct ktermios *tiosp) -{ - memset(pp, 0, sizeof(asyport_t)); - -/* - * Start of by setting the baud, char size, parity and stop bit info. - */ - pp->baudout = tty_get_baud_rate(tty); - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - pp->baudout = 57600; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - pp->baudout = 115200; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - pp->baudout = 230400; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - pp->baudout = 460800; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - pp->baudout = (portp->baud_base / portp->custom_divisor); - } - if (pp->baudout > STL_MAXBAUD) - pp->baudout = STL_MAXBAUD; - pp->baudin = pp->baudout; - - switch (tiosp->c_cflag & CSIZE) { - case CS5: - pp->csize = 5; - break; - case CS6: - pp->csize = 6; - break; - case CS7: - pp->csize = 7; - break; - default: - pp->csize = 8; - break; - } - - if (tiosp->c_cflag & CSTOPB) - pp->stopbs = PT_STOP2; - else - pp->stopbs = PT_STOP1; - - if (tiosp->c_cflag & PARENB) { - if (tiosp->c_cflag & PARODD) - pp->parity = PT_ODDPARITY; - else - pp->parity = PT_EVENPARITY; - } else { - pp->parity = PT_NOPARITY; - } - -/* - * Set up any flow control options enabled. - */ - if (tiosp->c_iflag & IXON) { - pp->flow |= F_IXON; - if (tiosp->c_iflag & IXANY) - pp->flow |= F_IXANY; - } - if (tiosp->c_cflag & CRTSCTS) - pp->flow |= (F_RTSFLOW | F_CTSFLOW); - - pp->startin = tiosp->c_cc[VSTART]; - pp->stopin = tiosp->c_cc[VSTOP]; - pp->startout = tiosp->c_cc[VSTART]; - pp->stopout = tiosp->c_cc[VSTOP]; - -/* - * Set up the RX char marking mask with those RX error types we must - * catch. We can get the slave to help us out a little here, it will - * ignore parity errors and breaks for us, and mark parity errors in - * the data stream. - */ - if (tiosp->c_iflag & IGNPAR) - pp->iflag |= FI_IGNRXERRS; - if (tiosp->c_iflag & IGNBRK) - pp->iflag |= FI_IGNBREAK; - - portp->rxmarkmsk = 0; - if (tiosp->c_iflag & (INPCK | PARMRK)) - pp->iflag |= FI_1MARKRXERRS; - if (tiosp->c_iflag & BRKINT) - portp->rxmarkmsk |= BRKINT; - -/* - * Set up clocal processing as required. - */ - if (tiosp->c_cflag & CLOCAL) - portp->port.flags &= ~ASYNC_CHECK_CD; - else - portp->port.flags |= ASYNC_CHECK_CD; - -/* - * Transfer any persistent flags into the asyport structure. - */ - pp->pflag = (portp->pflag & 0xffff); - pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0; - pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0; - pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0; -} - -/*****************************************************************************/ - -/* - * Construct a slave signals structure for setting the DTR and RTS - * signals as specified. - */ - -static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts) -{ - memset(sp, 0, sizeof(asysigs_t)); - if (dtr >= 0) { - sp->signal |= SG_DTR; - sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0); - } - if (rts >= 0) { - sp->signal |= SG_RTS; - sp->sigvalue |= ((rts > 0) ? SG_RTS : 0); - } -} - -/*****************************************************************************/ - -/* - * Convert the signals returned from the slave into a local TIOCM type - * signals value. We keep them locally in TIOCM format. - */ - -static long stli_mktiocm(unsigned long sigvalue) -{ - long tiocm = 0; - tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0); - tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0); - tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0); - tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0); - tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0); - tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0); - return(tiocm); -} - -/*****************************************************************************/ - -/* - * All panels and ports actually attached have been worked out. All - * we need to do here is set up the appropriate per port data structures. - */ - -static int stli_initports(struct stlibrd *brdp) -{ - struct stliport *portp; - unsigned int i, panelnr, panelport; - - for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { - portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); - if (!portp) { - printk(KERN_WARNING "istallion: failed to allocate port structure\n"); - continue; - } - tty_port_init(&portp->port); - portp->port.ops = &stli_port_ops; - portp->magic = STLI_PORTMAGIC; - portp->portnr = i; - portp->brdnr = brdp->brdnr; - portp->panelnr = panelnr; - portp->baud_base = STL_BAUDBASE; - portp->port.close_delay = STL_CLOSEDELAY; - portp->closing_wait = 30 * HZ; - init_waitqueue_head(&portp->port.open_wait); - init_waitqueue_head(&portp->port.close_wait); - init_waitqueue_head(&portp->raw_wait); - panelport++; - if (panelport >= brdp->panels[panelnr]) { - panelport = 0; - panelnr++; - } - brdp->ports[i] = portp; - } - - return 0; -} - -/*****************************************************************************/ - -/* - * All the following routines are board specific hardware operations. - */ - -static void stli_ecpinit(struct stlibrd *brdp) -{ - unsigned long memconf; - - outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); - udelay(10); - outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); - udelay(100); - - memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT; - outb(memconf, (brdp->iobase + ECP_ATMEMAR)); -} - -/*****************************************************************************/ - -static void stli_ecpenable(struct stlibrd *brdp) -{ - outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR)); -} - -/*****************************************************************************/ - -static void stli_ecpdisable(struct stlibrd *brdp) -{ - outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); -} - -/*****************************************************************************/ - -static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - unsigned char val; - - if (offset > brdp->memsize) { - printk(KERN_ERR "istallion: shared memory pointer=%x out of " - "range at line=%d(%d), brd=%d\n", - (int) offset, line, __LINE__, brdp->brdnr); - ptr = NULL; - val = 0; - } else { - ptr = brdp->membase + (offset % ECP_ATPAGESIZE); - val = (unsigned char) (offset / ECP_ATPAGESIZE); - } - outb(val, (brdp->iobase + ECP_ATMEMPR)); - return(ptr); -} - -/*****************************************************************************/ - -static void stli_ecpreset(struct stlibrd *brdp) -{ - outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); - udelay(10); - outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); - udelay(500); -} - -/*****************************************************************************/ - -static void stli_ecpintr(struct stlibrd *brdp) -{ - outb(0x1, brdp->iobase); -} - -/*****************************************************************************/ - -/* - * The following set of functions act on ECP EISA boards. - */ - -static void stli_ecpeiinit(struct stlibrd *brdp) -{ - unsigned long memconf; - - outb(0x1, (brdp->iobase + ECP_EIBRDENAB)); - outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); - udelay(10); - outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); - udelay(500); - - memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL; - outb(memconf, (brdp->iobase + ECP_EIMEMARL)); - memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH; - outb(memconf, (brdp->iobase + ECP_EIMEMARH)); -} - -/*****************************************************************************/ - -static void stli_ecpeienable(struct stlibrd *brdp) -{ - outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR)); -} - -/*****************************************************************************/ - -static void stli_ecpeidisable(struct stlibrd *brdp) -{ - outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); -} - -/*****************************************************************************/ - -static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - unsigned char val; - - if (offset > brdp->memsize) { - printk(KERN_ERR "istallion: shared memory pointer=%x out of " - "range at line=%d(%d), brd=%d\n", - (int) offset, line, __LINE__, brdp->brdnr); - ptr = NULL; - val = 0; - } else { - ptr = brdp->membase + (offset % ECP_EIPAGESIZE); - if (offset < ECP_EIPAGESIZE) - val = ECP_EIENABLE; - else - val = ECP_EIENABLE | 0x40; - } - outb(val, (brdp->iobase + ECP_EICONFR)); - return(ptr); -} - -/*****************************************************************************/ - -static void stli_ecpeireset(struct stlibrd *brdp) -{ - outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); - udelay(10); - outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); - udelay(500); -} - -/*****************************************************************************/ - -/* - * The following set of functions act on ECP MCA boards. - */ - -static void stli_ecpmcenable(struct stlibrd *brdp) -{ - outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR)); -} - -/*****************************************************************************/ - -static void stli_ecpmcdisable(struct stlibrd *brdp) -{ - outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); -} - -/*****************************************************************************/ - -static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - unsigned char val; - - if (offset > brdp->memsize) { - printk(KERN_ERR "istallion: shared memory pointer=%x out of " - "range at line=%d(%d), brd=%d\n", - (int) offset, line, __LINE__, brdp->brdnr); - ptr = NULL; - val = 0; - } else { - ptr = brdp->membase + (offset % ECP_MCPAGESIZE); - val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE; - } - outb(val, (brdp->iobase + ECP_MCCONFR)); - return(ptr); -} - -/*****************************************************************************/ - -static void stli_ecpmcreset(struct stlibrd *brdp) -{ - outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR)); - udelay(10); - outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); - udelay(500); -} - -/*****************************************************************************/ - -/* - * The following set of functions act on ECP PCI boards. - */ - -static void stli_ecppciinit(struct stlibrd *brdp) -{ - outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); - udelay(10); - outb(0, (brdp->iobase + ECP_PCICONFR)); - udelay(500); -} - -/*****************************************************************************/ - -static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - unsigned char val; - - if (offset > brdp->memsize) { - printk(KERN_ERR "istallion: shared memory pointer=%x out of " - "range at line=%d(%d), board=%d\n", - (int) offset, line, __LINE__, brdp->brdnr); - ptr = NULL; - val = 0; - } else { - ptr = brdp->membase + (offset % ECP_PCIPAGESIZE); - val = (offset / ECP_PCIPAGESIZE) << 1; - } - outb(val, (brdp->iobase + ECP_PCICONFR)); - return(ptr); -} - -/*****************************************************************************/ - -static void stli_ecppcireset(struct stlibrd *brdp) -{ - outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); - udelay(10); - outb(0, (brdp->iobase + ECP_PCICONFR)); - udelay(500); -} - -/*****************************************************************************/ - -/* - * The following routines act on ONboards. - */ - -static void stli_onbinit(struct stlibrd *brdp) -{ - unsigned long memconf; - - outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); - udelay(10); - outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR)); - mdelay(1000); - - memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT; - outb(memconf, (brdp->iobase + ONB_ATMEMAR)); - outb(0x1, brdp->iobase); - mdelay(1); -} - -/*****************************************************************************/ - -static void stli_onbenable(struct stlibrd *brdp) -{ - outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR)); -} - -/*****************************************************************************/ - -static void stli_onbdisable(struct stlibrd *brdp) -{ - outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR)); -} - -/*****************************************************************************/ - -static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - - if (offset > brdp->memsize) { - printk(KERN_ERR "istallion: shared memory pointer=%x out of " - "range at line=%d(%d), brd=%d\n", - (int) offset, line, __LINE__, brdp->brdnr); - ptr = NULL; - } else { - ptr = brdp->membase + (offset % ONB_ATPAGESIZE); - } - return(ptr); -} - -/*****************************************************************************/ - -static void stli_onbreset(struct stlibrd *brdp) -{ - outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); - udelay(10); - outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR)); - mdelay(1000); -} - -/*****************************************************************************/ - -/* - * The following routines act on ONboard EISA. - */ - -static void stli_onbeinit(struct stlibrd *brdp) -{ - unsigned long memconf; - - outb(0x1, (brdp->iobase + ONB_EIBRDENAB)); - outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); - udelay(10); - outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); - mdelay(1000); - - memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL; - outb(memconf, (brdp->iobase + ONB_EIMEMARL)); - memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH; - outb(memconf, (brdp->iobase + ONB_EIMEMARH)); - outb(0x1, brdp->iobase); - mdelay(1); -} - -/*****************************************************************************/ - -static void stli_onbeenable(struct stlibrd *brdp) -{ - outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR)); -} - -/*****************************************************************************/ - -static void stli_onbedisable(struct stlibrd *brdp) -{ - outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); -} - -/*****************************************************************************/ - -static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - unsigned char val; - - if (offset > brdp->memsize) { - printk(KERN_ERR "istallion: shared memory pointer=%x out of " - "range at line=%d(%d), brd=%d\n", - (int) offset, line, __LINE__, brdp->brdnr); - ptr = NULL; - val = 0; - } else { - ptr = brdp->membase + (offset % ONB_EIPAGESIZE); - if (offset < ONB_EIPAGESIZE) - val = ONB_EIENABLE; - else - val = ONB_EIENABLE | 0x40; - } - outb(val, (brdp->iobase + ONB_EICONFR)); - return(ptr); -} - -/*****************************************************************************/ - -static void stli_onbereset(struct stlibrd *brdp) -{ - outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); - udelay(10); - outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); - mdelay(1000); -} - -/*****************************************************************************/ - -/* - * The following routines act on Brumby boards. - */ - -static void stli_bbyinit(struct stlibrd *brdp) -{ - outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); - udelay(10); - outb(0, (brdp->iobase + BBY_ATCONFR)); - mdelay(1000); - outb(0x1, brdp->iobase); - mdelay(1); -} - -/*****************************************************************************/ - -static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - void __iomem *ptr; - unsigned char val; - - BUG_ON(offset > brdp->memsize); - - ptr = brdp->membase + (offset % BBY_PAGESIZE); - val = (unsigned char) (offset / BBY_PAGESIZE); - outb(val, (brdp->iobase + BBY_ATCONFR)); - return(ptr); -} - -/*****************************************************************************/ - -static void stli_bbyreset(struct stlibrd *brdp) -{ - outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); - udelay(10); - outb(0, (brdp->iobase + BBY_ATCONFR)); - mdelay(1000); -} - -/*****************************************************************************/ - -/* - * The following routines act on original old Stallion boards. - */ - -static void stli_stalinit(struct stlibrd *brdp) -{ - outb(0x1, brdp->iobase); - mdelay(1000); -} - -/*****************************************************************************/ - -static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) -{ - BUG_ON(offset > brdp->memsize); - return brdp->membase + (offset % STAL_PAGESIZE); -} - -/*****************************************************************************/ - -static void stli_stalreset(struct stlibrd *brdp) -{ - u32 __iomem *vecp; - - vecp = (u32 __iomem *) (brdp->membase + 0x30); - writel(0xffff0000, vecp); - outb(0, brdp->iobase); - mdelay(1000); -} - -/*****************************************************************************/ - -/* - * Try to find an ECP board and initialize it. This handles only ECP - * board types. - */ - -static int stli_initecp(struct stlibrd *brdp) -{ - cdkecpsig_t sig; - cdkecpsig_t __iomem *sigsp; - unsigned int status, nxtid; - char *name; - int retval, panelnr, nrports; - - if ((brdp->iobase == 0) || (brdp->memaddr == 0)) { - retval = -ENODEV; - goto err; - } - - brdp->iosize = ECP_IOSIZE; - - if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { - retval = -EIO; - goto err; - } - -/* - * Based on the specific board type setup the common vars to access - * and enable shared memory. Set all board specific information now - * as well. - */ - switch (brdp->brdtype) { - case BRD_ECP: - brdp->memsize = ECP_MEMSIZE; - brdp->pagesize = ECP_ATPAGESIZE; - brdp->init = stli_ecpinit; - brdp->enable = stli_ecpenable; - brdp->reenable = stli_ecpenable; - brdp->disable = stli_ecpdisable; - brdp->getmemptr = stli_ecpgetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_ecpreset; - name = "serial(EC8/64)"; - break; - - case BRD_ECPE: - brdp->memsize = ECP_MEMSIZE; - brdp->pagesize = ECP_EIPAGESIZE; - brdp->init = stli_ecpeiinit; - brdp->enable = stli_ecpeienable; - brdp->reenable = stli_ecpeienable; - brdp->disable = stli_ecpeidisable; - brdp->getmemptr = stli_ecpeigetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_ecpeireset; - name = "serial(EC8/64-EI)"; - break; - - case BRD_ECPMC: - brdp->memsize = ECP_MEMSIZE; - brdp->pagesize = ECP_MCPAGESIZE; - brdp->init = NULL; - brdp->enable = stli_ecpmcenable; - brdp->reenable = stli_ecpmcenable; - brdp->disable = stli_ecpmcdisable; - brdp->getmemptr = stli_ecpmcgetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_ecpmcreset; - name = "serial(EC8/64-MCA)"; - break; - - case BRD_ECPPCI: - brdp->memsize = ECP_PCIMEMSIZE; - brdp->pagesize = ECP_PCIPAGESIZE; - brdp->init = stli_ecppciinit; - brdp->enable = NULL; - brdp->reenable = NULL; - brdp->disable = NULL; - brdp->getmemptr = stli_ecppcigetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_ecppcireset; - name = "serial(EC/RA-PCI)"; - break; - - default: - retval = -EINVAL; - goto err_reg; - } - -/* - * The per-board operations structure is all set up, so now let's go - * and get the board operational. Firstly initialize board configuration - * registers. Set the memory mapping info so we can get at the boards - * shared memory. - */ - EBRDINIT(brdp); - - brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) { - retval = -ENOMEM; - goto err_reg; - } - -/* - * Now that all specific code is set up, enable the shared memory and - * look for the a signature area that will tell us exactly what board - * this is, and what it is connected to it. - */ - EBRDENABLE(brdp); - sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); - memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t)); - EBRDDISABLE(brdp); - - if (sig.magic != cpu_to_le32(ECP_MAGIC)) { - retval = -ENODEV; - goto err_unmap; - } - -/* - * Scan through the signature looking at the panels connected to the - * board. Calculate the total number of ports as we go. - */ - for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) { - status = sig.panelid[nxtid]; - if ((status & ECH_PNLIDMASK) != nxtid) - break; - - brdp->panelids[panelnr] = status; - nrports = (status & ECH_PNL16PORT) ? 16 : 8; - if ((nrports == 16) && ((status & ECH_PNLXPID) == 0)) - nxtid++; - brdp->panels[panelnr] = nrports; - brdp->nrports += nrports; - nxtid++; - brdp->nrpanels++; - } - - - set_bit(BST_FOUND, &brdp->state); - return 0; -err_unmap: - iounmap(brdp->membase); - brdp->membase = NULL; -err_reg: - release_region(brdp->iobase, brdp->iosize); -err: - return retval; -} - -/*****************************************************************************/ - -/* - * Try to find an ONboard, Brumby or Stallion board and initialize it. - * This handles only these board types. - */ - -static int stli_initonb(struct stlibrd *brdp) -{ - cdkonbsig_t sig; - cdkonbsig_t __iomem *sigsp; - char *name; - int i, retval; - -/* - * Do a basic sanity check on the IO and memory addresses. - */ - if (brdp->iobase == 0 || brdp->memaddr == 0) { - retval = -ENODEV; - goto err; - } - - brdp->iosize = ONB_IOSIZE; - - if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { - retval = -EIO; - goto err; - } - -/* - * Based on the specific board type setup the common vars to access - * and enable shared memory. Set all board specific information now - * as well. - */ - switch (brdp->brdtype) { - case BRD_ONBOARD: - case BRD_ONBOARD2: - brdp->memsize = ONB_MEMSIZE; - brdp->pagesize = ONB_ATPAGESIZE; - brdp->init = stli_onbinit; - brdp->enable = stli_onbenable; - brdp->reenable = stli_onbenable; - brdp->disable = stli_onbdisable; - brdp->getmemptr = stli_onbgetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_onbreset; - if (brdp->memaddr > 0x100000) - brdp->enabval = ONB_MEMENABHI; - else - brdp->enabval = ONB_MEMENABLO; - name = "serial(ONBoard)"; - break; - - case BRD_ONBOARDE: - brdp->memsize = ONB_EIMEMSIZE; - brdp->pagesize = ONB_EIPAGESIZE; - brdp->init = stli_onbeinit; - brdp->enable = stli_onbeenable; - brdp->reenable = stli_onbeenable; - brdp->disable = stli_onbedisable; - brdp->getmemptr = stli_onbegetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_onbereset; - name = "serial(ONBoard/E)"; - break; - - case BRD_BRUMBY4: - brdp->memsize = BBY_MEMSIZE; - brdp->pagesize = BBY_PAGESIZE; - brdp->init = stli_bbyinit; - brdp->enable = NULL; - brdp->reenable = NULL; - brdp->disable = NULL; - brdp->getmemptr = stli_bbygetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_bbyreset; - name = "serial(Brumby)"; - break; - - case BRD_STALLION: - brdp->memsize = STAL_MEMSIZE; - brdp->pagesize = STAL_PAGESIZE; - brdp->init = stli_stalinit; - brdp->enable = NULL; - brdp->reenable = NULL; - brdp->disable = NULL; - brdp->getmemptr = stli_stalgetmemptr; - brdp->intr = stli_ecpintr; - brdp->reset = stli_stalreset; - name = "serial(Stallion)"; - break; - - default: - retval = -EINVAL; - goto err_reg; - } - -/* - * The per-board operations structure is all set up, so now let's go - * and get the board operational. Firstly initialize board configuration - * registers. Set the memory mapping info so we can get at the boards - * shared memory. - */ - EBRDINIT(brdp); - - brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) { - retval = -ENOMEM; - goto err_reg; - } - -/* - * Now that all specific code is set up, enable the shared memory and - * look for the a signature area that will tell us exactly what board - * this is, and how many ports. - */ - EBRDENABLE(brdp); - sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); - memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t)); - EBRDDISABLE(brdp); - - if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) || - sig.magic1 != cpu_to_le16(ONB_MAGIC1) || - sig.magic2 != cpu_to_le16(ONB_MAGIC2) || - sig.magic3 != cpu_to_le16(ONB_MAGIC3)) { - retval = -ENODEV; - goto err_unmap; - } - -/* - * Scan through the signature alive mask and calculate how many ports - * there are on this board. - */ - brdp->nrpanels = 1; - if (sig.amask1) { - brdp->nrports = 32; - } else { - for (i = 0; (i < 16); i++) { - if (((sig.amask0 << i) & 0x8000) == 0) - break; - } - brdp->nrports = i; - } - brdp->panels[0] = brdp->nrports; - - - set_bit(BST_FOUND, &brdp->state); - return 0; -err_unmap: - iounmap(brdp->membase); - brdp->membase = NULL; -err_reg: - release_region(brdp->iobase, brdp->iosize); -err: - return retval; -} - -/*****************************************************************************/ - -/* - * Start up a running board. This routine is only called after the - * code has been down loaded to the board and is operational. It will - * read in the memory map, and get the show on the road... - */ - -static int stli_startbrd(struct stlibrd *brdp) -{ - cdkhdr_t __iomem *hdrp; - cdkmem_t __iomem *memp; - cdkasy_t __iomem *ap; - unsigned long flags; - unsigned int portnr, nrdevs, i; - struct stliport *portp; - int rc = 0; - u32 memoff; - - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); - nrdevs = hdrp->nrdevs; - -#if 0 - printk("%s(%d): CDK version %d.%d.%d --> " - "nrdevs=%d memp=%x hostp=%x slavep=%x\n", - __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification), - readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp), - readl(&hdrp->slavep)); -#endif - - if (nrdevs < (brdp->nrports + 1)) { - printk(KERN_ERR "istallion: slave failed to allocate memory for " - "all devices, devices=%d\n", nrdevs); - brdp->nrports = nrdevs - 1; - } - brdp->nrdevs = nrdevs; - brdp->hostoffset = hdrp->hostp - CDK_CDKADDR; - brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR; - brdp->bitsize = (nrdevs + 7) / 8; - memoff = readl(&hdrp->memp); - if (memoff > brdp->memsize) { - printk(KERN_ERR "istallion: corrupted shared memory region?\n"); - rc = -EIO; - goto stli_donestartup; - } - memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); - if (readw(&memp->dtype) != TYP_ASYNCTRL) { - printk(KERN_ERR "istallion: no slave control device found\n"); - goto stli_donestartup; - } - memp++; - -/* - * Cycle through memory allocation of each port. We are guaranteed to - * have all ports inside the first page of slave window, so no need to - * change pages while reading memory map. - */ - for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) { - if (readw(&memp->dtype) != TYP_ASYNC) - break; - portp = brdp->ports[portnr]; - if (portp == NULL) - break; - portp->devnr = i; - portp->addr = readl(&memp->offset); - portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs)); - portp->portidx = (unsigned char) (i / 8); - portp->portbit = (unsigned char) (0x1 << (i % 8)); - } - - writeb(0xff, &hdrp->slavereq); - -/* - * For each port setup a local copy of the RX and TX buffer offsets - * and sizes. We do this separate from the above, because we need to - * move the shared memory page... - */ - for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) { - portp = brdp->ports[portnr]; - if (portp == NULL) - break; - if (portp->addr == 0) - break; - ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); - if (ap != NULL) { - portp->rxsize = readw(&ap->rxq.size); - portp->txsize = readw(&ap->txq.size); - portp->rxoffset = readl(&ap->rxq.offset); - portp->txoffset = readl(&ap->txq.offset); - } - } - -stli_donestartup: - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); - - if (rc == 0) - set_bit(BST_STARTED, &brdp->state); - - if (! stli_timeron) { - stli_timeron++; - mod_timer(&stli_timerlist, STLI_TIMEOUT); - } - - return rc; -} - -/*****************************************************************************/ - -/* - * Probe and initialize the specified board. - */ - -static int __devinit stli_brdinit(struct stlibrd *brdp) -{ - int retval; - - switch (brdp->brdtype) { - case BRD_ECP: - case BRD_ECPE: - case BRD_ECPMC: - case BRD_ECPPCI: - retval = stli_initecp(brdp); - break; - case BRD_ONBOARD: - case BRD_ONBOARDE: - case BRD_ONBOARD2: - case BRD_BRUMBY4: - case BRD_STALLION: - retval = stli_initonb(brdp); - break; - default: - printk(KERN_ERR "istallion: board=%d is unknown board " - "type=%d\n", brdp->brdnr, brdp->brdtype); - retval = -ENODEV; - } - - if (retval) - return retval; - - stli_initports(brdp); - printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x " - "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], - brdp->brdnr, brdp->iobase, (int) brdp->memaddr, - brdp->nrpanels, brdp->nrports); - return 0; -} - -#if STLI_EISAPROBE != 0 -/*****************************************************************************/ - -/* - * Probe around trying to find where the EISA boards shared memory - * might be. This is a bit if hack, but it is the best we can do. - */ - -static int stli_eisamemprobe(struct stlibrd *brdp) -{ - cdkecpsig_t ecpsig, __iomem *ecpsigp; - cdkonbsig_t onbsig, __iomem *onbsigp; - int i, foundit; - -/* - * First up we reset the board, to get it into a known state. There - * is only 2 board types here we need to worry about. Don;t use the - * standard board init routine here, it programs up the shared - * memory address, and we don't know it yet... - */ - if (brdp->brdtype == BRD_ECPE) { - outb(0x1, (brdp->iobase + ECP_EIBRDENAB)); - outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); - udelay(10); - outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); - udelay(500); - stli_ecpeienable(brdp); - } else if (brdp->brdtype == BRD_ONBOARDE) { - outb(0x1, (brdp->iobase + ONB_EIBRDENAB)); - outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); - udelay(10); - outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); - mdelay(100); - outb(0x1, brdp->iobase); - mdelay(1); - stli_onbeenable(brdp); - } else { - return -ENODEV; - } - - foundit = 0; - brdp->memsize = ECP_MEMSIZE; - -/* - * Board shared memory is enabled, so now we have a poke around and - * see if we can find it. - */ - for (i = 0; (i < stli_eisamempsize); i++) { - brdp->memaddr = stli_eisamemprobeaddrs[i]; - brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) - continue; - - if (brdp->brdtype == BRD_ECPE) { - ecpsigp = stli_ecpeigetmemptr(brdp, - CDK_SIGADDR, __LINE__); - memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t)); - if (ecpsig.magic == cpu_to_le32(ECP_MAGIC)) - foundit = 1; - } else { - onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp, - CDK_SIGADDR, __LINE__); - memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t)); - if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) && - (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) && - (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) && - (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3))) - foundit = 1; - } - - iounmap(brdp->membase); - if (foundit) - break; - } - -/* - * Regardless of whether we found the shared memory or not we must - * disable the region. After that return success or failure. - */ - if (brdp->brdtype == BRD_ECPE) - stli_ecpeidisable(brdp); - else - stli_onbedisable(brdp); - - if (! foundit) { - brdp->memaddr = 0; - brdp->membase = NULL; - printk(KERN_ERR "istallion: failed to probe shared memory " - "region for %s in EISA slot=%d\n", - stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); - return -ENODEV; - } - return 0; -} -#endif - -static int stli_getbrdnr(void) -{ - unsigned int i; - - for (i = 0; i < STL_MAXBRDS; i++) { - if (!stli_brds[i]) { - if (i >= stli_nrbrds) - stli_nrbrds = i + 1; - return i; - } - } - return -1; -} - -#if STLI_EISAPROBE != 0 -/*****************************************************************************/ - -/* - * Probe around and try to find any EISA boards in system. The biggest - * problem here is finding out what memory address is associated with - * an EISA board after it is found. The registers of the ECPE and - * ONboardE are not readable - so we can't read them from there. We - * don't have access to the EISA CMOS (or EISA BIOS) so we don't - * actually have any way to find out the real value. The best we can - * do is go probing around in the usual places hoping we can find it. - */ - -static int __init stli_findeisabrds(void) -{ - struct stlibrd *brdp; - unsigned int iobase, eid, i; - int brdnr, found = 0; - -/* - * Firstly check if this is an EISA system. If this is not an EISA system then - * don't bother going any further! - */ - if (EISA_bus) - return 0; - -/* - * Looks like an EISA system, so go searching for EISA boards. - */ - for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) { - outb(0xff, (iobase + 0xc80)); - eid = inb(iobase + 0xc80); - eid |= inb(iobase + 0xc81) << 8; - if (eid != STL_EISAID) - continue; - -/* - * We have found a board. Need to check if this board was - * statically configured already (just in case!). - */ - for (i = 0; (i < STL_MAXBRDS); i++) { - brdp = stli_brds[i]; - if (brdp == NULL) - continue; - if (brdp->iobase == iobase) - break; - } - if (i < STL_MAXBRDS) - continue; - -/* - * We have found a Stallion board and it is not configured already. - * Allocate a board structure and initialize it. - */ - if ((brdp = stli_allocbrd()) == NULL) - return found ? : -ENOMEM; - brdnr = stli_getbrdnr(); - if (brdnr < 0) - return found ? : -ENOMEM; - brdp->brdnr = (unsigned int)brdnr; - eid = inb(iobase + 0xc82); - if (eid == ECP_EISAID) - brdp->brdtype = BRD_ECPE; - else if (eid == ONB_EISAID) - brdp->brdtype = BRD_ONBOARDE; - else - brdp->brdtype = BRD_UNKNOWN; - brdp->iobase = iobase; - outb(0x1, (iobase + 0xc84)); - if (stli_eisamemprobe(brdp)) - outb(0, (iobase + 0xc84)); - if (stli_brdinit(brdp) < 0) { - kfree(brdp); - continue; - } - - stli_brds[brdp->brdnr] = brdp; - found++; - - for (i = 0; i < brdp->nrports; i++) - tty_register_device(stli_serial, - brdp->brdnr * STL_MAXPORTS + i, NULL); - } - - return found; -} -#else -static inline int stli_findeisabrds(void) { return 0; } -#endif - -/*****************************************************************************/ - -/* - * Find the next available board number that is free. - */ - -/*****************************************************************************/ - -/* - * We have a Stallion board. Allocate a board structure and - * initialize it. Read its IO and MEMORY resources from PCI - * configuration space. - */ - -static int __devinit stli_pciprobe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct stlibrd *brdp; - unsigned int i; - int brdnr, retval = -EIO; - - retval = pci_enable_device(pdev); - if (retval) - goto err; - brdp = stli_allocbrd(); - if (brdp == NULL) { - retval = -ENOMEM; - goto err; - } - mutex_lock(&stli_brdslock); - brdnr = stli_getbrdnr(); - if (brdnr < 0) { - printk(KERN_INFO "istallion: too many boards found, " - "maximum supported %d\n", STL_MAXBRDS); - mutex_unlock(&stli_brdslock); - retval = -EIO; - goto err_fr; - } - brdp->brdnr = (unsigned int)brdnr; - stli_brds[brdp->brdnr] = brdp; - mutex_unlock(&stli_brdslock); - brdp->brdtype = BRD_ECPPCI; -/* - * We have all resources from the board, so lets setup the actual - * board structure now. - */ - brdp->iobase = pci_resource_start(pdev, 3); - brdp->memaddr = pci_resource_start(pdev, 2); - retval = stli_brdinit(brdp); - if (retval) - goto err_null; - - set_bit(BST_PROBED, &brdp->state); - pci_set_drvdata(pdev, brdp); - - EBRDENABLE(brdp); - brdp->enable = NULL; - brdp->disable = NULL; - - for (i = 0; i < brdp->nrports; i++) - tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i, - &pdev->dev); - - return 0; -err_null: - stli_brds[brdp->brdnr] = NULL; -err_fr: - kfree(brdp); -err: - return retval; -} - -static void __devexit stli_pciremove(struct pci_dev *pdev) -{ - struct stlibrd *brdp = pci_get_drvdata(pdev); - - stli_cleanup_ports(brdp); - - iounmap(brdp->membase); - if (brdp->iosize > 0) - release_region(brdp->iobase, brdp->iosize); - - stli_brds[brdp->brdnr] = NULL; - kfree(brdp); -} - -static struct pci_driver stli_pcidriver = { - .name = "istallion", - .id_table = istallion_pci_tbl, - .probe = stli_pciprobe, - .remove = __devexit_p(stli_pciremove) -}; -/*****************************************************************************/ - -/* - * Allocate a new board structure. Fill out the basic info in it. - */ - -static struct stlibrd *stli_allocbrd(void) -{ - struct stlibrd *brdp; - - brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); - if (!brdp) { - printk(KERN_ERR "istallion: failed to allocate memory " - "(size=%Zd)\n", sizeof(struct stlibrd)); - return NULL; - } - brdp->magic = STLI_BOARDMAGIC; - return brdp; -} - -/*****************************************************************************/ - -/* - * Scan through all the boards in the configuration and see what we - * can find. - */ - -static int __init stli_initbrds(void) -{ - struct stlibrd *brdp, *nxtbrdp; - struct stlconf conf; - unsigned int i, j, found = 0; - int retval; - - for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp); - stli_nrbrds++) { - memset(&conf, 0, sizeof(conf)); - if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0) - continue; - if ((brdp = stli_allocbrd()) == NULL) - continue; - brdp->brdnr = stli_nrbrds; - brdp->brdtype = conf.brdtype; - brdp->iobase = conf.ioaddr1; - brdp->memaddr = conf.memaddr; - if (stli_brdinit(brdp) < 0) { - kfree(brdp); - continue; - } - stli_brds[brdp->brdnr] = brdp; - found++; - - for (i = 0; i < brdp->nrports; i++) - tty_register_device(stli_serial, - brdp->brdnr * STL_MAXPORTS + i, NULL); - } - - retval = stli_findeisabrds(); - if (retval > 0) - found += retval; - -/* - * All found boards are initialized. Now for a little optimization, if - * no boards are sharing the "shared memory" regions then we can just - * leave them all enabled. This is in fact the usual case. - */ - stli_shared = 0; - if (stli_nrbrds > 1) { - for (i = 0; (i < stli_nrbrds); i++) { - brdp = stli_brds[i]; - if (brdp == NULL) - continue; - for (j = i + 1; (j < stli_nrbrds); j++) { - nxtbrdp = stli_brds[j]; - if (nxtbrdp == NULL) - continue; - if ((brdp->membase >= nxtbrdp->membase) && - (brdp->membase <= (nxtbrdp->membase + - nxtbrdp->memsize - 1))) { - stli_shared++; - break; - } - } - } - } - - if (stli_shared == 0) { - for (i = 0; (i < stli_nrbrds); i++) { - brdp = stli_brds[i]; - if (brdp == NULL) - continue; - if (test_bit(BST_FOUND, &brdp->state)) { - EBRDENABLE(brdp); - brdp->enable = NULL; - brdp->disable = NULL; - } - } - } - - retval = pci_register_driver(&stli_pcidriver); - if (retval && found == 0) { - printk(KERN_ERR "Neither isa nor eisa cards found nor pci " - "driver can be registered!\n"); - goto err; - } - - return 0; -err: - return retval; -} - -/*****************************************************************************/ - -/* - * Code to handle an "staliomem" read operation. This device is the - * contents of the board shared memory. It is used for down loading - * the slave image (and debugging :-) - */ - -static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp) -{ - unsigned long flags; - void __iomem *memptr; - struct stlibrd *brdp; - unsigned int brdnr; - int size, n; - void *p; - loff_t off = *offp; - - brdnr = iminor(fp->f_path.dentry->d_inode); - if (brdnr >= stli_nrbrds) - return -ENODEV; - brdp = stli_brds[brdnr]; - if (brdp == NULL) - return -ENODEV; - if (brdp->state == 0) - return -ENODEV; - if (off >= brdp->memsize || off + count < off) - return 0; - - size = min(count, (size_t)(brdp->memsize - off)); - - /* - * Copy the data a page at a time - */ - - p = (void *)__get_free_page(GFP_KERNEL); - if(p == NULL) - return -ENOMEM; - - while (size > 0) { - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - memptr = EBRDGETMEMPTR(brdp, off); - n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); - n = min(n, (int)PAGE_SIZE); - memcpy_fromio(p, memptr, n); - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); - if (copy_to_user(buf, p, n)) { - count = -EFAULT; - goto out; - } - off += n; - buf += n; - size -= n; - } -out: - *offp = off; - free_page((unsigned long)p); - return count; -} - -/*****************************************************************************/ - -/* - * Code to handle an "staliomem" write operation. This device is the - * contents of the board shared memory. It is used for down loading - * the slave image (and debugging :-) - * - * FIXME: copy under lock - */ - -static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp) -{ - unsigned long flags; - void __iomem *memptr; - struct stlibrd *brdp; - char __user *chbuf; - unsigned int brdnr; - int size, n; - void *p; - loff_t off = *offp; - - brdnr = iminor(fp->f_path.dentry->d_inode); - - if (brdnr >= stli_nrbrds) - return -ENODEV; - brdp = stli_brds[brdnr]; - if (brdp == NULL) - return -ENODEV; - if (brdp->state == 0) - return -ENODEV; - if (off >= brdp->memsize || off + count < off) - return 0; - - chbuf = (char __user *) buf; - size = min(count, (size_t)(brdp->memsize - off)); - - /* - * Copy the data a page at a time - */ - - p = (void *)__get_free_page(GFP_KERNEL); - if(p == NULL) - return -ENOMEM; - - while (size > 0) { - n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); - n = min(n, (int)PAGE_SIZE); - if (copy_from_user(p, chbuf, n)) { - if (count == 0) - count = -EFAULT; - goto out; - } - spin_lock_irqsave(&brd_lock, flags); - EBRDENABLE(brdp); - memptr = EBRDGETMEMPTR(brdp, off); - memcpy_toio(memptr, p, n); - EBRDDISABLE(brdp); - spin_unlock_irqrestore(&brd_lock, flags); - off += n; - chbuf += n; - size -= n; - } -out: - free_page((unsigned long) p); - *offp = off; - return count; -} - -/*****************************************************************************/ - -/* - * Return the board stats structure to user app. - */ - -static int stli_getbrdstats(combrd_t __user *bp) -{ - struct stlibrd *brdp; - unsigned int i; - - if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t))) - return -EFAULT; - if (stli_brdstats.brd >= STL_MAXBRDS) - return -ENODEV; - brdp = stli_brds[stli_brdstats.brd]; - if (brdp == NULL) - return -ENODEV; - - memset(&stli_brdstats, 0, sizeof(combrd_t)); - - stli_brdstats.brd = brdp->brdnr; - stli_brdstats.type = brdp->brdtype; - stli_brdstats.hwid = 0; - stli_brdstats.state = brdp->state; - stli_brdstats.ioaddr = brdp->iobase; - stli_brdstats.memaddr = brdp->memaddr; - stli_brdstats.nrpanels = brdp->nrpanels; - stli_brdstats.nrports = brdp->nrports; - for (i = 0; (i < brdp->nrpanels); i++) { - stli_brdstats.panels[i].panel = i; - stli_brdstats.panels[i].hwid = brdp->panelids[i]; - stli_brdstats.panels[i].nrports = brdp->panels[i]; - } - - if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t))) - return -EFAULT; - return 0; -} - -/*****************************************************************************/ - -/* - * Resolve the referenced port number into a port struct pointer. - */ - -static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, - unsigned int portnr) -{ - struct stlibrd *brdp; - unsigned int i; - - if (brdnr >= STL_MAXBRDS) - return NULL; - brdp = stli_brds[brdnr]; - if (brdp == NULL) - return NULL; - for (i = 0; (i < panelnr); i++) - portnr += brdp->panels[i]; - if (portnr >= brdp->nrports) - return NULL; - return brdp->ports[portnr]; -} - -/*****************************************************************************/ - -/* - * Return the port stats structure to user app. A NULL port struct - * pointer passed in means that we need to find out from the app - * what port to get stats for (used through board control device). - */ - -static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) -{ - unsigned long flags; - struct stlibrd *brdp; - int rc; - - memset(&stli_comstats, 0, sizeof(comstats_t)); - - if (portp == NULL) - return -ENODEV; - brdp = stli_brds[portp->brdnr]; - if (brdp == NULL) - return -ENODEV; - - mutex_lock(&portp->port.mutex); - if (test_bit(BST_STARTED, &brdp->state)) { - if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, - &stli_cdkstats, sizeof(asystats_t), 1)) < 0) { - mutex_unlock(&portp->port.mutex); - return rc; - } - } else { - memset(&stli_cdkstats, 0, sizeof(asystats_t)); - } - - stli_comstats.brd = portp->brdnr; - stli_comstats.panel = portp->panelnr; - stli_comstats.port = portp->portnr; - stli_comstats.state = portp->state; - stli_comstats.flags = portp->port.flags; - - spin_lock_irqsave(&brd_lock, flags); - if (tty != NULL) { - if (portp->port.tty == tty) { - stli_comstats.ttystate = tty->flags; - stli_comstats.rxbuffered = -1; - if (tty->termios != NULL) { - stli_comstats.cflags = tty->termios->c_cflag; - stli_comstats.iflags = tty->termios->c_iflag; - stli_comstats.oflags = tty->termios->c_oflag; - stli_comstats.lflags = tty->termios->c_lflag; - } - } - } - spin_unlock_irqrestore(&brd_lock, flags); - - stli_comstats.txtotal = stli_cdkstats.txchars; - stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover; - stli_comstats.txbuffered = stli_cdkstats.txringq; - stli_comstats.rxbuffered += stli_cdkstats.rxringq; - stli_comstats.rxoverrun = stli_cdkstats.overruns; - stli_comstats.rxparity = stli_cdkstats.parity; - stli_comstats.rxframing = stli_cdkstats.framing; - stli_comstats.rxlost = stli_cdkstats.ringover; - stli_comstats.rxbreaks = stli_cdkstats.rxbreaks; - stli_comstats.txbreaks = stli_cdkstats.txbreaks; - stli_comstats.txxon = stli_cdkstats.txstart; - stli_comstats.txxoff = stli_cdkstats.txstop; - stli_comstats.rxxon = stli_cdkstats.rxstart; - stli_comstats.rxxoff = stli_cdkstats.rxstop; - stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2; - stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff; - stli_comstats.modem = stli_cdkstats.dcdcnt; - stli_comstats.hwid = stli_cdkstats.hwid; - stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); - mutex_unlock(&portp->port.mutex); - - return 0; -} - -/*****************************************************************************/ - -/* - * Return the port stats structure to user app. A NULL port struct - * pointer passed in means that we need to find out from the app - * what port to get stats for (used through board control device). - */ - -static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, - comstats_t __user *cp) -{ - struct stlibrd *brdp; - int rc; - - if (!portp) { - if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t))) - return -EFAULT; - portp = stli_getport(stli_comstats.brd, stli_comstats.panel, - stli_comstats.port); - if (!portp) - return -ENODEV; - } - - brdp = stli_brds[portp->brdnr]; - if (!brdp) - return -ENODEV; - - if ((rc = stli_portcmdstats(tty, portp)) < 0) - return rc; - - return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ? - -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Clear the port stats structure. We also return it zeroed out... - */ - -static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) -{ - struct stlibrd *brdp; - int rc; - - if (!portp) { - if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t))) - return -EFAULT; - portp = stli_getport(stli_comstats.brd, stli_comstats.panel, - stli_comstats.port); - if (!portp) - return -ENODEV; - } - - brdp = stli_brds[portp->brdnr]; - if (!brdp) - return -ENODEV; - - mutex_lock(&portp->port.mutex); - - if (test_bit(BST_STARTED, &brdp->state)) { - if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) { - mutex_unlock(&portp->port.mutex); - return rc; - } - } - - memset(&stli_comstats, 0, sizeof(comstats_t)); - stli_comstats.brd = portp->brdnr; - stli_comstats.panel = portp->panelnr; - stli_comstats.port = portp->portnr; - mutex_unlock(&portp->port.mutex); - - if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) - return -EFAULT; - return 0; -} - -/*****************************************************************************/ - -/* - * Return the entire driver ports structure to a user app. - */ - -static int stli_getportstruct(struct stliport __user *arg) -{ - struct stliport stli_dummyport; - struct stliport *portp; - - if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport))) - return -EFAULT; - portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr, - stli_dummyport.portnr); - if (!portp) - return -ENODEV; - if (copy_to_user(arg, portp, sizeof(struct stliport))) - return -EFAULT; - return 0; -} - -/*****************************************************************************/ - -/* - * Return the entire driver board structure to a user app. - */ - -static int stli_getbrdstruct(struct stlibrd __user *arg) -{ - struct stlibrd stli_dummybrd; - struct stlibrd *brdp; - - if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd))) - return -EFAULT; - if (stli_dummybrd.brdnr >= STL_MAXBRDS) - return -ENODEV; - brdp = stli_brds[stli_dummybrd.brdnr]; - if (!brdp) - return -ENODEV; - if (copy_to_user(arg, brdp, sizeof(struct stlibrd))) - return -EFAULT; - return 0; -} - -/*****************************************************************************/ - -/* - * The "staliomem" device is also required to do some special operations on - * the board. We need to be able to send an interrupt to the board, - * reset it, and start/stop it. - */ - -static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) -{ - struct stlibrd *brdp; - int brdnr, rc, done; - void __user *argp = (void __user *)arg; - -/* - * First up handle the board independent ioctls. - */ - done = 0; - rc = 0; - - switch (cmd) { - case COM_GETPORTSTATS: - rc = stli_getportstats(NULL, NULL, argp); - done++; - break; - case COM_CLRPORTSTATS: - rc = stli_clrportstats(NULL, argp); - done++; - break; - case COM_GETBRDSTATS: - rc = stli_getbrdstats(argp); - done++; - break; - case COM_READPORT: - rc = stli_getportstruct(argp); - done++; - break; - case COM_READBOARD: - rc = stli_getbrdstruct(argp); - done++; - break; - } - if (done) - return rc; - -/* - * Now handle the board specific ioctls. These all depend on the - * minor number of the device they were called from. - */ - brdnr = iminor(fp->f_dentry->d_inode); - if (brdnr >= STL_MAXBRDS) - return -ENODEV; - brdp = stli_brds[brdnr]; - if (!brdp) - return -ENODEV; - if (brdp->state == 0) - return -ENODEV; - - switch (cmd) { - case STL_BINTR: - EBRDINTR(brdp); - break; - case STL_BSTART: - rc = stli_startbrd(brdp); - break; - case STL_BSTOP: - clear_bit(BST_STARTED, &brdp->state); - break; - case STL_BRESET: - clear_bit(BST_STARTED, &brdp->state); - EBRDRESET(brdp); - if (stli_shared == 0) { - if (brdp->reenable != NULL) - (* brdp->reenable)(brdp); - } - break; - default: - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -static const struct tty_operations stli_ops = { - .open = stli_open, - .close = stli_close, - .write = stli_write, - .put_char = stli_putchar, - .flush_chars = stli_flushchars, - .write_room = stli_writeroom, - .chars_in_buffer = stli_charsinbuffer, - .ioctl = stli_ioctl, - .set_termios = stli_settermios, - .throttle = stli_throttle, - .unthrottle = stli_unthrottle, - .stop = stli_stop, - .start = stli_start, - .hangup = stli_hangup, - .flush_buffer = stli_flushbuffer, - .break_ctl = stli_breakctl, - .wait_until_sent = stli_waituntilsent, - .send_xchar = stli_sendxchar, - .tiocmget = stli_tiocmget, - .tiocmset = stli_tiocmset, - .proc_fops = &stli_proc_fops, -}; - -static const struct tty_port_operations stli_port_ops = { - .carrier_raised = stli_carrier_raised, - .dtr_rts = stli_dtr_rts, - .activate = stli_activate, - .shutdown = stli_shutdown, -}; - -/*****************************************************************************/ -/* - * Loadable module initialization stuff. - */ - -static void istallion_cleanup_isa(void) -{ - struct stlibrd *brdp; - unsigned int j; - - for (j = 0; (j < stli_nrbrds); j++) { - if ((brdp = stli_brds[j]) == NULL || - test_bit(BST_PROBED, &brdp->state)) - continue; - - stli_cleanup_ports(brdp); - - iounmap(brdp->membase); - if (brdp->iosize > 0) - release_region(brdp->iobase, brdp->iosize); - kfree(brdp); - stli_brds[j] = NULL; - } -} - -static int __init istallion_module_init(void) -{ - unsigned int i; - int retval; - - printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); - - spin_lock_init(&stli_lock); - spin_lock_init(&brd_lock); - - stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); - if (!stli_txcookbuf) { - printk(KERN_ERR "istallion: failed to allocate memory " - "(size=%d)\n", STLI_TXBUFSIZE); - retval = -ENOMEM; - goto err; - } - - stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); - if (!stli_serial) { - retval = -ENOMEM; - goto err_free; - } - - stli_serial->owner = THIS_MODULE; - stli_serial->driver_name = stli_drvname; - stli_serial->name = stli_serialname; - stli_serial->major = STL_SERIALMAJOR; - stli_serial->minor_start = 0; - stli_serial->type = TTY_DRIVER_TYPE_SERIAL; - stli_serial->subtype = SERIAL_TYPE_NORMAL; - stli_serial->init_termios = stli_deftermios; - stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - tty_set_operations(stli_serial, &stli_ops); - - retval = tty_register_driver(stli_serial); - if (retval) { - printk(KERN_ERR "istallion: failed to register serial driver\n"); - goto err_ttyput; - } - - retval = stli_initbrds(); - if (retval) - goto err_ttyunr; - -/* - * Set up a character driver for the shared memory region. We need this - * to down load the slave code image. Also it is a useful debugging tool. - */ - retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); - if (retval) { - printk(KERN_ERR "istallion: failed to register serial memory " - "device\n"); - goto err_deinit; - } - - istallion_class = class_create(THIS_MODULE, "staliomem"); - for (i = 0; i < 4; i++) - device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), - NULL, "staliomem%d", i); - - return 0; -err_deinit: - pci_unregister_driver(&stli_pcidriver); - istallion_cleanup_isa(); -err_ttyunr: - tty_unregister_driver(stli_serial); -err_ttyput: - put_tty_driver(stli_serial); -err_free: - kfree(stli_txcookbuf); -err: - return retval; -} - -/*****************************************************************************/ - -static void __exit istallion_module_exit(void) -{ - unsigned int j; - - printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, - stli_drvversion); - - if (stli_timeron) { - stli_timeron = 0; - del_timer_sync(&stli_timerlist); - } - - unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); - - for (j = 0; j < 4; j++) - device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j)); - class_destroy(istallion_class); - - pci_unregister_driver(&stli_pcidriver); - istallion_cleanup_isa(); - - tty_unregister_driver(stli_serial); - put_tty_driver(stli_serial); - - kfree(stli_txcookbuf); -} - -module_init(istallion_module_init); -module_exit(istallion_module_exit); diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c deleted file mode 100644 index 602643a40b4b..000000000000 --- a/drivers/char/riscom8.c +++ /dev/null @@ -1,1560 +0,0 @@ -/* - * linux/drivers/char/riscom.c -- RISCom/8 multiport serial driver. - * - * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) - * - * This code is loosely based on the Linux serial driver, written by - * Linus Torvalds, Theodore T'so and others. The RISCom/8 card - * programming info was obtained from various drivers for other OSes - * (FreeBSD, ISC, etc), but no source code from those drivers were - * directly included in this driver. - * - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Revision 1.1 - * - * ChangeLog: - * Arnaldo Carvalho de Melo - 27-Jun-2001 - * - get rid of check_region and several cleanups - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "riscom8.h" -#include "riscom8_reg.h" - -/* Am I paranoid or not ? ;-) */ -#define RISCOM_PARANOIA_CHECK - -/* - * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals. - * You can slightly speed up things by #undefing the following option, - * if you are REALLY sure that your board is correct one. - */ - -#define RISCOM_BRAIN_DAMAGED_CTS - -/* - * The following defines are mostly for testing purposes. But if you need - * some nice reporting in your syslog, you can define them also. - */ -#undef RC_REPORT_FIFO -#undef RC_REPORT_OVERRUN - - -#define RISCOM_LEGAL_FLAGS \ - (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ - ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ - ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) - -static struct tty_driver *riscom_driver; - -static DEFINE_SPINLOCK(riscom_lock); - -static struct riscom_board rc_board[RC_NBOARD] = { - { - .base = RC_IOBASE1, - }, - { - .base = RC_IOBASE2, - }, - { - .base = RC_IOBASE3, - }, - { - .base = RC_IOBASE4, - }, -}; - -static struct riscom_port rc_port[RC_NBOARD * RC_NPORT]; - -/* RISCom/8 I/O ports addresses (without address translation) */ -static unsigned short rc_ioport[] = { -#if 1 - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, -#else - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10, - 0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62, - 0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101 -#endif -}; -#define RC_NIOPORT ARRAY_SIZE(rc_ioport) - - -static int rc_paranoia_check(struct riscom_port const *port, - char *name, const char *routine) -{ -#ifdef RISCOM_PARANOIA_CHECK - static const char badmagic[] = KERN_INFO - "rc: Warning: bad riscom port magic number for device %s in %s\n"; - static const char badinfo[] = KERN_INFO - "rc: Warning: null riscom port for device %s in %s\n"; - - if (!port) { - printk(badinfo, name, routine); - return 1; - } - if (port->magic != RISCOM8_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* - * - * Service functions for RISCom/8 driver. - * - */ - -/* Get board number from pointer */ -static inline int board_No(struct riscom_board const *bp) -{ - return bp - rc_board; -} - -/* Get port number from pointer */ -static inline int port_No(struct riscom_port const *port) -{ - return RC_PORT(port - rc_port); -} - -/* Get pointer to board from pointer to port */ -static inline struct riscom_board *port_Board(struct riscom_port const *port) -{ - return &rc_board[RC_BOARD(port - rc_port)]; -} - -/* Input Byte from CL CD180 register */ -static inline unsigned char rc_in(struct riscom_board const *bp, - unsigned short reg) -{ - return inb(bp->base + RC_TO_ISA(reg)); -} - -/* Output Byte to CL CD180 register */ -static inline void rc_out(struct riscom_board const *bp, unsigned short reg, - unsigned char val) -{ - outb(val, bp->base + RC_TO_ISA(reg)); -} - -/* Wait for Channel Command Register ready */ -static void rc_wait_CCR(struct riscom_board const *bp) -{ - unsigned long delay; - - /* FIXME: need something more descriptive then 100000 :) */ - for (delay = 100000; delay; delay--) - if (!rc_in(bp, CD180_CCR)) - return; - - printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp)); -} - -/* - * RISCom/8 probe functions. - */ - -static int rc_request_io_range(struct riscom_board * const bp) -{ - int i; - - for (i = 0; i < RC_NIOPORT; i++) - if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1, - "RISCom/8")) { - goto out_release; - } - return 0; -out_release: - printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n", - board_No(bp), bp->base); - while (--i >= 0) - release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1); - return 1; -} - -static void rc_release_io_range(struct riscom_board * const bp) -{ - int i; - - for (i = 0; i < RC_NIOPORT; i++) - release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1); -} - -/* Reset and setup CD180 chip */ -static void __init rc_init_CD180(struct riscom_board const *bp) -{ - unsigned long flags; - - spin_lock_irqsave(&riscom_lock, flags); - - rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ - rc_wait_CCR(bp); /* Wait for CCR ready */ - rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ - spin_unlock_irqrestore(&riscom_lock, flags); - msleep(50); /* Delay 0.05 sec */ - spin_lock_irqsave(&riscom_lock, flags); - rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ - rc_out(bp, CD180_GICR, 0); /* Clear all bits */ - rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ - rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for tx intr */ - rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for rx intr */ - - /* Setting up prescaler. We need 4 ticks per 1 ms */ - rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); - rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); - - spin_unlock_irqrestore(&riscom_lock, flags); -} - -/* Main probing routine, also sets irq. */ -static int __init rc_probe(struct riscom_board *bp) -{ - unsigned char val1, val2; - int irqs = 0; - int retries; - - bp->irq = 0; - - if (rc_request_io_range(bp)) - return 1; - - /* Are the I/O ports here ? */ - rc_out(bp, CD180_PPRL, 0x5a); - outb(0xff, 0x80); - val1 = rc_in(bp, CD180_PPRL); - rc_out(bp, CD180_PPRL, 0xa5); - outb(0x00, 0x80); - val2 = rc_in(bp, CD180_PPRL); - - if ((val1 != 0x5a) || (val2 != 0xa5)) { - printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n", - board_No(bp), bp->base); - goto out_release; - } - - /* It's time to find IRQ for this board */ - for (retries = 0; retries < 5 && irqs <= 0; retries++) { - irqs = probe_irq_on(); - rc_init_CD180(bp); /* Reset CD180 chip */ - rc_out(bp, CD180_CAR, 2); /* Select port 2 */ - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */ - rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr */ - msleep(50); - irqs = probe_irq_off(irqs); - val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */ - val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */ - rc_init_CD180(bp); /* Reset CD180 again */ - - if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX))) { - printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not " - "found.\n", board_No(bp), bp->base); - goto out_release; - } - } - - if (irqs <= 0) { - printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board " - "at 0x%03x.\n", board_No(bp), bp->base); - goto out_release; - } - bp->irq = irqs; - bp->flags |= RC_BOARD_PRESENT; - - printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at " - "0x%03x, IRQ %d.\n", - board_No(bp), - (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A', /* Board revision */ - bp->base, bp->irq); - - return 0; -out_release: - rc_release_io_range(bp); - return 1; -} - -/* - * - * Interrupt processing routines. - * - */ - -static struct riscom_port *rc_get_port(struct riscom_board const *bp, - unsigned char const *what) -{ - unsigned char channel; - struct riscom_port *port; - - channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF; - if (channel < CD180_NCH) { - port = &rc_port[board_No(bp) * RC_NPORT + channel]; - if (port->port.flags & ASYNC_INITIALIZED) - return port; - } - printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n", - board_No(bp), what, channel); - return NULL; -} - -static void rc_receive_exc(struct riscom_board const *bp) -{ - struct riscom_port *port; - struct tty_struct *tty; - unsigned char status; - unsigned char ch, flag; - - port = rc_get_port(bp, "Receive"); - if (port == NULL) - return; - - tty = tty_port_tty_get(&port->port); - -#ifdef RC_REPORT_OVERRUN - status = rc_in(bp, CD180_RCSR); - if (status & RCSR_OE) - port->overrun++; - status &= port->mark_mask; -#else - status = rc_in(bp, CD180_RCSR) & port->mark_mask; -#endif - ch = rc_in(bp, CD180_RDR); - if (!status) - goto out; - if (status & RCSR_TOUT) { - printk(KERN_WARNING "rc%d: port %d: Receiver timeout. " - "Hardware problems ?\n", - board_No(bp), port_No(port)); - goto out; - - } else if (status & RCSR_BREAK) { - printk(KERN_INFO "rc%d: port %d: Handling break...\n", - board_No(bp), port_No(port)); - flag = TTY_BREAK; - if (tty && (port->port.flags & ASYNC_SAK)) - do_SAK(tty); - - } else if (status & RCSR_PE) - flag = TTY_PARITY; - - else if (status & RCSR_FE) - flag = TTY_FRAME; - - else if (status & RCSR_OE) - flag = TTY_OVERRUN; - else - flag = TTY_NORMAL; - - if (tty) { - tty_insert_flip_char(tty, ch, flag); - tty_flip_buffer_push(tty); - } -out: - tty_kref_put(tty); -} - -static void rc_receive(struct riscom_board const *bp) -{ - struct riscom_port *port; - struct tty_struct *tty; - unsigned char count; - - port = rc_get_port(bp, "Receive"); - if (port == NULL) - return; - - tty = tty_port_tty_get(&port->port); - - count = rc_in(bp, CD180_RDCR); - -#ifdef RC_REPORT_FIFO - port->hits[count > 8 ? 9 : count]++; -#endif - - while (count--) { - u8 ch = rc_in(bp, CD180_RDR); - if (tty) - tty_insert_flip_char(tty, ch, TTY_NORMAL); - } - if (tty) { - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } -} - -static void rc_transmit(struct riscom_board const *bp) -{ - struct riscom_port *port; - struct tty_struct *tty; - unsigned char count; - - port = rc_get_port(bp, "Transmit"); - if (port == NULL) - return; - - tty = tty_port_tty_get(&port->port); - - if (port->IER & IER_TXEMPTY) { - /* FIFO drained */ - rc_out(bp, CD180_CAR, port_No(port)); - port->IER &= ~IER_TXEMPTY; - rc_out(bp, CD180_IER, port->IER); - goto out; - } - - if ((port->xmit_cnt <= 0 && !port->break_length) - || (tty && (tty->stopped || tty->hw_stopped))) { - rc_out(bp, CD180_CAR, port_No(port)); - port->IER &= ~IER_TXRDY; - rc_out(bp, CD180_IER, port->IER); - goto out; - } - - if (port->break_length) { - if (port->break_length > 0) { - if (port->COR2 & COR2_ETC) { - rc_out(bp, CD180_TDR, CD180_C_ESC); - rc_out(bp, CD180_TDR, CD180_C_SBRK); - port->COR2 &= ~COR2_ETC; - } - count = min_t(int, port->break_length, 0xff); - rc_out(bp, CD180_TDR, CD180_C_ESC); - rc_out(bp, CD180_TDR, CD180_C_DELAY); - rc_out(bp, CD180_TDR, count); - port->break_length -= count; - if (port->break_length == 0) - port->break_length--; - } else { - rc_out(bp, CD180_TDR, CD180_C_ESC); - rc_out(bp, CD180_TDR, CD180_C_EBRK); - rc_out(bp, CD180_COR2, port->COR2); - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_CORCHG2); - port->break_length = 0; - } - goto out; - } - - count = CD180_NFIFO; - do { - rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); - if (--port->xmit_cnt <= 0) - break; - } while (--count > 0); - - if (port->xmit_cnt <= 0) { - rc_out(bp, CD180_CAR, port_No(port)); - port->IER &= ~IER_TXRDY; - rc_out(bp, CD180_IER, port->IER); - } - if (tty && port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); -out: - tty_kref_put(tty); -} - -static void rc_check_modem(struct riscom_board const *bp) -{ - struct riscom_port *port; - struct tty_struct *tty; - unsigned char mcr; - - port = rc_get_port(bp, "Modem"); - if (port == NULL) - return; - - tty = tty_port_tty_get(&port->port); - - mcr = rc_in(bp, CD180_MCR); - if (mcr & MCR_CDCHG) { - if (rc_in(bp, CD180_MSVR) & MSVR_CD) - wake_up_interruptible(&port->port.open_wait); - else if (tty) - tty_hangup(tty); - } - -#ifdef RISCOM_BRAIN_DAMAGED_CTS - if (mcr & MCR_CTSCHG) { - if (rc_in(bp, CD180_MSVR) & MSVR_CTS) { - port->IER |= IER_TXRDY; - if (tty) { - tty->hw_stopped = 0; - if (port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); - } - } else { - if (tty) - tty->hw_stopped = 1; - port->IER &= ~IER_TXRDY; - } - rc_out(bp, CD180_IER, port->IER); - } - if (mcr & MCR_DSRCHG) { - if (rc_in(bp, CD180_MSVR) & MSVR_DSR) { - port->IER |= IER_TXRDY; - if (tty) { - tty->hw_stopped = 0; - if (port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); - } - } else { - if (tty) - tty->hw_stopped = 1; - port->IER &= ~IER_TXRDY; - } - rc_out(bp, CD180_IER, port->IER); - } -#endif /* RISCOM_BRAIN_DAMAGED_CTS */ - - /* Clear change bits */ - rc_out(bp, CD180_MCR, 0); - tty_kref_put(tty); -} - -/* The main interrupt processing routine */ -static irqreturn_t rc_interrupt(int dummy, void *dev_id) -{ - unsigned char status; - unsigned char ack; - struct riscom_board *bp = dev_id; - unsigned long loop = 0; - int handled = 0; - - if (!(bp->flags & RC_BOARD_ACTIVE)) - return IRQ_NONE; - - while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) & - (RC_BSR_TOUT | RC_BSR_TINT | - RC_BSR_MINT | RC_BSR_RINT))) { - handled = 1; - if (status & RC_BSR_TOUT) - printk(KERN_WARNING "rc%d: Got timeout. Hardware " - "error?\n", board_No(bp)); - else if (status & RC_BSR_RINT) { - ack = rc_in(bp, RC_ACK_RINT); - if (ack == (RC_ID | GIVR_IT_RCV)) - rc_receive(bp); - else if (ack == (RC_ID | GIVR_IT_REXC)) - rc_receive_exc(bp); - else - printk(KERN_WARNING "rc%d: Bad receive ack " - "0x%02x.\n", - board_No(bp), ack); - } else if (status & RC_BSR_TINT) { - ack = rc_in(bp, RC_ACK_TINT); - if (ack == (RC_ID | GIVR_IT_TX)) - rc_transmit(bp); - else - printk(KERN_WARNING "rc%d: Bad transmit ack " - "0x%02x.\n", - board_No(bp), ack); - } else /* if (status & RC_BSR_MINT) */ { - ack = rc_in(bp, RC_ACK_MINT); - if (ack == (RC_ID | GIVR_IT_MODEM)) - rc_check_modem(bp); - else - printk(KERN_WARNING "rc%d: Bad modem ack " - "0x%02x.\n", - board_No(bp), ack); - } - rc_out(bp, CD180_EOIR, 0); /* Mark end of interrupt */ - rc_out(bp, RC_CTOUT, 0); /* Clear timeout flag */ - } - return IRQ_RETVAL(handled); -} - -/* - * Routines for open & close processing. - */ - -/* Called with disabled interrupts */ -static int rc_setup_board(struct riscom_board *bp) -{ - int error; - - if (bp->flags & RC_BOARD_ACTIVE) - return 0; - - error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED, - "RISCom/8", bp); - if (error) - return error; - - rc_out(bp, RC_CTOUT, 0); /* Just in case */ - bp->DTR = ~0; - rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ - - bp->flags |= RC_BOARD_ACTIVE; - - return 0; -} - -/* Called with disabled interrupts */ -static void rc_shutdown_board(struct riscom_board *bp) -{ - if (!(bp->flags & RC_BOARD_ACTIVE)) - return; - - bp->flags &= ~RC_BOARD_ACTIVE; - - free_irq(bp->irq, NULL); - - bp->DTR = ~0; - rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ - -} - -/* - * Setting up port characteristics. - * Must be called with disabled interrupts - */ -static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp, - struct riscom_port *port) -{ - unsigned long baud; - long tmp; - unsigned char cor1 = 0, cor3 = 0; - unsigned char mcor1 = 0, mcor2 = 0; - - port->IER = 0; - port->COR2 = 0; - port->MSVR = MSVR_RTS; - - baud = tty_get_baud_rate(tty); - - /* Select port on the board */ - rc_out(bp, CD180_CAR, port_No(port)); - - if (!baud) { - /* Drop DTR & exit */ - bp->DTR |= (1u << port_No(port)); - rc_out(bp, RC_DTR, bp->DTR); - return; - } else { - /* Set DTR on */ - bp->DTR &= ~(1u << port_No(port)); - rc_out(bp, RC_DTR, bp->DTR); - } - - /* - * Now we must calculate some speed depended things - */ - - /* Set baud rate for port */ - tmp = (((RC_OSCFREQ + baud/2) / baud + - CD180_TPC/2) / CD180_TPC); - - rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); - rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff); - rc_out(bp, CD180_RBPRL, tmp & 0xff); - rc_out(bp, CD180_TBPRL, tmp & 0xff); - - baud = (baud + 5) / 10; /* Estimated CPS */ - - /* Two timer ticks seems enough to wakeup something like SLIP driver */ - tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO; - port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? - SERIAL_XMIT_SIZE - 1 : tmp); - - /* Receiver timeout will be transmission time for 1.5 chars */ - tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud; - tmp = (tmp > 0xff) ? 0xff : tmp; - rc_out(bp, CD180_RTPR, tmp); - - switch (C_CSIZE(tty)) { - case CS5: - cor1 |= COR1_5BITS; - break; - case CS6: - cor1 |= COR1_6BITS; - break; - case CS7: - cor1 |= COR1_7BITS; - break; - case CS8: - cor1 |= COR1_8BITS; - break; - } - if (C_CSTOPB(tty)) - cor1 |= COR1_2SB; - - cor1 |= COR1_IGNORE; - if (C_PARENB(tty)) { - cor1 |= COR1_NORMPAR; - if (C_PARODD(tty)) - cor1 |= COR1_ODDP; - if (I_INPCK(tty)) - cor1 &= ~COR1_IGNORE; - } - /* Set marking of some errors */ - port->mark_mask = RCSR_OE | RCSR_TOUT; - if (I_INPCK(tty)) - port->mark_mask |= RCSR_FE | RCSR_PE; - if (I_BRKINT(tty) || I_PARMRK(tty)) - port->mark_mask |= RCSR_BREAK; - if (I_IGNPAR(tty)) - port->mark_mask &= ~(RCSR_FE | RCSR_PE); - if (I_IGNBRK(tty)) { - port->mark_mask &= ~RCSR_BREAK; - if (I_IGNPAR(tty)) - /* Real raw mode. Ignore all */ - port->mark_mask &= ~RCSR_OE; - } - /* Enable Hardware Flow Control */ - if (C_CRTSCTS(tty)) { -#ifdef RISCOM_BRAIN_DAMAGED_CTS - port->IER |= IER_DSR | IER_CTS; - mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; - mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; - tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & - (MSVR_CTS|MSVR_DSR)); -#else - port->COR2 |= COR2_CTSAE; -#endif - } - /* Enable Software Flow Control. FIXME: I'm not sure about this */ - /* Some people reported that it works, but I still doubt */ - if (I_IXON(tty)) { - port->COR2 |= COR2_TXIBE; - cor3 |= (COR3_FCT | COR3_SCDE); - if (I_IXANY(tty)) - port->COR2 |= COR2_IXM; - rc_out(bp, CD180_SCHR1, START_CHAR(tty)); - rc_out(bp, CD180_SCHR2, STOP_CHAR(tty)); - rc_out(bp, CD180_SCHR3, START_CHAR(tty)); - rc_out(bp, CD180_SCHR4, STOP_CHAR(tty)); - } - if (!C_CLOCAL(tty)) { - /* Enable CD check */ - port->IER |= IER_CD; - mcor1 |= MCOR1_CDZD; - mcor2 |= MCOR2_CDOD; - } - - if (C_CREAD(tty)) - /* Enable receiver */ - port->IER |= IER_RXD; - - /* Set input FIFO size (1-8 bytes) */ - cor3 |= RISCOM_RXFIFO; - /* Setting up CD180 channel registers */ - rc_out(bp, CD180_COR1, cor1); - rc_out(bp, CD180_COR2, port->COR2); - rc_out(bp, CD180_COR3, cor3); - /* Make CD180 know about registers change */ - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); - /* Setting up modem option registers */ - rc_out(bp, CD180_MCOR1, mcor1); - rc_out(bp, CD180_MCOR2, mcor2); - /* Enable CD180 transmitter & receiver */ - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN); - /* Enable interrupts */ - rc_out(bp, CD180_IER, port->IER); - /* And finally set RTS on */ - rc_out(bp, CD180_MSVR, port->MSVR); -} - -/* Must be called with interrupts enabled */ -static int rc_activate_port(struct tty_port *port, struct tty_struct *tty) -{ - struct riscom_port *rp = container_of(port, struct riscom_port, port); - struct riscom_board *bp = port_Board(rp); - unsigned long flags; - - if (tty_port_alloc_xmit_buf(port) < 0) - return -ENOMEM; - - spin_lock_irqsave(&riscom_lock, flags); - - clear_bit(TTY_IO_ERROR, &tty->flags); - bp->count++; - rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0; - rc_change_speed(tty, bp, rp); - spin_unlock_irqrestore(&riscom_lock, flags); - return 0; -} - -/* Must be called with interrupts disabled */ -static void rc_shutdown_port(struct tty_struct *tty, - struct riscom_board *bp, struct riscom_port *port) -{ -#ifdef RC_REPORT_OVERRUN - printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", - board_No(bp), port_No(port), port->overrun); -#endif -#ifdef RC_REPORT_FIFO - { - int i; - - printk(KERN_INFO "rc%d: port %d: FIFO hits [ ", - board_No(bp), port_No(port)); - for (i = 0; i < 10; i++) - printk("%ld ", port->hits[i]); - printk("].\n"); - } -#endif - tty_port_free_xmit_buf(&port->port); - - /* Select port */ - rc_out(bp, CD180_CAR, port_No(port)); - /* Reset port */ - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_SOFTRESET); - /* Disable all interrupts from this port */ - port->IER = 0; - rc_out(bp, CD180_IER, port->IER); - - set_bit(TTY_IO_ERROR, &tty->flags); - - if (--bp->count < 0) { - printk(KERN_INFO "rc%d: rc_shutdown_port: " - "bad board count: %d\n", - board_No(bp), bp->count); - bp->count = 0; - } - /* - * If this is the last opened port on the board - * shutdown whole board - */ - if (!bp->count) - rc_shutdown_board(bp); -} - -static int carrier_raised(struct tty_port *port) -{ - struct riscom_port *p = container_of(port, struct riscom_port, port); - struct riscom_board *bp = port_Board(p); - unsigned long flags; - int CD; - - spin_lock_irqsave(&riscom_lock, flags); - rc_out(bp, CD180_CAR, port_No(p)); - CD = rc_in(bp, CD180_MSVR) & MSVR_CD; - rc_out(bp, CD180_MSVR, MSVR_RTS); - bp->DTR &= ~(1u << port_No(p)); - rc_out(bp, RC_DTR, bp->DTR); - spin_unlock_irqrestore(&riscom_lock, flags); - return CD; -} - -static void dtr_rts(struct tty_port *port, int onoff) -{ - struct riscom_port *p = container_of(port, struct riscom_port, port); - struct riscom_board *bp = port_Board(p); - unsigned long flags; - - spin_lock_irqsave(&riscom_lock, flags); - bp->DTR &= ~(1u << port_No(p)); - if (onoff == 0) - bp->DTR |= (1u << port_No(p)); - rc_out(bp, RC_DTR, bp->DTR); - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static int rc_open(struct tty_struct *tty, struct file *filp) -{ - int board; - int error; - struct riscom_port *port; - struct riscom_board *bp; - - board = RC_BOARD(tty->index); - if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT)) - return -ENODEV; - - bp = &rc_board[board]; - port = rc_port + board * RC_NPORT + RC_PORT(tty->index); - if (rc_paranoia_check(port, tty->name, "rc_open")) - return -ENODEV; - - error = rc_setup_board(bp); - if (error) - return error; - - tty->driver_data = port; - return tty_port_open(&port->port, tty, filp); -} - -static void rc_flush_buffer(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) - return; - - spin_lock_irqsave(&riscom_lock, flags); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - spin_unlock_irqrestore(&riscom_lock, flags); - - tty_wakeup(tty); -} - -static void rc_close_port(struct tty_port *port) -{ - unsigned long flags; - struct riscom_port *rp = container_of(port, struct riscom_port, port); - struct riscom_board *bp = port_Board(rp); - unsigned long timeout; - - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - - spin_lock_irqsave(&riscom_lock, flags); - rp->IER &= ~IER_RXD; - - rp->IER &= ~IER_TXRDY; - rp->IER |= IER_TXEMPTY; - rc_out(bp, CD180_CAR, port_No(rp)); - rc_out(bp, CD180_IER, rp->IER); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies + HZ; - while (rp->IER & IER_TXEMPTY) { - spin_unlock_irqrestore(&riscom_lock, flags); - msleep_interruptible(jiffies_to_msecs(rp->timeout)); - spin_lock_irqsave(&riscom_lock, flags); - if (time_after(jiffies, timeout)) - break; - } - rc_shutdown_port(port->tty, bp, rp); - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static void rc_close(struct tty_struct *tty, struct file *filp) -{ - struct riscom_port *port = tty->driver_data; - - if (!port || rc_paranoia_check(port, tty->name, "close")) - return; - tty_port_close(&port->port, tty, filp); -} - -static int rc_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp; - int c, total = 0; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_write")) - return 0; - - bp = port_Board(port); - - while (1) { - spin_lock_irqsave(&riscom_lock, flags); - - c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; /* lock continues to be held */ - - memcpy(port->port.xmit_buf + port->xmit_head, buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; - - spin_unlock_irqrestore(&riscom_lock, flags); - - buf += c; - count -= c; - total += c; - } - - if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && - !(port->IER & IER_TXRDY)) { - port->IER |= IER_TXRDY; - rc_out(bp, CD180_CAR, port_No(port)); - rc_out(bp, CD180_IER, port->IER); - } - - spin_unlock_irqrestore(&riscom_lock, flags); - - return total; -} - -static int rc_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct riscom_port *port = tty->driver_data; - unsigned long flags; - int ret = 0; - - if (rc_paranoia_check(port, tty->name, "rc_put_char")) - return 0; - - spin_lock_irqsave(&riscom_lock, flags); - - if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) - goto out; - - port->port.xmit_buf[port->xmit_head++] = ch; - port->xmit_head &= SERIAL_XMIT_SIZE - 1; - port->xmit_cnt++; - ret = 1; - -out: - spin_unlock_irqrestore(&riscom_lock, flags); - return ret; -} - -static void rc_flush_chars(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_flush_chars")) - return; - - if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped) - return; - - spin_lock_irqsave(&riscom_lock, flags); - - port->IER |= IER_TXRDY; - rc_out(port_Board(port), CD180_CAR, port_No(port)); - rc_out(port_Board(port), CD180_IER, port->IER); - - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static int rc_write_room(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - int ret; - - if (rc_paranoia_check(port, tty->name, "rc_write_room")) - return 0; - - ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} - -static int rc_chars_in_buffer(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - - if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer")) - return 0; - - return port->xmit_cnt; -} - -static int rc_tiocmget(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp; - unsigned char status; - unsigned int result; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, __func__)) - return -ENODEV; - - bp = port_Board(port); - - spin_lock_irqsave(&riscom_lock, flags); - - rc_out(bp, CD180_CAR, port_No(port)); - status = rc_in(bp, CD180_MSVR); - result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; - - spin_unlock_irqrestore(&riscom_lock, flags); - - result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) - | ((status & MSVR_DTR) ? TIOCM_DTR : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - | ((status & MSVR_DSR) ? TIOCM_DSR : 0) - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); - return result; -} - -static int rc_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct riscom_port *port = tty->driver_data; - unsigned long flags; - struct riscom_board *bp; - - if (rc_paranoia_check(port, tty->name, __func__)) - return -ENODEV; - - bp = port_Board(port); - - spin_lock_irqsave(&riscom_lock, flags); - - if (set & TIOCM_RTS) - port->MSVR |= MSVR_RTS; - if (set & TIOCM_DTR) - bp->DTR &= ~(1u << port_No(port)); - - if (clear & TIOCM_RTS) - port->MSVR &= ~MSVR_RTS; - if (clear & TIOCM_DTR) - bp->DTR |= (1u << port_No(port)); - - rc_out(bp, CD180_CAR, port_No(port)); - rc_out(bp, CD180_MSVR, port->MSVR); - rc_out(bp, RC_DTR, bp->DTR); - - spin_unlock_irqrestore(&riscom_lock, flags); - - return 0; -} - -static int rc_send_break(struct tty_struct *tty, int length) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp = port_Board(port); - unsigned long flags; - - if (length == 0 || length == -1) - return -EOPNOTSUPP; - - spin_lock_irqsave(&riscom_lock, flags); - - port->break_length = RISCOM_TPS / HZ * length; - port->COR2 |= COR2_ETC; - port->IER |= IER_TXRDY; - rc_out(bp, CD180_CAR, port_No(port)); - rc_out(bp, CD180_COR2, port->COR2); - rc_out(bp, CD180_IER, port->IER); - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_CORCHG2); - rc_wait_CCR(bp); - - spin_unlock_irqrestore(&riscom_lock, flags); - return 0; -} - -static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, - struct serial_struct __user *newinfo) -{ - struct serial_struct tmp; - struct riscom_board *bp = port_Board(port); - int change_speed; - - if (copy_from_user(&tmp, newinfo, sizeof(tmp))) - return -EFAULT; - - mutex_lock(&port->port.mutex); - change_speed = ((port->port.flags & ASYNC_SPD_MASK) != - (tmp.flags & ASYNC_SPD_MASK)); - - if (!capable(CAP_SYS_ADMIN)) { - if ((tmp.close_delay != port->port.close_delay) || - (tmp.closing_wait != port->port.closing_wait) || - ((tmp.flags & ~ASYNC_USR_MASK) != - (port->port.flags & ~ASYNC_USR_MASK))) { - mutex_unlock(&port->port.mutex); - return -EPERM; - } - port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | - (tmp.flags & ASYNC_USR_MASK)); - } else { - port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | - (tmp.flags & ASYNC_FLAGS)); - port->port.close_delay = tmp.close_delay; - port->port.closing_wait = tmp.closing_wait; - } - if (change_speed) { - unsigned long flags; - - spin_lock_irqsave(&riscom_lock, flags); - rc_change_speed(tty, bp, port); - spin_unlock_irqrestore(&riscom_lock, flags); - } - mutex_unlock(&port->port.mutex); - return 0; -} - -static int rc_get_serial_info(struct riscom_port *port, - struct serial_struct __user *retinfo) -{ - struct serial_struct tmp; - struct riscom_board *bp = port_Board(port); - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = PORT_CIRRUS; - tmp.line = port - rc_port; - - mutex_lock(&port->port.mutex); - tmp.port = bp->base; - tmp.irq = bp->irq; - tmp.flags = port->port.flags; - tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; - tmp.close_delay = port->port.close_delay * HZ/100; - tmp.closing_wait = port->port.closing_wait * HZ/100; - mutex_unlock(&port->port.mutex); - tmp.xmit_fifo_size = CD180_NFIFO; - return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; -} - -static int rc_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct riscom_port *port = tty->driver_data; - void __user *argp = (void __user *)arg; - int retval; - - if (rc_paranoia_check(port, tty->name, "rc_ioctl")) - return -ENODEV; - - switch (cmd) { - case TIOCGSERIAL: - retval = rc_get_serial_info(port, argp); - break; - case TIOCSSERIAL: - retval = rc_set_serial_info(tty, port, argp); - break; - default: - retval = -ENOIOCTLCMD; - } - return retval; -} - -static void rc_throttle(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_throttle")) - return; - bp = port_Board(port); - - spin_lock_irqsave(&riscom_lock, flags); - port->MSVR &= ~MSVR_RTS; - rc_out(bp, CD180_CAR, port_No(port)); - if (I_IXOFF(tty)) { - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_SSCH2); - rc_wait_CCR(bp); - } - rc_out(bp, CD180_MSVR, port->MSVR); - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static void rc_unthrottle(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_unthrottle")) - return; - bp = port_Board(port); - - spin_lock_irqsave(&riscom_lock, flags); - port->MSVR |= MSVR_RTS; - rc_out(bp, CD180_CAR, port_No(port)); - if (I_IXOFF(tty)) { - rc_wait_CCR(bp); - rc_out(bp, CD180_CCR, CCR_SSCH1); - rc_wait_CCR(bp); - } - rc_out(bp, CD180_MSVR, port->MSVR); - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static void rc_stop(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_stop")) - return; - - bp = port_Board(port); - - spin_lock_irqsave(&riscom_lock, flags); - port->IER &= ~IER_TXRDY; - rc_out(bp, CD180_CAR, port_No(port)); - rc_out(bp, CD180_IER, port->IER); - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static void rc_start(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - struct riscom_board *bp; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_start")) - return; - - bp = port_Board(port); - - spin_lock_irqsave(&riscom_lock, flags); - - if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) { - port->IER |= IER_TXRDY; - rc_out(bp, CD180_CAR, port_No(port)); - rc_out(bp, CD180_IER, port->IER); - } - spin_unlock_irqrestore(&riscom_lock, flags); -} - -static void rc_hangup(struct tty_struct *tty) -{ - struct riscom_port *port = tty->driver_data; - - if (rc_paranoia_check(port, tty->name, "rc_hangup")) - return; - - tty_port_hangup(&port->port); -} - -static void rc_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct riscom_port *port = tty->driver_data; - unsigned long flags; - - if (rc_paranoia_check(port, tty->name, "rc_set_termios")) - return; - - spin_lock_irqsave(&riscom_lock, flags); - rc_change_speed(tty, port_Board(port), port); - spin_unlock_irqrestore(&riscom_lock, flags); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rc_start(tty); - } -} - -static const struct tty_operations riscom_ops = { - .open = rc_open, - .close = rc_close, - .write = rc_write, - .put_char = rc_put_char, - .flush_chars = rc_flush_chars, - .write_room = rc_write_room, - .chars_in_buffer = rc_chars_in_buffer, - .flush_buffer = rc_flush_buffer, - .ioctl = rc_ioctl, - .throttle = rc_throttle, - .unthrottle = rc_unthrottle, - .set_termios = rc_set_termios, - .stop = rc_stop, - .start = rc_start, - .hangup = rc_hangup, - .tiocmget = rc_tiocmget, - .tiocmset = rc_tiocmset, - .break_ctl = rc_send_break, -}; - -static const struct tty_port_operations riscom_port_ops = { - .carrier_raised = carrier_raised, - .dtr_rts = dtr_rts, - .shutdown = rc_close_port, - .activate = rc_activate_port, -}; - - -static int __init rc_init_drivers(void) -{ - int error; - int i; - - riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT); - if (!riscom_driver) - return -ENOMEM; - - riscom_driver->owner = THIS_MODULE; - riscom_driver->name = "ttyL"; - riscom_driver->major = RISCOM8_NORMAL_MAJOR; - riscom_driver->type = TTY_DRIVER_TYPE_SERIAL; - riscom_driver->subtype = SERIAL_TYPE_NORMAL; - riscom_driver->init_termios = tty_std_termios; - riscom_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - riscom_driver->init_termios.c_ispeed = 9600; - riscom_driver->init_termios.c_ospeed = 9600; - riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; - tty_set_operations(riscom_driver, &riscom_ops); - error = tty_register_driver(riscom_driver); - if (error != 0) { - put_tty_driver(riscom_driver); - printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, " - "error = %d\n", error); - return 1; - } - memset(rc_port, 0, sizeof(rc_port)); - for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { - tty_port_init(&rc_port[i].port); - rc_port[i].port.ops = &riscom_port_ops; - rc_port[i].magic = RISCOM8_MAGIC; - } - return 0; -} - -static void rc_release_drivers(void) -{ - tty_unregister_driver(riscom_driver); - put_tty_driver(riscom_driver); -} - -#ifndef MODULE -/* - * Called at boot time. - * - * You can specify IO base for up to RC_NBOARD cards, - * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt. - * Note that there will be no probing at default - * addresses in this case. - * - */ -static int __init riscom8_setup(char *str) -{ - int ints[RC_NBOARD]; - int i; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - for (i = 0; i < RC_NBOARD; i++) { - if (i < ints[0]) - rc_board[i].base = ints[i+1]; - else - rc_board[i].base = 0; - } - return 1; -} - -__setup("riscom8=", riscom8_setup); -#endif - -static char banner[] __initdata = - KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin " - "1994-1996.\n"; -static char no_boards_msg[] __initdata = - KERN_INFO "rc: No RISCom/8 boards detected.\n"; - -/* - * This routine must be called by kernel at boot time - */ -static int __init riscom8_init(void) -{ - int i; - int found = 0; - - printk(banner); - - if (rc_init_drivers()) - return -EIO; - - for (i = 0; i < RC_NBOARD; i++) - if (rc_board[i].base && !rc_probe(&rc_board[i])) - found++; - if (!found) { - rc_release_drivers(); - printk(no_boards_msg); - return -EIO; - } - return 0; -} - -#ifdef MODULE -static int iobase; -static int iobase1; -static int iobase2; -static int iobase3; -module_param(iobase, int, 0); -module_param(iobase1, int, 0); -module_param(iobase2, int, 0); -module_param(iobase3, int, 0); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR); -#endif /* MODULE */ - -/* - * You can setup up to 4 boards (current value of RC_NBOARD) - * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter. - * - */ -static int __init riscom8_init_module(void) -{ -#ifdef MODULE - int i; - - if (iobase || iobase1 || iobase2 || iobase3) { - for (i = 0; i < RC_NBOARD; i++) - rc_board[i].base = 0; - } - - if (iobase) - rc_board[0].base = iobase; - if (iobase1) - rc_board[1].base = iobase1; - if (iobase2) - rc_board[2].base = iobase2; - if (iobase3) - rc_board[3].base = iobase3; -#endif /* MODULE */ - - return riscom8_init(); -} - -static void __exit riscom8_exit_module(void) -{ - int i; - - rc_release_drivers(); - for (i = 0; i < RC_NBOARD; i++) - if (rc_board[i].flags & RC_BOARD_PRESENT) - rc_release_io_range(&rc_board[i]); - -} - -module_init(riscom8_init_module); -module_exit(riscom8_exit_module); diff --git a/drivers/char/riscom8.h b/drivers/char/riscom8.h deleted file mode 100644 index c9876b3f9714..000000000000 --- a/drivers/char/riscom8.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * linux/drivers/char/riscom8.h -- RISCom/8 multiport serial driver. - * - * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) - * - * This code is loosely based on the Linux serial driver, written by - * Linus Torvalds, Theodore T'so and others. The RISCom/8 card - * programming info was obtained from various drivers for other OSes - * (FreeBSD, ISC, etc), but no source code from those drivers were - * directly included in this driver. - * - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __LINUX_RISCOM8_H -#define __LINUX_RISCOM8_H - -#include - -#ifdef __KERNEL__ - -#define RC_NBOARD 4 -/* NOTE: RISCom decoder recognizes 16 addresses... */ -#define RC_NPORT 8 -#define RC_BOARD(line) (((line) >> 3) & 0x07) -#define RC_PORT(line) ((line) & (RC_NPORT - 1)) - -/* Ticks per sec. Used for setting receiver timeout and break length */ -#define RISCOM_TPS 4000 - -/* Yeah, after heavy testing I decided it must be 6. - * Sure, You can change it if needed. - */ -#define RISCOM_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ - -#define RISCOM8_MAGIC 0x0907 - -#define RC_IOBASE1 0x220 -#define RC_IOBASE2 0x240 -#define RC_IOBASE3 0x250 -#define RC_IOBASE4 0x260 - -struct riscom_board { - unsigned long flags; - unsigned short base; - unsigned char irq; - signed char count; - unsigned char DTR; -}; - -#define RC_BOARD_PRESENT 0x00000001 -#define RC_BOARD_ACTIVE 0x00000002 - -struct riscom_port { - int magic; - struct tty_port port; - int baud_base; - int timeout; - int custom_divisor; - int xmit_head; - int xmit_tail; - int xmit_cnt; - short wakeup_chars; - short break_length; - unsigned char mark_mask; - unsigned char IER; - unsigned char MSVR; - unsigned char COR2; -#ifdef RC_REPORT_OVERRUN - unsigned long overrun; -#endif -#ifdef RC_REPORT_FIFO - unsigned long hits[10]; -#endif -}; - -#endif /* __KERNEL__ */ -#endif /* __LINUX_RISCOM8_H */ diff --git a/drivers/char/riscom8_reg.h b/drivers/char/riscom8_reg.h deleted file mode 100644 index a32475ed0d18..000000000000 --- a/drivers/char/riscom8_reg.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * linux/drivers/char/riscom8_reg.h -- RISCom/8 multiport serial driver. - */ - -/* - * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc. - */ - -/* - * Address mapping between Cirrus Logic CD180 chip internal registers - * and ISA port addresses: - * - * CL-CD180 A6 A5 A4 A3 A2 A1 A0 - * ISA A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 - */ -#define RC_TO_ISA(r) ((((r)&0x07)<<1) | (((r)&~0x07)<<7)) - - -/* RISCom/8 On-Board Registers (assuming address translation) */ - -#define RC_RI 0x100 /* Ring Indicator Register (R/O) */ -#define RC_DTR 0x100 /* DTR Register (W/O) */ -#define RC_BSR 0x101 /* Board Status Register (R/O) */ -#define RC_CTOUT 0x101 /* Clear Timeout (W/O) */ - - -/* Board Status Register */ - -#define RC_BSR_TOUT 0x08 /* Hardware Timeout */ -#define RC_BSR_RINT 0x04 /* Receiver Interrupt */ -#define RC_BSR_TINT 0x02 /* Transmitter Interrupt */ -#define RC_BSR_MINT 0x01 /* Modem Ctl Interrupt */ - - -/* On-board oscillator frequency (in Hz) */ -#define RC_OSCFREQ 9830400 - -/* Values of choice for Interrupt ACKs */ -#define RC_ACK_MINT 0x81 /* goes to PILR1 */ -#define RC_ACK_RINT 0x82 /* goes to PILR3 */ -#define RC_ACK_TINT 0x84 /* goes to PILR2 */ - -/* Chip ID (sorry, only one chip now) */ -#define RC_ID 0x10 - -/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */ - -#define CD180_NCH 8 /* Total number of channels */ -#define CD180_TPC 16 /* Ticks per character */ -#define CD180_NFIFO 8 /* TX FIFO size */ - - -/* Global registers */ - -#define CD180_GIVR 0x40 /* Global Interrupt Vector Register */ -#define CD180_GICR 0x41 /* Global Interrupting Channel Register */ -#define CD180_PILR1 0x61 /* Priority Interrupt Level Register 1 */ -#define CD180_PILR2 0x62 /* Priority Interrupt Level Register 2 */ -#define CD180_PILR3 0x63 /* Priority Interrupt Level Register 3 */ -#define CD180_CAR 0x64 /* Channel Access Register */ -#define CD180_GFRCR 0x6b /* Global Firmware Revision Code Register */ -#define CD180_PPRH 0x70 /* Prescaler Period Register High */ -#define CD180_PPRL 0x71 /* Prescaler Period Register Low */ -#define CD180_RDR 0x78 /* Receiver Data Register */ -#define CD180_RCSR 0x7a /* Receiver Character Status Register */ -#define CD180_TDR 0x7b /* Transmit Data Register */ -#define CD180_EOIR 0x7f /* End of Interrupt Register */ - - -/* Channel Registers */ - -#define CD180_CCR 0x01 /* Channel Command Register */ -#define CD180_IER 0x02 /* Interrupt Enable Register */ -#define CD180_COR1 0x03 /* Channel Option Register 1 */ -#define CD180_COR2 0x04 /* Channel Option Register 2 */ -#define CD180_COR3 0x05 /* Channel Option Register 3 */ -#define CD180_CCSR 0x06 /* Channel Control Status Register */ -#define CD180_RDCR 0x07 /* Receive Data Count Register */ -#define CD180_SCHR1 0x09 /* Special Character Register 1 */ -#define CD180_SCHR2 0x0a /* Special Character Register 2 */ -#define CD180_SCHR3 0x0b /* Special Character Register 3 */ -#define CD180_SCHR4 0x0c /* Special Character Register 4 */ -#define CD180_MCOR1 0x10 /* Modem Change Option 1 Register */ -#define CD180_MCOR2 0x11 /* Modem Change Option 2 Register */ -#define CD180_MCR 0x12 /* Modem Change Register */ -#define CD180_RTPR 0x18 /* Receive Timeout Period Register */ -#define CD180_MSVR 0x28 /* Modem Signal Value Register */ -#define CD180_RBPRH 0x31 /* Receive Baud Rate Period Register High */ -#define CD180_RBPRL 0x32 /* Receive Baud Rate Period Register Low */ -#define CD180_TBPRH 0x39 /* Transmit Baud Rate Period Register High */ -#define CD180_TBPRL 0x3a /* Transmit Baud Rate Period Register Low */ - - -/* Global Interrupt Vector Register (R/W) */ - -#define GIVR_ITMASK 0x07 /* Interrupt type mask */ -#define GIVR_IT_MODEM 0x01 /* Modem Signal Change Interrupt */ -#define GIVR_IT_TX 0x02 /* Transmit Data Interrupt */ -#define GIVR_IT_RCV 0x03 /* Receive Good Data Interrupt */ -#define GIVR_IT_REXC 0x07 /* Receive Exception Interrupt */ - - -/* Global Interrupt Channel Register (R/W) */ - -#define GICR_CHAN 0x1c /* Channel Number Mask */ -#define GICR_CHAN_OFF 2 /* Channel Number Offset */ - - -/* Channel Address Register (R/W) */ - -#define CAR_CHAN 0x07 /* Channel Number Mask */ -#define CAR_A7 0x08 /* A7 Address Extension (unused) */ - - -/* Receive Character Status Register (R/O) */ - -#define RCSR_TOUT 0x80 /* Rx Timeout */ -#define RCSR_SCDET 0x70 /* Special Character Detected Mask */ -#define RCSR_NO_SC 0x00 /* No Special Characters Detected */ -#define RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected */ -#define RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected */ -#define RCSR_SC_3 0x30 /* Special Char 3 Detected */ -#define RCSR_SC_4 0x40 /* Special Char 4 Detected */ -#define RCSR_BREAK 0x08 /* Break has been detected */ -#define RCSR_PE 0x04 /* Parity Error */ -#define RCSR_FE 0x02 /* Frame Error */ -#define RCSR_OE 0x01 /* Overrun Error */ - - -/* Channel Command Register (R/W) (commands in groups can be OR-ed) */ - -#define CCR_HARDRESET 0x81 /* Reset the chip */ - -#define CCR_SOFTRESET 0x80 /* Soft Channel Reset */ - -#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */ -#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */ -#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */ - -#define CCR_SSCH1 0x21 /* Send Special Character 1 */ - -#define CCR_SSCH2 0x22 /* Send Special Character 2 */ - -#define CCR_SSCH3 0x23 /* Send Special Character 3 */ - -#define CCR_SSCH4 0x24 /* Send Special Character 4 */ - -#define CCR_TXEN 0x18 /* Enable Transmitter */ -#define CCR_RXEN 0x12 /* Enable Receiver */ - -#define CCR_TXDIS 0x14 /* Disable Transmitter */ -#define CCR_RXDIS 0x11 /* Disable Receiver */ - - -/* Interrupt Enable Register (R/W) */ - -#define IER_DSR 0x80 /* Enable interrupt on DSR change */ -#define IER_CD 0x40 /* Enable interrupt on CD change */ -#define IER_CTS 0x20 /* Enable interrupt on CTS change */ -#define IER_RXD 0x10 /* Enable interrupt on Receive Data */ -#define IER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */ -#define IER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */ -#define IER_TXEMPTY 0x02 /* Enable interrupt on TX completely empty */ -#define IER_RET 0x01 /* Enable interrupt on RX Exc. Timeout */ - - -/* Channel Option Register 1 (R/W) */ - -#define COR1_ODDP 0x80 /* Odd Parity */ -#define COR1_PARMODE 0x60 /* Parity Mode mask */ -#define COR1_NOPAR 0x00 /* No Parity */ -#define COR1_FORCEPAR 0x20 /* Force Parity */ -#define COR1_NORMPAR 0x40 /* Normal Parity */ -#define COR1_IGNORE 0x10 /* Ignore Parity on RX */ -#define COR1_STOPBITS 0x0c /* Number of Stop Bits */ -#define COR1_1SB 0x00 /* 1 Stop Bit */ -#define COR1_15SB 0x04 /* 1.5 Stop Bits */ -#define COR1_2SB 0x08 /* 2 Stop Bits */ -#define COR1_CHARLEN 0x03 /* Character Length */ -#define COR1_5BITS 0x00 /* 5 bits */ -#define COR1_6BITS 0x01 /* 6 bits */ -#define COR1_7BITS 0x02 /* 7 bits */ -#define COR1_8BITS 0x03 /* 8 bits */ - - -/* Channel Option Register 2 (R/W) */ - -#define COR2_IXM 0x80 /* Implied XON mode */ -#define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */ -#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */ -#define COR2_LLM 0x10 /* Local Loopback Mode */ -#define COR2_RLM 0x08 /* Remote Loopback Mode */ -#define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */ -#define COR2_CTSAE 0x02 /* CTS Automatic Enable */ -#define COR2_DSRAE 0x01 /* DSR Automatic Enable */ - - -/* Channel Option Register 3 (R/W) */ - -#define COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3) */ -#define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4) */ -#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */ -#define COR3_SCDE 0x10 /* Special Character Detection Enable */ -#define COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8) */ - - -/* Channel Control Status Register (R/O) */ - -#define CCSR_RXEN 0x80 /* Receiver Enabled */ -#define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent) */ -#define CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent) */ -#define CCSR_TXEN 0x08 /* Transmitter Enabled */ -#define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */ -#define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */ - - -/* Modem Change Option Register 1 (R/W) */ - -#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */ -#define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */ -#define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */ -#define MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8) */ -#define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */ - - -/* Modem Change Option Register 2 (R/W) */ - -#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */ -#define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */ -#define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */ - - -/* Modem Change Register (R/W) */ - -#define MCR_DSRCHG 0x80 /* DSR Changed */ -#define MCR_CDCHG 0x40 /* CD Changed */ -#define MCR_CTSCHG 0x20 /* CTS Changed */ - - -/* Modem Signal Value Register (R/W) */ - -#define MSVR_DSR 0x80 /* Current state of DSR input */ -#define MSVR_CD 0x40 /* Current state of CD input */ -#define MSVR_CTS 0x20 /* Current state of CTS input */ -#define MSVR_DTR 0x02 /* Current state of DTR output */ -#define MSVR_RTS 0x01 /* Current state of RTS output */ - - -/* Escape characters */ - -#define CD180_C_ESC 0x00 /* Escape character */ -#define CD180_C_SBRK 0x81 /* Start sending BREAK */ -#define CD180_C_DELAY 0x82 /* Delay output */ -#define CD180_C_EBRK 0x83 /* Stop sending BREAK */ diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c deleted file mode 100644 index 674af6933978..000000000000 --- a/drivers/char/serial167.c +++ /dev/null @@ -1,2489 +0,0 @@ -/* - * linux/drivers/char/serial167.c - * - * Driver for MVME166/7 board serial ports, which are via a CD2401. - * Based very much on cyclades.c. - * - * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk] - * - * ============================================================== - * - * static char rcsid[] = - * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $"; - * - * linux/kernel/cyclades.c - * - * Maintained by Marcio Saito (cyclades@netcom.com) and - * Randolph Bentson (bentson@grieg.seaslug.org) - * - * Much of the design and some of the code came from serial.c - * which was copyright (C) 1991, 1992 Linus Torvalds. It was - * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, - * and then fixed as suggested by Michael K. Johnson 12/12/92. - * - * This version does not support shared irq's. - * - * $Log: cyclades.c,v $ - * Revision 1.36.1.4 1995/03/29 06:14:14 bentson - * disambiguate between Cyclom-16Y and Cyclom-32Ye; - * - * Changes: - * - * 200 lines of changes record removed - RGH 11-10-95, starting work on - * converting this to drive serial ports on mvme166 (cd2401). - * - * Arnaldo Carvalho de Melo - 2000/08/25 - * - get rid of verify_area - * - use get_user to access memory from userspace in set_threshold, - * set_default_threshold and set_timeout - * - don't use the panic function in serial167_init - * - do resource release on failure on serial167_init - * - include missing restore_flags in mvme167_serial_console_setup - * - * Kars de Jong - 2004/09/06 - * - replace bottom half handler with task queue handler - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define SERIAL_PARANOIA_CHECK -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_THROTTLE -#undef SERIAL_DEBUG_OTHER -#undef SERIAL_DEBUG_IO -#undef SERIAL_DEBUG_COUNT -#undef SERIAL_DEBUG_DTR -#undef CYCLOM_16Y_HACK -#define CYCLOM_ENABLE_MONITORING - -#define WAKEUP_CHARS 256 - -#define STD_COM_FLAGS (0) - -static struct tty_driver *cy_serial_driver; -extern int serial_console; -static struct cyclades_port *serial_console_info = NULL; -static unsigned int serial_console_cflag = 0; -u_char initial_console_speed; - -/* Base address of cd2401 chip on mvme166/7 */ - -#define BASE_ADDR (0xfff45000) -#define pcc2chip ((volatile u_char *)0xfff42000) -#define PccSCCMICR 0x1d -#define PccSCCTICR 0x1e -#define PccSCCRICR 0x1f -#define PccTPIACKR 0x25 -#define PccRPIACKR 0x27 -#define PccIMLR 0x3f - -/* This is the per-port data structure */ -struct cyclades_port cy_port[] = { - /* CARD# */ - {-1}, /* ttyS0 */ - {-1}, /* ttyS1 */ - {-1}, /* ttyS2 */ - {-1}, /* ttyS3 */ -}; - -#define NR_PORTS ARRAY_SIZE(cy_port) - -/* - * This is used to look up the divisor speeds and the timeouts - * We're normally limited to 15 distinct baud rates. The extra - * are accessed via settings in info->flags. - * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - * 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 -}; - -#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_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 -}; - -/* 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 void shutdown(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 *); -#ifdef CYCLOM_SHOW_STATUS -static void show_status(int); -#endif - -/* - * I have my own version of udelay(), as it is needed when initialising - * the chip, before the delay loop has been calibrated. Should probably - * reference one of the vmechip2 or pccchip2 counter for an accurate - * delay, but this wild guess will do for now. - */ - -void my_udelay(long us) -{ - u_char x; - volatile u_char *p = &x; - int i; - - while (us--) - for (i = 100; i; i--) - x |= *p; -} - -static inline int serial_paranoia_check(struct cyclades_port *info, char *name, - const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - if (!info) { - printk("Warning: null cyclades_port for (%s) in %s\n", name, - routine); - return 1; - } - - if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) { - 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 */ - -#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); - printk(KERN_EMERG "%s", data); - local_irq_restore(flags); -} - -char scrn[2]; -void CP(char data) -{ - unsigned long flags; - local_irq_save(flags); - scrn[0] = data; - printk(KERN_EMERG "%c", 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 */ -#endif - -/* This routine waits up to 1000 micro-seconds for the previous - command to the Cirrus chip to complete and then issues the - 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) -{ - unsigned long flags; - volatile int i; - - 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); - } - /* if the CCR never cleared, the previous command - 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 */ - -/* 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) -{ - struct cyclades_port *info = 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); /* */ -#endif - - if (serial_paranoia_check(info, tty->name, "cy_stop")) - return; - - channel = info->line; - - 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) -{ - struct cyclades_port *info = 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); /* */ -#endif - - if (serial_paranoia_check(info, tty->name, "cy_start")) - return; - - channel = info->line; - - local_irq_save(flags); - base_addr[CyCAR] = (u_char) (channel); - base_addr[CyIER] |= CyTxMpty; - local_irq_restore(flags); -} /* cy_start */ - -/* 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) -{ - 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 */ - - 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 lose - 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) -{ - 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('!'); */ - wake_up_interruptible(&info->open_wait); - } else { -/* CP('@'); */ - tty_hangup(info->tty); - wake_up_interruptible(&info->open_wait); - info->flags &= ~ASYNC_NORMAL_ACTIVE; - } - } - 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; - tty_wakeup(info->tty); - } - } else { - if (!(mdm_status & CyCTS)) { - /* !!! cy_stop isn't used because... */ - info->tty->stopped = 1; - base_addr[CyIER] &= - ~(CyTxMpty | CyTxRdy); - } - } - } - if (mdm_status & CyDSR) { - } - } - base_addr[CyMEOIR] = 0; - return IRQ_HANDLED; -} /* cy_modem_interrupt */ - -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; - - /* determine the channel and change to that context */ - channel = (u_short) (base_addr[CyLICR] >> 2); - - /* 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 = &cy_port[channel]; - info->last_active = jiffies; - if (info->tty == 0) { - base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); - 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); - base_addr[CyTDR] = outch; - base_addr[CyTDR] = 0; - char_count--; - char_count--; - } else { - break; - } - } - } - - if (info->xmit_cnt < WAKEUP_CHARS) - tty_wakeup(info->tty); - - 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) -{ - 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; - - /* 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]; - - /* 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 - while (char_count--) { - data = base_addr[CyRDR]; - tty_insert_flip_char(tty, data, TTY_NORMAL); -#ifdef CYCLOM_16Y_HACK - udelay(10L); -#endif - } - tty_schedule_flip(tty); - } - /* end of service */ - base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; - return IRQ_HANDLED; -} /* cy_rx_interrupt */ - -/* This is called whenever a port becomes active; - interrupts are enabled and DTR & RTS are turned on. - */ -static int startup(struct cyclades_port *info) -{ - unsigned long flags; - volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; - int channel; - - if (info->flags & ASYNC_INITIALIZED) { - return 0; - } - - if (!info->type) { - if (info->tty) { - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - return 0; - } - if (!info->xmit_buf) { - info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); - if (!info->xmit_buf) { - return -ENOMEM; - } - } - - config_setup(info); - - channel = info->line; - -#ifdef SERIAL_DEBUG_OPEN - 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); - - 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]); -#endif - - base_addr[CyIER] |= CyRxData; - info->flags |= ASYNC_INITIALIZED; - - 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); - -#ifdef SERIAL_DEBUG_OPEN - printk(" done\n"); -#endif - return 0; -} /* startup */ - -void start_xmit(struct cyclades_port *info) -{ - unsigned long flags; - volatile unsigned char *base_addr = (u_char *) BASE_ADDR; - int channel; - - channel = info->line; - local_irq_save(flags); - base_addr[CyCAR] = channel; - base_addr[CyIER] |= CyTxMpty; - 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) -{ - unsigned long flags; - volatile unsigned char *base_addr = (u_char *) BASE_ADDR; - int channel; - - if (!(info->flags & ASYNC_INITIALIZED)) { -/* CP('$'); */ - return; - } - - channel = info->line; - -#ifdef SERIAL_DEBUG_OPEN - 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; - } - - base_addr[CyCAR] = (u_char) channel; - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - base_addr[CyMSVR1] = 0; -/* CP('C');CP('1'); */ - 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]); -#endif - } - 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); - } - info->flags &= ~ASYNC_INITIALIZED; - local_irq_restore(flags); - -#ifdef SERIAL_DEBUG_OPEN - printk(" done\n"); -#endif -} /* shutdown */ - -/* - * This routine finds or computes the various line characteristics. - */ -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; -#ifdef CBAUDEX -/* Starting with kernel 1.1.65, there is direct support for - higher baud rates. The following code supports those - changes. The conditional aspect allows this driver to be - used for earlier as well as later kernel versions. (The - mapping is slightly different from serial.c because there - 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; -#ifdef B78600 - 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->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 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; - - /*********************************************** - The hardware option, CyRtsAO, presents RTS when - the chip has characters to send. Since most modems - use RTS as reverse (inbound) flow control, this - option is not used. If inbound flow control is - necessary, DTR can be programmed to provide the - appropriate signals for use with a non-standard - cable. Contact Marcio Saito for details. - ***********************************************/ - - channel = info->line; - - 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; - if (base_addr[CyLIVR] != 0x5c) - base_addr[CyLIVR] = 0x5c; - - /* tx and rx baud rate */ - - if (base_addr[CyCOR1] != info->cor1) - need_init_chan = 1; - if (base_addr[CyTCOR] != info->tco) - base_addr[CyTCOR] = info->tco; - if (base_addr[CyTBPR] != info->tbpr) - base_addr[CyTBPR] = info->tbpr; - if (base_addr[CyRCOR] != info->rco) - base_addr[CyRCOR] = info->rco; - if (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); - if (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); - if (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; - if (base_addr[CyCOR2] != info->cor2) - base_addr[CyCOR2] = info->cor2; - if (base_addr[CyCOR3] != info->cor3) - base_addr[CyCOR3] = info->cor3; - if (base_addr[CyCOR4] != info->cor4) - base_addr[CyCOR4] = info->cor4; - if (base_addr[CyCOR5] != info->cor5) - base_addr[CyCOR5] = info->cor5; - if (base_addr[CyCOR6] != info->cor6) - base_addr[CyCOR6] = info->cor6; - if (base_addr[CyCOR7] != info->cor7) - base_addr[CyCOR7] = info->cor7; - - if (need_init_chan) - write_cy_cmd(base_addr, CyINIT_CHAN); - - 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; - if (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; -#ifdef SERIAL_DEBUG_DTR - 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; -#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 - } - - if (info->tty) { - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - - local_irq_restore(flags); - -} /* config_setup */ - -static int cy_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct cyclades_port *info = tty->driver_data; - unsigned long flags; - -#ifdef SERIAL_DEBUG_IO - printk("cy_put_char %s(0x%02x)\n", tty->name, ch); -#endif - - if (serial_paranoia_check(info, tty->name, "cy_put_char")) - return 0; - - if (!info->xmit_buf) - return 0; - - local_irq_save(flags); - if (info->xmit_cnt >= PAGE_SIZE - 1) { - local_irq_restore(flags); - return 0; - } - - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= PAGE_SIZE - 1; - info->xmit_cnt++; - local_irq_restore(flags); - return 1; -} /* cy_put_char */ - -static void cy_flush_chars(struct tty_struct *tty) -{ - struct cyclades_port *info = 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); /* */ -#endif - - 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; - - channel = info->line; - - local_irq_save(flags); - base_addr[CyCAR] = channel; - base_addr[CyIER] |= CyTxMpty; - 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, - start it off by enabling interrupts. The interrupt service - 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) -{ - struct cyclades_port *info = tty->driver_data; - unsigned long flags; - int c, total = 0; - -#ifdef SERIAL_DEBUG_IO - 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 */ - -static int cy_write_room(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - int ret; - -#ifdef SERIAL_DEBUG_IO - 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 */ - -static int cy_chars_in_buffer(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - -#ifdef SERIAL_DEBUG_IO - 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 */ - -static void cy_flush_buffer(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - unsigned long flags; - -#ifdef SERIAL_DEBUG_IO - printk("cy_flush_buffer %s\n", tty->name); /* */ -#endif - - 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 */ - -/* 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) -{ - struct cyclades_port *info = 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); -#endif - - 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!!! */ - } - - channel = info->line; - - local_irq_save(flags); - base_addr[CyCAR] = (u_char) channel; - base_addr[CyMSVR1] = 0; - local_irq_restore(flags); -} /* cy_throttle */ - -static void cy_unthrottle(struct tty_struct *tty) -{ - struct cyclades_port *info = 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); -#endif - - 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!!! */ - } - - channel = info->line; - - local_irq_save(flags); - base_addr[CyCAR] = (u_char) channel; - base_addr[CyMSVR1] = CyRTS; - local_irq_restore(flags); -} /* cy_unthrottle */ - -static int -get_serial_info(struct cyclades_port *info, - struct serial_struct __user * retinfo) -{ - 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 */ - -static int -set_serial_info(struct cyclades_port *info, - struct serial_struct __user * new_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 (!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; - -check_and_exit: - if (info->flags & ASYNC_INITIALIZED) { - config_setup(info); - return 0; - } - return startup(info); -} /* set_serial_info */ - -static int cy_tiocmget(struct tty_struct *tty) -{ - struct cyclades_port *info = 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 */ - -static int -cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) -{ - struct cyclades_port *info = 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); - } - if (set & TIOCM_DTR) { - local_irq_save(flags); - base_addr[CyCAR] = (u_char) channel; -/* CP('S');CP('2'); */ - 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); - } - - if (clear & TIOCM_RTS) { - local_irq_save(flags); - base_addr[CyCAR] = (u_char) channel; - base_addr[CyMSVR1] = 0; - local_irq_restore(flags); - } - if (clear & TIOCM_DTR) { - local_irq_save(flags); - base_addr[CyCAR] = (u_char) channel; -/* CP('C');CP('2'); */ - 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]); -#endif - 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 */ - -static int -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; -} - -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; -} - -static int -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); -} - -static int -set_default_threshold(struct cyclades_port *info, unsigned long __user * arg) -{ - unsigned long value; - - if (get_user(value, arg)) - return -EFAULT; - - info->default_threshold = value & 0x0f; - return 0; -} - -static int -get_default_threshold(struct cyclades_port *info, unsigned long __user * value) -{ - return put_user(info->default_threshold, value); -} - -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; -} - -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); -} - -static int set_default_timeout(struct cyclades_port *info, unsigned long value) -{ - info->default_timeout = value & 0xff; - return 0; -} - -static int -get_default_timeout(struct cyclades_port *info, unsigned long __user * value) -{ - return put_user(info->default_timeout, value); -} - -static int -cy_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct cyclades_port *info = 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 - - tty_lock(); - - 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; - -/* The following commands are incompletely implemented!!! */ - case TIOCGSERIAL: - ret_val = get_serial_info(info, argp); - break; - case TIOCSSERIAL: - ret_val = set_serial_info(info, argp); - break; - default: - ret_val = -ENOIOCTLCMD; - } - tty_unlock(); - -#ifdef SERIAL_DEBUG_OTHER - printk("cy_ioctl done\n"); -#endif - - return ret_val; -} /* cy_ioctl */ - -static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct cyclades_port *info = tty->driver_data; - -#ifdef SERIAL_DEBUG_OTHER - printk("cy_set_termios %s\n", tty->name); -#endif - - 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); - } -#ifdef tytso_patch_94Nov25_1726 - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); -#endif -} /* cy_set_termios */ - -static void cy_close(struct tty_struct *tty, struct file *filp) -{ - struct cyclades_port *info = tty->driver_data; - -/* CP('C'); */ -#ifdef SERIAL_DEBUG_OTHER - printk("cy_close %s\n", tty->name); -#endif - - 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; - } -#ifdef SERIAL_DEBUG_COUNT - 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); -#ifdef SERIAL_DEBUG_COUNT - 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); - cy_flush_buffer(tty); - tty_ldisc_flush(tty); - 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"); -#endif -} /* cy_close */ - -/* - * cy_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void cy_hangup(struct tty_struct *tty) -{ - struct cyclades_port *info = tty->driver_data; - -#ifdef SERIAL_DEBUG_OTHER - printk("cy_hangup %s\n", tty->name); /* */ -#endif - - if (serial_paranoia_check(info, tty->name, "cy_hangup")) - return; - - shutdown(info); -#if 0 - info->event = 0; - info->count = 0; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: setting count to 0\n", __LINE__); -#endif - info->tty = 0; -#endif - info->flags &= ~ASYNC_NORMAL_ACTIVE; - wake_up_interruptible(&info->open_wait); -} /* cy_hangup */ - -/* - * ------------------------------------------------------------ - * cy_open() and friends - * ------------------------------------------------------------ - */ - -static int -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); -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: %s, count = %d\n", - tty->name, info->count); - /**/ -#endif - info->count--; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); -#endif - info->blocked_open++; - - channel = info->line; - - while (1) { - local_irq_save(flags); - base_addr[CyCAR] = (u_char) channel; - base_addr[CyMSVR1] = CyRTS; -/* CP('S');CP('4'); */ - 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; -/* 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; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: %s, count = %d\n", - tty->name, info->count); - /**/ -#endif - tty_unlock(); - schedule(); - tty_lock(); - } - __set_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); -#endif - } - info->blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - 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 */ - -/* - * 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) -{ - 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; - } -#ifdef SERIAL_DEBUG_OTHER - printk("cy_open %s\n", tty->name); /* */ -#endif - 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); - /**/ -#endif - info->count++; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); -#endif - tty->driver_data = info; - info->tty = tty; - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) { - return 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); -#endif - return retval; - } -#ifdef SERIAL_DEBUG_OPEN - printk("cy_open done\n"); - /**/ -#endif - return 0; -} /* cy_open */ - -/* - * --------------------------------------------------------------------- - * serial167_init() and friends - * - * serial167_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static void show_version(void) -{ - printk("MVME166/167 cd2401 driver\n"); -} /* show_version */ - -/* initialize chips on card -- return number of valid - chips (which is number of ports/4) */ - -/* - * This initialises the hardware to a reasonable state. It should - * probe the chip first so as to copy 166-Bug setup as a default for - * port 0. It initialises CMR to CyASYNC; that is never done again, so - * as to limit the number of CyINIT_CHAN commands in normal running. - * - * ... I wonder what I should do if this fails ... - */ - -void mvme167_serial_console_setup(int cflag) -{ - volatile unsigned char *base_addr = (u_char *) BASE_ADDR; - int ch; - u_char spd; - u_char rcor, rbpr, badspeed = 0; - unsigned long flags; - - local_irq_save(flags); - - /* - * First probe channel zero of the chip, to see what speed has - * been selected. - */ - - base_addr[CyCAR] = 0; - - rcor = base_addr[CyRCOR] << 5; - rbpr = base_addr[CyRBPR]; - - for (spd = 0; spd < sizeof(baud_bpr); spd++) - if (rbpr == baud_bpr[spd] && rcor == baud_co[spd]) - break; - if (spd >= sizeof(baud_bpr)) { - spd = 14; /* 19200 */ - badspeed = 1; /* Failed to identify speed */ - } - initial_console_speed = spd; - - /* 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; - } - - 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; - } - - /* - * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms - * tick - */ - - 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 */ - - /* - * Attempt to set up all channels to something reasonable, and - * bang out a INIT_CHAN command. We should then be able to limit - * the amount of fiddling we have to do in normal running. - */ - - 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[CyLIVR] = 0x5c; - base_addr[CyTCOR] = baud_co[spd]; - base_addr[CyTBPR] = baud_bpr[spd]; - base_addr[CyRCOR] = baud_co[spd] >> 5; - base_addr[CyRBPR] = baud_bpr[spd]; - base_addr[CySCHR1] = 'Q' & 0x1f; - base_addr[CySCHR2] = 'X' & 0x1f; - 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[spd]; - base_addr[CyCOR5] = 0; - base_addr[CyCOR6] = 0; - 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); - } - - /* - * Now do specials for channel zero.... - */ - - base_addr[CyMSVR1] = CyRTS; - base_addr[CyMSVR2] = CyDTR; - base_addr[CyIER] = CyRxData; - 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]); - if (badspeed) - 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, - .close = cy_close, - .write = cy_write, - .put_char = cy_put_char, - .flush_chars = cy_flush_chars, - .write_room = cy_write_room, - .chars_in_buffer = cy_chars_in_buffer, - .flush_buffer = cy_flush_buffer, - .ioctl = cy_ioctl, - .throttle = cy_throttle, - .unthrottle = cy_unthrottle, - .set_termios = cy_set_termios, - .stop = cy_stop, - .start = cy_start, - .hangup = cy_hangup, - .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 - for Cyclom cards in the system. As each is found, it is probed - to discover how many chips (and thus how many ports) are present. - These ports are mapped to the tty ports 64 and upward in monotonic - fashion. If an 8-port card is replaced with a 16-port card, the - port mapping on a following card will shift. - - This approach is different from what is used in the other serial - device driver because the Cyclom is more properly a multiplexer, - not just an aggregation of serial ports on one card. - - 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) -{ - struct cyclades_port *info; - int ret = 0; - int good_ports = 0; - int port_num = 0; - int index; - int DefSpeed; -#ifdef notyet - struct sigaction sa; -#endif - - if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401)) - return 0; - - cy_serial_driver = alloc_tty_driver(NR_PORTS); - if (!cy_serial_driver) - return -ENOMEM; - -#if 0 - scrn[1] = '\0'; -#endif - - 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; -#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); - - 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; - } - - port_num = 0; - info = cy_port; - for (index = 0; index < 1; index++) { - - 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->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_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 "); - } - } - } - printk("\n"); - } - while (port_num < NR_PORTS) { - info->line = -1; - port_num++; - info++; - } - - 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); -cleanup_irq_cd2401_modem: - free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); -cleanup_irq_cd2401_errors: - 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 */ - -module_init(serial167_init); - -#ifdef CYCLOM_SHOW_STATUS -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); - -/* Global Registers */ - - printk(" CyGFRCR %x\n", base_addr[CyGFRCR]); - printk(" CyCAR %x\n", base_addr[CyCAR]); - printk(" CyRISR %x\n", base_addr[CyRISR]); - printk(" CyTISR %x\n", base_addr[CyTISR]); - printk(" CyMISR %x\n", base_addr[CyMISR]); - printk(" CyRIR %x\n", base_addr[CyRIR]); - printk(" CyTIR %x\n", base_addr[CyTIR]); - printk(" CyMIR %x\n", base_addr[CyMIR]); - printk(" CyTPR %x\n", base_addr[CyTPR]); - - base_addr[CyCAR] = (u_char) channel; - -/* Virtual Registers */ - -#if 0 - printk(" CyRIVR %x\n", base_addr[CyRIVR]); - printk(" CyTIVR %x\n", base_addr[CyTIVR]); - printk(" CyMIVR %x\n", base_addr[CyMIVR]); - printk(" CyMISR %x\n", base_addr[CyMISR]); -#endif - -/* Channel Registers */ - - printk(" CyCCR %x\n", base_addr[CyCCR]); - printk(" CyIER %x\n", base_addr[CyIER]); - printk(" CyCOR1 %x\n", base_addr[CyCOR1]); - printk(" CyCOR2 %x\n", base_addr[CyCOR2]); - printk(" CyCOR3 %x\n", base_addr[CyCOR3]); - printk(" CyCOR4 %x\n", base_addr[CyCOR4]); - printk(" CyCOR5 %x\n", base_addr[CyCOR5]); -#if 0 - printk(" CyCCSR %x\n", base_addr[CyCCSR]); - printk(" CyRDCR %x\n", base_addr[CyRDCR]); -#endif - printk(" CySCHR1 %x\n", base_addr[CySCHR1]); - printk(" CySCHR2 %x\n", base_addr[CySCHR2]); -#if 0 - printk(" CySCHR3 %x\n", base_addr[CySCHR3]); - printk(" CySCHR4 %x\n", base_addr[CySCHR4]); - printk(" CySCRL %x\n", base_addr[CySCRL]); - printk(" CySCRH %x\n", base_addr[CySCRH]); - printk(" CyLNC %x\n", base_addr[CyLNC]); - printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]); - printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]); -#endif - printk(" CyRTPRL %x\n", base_addr[CyRTPRL]); - printk(" CyRTPRH %x\n", base_addr[CyRTPRH]); - printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]); - printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]); - printk(" CyRBPR %x\n", base_addr[CyRBPR]); - printk(" CyRCOR %x\n", base_addr[CyRCOR]); - printk(" CyTBPR %x\n", base_addr[CyTBPR]); - printk(" CyTCOR %x\n", base_addr[CyTCOR]); - - local_irq_restore(flags); -} /* show_status */ -#endif - -#if 0 -/* Dummy routine in mvme16x/config.c for now */ - -/* Serial console setup. Called from linux/init/main.c */ - -void console_setup(char *str, int *ints) -{ - char *s; - int baud, bits, parity; - int cflag = 0; - - /* Sanity check. */ - 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 ((s = strchr(str, ','))) { - do { - s++; - } 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 (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; - } - - serial_console_info = &cy_port[ints[1]]; - serial_console_cflag = cflag; - serial_console = ints[1] + 64; /*callout_driver.minor_start */ -} -#endif - -/* - * The following is probably out of date for 2.1.x serial console stuff. - * - * The console is registered early on from arch/m68k/kernel/setup.c, and - * it therefore relies on the chip being setup correctly by 166-Bug. This - * seems reasonable, as the serial port has been used to invoke the system - * boot. It also means that this function must not rely on any data - * initialisation performed by serial167_init() etc. - * - * Of course, once the console has been registered, we had better ensure - * that serial167_init() doesn't leave the chip non-functional. - * - * The console must be locked when we get here. - */ - -void serial167_console_write(struct console *co, const char *str, - unsigned count) -{ - volatile unsigned char *base_addr = (u_char *) BASE_ADDR; - unsigned long flags; - volatile u_char sink; - u_char ier; - int port; - u_char do_lf = 0; - int i = 0; - - local_irq_save(flags); - - /* Ensure transmitter is enabled! */ - - port = 0; - base_addr[CyCAR] = (u_char) port; - while (base_addr[CyCCR]) - ; - base_addr[CyCCR] = CyENB_XMTR; - - ier = base_addr[CyIER]; - base_addr[CyIER] = CyTxMpty; - - while (1) { - if (pcc2chip[PccSCCTICR] & 0x20) { - /* We have a Tx int. Acknowledge it */ - sink = pcc2chip[PccTPIACKR]; - if ((base_addr[CyLICR] >> 2) == port) { - if (i == count) { - /* Last char of string is now output */ - base_addr[CyTEOIR] = CyNOTRANS; - break; - } - if (do_lf) { - base_addr[CyTDR] = '\n'; - str++; - i++; - do_lf = 0; - } else if (*str == '\n') { - base_addr[CyTDR] = '\r'; - do_lf = 1; - } else { - base_addr[CyTDR] = *str++; - i++; - } - base_addr[CyTEOIR] = 0; - } else - base_addr[CyTEOIR] = CyNOTRANS; - } - } - - base_addr[CyIER] = ier; - - local_irq_restore(flags); -} - -static struct tty_driver *serial167_console_device(struct console *c, - int *index) -{ - *index = c->index; - return cy_serial_driver; -} - -static struct console sercons = { - .name = "ttyS", - .write = serial167_console_write, - .device = serial167_console_device, - .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) { - mvme167_serial_console_setup(0); - register_console(&sercons); - } - return 0; -} - -console_initcall(serial167_console_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c deleted file mode 100644 index 47e5753f732a..000000000000 --- a/drivers/char/specialix.c +++ /dev/null @@ -1,2368 +0,0 @@ -/* - * specialix.c -- specialix IO8+ multiport serial driver. - * - * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) - * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) - * - * Specialix pays for the development and support of this driver. - * Please DO contact io8-linux@specialix.co.uk if you require - * support. But please read the documentation (specialix.txt) - * first. - * - * This driver was developped in the BitWizard linux device - * driver service. If you require a linux device driver for your - * product, please contact devices@BitWizard.nl for a quote. - * - * This code is firmly based on the riscom/8 serial driver, - * written by Dmitry Gorodchanin. The specialix IO8+ card - * programming information was obtained from the CL-CD1865 Data - * Book, and Specialix document number 6200059: IO8+ Hardware - * Functional Specification. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, - * USA. - * - * Revision history: - * - * Revision 1.0: April 1st 1997. - * Initial release for alpha testing. - * Revision 1.1: April 14th 1997. - * Incorporated Richard Hudsons suggestions, - * removed some debugging printk's. - * Revision 1.2: April 15th 1997. - * Ported to 2.1.x kernels. - * Revision 1.3: April 17th 1997 - * Backported to 2.0. (Compatibility macros). - * Revision 1.4: April 18th 1997 - * Fixed DTR/RTS bug that caused the card to indicate - * "don't send data" to a modem after the password prompt. - * Fixed bug for premature (fake) interrupts. - * Revision 1.5: April 19th 1997 - * fixed a minor typo in the header file, cleanup a little. - * performance warnings are now MAXed at once per minute. - * Revision 1.6: May 23 1997 - * Changed the specialix=... format to include interrupt. - * Revision 1.7: May 27 1997 - * Made many more debug printk's a compile time option. - * Revision 1.8: Jul 1 1997 - * port to linux-2.1.43 kernel. - * Revision 1.9: Oct 9 1998 - * Added stuff for the IO8+/PCI version. - * Revision 1.10: Oct 22 1999 / Jan 21 2000. - * Added stuff for setserial. - * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr) - * - */ - -#define VERSION "1.11" - - -/* - * There is a bunch of documentation about the card, jumpers, config - * settings, restrictions, cables, device names and numbers in - * Documentation/serial/specialix.txt - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "specialix_io8.h" -#include "cd1865.h" - - -/* - This driver can spew a whole lot of debugging output at you. If you - need maximum performance, you should disable the DEBUG define. To - aid in debugging in the field, I'm leaving the compile-time debug - features enabled, and disable them "runtime". That allows me to - instruct people with problems to enable debugging without requiring - them to recompile... -*/ -#define DEBUG - -static int sx_debug; -static int sx_rxfifo = SPECIALIX_RXFIFO; -static int sx_rtscts; - -#ifdef DEBUG -#define dprintk(f, str...) if (sx_debug & f) printk(str) -#else -#define dprintk(f, str...) /* nothing */ -#endif - -#define SX_DEBUG_FLOW 0x0001 -#define SX_DEBUG_DATA 0x0002 -#define SX_DEBUG_PROBE 0x0004 -#define SX_DEBUG_CHAN 0x0008 -#define SX_DEBUG_INIT 0x0010 -#define SX_DEBUG_RX 0x0020 -#define SX_DEBUG_TX 0x0040 -#define SX_DEBUG_IRQ 0x0080 -#define SX_DEBUG_OPEN 0x0100 -#define SX_DEBUG_TERMIOS 0x0200 -#define SX_DEBUG_SIGNALS 0x0400 -#define SX_DEBUG_FIFO 0x0800 - - -#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) -#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) - - -/* Configurable options: */ - -/* Am I paranoid or not ? ;-) */ -#define SPECIALIX_PARANOIA_CHECK - -/* - * The following defines are mostly for testing purposes. But if you need - * some nice reporting in your syslog, you can define them also. - */ -#undef SX_REPORT_FIFO -#undef SX_REPORT_OVERRUN - - - - -#define SPECIALIX_LEGAL_FLAGS \ - (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ - ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ - ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) - -static struct tty_driver *specialix_driver; - -static struct specialix_board sx_board[SX_NBOARD] = { - { 0, SX_IOBASE1, 9, }, - { 0, SX_IOBASE2, 11, }, - { 0, SX_IOBASE3, 12, }, - { 0, SX_IOBASE4, 15, }, -}; - -static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; - - -static int sx_paranoia_check(struct specialix_port const *port, - char *name, const char *routine) -{ -#ifdef SPECIALIX_PARANOIA_CHECK - static const char *badmagic = KERN_ERR - "sx: Warning: bad specialix port magic number for device %s in %s\n"; - static const char *badinfo = KERN_ERR - "sx: Warning: null specialix port for device %s in %s\n"; - - if (!port) { - printk(badinfo, name, routine); - return 1; - } - if (port->magic != SPECIALIX_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - - -/* - * - * Service functions for specialix IO8+ driver. - * - */ - -/* Get board number from pointer */ -static inline int board_No(struct specialix_board *bp) -{ - return bp - sx_board; -} - - -/* Get port number from pointer */ -static inline int port_No(struct specialix_port const *port) -{ - return SX_PORT(port - sx_port); -} - - -/* Get pointer to board from pointer to port */ -static inline struct specialix_board *port_Board( - struct specialix_port const *port) -{ - return &sx_board[SX_BOARD(port - sx_port)]; -} - - -/* Input Byte from CL CD186x register */ -static inline unsigned char sx_in(struct specialix_board *bp, - unsigned short reg) -{ - bp->reg = reg | 0x80; - outb(reg | 0x80, bp->base + SX_ADDR_REG); - return inb(bp->base + SX_DATA_REG); -} - - -/* Output Byte to CL CD186x register */ -static inline void sx_out(struct specialix_board *bp, unsigned short reg, - unsigned char val) -{ - bp->reg = reg | 0x80; - outb(reg | 0x80, bp->base + SX_ADDR_REG); - outb(val, bp->base + SX_DATA_REG); -} - - -/* Input Byte from CL CD186x register */ -static inline unsigned char sx_in_off(struct specialix_board *bp, - unsigned short reg) -{ - bp->reg = reg; - outb(reg, bp->base + SX_ADDR_REG); - return inb(bp->base + SX_DATA_REG); -} - - -/* Output Byte to CL CD186x register */ -static inline void sx_out_off(struct specialix_board *bp, - unsigned short reg, unsigned char val) -{ - bp->reg = reg; - outb(reg, bp->base + SX_ADDR_REG); - outb(val, bp->base + SX_DATA_REG); -} - - -/* Wait for Channel Command Register ready */ -static void sx_wait_CCR(struct specialix_board *bp) -{ - unsigned long delay, flags; - unsigned char ccr; - - for (delay = SX_CCR_TIMEOUT; delay; delay--) { - spin_lock_irqsave(&bp->lock, flags); - ccr = sx_in(bp, CD186x_CCR); - spin_unlock_irqrestore(&bp->lock, flags); - if (!ccr) - return; - udelay(1); - } - - printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); -} - - -/* Wait for Channel Command Register ready */ -static void sx_wait_CCR_off(struct specialix_board *bp) -{ - unsigned long delay; - unsigned char crr; - unsigned long flags; - - for (delay = SX_CCR_TIMEOUT; delay; delay--) { - spin_lock_irqsave(&bp->lock, flags); - crr = sx_in_off(bp, CD186x_CCR); - spin_unlock_irqrestore(&bp->lock, flags); - if (!crr) - return; - udelay(1); - } - - printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); -} - - -/* - * specialix IO8+ IO range functions. - */ - -static int sx_request_io_range(struct specialix_board *bp) -{ - return request_region(bp->base, - bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, - "specialix IO8+") == NULL; -} - - -static void sx_release_io_range(struct specialix_board *bp) -{ - release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? - SX_PCI_IO_SPACE : SX_IO_SPACE); -} - - -/* Set the IRQ using the RTS lines that run to the PAL on the board.... */ -static int sx_set_irq(struct specialix_board *bp) -{ - int virq; - int i; - unsigned long flags; - - if (bp->flags & SX_BOARD_IS_PCI) - return 1; - switch (bp->irq) { - /* In the same order as in the docs... */ - case 15: - virq = 0; - break; - case 12: - virq = 1; - break; - case 11: - virq = 2; - break; - case 9: - virq = 3; - break; - default:printk(KERN_ERR - "Speclialix: cannot set irq to %d.\n", bp->irq); - return 0; - } - spin_lock_irqsave(&bp->lock, flags); - for (i = 0; i < 2; i++) { - sx_out(bp, CD186x_CAR, i); - sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); - } - spin_unlock_irqrestore(&bp->lock, flags); - return 1; -} - - -/* Reset and setup CD186x chip */ -static int sx_init_CD186x(struct specialix_board *bp) -{ - unsigned long flags; - int scaler; - int rv = 1; - - func_enter(); - sx_wait_CCR_off(bp); /* Wait for CCR ready */ - spin_lock_irqsave(&bp->lock, flags); - sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */ - spin_unlock_irqrestore(&bp->lock, flags); - msleep(50); /* Delay 0.05 sec */ - spin_lock_irqsave(&bp->lock, flags); - sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */ - sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */ - sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */ - sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ - sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ - /* Set RegAckEn */ - sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); - - /* Setting up prescaler. We need 4 ticks per 1 ms */ - scaler = SX_OSCFREQ/SPECIALIX_TPS; - - sx_out_off(bp, CD186x_PPRH, scaler >> 8); - sx_out_off(bp, CD186x_PPRL, scaler & 0xff); - spin_unlock_irqrestore(&bp->lock, flags); - - if (!sx_set_irq(bp)) { - /* Figure out how to pass this along... */ - printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); - rv = 0; - } - - func_exit(); - return rv; -} - - -static int read_cross_byte(struct specialix_board *bp, int reg, int bit) -{ - int i; - int t; - unsigned long flags; - - spin_lock_irqsave(&bp->lock, flags); - for (i = 0, t = 0; i < 8; i++) { - sx_out_off(bp, CD186x_CAR, i); - if (sx_in_off(bp, reg) & bit) - t |= 1 << i; - } - spin_unlock_irqrestore(&bp->lock, flags); - - return t; -} - - -/* Main probing routine, also sets irq. */ -static int sx_probe(struct specialix_board *bp) -{ - unsigned char val1, val2; - int rev; - int chip; - - func_enter(); - - if (sx_request_io_range(bp)) { - func_exit(); - return 1; - } - - /* Are the I/O ports here ? */ - sx_out_off(bp, CD186x_PPRL, 0x5a); - udelay(1); - val1 = sx_in_off(bp, CD186x_PPRL); - - sx_out_off(bp, CD186x_PPRL, 0xa5); - udelay(1); - val2 = sx_in_off(bp, CD186x_PPRL); - - - if (val1 != 0x5a || val2 != 0xa5) { - printk(KERN_INFO - "sx%d: specialix IO8+ Board at 0x%03x not found.\n", - board_No(bp), bp->base); - sx_release_io_range(bp); - func_exit(); - return 1; - } - - /* Check the DSR lines that Specialix uses as board - identification */ - val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); - val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); - dprintk(SX_DEBUG_INIT, - "sx%d: DSR lines are: %02x, rts lines are: %02x\n", - board_No(bp), val1, val2); - - /* They managed to switch the bit order between the docs and - the IO8+ card. The new PCI card now conforms to old docs. - They changed the PCI docs to reflect the situation on the - old card. */ - val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; - if (val1 != val2) { - printk(KERN_INFO - "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", - board_No(bp), val2, bp->base, val1); - sx_release_io_range(bp); - func_exit(); - return 1; - } - - - /* Reset CD186x again */ - if (!sx_init_CD186x(bp)) { - sx_release_io_range(bp); - func_exit(); - return 1; - } - - sx_request_io_range(bp); - bp->flags |= SX_BOARD_PRESENT; - - /* Chip revcode pkgtype - GFRCR SRCR bit 7 - CD180 rev B 0x81 0 - CD180 rev C 0x82 0 - CD1864 rev A 0x82 1 - CD1865 rev A 0x83 1 -- Do not use!!! Does not work. - CD1865 rev B 0x84 1 - -- Thanks to Gwen Wang, Cirrus Logic. - */ - - switch (sx_in_off(bp, CD186x_GFRCR)) { - case 0x82: - chip = 1864; - rev = 'A'; - break; - case 0x83: - chip = 1865; - rev = 'A'; - break; - case 0x84: - chip = 1865; - rev = 'B'; - break; - case 0x85: - chip = 1865; - rev = 'C'; - break; /* Does not exist at this time */ - default: - chip = -1; - rev = 'x'; - } - - dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); - - printk(KERN_INFO - "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", - board_No(bp), bp->base, bp->irq, chip, rev); - - func_exit(); - return 0; -} - -/* - * - * Interrupt processing routines. - * */ - -static struct specialix_port *sx_get_port(struct specialix_board *bp, - unsigned char const *what) -{ - unsigned char channel; - struct specialix_port *port = NULL; - - channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; - dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); - if (channel < CD186x_NCH) { - port = &sx_port[board_No(bp) * SX_NPORT + channel]; - dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", - board_No(bp) * SX_NPORT + channel, port, - port->port.flags & ASYNC_INITIALIZED); - - if (port->port.flags & ASYNC_INITIALIZED) { - dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); - func_exit(); - return port; - } - } - printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", - board_No(bp), what, channel); - return NULL; -} - - -static void sx_receive_exc(struct specialix_board *bp) -{ - struct specialix_port *port; - struct tty_struct *tty; - unsigned char status; - unsigned char ch, flag; - - func_enter(); - - port = sx_get_port(bp, "Receive"); - if (!port) { - dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); - func_exit(); - return; - } - tty = port->port.tty; - - status = sx_in(bp, CD186x_RCSR); - - dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); - if (status & RCSR_OE) { - port->overrun++; - dprintk(SX_DEBUG_FIFO, - "sx%d: port %d: Overrun. Total %ld overruns.\n", - board_No(bp), port_No(port), port->overrun); - } - status &= port->mark_mask; - - /* This flip buffer check needs to be below the reading of the - status register to reset the chip's IRQ.... */ - if (tty_buffer_request_room(tty, 1) == 0) { - dprintk(SX_DEBUG_FIFO, - "sx%d: port %d: Working around flip buffer overflow.\n", - board_No(bp), port_No(port)); - func_exit(); - return; - } - - ch = sx_in(bp, CD186x_RDR); - if (!status) { - func_exit(); - return; - } - if (status & RCSR_TOUT) { - printk(KERN_INFO - "sx%d: port %d: Receiver timeout. Hardware problems ?\n", - board_No(bp), port_No(port)); - func_exit(); - return; - - } else if (status & RCSR_BREAK) { - dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", - board_No(bp), port_No(port)); - flag = TTY_BREAK; - if (port->port.flags & ASYNC_SAK) - do_SAK(tty); - - } else if (status & RCSR_PE) - flag = TTY_PARITY; - - else if (status & RCSR_FE) - flag = TTY_FRAME; - - else if (status & RCSR_OE) - flag = TTY_OVERRUN; - - else - flag = TTY_NORMAL; - - if (tty_insert_flip_char(tty, ch, flag)) - tty_flip_buffer_push(tty); - func_exit(); -} - - -static void sx_receive(struct specialix_board *bp) -{ - struct specialix_port *port; - struct tty_struct *tty; - unsigned char count; - - func_enter(); - - port = sx_get_port(bp, "Receive"); - if (port == NULL) { - dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); - func_exit(); - return; - } - tty = port->port.tty; - - count = sx_in(bp, CD186x_RDCR); - dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); - port->hits[count > 8 ? 9 : count]++; - - while (count--) - tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); - tty_flip_buffer_push(tty); - func_exit(); -} - - -static void sx_transmit(struct specialix_board *bp) -{ - struct specialix_port *port; - struct tty_struct *tty; - unsigned char count; - - func_enter(); - port = sx_get_port(bp, "Transmit"); - if (port == NULL) { - func_exit(); - return; - } - dprintk(SX_DEBUG_TX, "port: %p\n", port); - tty = port->port.tty; - - if (port->IER & IER_TXEMPTY) { - /* FIFO drained */ - sx_out(bp, CD186x_CAR, port_No(port)); - port->IER &= ~IER_TXEMPTY; - sx_out(bp, CD186x_IER, port->IER); - func_exit(); - return; - } - - if ((port->xmit_cnt <= 0 && !port->break_length) - || tty->stopped || tty->hw_stopped) { - sx_out(bp, CD186x_CAR, port_No(port)); - port->IER &= ~IER_TXRDY; - sx_out(bp, CD186x_IER, port->IER); - func_exit(); - return; - } - - if (port->break_length) { - if (port->break_length > 0) { - if (port->COR2 & COR2_ETC) { - sx_out(bp, CD186x_TDR, CD186x_C_ESC); - sx_out(bp, CD186x_TDR, CD186x_C_SBRK); - port->COR2 &= ~COR2_ETC; - } - count = min_t(int, port->break_length, 0xff); - sx_out(bp, CD186x_TDR, CD186x_C_ESC); - sx_out(bp, CD186x_TDR, CD186x_C_DELAY); - sx_out(bp, CD186x_TDR, count); - port->break_length -= count; - if (port->break_length == 0) - port->break_length--; - } else { - sx_out(bp, CD186x_TDR, CD186x_C_ESC); - sx_out(bp, CD186x_TDR, CD186x_C_EBRK); - sx_out(bp, CD186x_COR2, port->COR2); - sx_wait_CCR(bp); - sx_out(bp, CD186x_CCR, CCR_CORCHG2); - port->break_length = 0; - } - - func_exit(); - return; - } - - count = CD186x_NFIFO; - do { - sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); - if (--port->xmit_cnt <= 0) - break; - } while (--count > 0); - - if (port->xmit_cnt <= 0) { - sx_out(bp, CD186x_CAR, port_No(port)); - port->IER &= ~IER_TXRDY; - sx_out(bp, CD186x_IER, port->IER); - } - if (port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); - - func_exit(); -} - - -static void sx_check_modem(struct specialix_board *bp) -{ - struct specialix_port *port; - struct tty_struct *tty; - unsigned char mcr; - int msvr_cd; - - dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); - port = sx_get_port(bp, "Modem"); - if (port == NULL) - return; - - tty = port->port.tty; - - mcr = sx_in(bp, CD186x_MCR); - - if ((mcr & MCR_CDCHG)) { - dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); - msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; - if (msvr_cd) { - dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); - wake_up_interruptible(&port->port.open_wait); - } else { - dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); - tty_hangup(tty); - } - } - -#ifdef SPECIALIX_BRAIN_DAMAGED_CTS - if (mcr & MCR_CTSCHG) { - if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) { - tty->hw_stopped = 0; - port->IER |= IER_TXRDY; - if (port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); - } else { - tty->hw_stopped = 1; - port->IER &= ~IER_TXRDY; - } - sx_out(bp, CD186x_IER, port->IER); - } - if (mcr & MCR_DSSXHG) { - if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) { - tty->hw_stopped = 0; - port->IER |= IER_TXRDY; - if (port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); - } else { - tty->hw_stopped = 1; - port->IER &= ~IER_TXRDY; - } - sx_out(bp, CD186x_IER, port->IER); - } -#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */ - - /* Clear change bits */ - sx_out(bp, CD186x_MCR, 0); -} - - -/* The main interrupt processing routine */ -static irqreturn_t sx_interrupt(int dummy, void *dev_id) -{ - unsigned char status; - unsigned char ack; - struct specialix_board *bp = dev_id; - unsigned long loop = 0; - int saved_reg; - unsigned long flags; - - func_enter(); - - spin_lock_irqsave(&bp->lock, flags); - - dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, - port_No(sx_get_port(bp, "INT")), - SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); - if (!(bp->flags & SX_BOARD_ACTIVE)) { - dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", - bp->irq); - spin_unlock_irqrestore(&bp->lock, flags); - func_exit(); - return IRQ_NONE; - } - - saved_reg = bp->reg; - - while (++loop < 16) { - status = sx_in(bp, CD186x_SRSR) & - (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); - if (status == 0) - break; - if (status & SRSR_RREQint) { - ack = sx_in(bp, CD186x_RRAR); - - if (ack == (SX_ID | GIVR_IT_RCV)) - sx_receive(bp); - else if (ack == (SX_ID | GIVR_IT_REXC)) - sx_receive_exc(bp); - else - printk(KERN_ERR - "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", - board_No(bp), status, ack); - - } else if (status & SRSR_TREQint) { - ack = sx_in(bp, CD186x_TRAR); - - if (ack == (SX_ID | GIVR_IT_TX)) - sx_transmit(bp); - else - printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", - board_No(bp), status, ack, - port_No(sx_get_port(bp, "Int"))); - } else if (status & SRSR_MREQint) { - ack = sx_in(bp, CD186x_MRAR); - - if (ack == (SX_ID | GIVR_IT_MODEM)) - sx_check_modem(bp); - else - printk(KERN_ERR - "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", - board_No(bp), status, ack); - - } - - sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ - } - bp->reg = saved_reg; - outb(bp->reg, bp->base + SX_ADDR_REG); - spin_unlock_irqrestore(&bp->lock, flags); - func_exit(); - return IRQ_HANDLED; -} - - -/* - * Routines for open & close processing. - */ - -static void turn_ints_off(struct specialix_board *bp) -{ - unsigned long flags; - - func_enter(); - spin_lock_irqsave(&bp->lock, flags); - (void) sx_in_off(bp, 0); /* Turn off interrupts. */ - spin_unlock_irqrestore(&bp->lock, flags); - - func_exit(); -} - -static void turn_ints_on(struct specialix_board *bp) -{ - unsigned long flags; - - func_enter(); - - spin_lock_irqsave(&bp->lock, flags); - (void) sx_in(bp, 0); /* Turn ON interrupts. */ - spin_unlock_irqrestore(&bp->lock, flags); - - func_exit(); -} - - -/* Called with disabled interrupts */ -static int sx_setup_board(struct specialix_board *bp) -{ - int error; - - if (bp->flags & SX_BOARD_ACTIVE) - return 0; - - if (bp->flags & SX_BOARD_IS_PCI) - error = request_irq(bp->irq, sx_interrupt, - IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); - else - error = request_irq(bp->irq, sx_interrupt, - IRQF_DISABLED, "specialix IO8+", bp); - - if (error) - return error; - - turn_ints_on(bp); - bp->flags |= SX_BOARD_ACTIVE; - - return 0; -} - - -/* Called with disabled interrupts */ -static void sx_shutdown_board(struct specialix_board *bp) -{ - func_enter(); - - if (!(bp->flags & SX_BOARD_ACTIVE)) { - func_exit(); - return; - } - - bp->flags &= ~SX_BOARD_ACTIVE; - - dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", - bp->irq, board_No(bp)); - free_irq(bp->irq, bp); - turn_ints_off(bp); - func_exit(); -} - -static unsigned int sx_crtscts(struct tty_struct *tty) -{ - if (sx_rtscts) - return C_CRTSCTS(tty); - return 1; -} - -/* - * Setting up port characteristics. - * Must be called with disabled interrupts - */ -static void sx_change_speed(struct specialix_board *bp, - struct specialix_port *port) -{ - struct tty_struct *tty; - unsigned long baud; - long tmp; - unsigned char cor1 = 0, cor3 = 0; - unsigned char mcor1 = 0, mcor2 = 0; - static unsigned long again; - unsigned long flags; - - func_enter(); - - tty = port->port.tty; - if (!tty || !tty->termios) { - func_exit(); - return; - } - - port->IER = 0; - port->COR2 = 0; - /* Select port on the board */ - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CAR, port_No(port)); - - /* The Specialix board doens't implement the RTS lines. - They are used to set the IRQ level. Don't touch them. */ - if (sx_crtscts(tty)) - port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); - else - port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); - spin_unlock_irqrestore(&bp->lock, flags); - dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); - baud = tty_get_baud_rate(tty); - - if (baud == 38400) { - if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baud = 57600; - if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baud = 115200; - } - - if (!baud) { - /* Drop DTR & exit */ - dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); - if (!sx_crtscts(tty)) { - port->MSVR &= ~MSVR_DTR; - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock_irqrestore(&bp->lock, flags); - } else - dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); - return; - } else { - /* Set DTR on */ - if (!sx_crtscts(tty)) - port->MSVR |= MSVR_DTR; - } - - /* - * Now we must calculate some speed depended things - */ - - /* Set baud rate for port */ - tmp = port->custom_divisor ; - if (tmp) - printk(KERN_INFO - "sx%d: Using custom baud rate divisor %ld. \n" - "This is an untested option, please be careful.\n", - port_No(port), tmp); - else - tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / - CD186x_TPC); - - if (tmp < 0x10 && time_before(again, jiffies)) { - again = jiffies + HZ * 60; - /* Page 48 of version 2.0 of the CL-CD1865 databook */ - if (tmp >= 12) { - printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" - "Performance degradation is possible.\n" - "Read specialix.txt for more info.\n", - port_No(port), tmp); - } else { - printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" - "Warning: overstressing Cirrus chip. This might not work.\n" - "Read specialix.txt for more info.\n", port_No(port), tmp); - } - } - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); - sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); - sx_out(bp, CD186x_RBPRL, tmp & 0xff); - sx_out(bp, CD186x_TBPRL, tmp & 0xff); - spin_unlock_irqrestore(&bp->lock, flags); - if (port->custom_divisor) - baud = (SX_OSCFREQ + port->custom_divisor/2) / - port->custom_divisor; - baud = (baud + 5) / 10; /* Estimated CPS */ - - /* Two timer ticks seems enough to wakeup something like SLIP driver */ - tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; - port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? - SERIAL_XMIT_SIZE - 1 : tmp); - - /* Receiver timeout will be transmission time for 1.5 chars */ - tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud; - tmp = (tmp > 0xff) ? 0xff : tmp; - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_RTPR, tmp); - spin_unlock_irqrestore(&bp->lock, flags); - switch (C_CSIZE(tty)) { - case CS5: - cor1 |= COR1_5BITS; - break; - case CS6: - cor1 |= COR1_6BITS; - break; - case CS7: - cor1 |= COR1_7BITS; - break; - case CS8: - cor1 |= COR1_8BITS; - break; - } - - if (C_CSTOPB(tty)) - cor1 |= COR1_2SB; - - cor1 |= COR1_IGNORE; - if (C_PARENB(tty)) { - cor1 |= COR1_NORMPAR; - if (C_PARODD(tty)) - cor1 |= COR1_ODDP; - if (I_INPCK(tty)) - cor1 &= ~COR1_IGNORE; - } - /* Set marking of some errors */ - port->mark_mask = RCSR_OE | RCSR_TOUT; - if (I_INPCK(tty)) - port->mark_mask |= RCSR_FE | RCSR_PE; - if (I_BRKINT(tty) || I_PARMRK(tty)) - port->mark_mask |= RCSR_BREAK; - if (I_IGNPAR(tty)) - port->mark_mask &= ~(RCSR_FE | RCSR_PE); - if (I_IGNBRK(tty)) { - port->mark_mask &= ~RCSR_BREAK; - if (I_IGNPAR(tty)) - /* Real raw mode. Ignore all */ - port->mark_mask &= ~RCSR_OE; - } - /* Enable Hardware Flow Control */ - if (C_CRTSCTS(tty)) { -#ifdef SPECIALIX_BRAIN_DAMAGED_CTS - port->IER |= IER_DSR | IER_CTS; - mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; - mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; - spin_lock_irqsave(&bp->lock, flags); - tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & - (MSVR_CTS|MSVR_DSR)); - spin_unlock_irqrestore(&bp->lock, flags); -#else - port->COR2 |= COR2_CTSAE; -#endif - } - /* Enable Software Flow Control. FIXME: I'm not sure about this */ - /* Some people reported that it works, but I still doubt it */ - if (I_IXON(tty)) { - port->COR2 |= COR2_TXIBE; - cor3 |= (COR3_FCT | COR3_SCDE); - if (I_IXANY(tty)) - port->COR2 |= COR2_IXM; - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_SCHR1, START_CHAR(tty)); - sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty)); - sx_out(bp, CD186x_SCHR3, START_CHAR(tty)); - sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty)); - spin_unlock_irqrestore(&bp->lock, flags); - } - if (!C_CLOCAL(tty)) { - /* Enable CD check */ - port->IER |= IER_CD; - mcor1 |= MCOR1_CDZD; - mcor2 |= MCOR2_CDOD; - } - - if (C_CREAD(tty)) - /* Enable receiver */ - port->IER |= IER_RXD; - - /* Set input FIFO size (1-8 bytes) */ - cor3 |= sx_rxfifo; - /* Setting up CD186x channel registers */ - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_COR1, cor1); - sx_out(bp, CD186x_COR2, port->COR2); - sx_out(bp, CD186x_COR3, cor3); - spin_unlock_irqrestore(&bp->lock, flags); - /* Make CD186x know about registers change */ - sx_wait_CCR(bp); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); - /* Setting up modem option registers */ - dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", - mcor1, mcor2); - sx_out(bp, CD186x_MCOR1, mcor1); - sx_out(bp, CD186x_MCOR2, mcor2); - spin_unlock_irqrestore(&bp->lock, flags); - /* Enable CD186x transmitter & receiver */ - sx_wait_CCR(bp); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN); - /* Enable interrupts */ - sx_out(bp, CD186x_IER, port->IER); - /* And finally set the modem lines... */ - sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock_irqrestore(&bp->lock, flags); - - func_exit(); -} - - -/* Must be called with interrupts enabled */ -static int sx_setup_port(struct specialix_board *bp, - struct specialix_port *port) -{ - unsigned long flags; - - func_enter(); - - if (port->port.flags & ASYNC_INITIALIZED) { - func_exit(); - return 0; - } - - if (!port->xmit_buf) { - /* We may sleep in get_zeroed_page() */ - unsigned long tmp; - - tmp = get_zeroed_page(GFP_KERNEL); - if (tmp == 0L) { - func_exit(); - return -ENOMEM; - } - - if (port->xmit_buf) { - free_page(tmp); - func_exit(); - return -ERESTARTSYS; - } - port->xmit_buf = (unsigned char *) tmp; - } - - spin_lock_irqsave(&port->lock, flags); - - if (port->port.tty) - clear_bit(TTY_IO_ERROR, &port->port.tty->flags); - - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - sx_change_speed(bp, port); - port->port.flags |= ASYNC_INITIALIZED; - - spin_unlock_irqrestore(&port->lock, flags); - - - func_exit(); - return 0; -} - - -/* Must be called with interrupts disabled */ -static void sx_shutdown_port(struct specialix_board *bp, - struct specialix_port *port) -{ - struct tty_struct *tty; - int i; - unsigned long flags; - - func_enter(); - - if (!(port->port.flags & ASYNC_INITIALIZED)) { - func_exit(); - return; - } - - if (sx_debug & SX_DEBUG_FIFO) { - dprintk(SX_DEBUG_FIFO, - "sx%d: port %d: %ld overruns, FIFO hits [ ", - board_No(bp), port_No(port), port->overrun); - for (i = 0; i < 10; i++) - dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); - dprintk(SX_DEBUG_FIFO, "].\n"); - } - - if (port->xmit_buf) { - free_page((unsigned long) port->xmit_buf); - port->xmit_buf = NULL; - } - - /* Select port */ - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CAR, port_No(port)); - - tty = port->port.tty; - if (tty == NULL || C_HUPCL(tty)) { - /* Drop DTR */ - sx_out(bp, CD186x_MSVDTR, 0); - } - spin_unlock_irqrestore(&bp->lock, flags); - /* Reset port */ - sx_wait_CCR(bp); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CCR, CCR_SOFTRESET); - /* Disable all interrupts from this port */ - port->IER = 0; - sx_out(bp, CD186x_IER, port->IER); - spin_unlock_irqrestore(&bp->lock, flags); - if (tty) - set_bit(TTY_IO_ERROR, &tty->flags); - port->port.flags &= ~ASYNC_INITIALIZED; - - if (!bp->count) - sx_shutdown_board(bp); - func_exit(); -} - - -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct specialix_port *port) -{ - DECLARE_WAITQUEUE(wait, current); - struct specialix_board *bp = port_Board(port); - int retval; - int do_clocal = 0; - int CD; - unsigned long flags; - - func_enter(); - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { - interruptible_sleep_on(&port->port.close_wait); - if (port->port.flags & ASYNC_HUP_NOTIFY) { - func_exit(); - return -EAGAIN; - } else { - func_exit(); - return -ERESTARTSYS; - } - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - port->port.flags |= ASYNC_NORMAL_ACTIVE; - func_exit(); - return 0; - } - - if (C_CLOCAL(tty)) - do_clocal = 1; - - /* - * 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 - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&port->port.open_wait, &wait); - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) - port->port.count--; - spin_unlock_irqrestore(&port->lock, flags); - port->port.blocked_open++; - while (1) { - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CAR, port_No(port)); - CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; - if (sx_crtscts(tty)) { - /* Activate RTS */ - port->MSVR |= MSVR_DTR; /* WTF? */ - sx_out(bp, CD186x_MSVR, port->MSVR); - } else { - /* Activate DTR */ - port->MSVR |= MSVR_DTR; - sx_out(bp, CD186x_MSVR, port->MSVR); - } - spin_unlock_irqrestore(&bp->lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(port->port.flags & ASYNC_INITIALIZED)) { - if (port->port.flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(port->port.flags & ASYNC_CLOSING) && - (do_clocal || CD)) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - tty_unlock(); - schedule(); - tty_lock(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->port.open_wait, &wait); - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) - port->port.count++; - port->port.blocked_open--; - spin_unlock_irqrestore(&port->lock, flags); - if (retval) { - func_exit(); - return retval; - } - - port->port.flags |= ASYNC_NORMAL_ACTIVE; - func_exit(); - return 0; -} - - -static int sx_open(struct tty_struct *tty, struct file *filp) -{ - int board; - int error; - struct specialix_port *port; - struct specialix_board *bp; - int i; - unsigned long flags; - - func_enter(); - - board = SX_BOARD(tty->index); - - if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) { - func_exit(); - return -ENODEV; - } - - bp = &sx_board[board]; - port = sx_port + board * SX_NPORT + SX_PORT(tty->index); - port->overrun = 0; - for (i = 0; i < 10; i++) - port->hits[i] = 0; - - dprintk(SX_DEBUG_OPEN, - "Board = %d, bp = %p, port = %p, portno = %d.\n", - board, bp, port, SX_PORT(tty->index)); - - if (sx_paranoia_check(port, tty->name, "sx_open")) { - func_enter(); - return -ENODEV; - } - - error = sx_setup_board(bp); - if (error) { - func_exit(); - return error; - } - - spin_lock_irqsave(&bp->lock, flags); - port->port.count++; - bp->count++; - tty->driver_data = port; - port->port.tty = tty; - spin_unlock_irqrestore(&bp->lock, flags); - - error = sx_setup_port(bp, port); - if (error) { - func_enter(); - return error; - } - - error = block_til_ready(tty, filp, port); - if (error) { - func_enter(); - return error; - } - - func_exit(); - return 0; -} - -static void sx_flush_buffer(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - unsigned long flags; - struct specialix_board *bp; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) { - func_exit(); - return; - } - - bp = port_Board(port); - spin_lock_irqsave(&port->lock, flags); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - spin_unlock_irqrestore(&port->lock, flags); - tty_wakeup(tty); - - func_exit(); -} - -static void sx_close(struct tty_struct *tty, struct file *filp) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned long flags; - unsigned long timeout; - - func_enter(); - if (!port || sx_paranoia_check(port, tty->name, "close")) { - func_exit(); - return; - } - spin_lock_irqsave(&port->lock, flags); - - if (tty_hung_up_p(filp)) { - spin_unlock_irqrestore(&port->lock, flags); - func_exit(); - return; - } - - bp = port_Board(port); - if (tty->count == 1 && port->port.count != 1) { - printk(KERN_ERR "sx%d: sx_close: bad port count;" - " tty->count is 1, port count is %d\n", - board_No(bp), port->port.count); - port->port.count = 1; - } - - if (port->port.count > 1) { - port->port.count--; - bp->count--; - - spin_unlock_irqrestore(&port->lock, flags); - - func_exit(); - return; - } - port->port.flags |= ASYNC_CLOSING; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - spin_unlock_irqrestore(&port->lock, flags); - dprintk(SX_DEBUG_OPEN, "Closing\n"); - if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, port->port.closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - dprintk(SX_DEBUG_OPEN, "Closed\n"); - port->IER &= ~IER_RXD; - if (port->port.flags & ASYNC_INITIALIZED) { - port->IER &= ~IER_TXRDY; - port->IER |= IER_TXEMPTY; - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CAR, port_No(port)); - sx_out(bp, CD186x_IER, port->IER); - spin_unlock_irqrestore(&bp->lock, flags); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies+HZ; - while (port->IER & IER_TXEMPTY) { - set_current_state(TASK_INTERRUPTIBLE); - msleep_interruptible(jiffies_to_msecs(port->timeout)); - if (time_after(jiffies, timeout)) { - printk(KERN_INFO "Timeout waiting for close\n"); - break; - } - } - - } - - if (--bp->count < 0) { - printk(KERN_ERR - "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", - board_No(bp), bp->count, tty->index); - bp->count = 0; - } - if (--port->port.count < 0) { - printk(KERN_ERR - "sx%d: sx_close: bad port count for tty%d: %d\n", - board_No(bp), port_No(port), port->port.count); - port->port.count = 0; - } - - sx_shutdown_port(bp, port); - sx_flush_buffer(tty); - tty_ldisc_flush(tty); - spin_lock_irqsave(&port->lock, flags); - tty->closing = 0; - port->port.tty = NULL; - spin_unlock_irqrestore(&port->lock, flags); - if (port->port.blocked_open) { - if (port->port.close_delay) - msleep_interruptible( - jiffies_to_msecs(port->port.close_delay)); - wake_up_interruptible(&port->port.open_wait); - } - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&port->port.close_wait); - - func_exit(); -} - - -static int sx_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - int c, total = 0; - unsigned long flags; - - func_enter(); - if (sx_paranoia_check(port, tty->name, "sx_write")) { - func_exit(); - return 0; - } - - bp = port_Board(port); - - if (!port->xmit_buf) { - func_exit(); - return 0; - } - - while (1) { - spin_lock_irqsave(&port->lock, flags); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) { - spin_unlock_irqrestore(&port->lock, flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; - spin_unlock_irqrestore(&port->lock, flags); - - buf += c; - count -= c; - total += c; - } - - spin_lock_irqsave(&bp->lock, flags); - if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && - !(port->IER & IER_TXRDY)) { - port->IER |= IER_TXRDY; - sx_out(bp, CD186x_CAR, port_No(port)); - sx_out(bp, CD186x_IER, port->IER); - } - spin_unlock_irqrestore(&bp->lock, flags); - func_exit(); - - return total; -} - - -static int sx_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct specialix_port *port = tty->driver_data; - unsigned long flags; - struct specialix_board *bp; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_put_char")) { - func_exit(); - return 0; - } - dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); - if (!port->xmit_buf) { - func_exit(); - return 0; - } - bp = port_Board(port); - spin_lock_irqsave(&port->lock, flags); - - dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", - port->xmit_cnt, port->xmit_buf); - if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { - spin_unlock_irqrestore(&port->lock, flags); - dprintk(SX_DEBUG_TX, "Exit size\n"); - func_exit(); - return 0; - } - dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); - port->xmit_buf[port->xmit_head++] = ch; - port->xmit_head &= SERIAL_XMIT_SIZE - 1; - port->xmit_cnt++; - spin_unlock_irqrestore(&port->lock, flags); - - func_exit(); - return 1; -} - - -static void sx_flush_chars(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - unsigned long flags; - struct specialix_board *bp = port_Board(port); - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) { - func_exit(); - return; - } - if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !port->xmit_buf) { - func_exit(); - return; - } - spin_lock_irqsave(&bp->lock, flags); - port->IER |= IER_TXRDY; - sx_out(port_Board(port), CD186x_CAR, port_No(port)); - sx_out(port_Board(port), CD186x_IER, port->IER); - spin_unlock_irqrestore(&bp->lock, flags); - - func_exit(); -} - - -static int sx_write_room(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - int ret; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_write_room")) { - func_exit(); - return 0; - } - - ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; - if (ret < 0) - ret = 0; - - func_exit(); - return ret; -} - - -static int sx_chars_in_buffer(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) { - func_exit(); - return 0; - } - func_exit(); - return port->xmit_cnt; -} - -static int sx_tiocmget(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned char status; - unsigned int result; - unsigned long flags; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, __func__)) { - func_exit(); - return -ENODEV; - } - - bp = port_Board(port); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CAR, port_No(port)); - status = sx_in(bp, CD186x_MSVR); - spin_unlock_irqrestore(&bp->lock, flags); - dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", - port_No(port), status, sx_in(bp, CD186x_CAR)); - dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); - if (sx_crtscts(port->port.tty)) { - result = TIOCM_DTR | TIOCM_DSR - | ((status & MSVR_DTR) ? TIOCM_RTS : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); - } else { - result = TIOCM_RTS | TIOCM_DSR - | ((status & MSVR_DTR) ? TIOCM_DTR : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); - } - - func_exit(); - - return result; -} - - -static int sx_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct specialix_port *port = tty->driver_data; - unsigned long flags; - struct specialix_board *bp; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, __func__)) { - func_exit(); - return -ENODEV; - } - - bp = port_Board(port); - - spin_lock_irqsave(&port->lock, flags); - if (sx_crtscts(port->port.tty)) { - if (set & TIOCM_RTS) - port->MSVR |= MSVR_DTR; - } else { - if (set & TIOCM_DTR) - port->MSVR |= MSVR_DTR; - } - if (sx_crtscts(port->port.tty)) { - if (clear & TIOCM_RTS) - port->MSVR &= ~MSVR_DTR; - } else { - if (clear & TIOCM_DTR) - port->MSVR &= ~MSVR_DTR; - } - spin_lock(&bp->lock); - sx_out(bp, CD186x_CAR, port_No(port)); - sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock(&bp->lock); - spin_unlock_irqrestore(&port->lock, flags); - func_exit(); - return 0; -} - - -static int sx_send_break(struct tty_struct *tty, int length) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp = port_Board(port); - unsigned long flags; - - func_enter(); - if (length == 0 || length == -1) - return -EOPNOTSUPP; - - spin_lock_irqsave(&port->lock, flags); - port->break_length = SPECIALIX_TPS / HZ * length; - port->COR2 |= COR2_ETC; - port->IER |= IER_TXRDY; - spin_lock(&bp->lock); - sx_out(bp, CD186x_CAR, port_No(port)); - sx_out(bp, CD186x_COR2, port->COR2); - sx_out(bp, CD186x_IER, port->IER); - spin_unlock(&bp->lock); - spin_unlock_irqrestore(&port->lock, flags); - sx_wait_CCR(bp); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CCR, CCR_CORCHG2); - spin_unlock_irqrestore(&bp->lock, flags); - sx_wait_CCR(bp); - - func_exit(); - return 0; -} - - -static int sx_set_serial_info(struct specialix_port *port, - struct serial_struct __user *newinfo) -{ - struct serial_struct tmp; - struct specialix_board *bp = port_Board(port); - int change_speed; - - func_enter(); - - if (copy_from_user(&tmp, newinfo, sizeof(tmp))) { - func_enter(); - return -EFAULT; - } - - mutex_lock(&port->port.mutex); - change_speed = ((port->port.flags & ASYNC_SPD_MASK) != - (tmp.flags & ASYNC_SPD_MASK)); - change_speed |= (tmp.custom_divisor != port->custom_divisor); - - if (!capable(CAP_SYS_ADMIN)) { - if ((tmp.close_delay != port->port.close_delay) || - (tmp.closing_wait != port->port.closing_wait) || - ((tmp.flags & ~ASYNC_USR_MASK) != - (port->port.flags & ~ASYNC_USR_MASK))) { - func_exit(); - mutex_unlock(&port->port.mutex); - return -EPERM; - } - port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | - (tmp.flags & ASYNC_USR_MASK)); - port->custom_divisor = tmp.custom_divisor; - } else { - port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | - (tmp.flags & ASYNC_FLAGS)); - port->port.close_delay = tmp.close_delay; - port->port.closing_wait = tmp.closing_wait; - port->custom_divisor = tmp.custom_divisor; - } - if (change_speed) - sx_change_speed(bp, port); - - func_exit(); - mutex_unlock(&port->port.mutex); - return 0; -} - - -static int sx_get_serial_info(struct specialix_port *port, - struct serial_struct __user *retinfo) -{ - struct serial_struct tmp; - struct specialix_board *bp = port_Board(port); - - func_enter(); - - memset(&tmp, 0, sizeof(tmp)); - mutex_lock(&port->port.mutex); - tmp.type = PORT_CIRRUS; - tmp.line = port - sx_port; - tmp.port = bp->base; - tmp.irq = bp->irq; - tmp.flags = port->port.flags; - tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC; - tmp.close_delay = port->port.close_delay * HZ/100; - tmp.closing_wait = port->port.closing_wait * HZ/100; - tmp.custom_divisor = port->custom_divisor; - tmp.xmit_fifo_size = CD186x_NFIFO; - mutex_unlock(&port->port.mutex); - if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { - func_exit(); - return -EFAULT; - } - - func_exit(); - return 0; -} - - -static int sx_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct specialix_port *port = tty->driver_data; - void __user *argp = (void __user *)arg; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_ioctl")) { - func_exit(); - return -ENODEV; - } - - switch (cmd) { - case TIOCGSERIAL: - func_exit(); - return sx_get_serial_info(port, argp); - case TIOCSSERIAL: - func_exit(); - return sx_set_serial_info(port, argp); - default: - func_exit(); - return -ENOIOCTLCMD; - } - func_exit(); - return 0; -} - - -static void sx_throttle(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned long flags; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_throttle")) { - func_exit(); - return; - } - - bp = port_Board(port); - - /* Use DTR instead of RTS ! */ - if (sx_crtscts(tty)) - port->MSVR &= ~MSVR_DTR; - else { - /* Auch!!! I think the system shouldn't call this then. */ - /* Or maybe we're supposed (allowed?) to do our side of hw - handshake anyway, even when hardware handshake is off. - When you see this in your logs, please report.... */ - printk(KERN_ERR - "sx%d: Need to throttle, but can't (hardware hs is off)\n", - port_No(port)); - } - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CAR, port_No(port)); - spin_unlock_irqrestore(&bp->lock, flags); - if (I_IXOFF(tty)) { - sx_wait_CCR(bp); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CCR, CCR_SSCH2); - spin_unlock_irqrestore(&bp->lock, flags); - sx_wait_CCR(bp); - } - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock_irqrestore(&bp->lock, flags); - - func_exit(); -} - - -static void sx_unthrottle(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned long flags; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) { - func_exit(); - return; - } - - bp = port_Board(port); - - spin_lock_irqsave(&port->lock, flags); - /* XXXX Use DTR INSTEAD???? */ - if (sx_crtscts(tty)) - port->MSVR |= MSVR_DTR; - /* Else clause: see remark in "sx_throttle"... */ - spin_lock(&bp->lock); - sx_out(bp, CD186x_CAR, port_No(port)); - spin_unlock(&bp->lock); - if (I_IXOFF(tty)) { - spin_unlock_irqrestore(&port->lock, flags); - sx_wait_CCR(bp); - spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_CCR, CCR_SSCH1); - spin_unlock_irqrestore(&bp->lock, flags); - sx_wait_CCR(bp); - spin_lock_irqsave(&port->lock, flags); - } - spin_lock(&bp->lock); - sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock(&bp->lock); - spin_unlock_irqrestore(&port->lock, flags); - - func_exit(); -} - - -static void sx_stop(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned long flags; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_stop")) { - func_exit(); - return; - } - - bp = port_Board(port); - - spin_lock_irqsave(&port->lock, flags); - port->IER &= ~IER_TXRDY; - spin_lock(&bp->lock); - sx_out(bp, CD186x_CAR, port_No(port)); - sx_out(bp, CD186x_IER, port->IER); - spin_unlock(&bp->lock); - spin_unlock_irqrestore(&port->lock, flags); - - func_exit(); -} - - -static void sx_start(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned long flags; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_start")) { - func_exit(); - return; - } - - bp = port_Board(port); - - spin_lock_irqsave(&port->lock, flags); - if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { - port->IER |= IER_TXRDY; - spin_lock(&bp->lock); - sx_out(bp, CD186x_CAR, port_No(port)); - sx_out(bp, CD186x_IER, port->IER); - spin_unlock(&bp->lock); - } - spin_unlock_irqrestore(&port->lock, flags); - - func_exit(); -} - -static void sx_hangup(struct tty_struct *tty) -{ - struct specialix_port *port = tty->driver_data; - struct specialix_board *bp; - unsigned long flags; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_hangup")) { - func_exit(); - return; - } - - bp = port_Board(port); - - sx_shutdown_port(bp, port); - spin_lock_irqsave(&port->lock, flags); - bp->count -= port->port.count; - if (bp->count < 0) { - printk(KERN_ERR - "sx%d: sx_hangup: bad board count: %d port: %d\n", - board_No(bp), bp->count, tty->index); - bp->count = 0; - } - port->port.count = 0; - port->port.flags &= ~ASYNC_NORMAL_ACTIVE; - port->port.tty = NULL; - spin_unlock_irqrestore(&port->lock, flags); - wake_up_interruptible(&port->port.open_wait); - - func_exit(); -} - - -static void sx_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct specialix_port *port = tty->driver_data; - unsigned long flags; - struct specialix_board *bp; - - if (sx_paranoia_check(port, tty->name, "sx_set_termios")) - return; - - bp = port_Board(port); - spin_lock_irqsave(&port->lock, flags); - sx_change_speed(port_Board(port), port); - spin_unlock_irqrestore(&port->lock, flags); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - sx_start(tty); - } -} - -static const struct tty_operations sx_ops = { - .open = sx_open, - .close = sx_close, - .write = sx_write, - .put_char = sx_put_char, - .flush_chars = sx_flush_chars, - .write_room = sx_write_room, - .chars_in_buffer = sx_chars_in_buffer, - .flush_buffer = sx_flush_buffer, - .ioctl = sx_ioctl, - .throttle = sx_throttle, - .unthrottle = sx_unthrottle, - .set_termios = sx_set_termios, - .stop = sx_stop, - .start = sx_start, - .hangup = sx_hangup, - .tiocmget = sx_tiocmget, - .tiocmset = sx_tiocmset, - .break_ctl = sx_send_break, -}; - -static int sx_init_drivers(void) -{ - int error; - int i; - - func_enter(); - - specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT); - if (!specialix_driver) { - printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n"); - func_exit(); - return 1; - } - - specialix_driver->owner = THIS_MODULE; - specialix_driver->name = "ttyW"; - specialix_driver->major = SPECIALIX_NORMAL_MAJOR; - specialix_driver->type = TTY_DRIVER_TYPE_SERIAL; - specialix_driver->subtype = SERIAL_TYPE_NORMAL; - specialix_driver->init_termios = tty_std_termios; - specialix_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - specialix_driver->init_termios.c_ispeed = 9600; - specialix_driver->init_termios.c_ospeed = 9600; - specialix_driver->flags = TTY_DRIVER_REAL_RAW | - TTY_DRIVER_HARDWARE_BREAK; - tty_set_operations(specialix_driver, &sx_ops); - - error = tty_register_driver(specialix_driver); - if (error) { - put_tty_driver(specialix_driver); - printk(KERN_ERR - "sx: Couldn't register specialix IO8+ driver, error = %d\n", - error); - func_exit(); - return 1; - } - memset(sx_port, 0, sizeof(sx_port)); - for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { - sx_port[i].magic = SPECIALIX_MAGIC; - tty_port_init(&sx_port[i].port); - spin_lock_init(&sx_port[i].lock); - } - - func_exit(); - return 0; -} - -static void sx_release_drivers(void) -{ - func_enter(); - - tty_unregister_driver(specialix_driver); - put_tty_driver(specialix_driver); - func_exit(); -} - -/* - * This routine must be called by kernel at boot time - */ -static int __init specialix_init(void) -{ - int i; - int found = 0; - - func_enter(); - - printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); - printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); - if (sx_rtscts) - printk(KERN_INFO - "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); - else - printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); - - for (i = 0; i < SX_NBOARD; i++) - spin_lock_init(&sx_board[i].lock); - - if (sx_init_drivers()) { - func_exit(); - return -EIO; - } - - for (i = 0; i < SX_NBOARD; i++) - if (sx_board[i].base && !sx_probe(&sx_board[i])) - found++; - -#ifdef CONFIG_PCI - { - struct pci_dev *pdev = NULL; - - i = 0; - while (i < SX_NBOARD) { - if (sx_board[i].flags & SX_BOARD_PRESENT) { - i++; - continue; - } - pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_IO8, pdev); - if (!pdev) - break; - - if (pci_enable_device(pdev)) - continue; - - sx_board[i].irq = pdev->irq; - - sx_board[i].base = pci_resource_start(pdev, 2); - - sx_board[i].flags |= SX_BOARD_IS_PCI; - if (!sx_probe(&sx_board[i])) - found++; - } - /* May exit pci_get sequence early with lots of boards */ - if (pdev != NULL) - pci_dev_put(pdev); - } -#endif - - if (!found) { - sx_release_drivers(); - printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n"); - func_exit(); - return -EIO; - } - - func_exit(); - return 0; -} - -static int iobase[SX_NBOARD] = {0,}; -static int irq[SX_NBOARD] = {0,}; - -module_param_array(iobase, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param(sx_debug, int, 0); -module_param(sx_rtscts, int, 0); -module_param(sx_rxfifo, int, 0); - -/* - * You can setup up to 4 boards. - * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter. - * You should specify the IRQs too in that case "irq=....,...". - * - * More than 4 boards in one computer is not possible, as the card can - * only use 4 different interrupts. - * - */ -static int __init specialix_init_module(void) -{ - int i; - - func_enter(); - - if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { - for (i = 0; i < SX_NBOARD; i++) { - sx_board[i].base = iobase[i]; - sx_board[i].irq = irq[i]; - sx_board[i].count = 0; - } - } - - func_exit(); - - return specialix_init(); -} - -static void __exit specialix_exit_module(void) -{ - int i; - - func_enter(); - - sx_release_drivers(); - for (i = 0; i < SX_NBOARD; i++) - if (sx_board[i].flags & SX_BOARD_PRESENT) - sx_release_io_range(&sx_board[i]); - func_exit(); -} - -static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = { - { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) }, - { } -}; -MODULE_DEVICE_TABLE(pci, specialx_pci_tbl); - -module_init(specialix_init_module); -module_exit(specialix_exit_module); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR); diff --git a/drivers/char/specialix_io8.h b/drivers/char/specialix_io8.h deleted file mode 100644 index c63005274d9b..000000000000 --- a/drivers/char/specialix_io8.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * linux/drivers/char/specialix_io8.h -- - * Specialix IO8+ multiport serial driver. - * - * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) - * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) - * - * - * Specialix pays for the development and support of this driver. - * Please DO contact io8-linux@specialix.co.uk if you require - * support. - * - * This driver was developped in the BitWizard linux device - * driver service. If you require a linux device driver for your - * product, please contact devices@BitWizard.nl for a quote. - * - * This code is firmly based on the riscom/8 serial driver, - * written by Dmitry Gorodchanin. The specialix IO8+ card - * programming information was obtained from the CL-CD1865 Data - * Book, and Specialix document number 6200059: IO8+ Hardware - * Functional Specification. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, - * USA. - * */ - -#ifndef __LINUX_SPECIALIX_H -#define __LINUX_SPECIALIX_H - -#include - -#ifdef __KERNEL__ - -/* You can have max 4 ISA cards in one PC, and I recommend not much -more than a few PCI versions of the card. */ - -#define SX_NBOARD 8 - -/* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */ -#define SX_IO_SPACE 4 -/* The PCI version decodes 8 addresses, but still only 2 are used. */ -#define SX_PCI_IO_SPACE 8 - -/* eight ports per board. */ -#define SX_NPORT 8 -#define SX_BOARD(line) ((line) / SX_NPORT) -#define SX_PORT(line) ((line) & (SX_NPORT - 1)) - - -#define SX_DATA_REG 0 /* Base+0 : Data register */ -#define SX_ADDR_REG 1 /* base+1 : Address register. */ - -#define MHz *1000000 /* I'm ashamed of myself. */ - -/* On-board oscillator frequency */ -#define SX_OSCFREQ (25 MHz/2) -/* There is a 25MHz crystal on the board, but the chip is in /2 mode */ - - -/* Ticks per sec. Used for setting receiver timeout and break length */ -#define SPECIALIX_TPS 4000 - -/* Yeah, after heavy testing I decided it must be 6. - * Sure, You can change it if needed. - */ -#define SPECIALIX_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ - -#define SPECIALIX_MAGIC 0x0907 - -#define SX_CCR_TIMEOUT 10000 /* CCR timeout. You may need to wait upto - 10 milliseconds before the internal - processor is available again after - you give it a command */ - -#define SX_IOBASE1 0x100 -#define SX_IOBASE2 0x180 -#define SX_IOBASE3 0x250 -#define SX_IOBASE4 0x260 - -struct specialix_board { - unsigned long flags; - unsigned short base; - unsigned char irq; - //signed char count; - int count; - unsigned char DTR; - int reg; - spinlock_t lock; -}; - -#define SX_BOARD_PRESENT 0x00000001 -#define SX_BOARD_ACTIVE 0x00000002 -#define SX_BOARD_IS_PCI 0x00000004 - - -struct specialix_port { - int magic; - struct tty_port port; - int baud_base; - int flags; - int timeout; - unsigned char * xmit_buf; - int custom_divisor; - int xmit_head; - int xmit_tail; - int xmit_cnt; - short wakeup_chars; - short break_length; - unsigned char mark_mask; - unsigned char IER; - unsigned char MSVR; - unsigned char COR2; - unsigned long overrun; - unsigned long hits[10]; - spinlock_t lock; -}; - -#endif /* __KERNEL__ */ -#endif /* __LINUX_SPECIALIX_H */ - - - - - - - - - diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c deleted file mode 100644 index 4fff5cd3b163..000000000000 --- a/drivers/char/stallion.c +++ /dev/null @@ -1,4651 +0,0 @@ -/*****************************************************************************/ - -/* - * stallion.c -- stallion multiport serial driver. - * - * Copyright (C) 1996-1999 Stallion Technologies - * Copyright (C) 1994-1996 Greg Ungerer. - * - * This code is loosely based on the Linux serial driver, written by - * Linus Torvalds, Theodore T'so and others. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -/*****************************************************************************/ - -/* - * Define different board types. Use the standard Stallion "assigned" - * board numbers. Boards supported in this driver are abbreviated as - * EIO = EasyIO and ECH = EasyConnection 8/32. - */ -#define BRD_EASYIO 20 -#define BRD_ECH 21 -#define BRD_ECHMC 22 -#define BRD_ECHPCI 26 -#define BRD_ECH64PCI 27 -#define BRD_EASYIOPCI 28 - -struct stlconf { - unsigned int brdtype; - int ioaddr1; - int ioaddr2; - unsigned long memaddr; - int irq; - int irqtype; -}; - -static unsigned int stl_nrbrds; - -/*****************************************************************************/ - -/* - * Define some important driver characteristics. Device major numbers - * allocated as per Linux Device Registry. - */ -#ifndef STL_SIOMEMMAJOR -#define STL_SIOMEMMAJOR 28 -#endif -#ifndef STL_SERIALMAJOR -#define STL_SERIALMAJOR 24 -#endif -#ifndef STL_CALLOUTMAJOR -#define STL_CALLOUTMAJOR 25 -#endif - -/* - * Set the TX buffer size. Bigger is better, but we don't want - * to chew too much memory with buffers! - */ -#define STL_TXBUFLOW 512 -#define STL_TXBUFSIZE 4096 - -/*****************************************************************************/ - -/* - * Define our local driver identity first. Set up stuff to deal with - * all the local structures required by a serial tty driver. - */ -static char *stl_drvtitle = "Stallion Multiport Serial Driver"; -static char *stl_drvname = "stallion"; -static char *stl_drvversion = "5.6.0"; - -static struct tty_driver *stl_serial; - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. Basically all it defines is a raw port - * at 9600, 8 data bits, 1 stop bit. - */ -static struct ktermios stl_deftermios = { - .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), - .c_cc = INIT_C_CC, - .c_ispeed = 9600, - .c_ospeed = 9600, -}; - -/* - * Define global place to put buffer overflow characters. - */ -static char stl_unwanted[SC26198_RXFIFOSIZE]; - -/*****************************************************************************/ - -static DEFINE_MUTEX(stl_brdslock); -static struct stlbrd *stl_brds[STL_MAXBRDS]; - -static const struct tty_port_operations stl_port_ops; - -/* - * Per board state flags. Used with the state field of the board struct. - * Not really much here! - */ -#define BRD_FOUND 0x1 -#define STL_PROBED 0x2 - - -/* - * Define the port structure istate flags. These set of flags are - * modified at interrupt time - so setting and reseting them needs - * to be atomic. Use the bit clear/setting routines for this. - */ -#define ASYI_TXBUSY 1 -#define ASYI_TXLOW 2 -#define ASYI_TXFLOWED 3 - -/* - * Define an array of board names as printable strings. Handy for - * referencing boards when printing trace and stuff. - */ -static char *stl_brdnames[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "EasyIO", - "EC8/32-AT", - "EC8/32-MC", - NULL, - NULL, - NULL, - "EC8/32-PCI", - "EC8/64-PCI", - "EasyIO-PCI", -}; - -/*****************************************************************************/ - -/* - * Define some string labels for arguments passed from the module - * load line. These allow for easy board definitions, and easy - * modification of the io, memory and irq resoucres. - */ -static unsigned int stl_nargs; -static char *board0[4]; -static char *board1[4]; -static char *board2[4]; -static char *board3[4]; - -static char **stl_brdsp[] = { - (char **) &board0, - (char **) &board1, - (char **) &board2, - (char **) &board3 -}; - -/* - * Define a set of common board names, and types. This is used to - * parse any module arguments. - */ - -static struct { - char *name; - int type; -} stl_brdstr[] = { - { "easyio", BRD_EASYIO }, - { "eio", BRD_EASYIO }, - { "20", BRD_EASYIO }, - { "ec8/32", BRD_ECH }, - { "ec8/32-at", BRD_ECH }, - { "ec8/32-isa", BRD_ECH }, - { "ech", BRD_ECH }, - { "echat", BRD_ECH }, - { "21", BRD_ECH }, - { "ec8/32-mc", BRD_ECHMC }, - { "ec8/32-mca", BRD_ECHMC }, - { "echmc", BRD_ECHMC }, - { "echmca", BRD_ECHMC }, - { "22", BRD_ECHMC }, - { "ec8/32-pc", BRD_ECHPCI }, - { "ec8/32-pci", BRD_ECHPCI }, - { "26", BRD_ECHPCI }, - { "ec8/64-pc", BRD_ECH64PCI }, - { "ec8/64-pci", BRD_ECH64PCI }, - { "ech-pci", BRD_ECH64PCI }, - { "echpci", BRD_ECH64PCI }, - { "echpc", BRD_ECH64PCI }, - { "27", BRD_ECH64PCI }, - { "easyio-pc", BRD_EASYIOPCI }, - { "easyio-pci", BRD_EASYIOPCI }, - { "eio-pci", BRD_EASYIOPCI }, - { "eiopci", BRD_EASYIOPCI }, - { "28", BRD_EASYIOPCI }, -}; - -/* - * Define the module agruments. - */ - -module_param_array(board0, charp, &stl_nargs, 0); -MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); -module_param_array(board1, charp, &stl_nargs, 0); -MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]"); -module_param_array(board2, charp, &stl_nargs, 0); -MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]"); -module_param_array(board3, charp, &stl_nargs, 0); -MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]"); - -/*****************************************************************************/ - -/* - * Hardware ID bits for the EasyIO and ECH boards. These defines apply - * to the directly accessible io ports of these boards (not the uarts - - * they are in cd1400.h and sc26198.h). - */ -#define EIO_8PORTRS 0x04 -#define EIO_4PORTRS 0x05 -#define EIO_8PORTDI 0x00 -#define EIO_8PORTM 0x06 -#define EIO_MK3 0x03 -#define EIO_IDBITMASK 0x07 - -#define EIO_BRDMASK 0xf0 -#define ID_BRD4 0x10 -#define ID_BRD8 0x20 -#define ID_BRD16 0x30 - -#define EIO_INTRPEND 0x08 -#define EIO_INTEDGE 0x00 -#define EIO_INTLEVEL 0x08 -#define EIO_0WS 0x10 - -#define ECH_ID 0xa0 -#define ECH_IDBITMASK 0xe0 -#define ECH_BRDENABLE 0x08 -#define ECH_BRDDISABLE 0x00 -#define ECH_INTENABLE 0x01 -#define ECH_INTDISABLE 0x00 -#define ECH_INTLEVEL 0x02 -#define ECH_INTEDGE 0x00 -#define ECH_INTRPEND 0x01 -#define ECH_BRDRESET 0x01 - -#define ECHMC_INTENABLE 0x01 -#define ECHMC_BRDRESET 0x02 - -#define ECH_PNLSTATUS 2 -#define ECH_PNL16PORT 0x20 -#define ECH_PNLIDMASK 0x07 -#define ECH_PNLXPID 0x40 -#define ECH_PNLINTRPEND 0x80 - -#define ECH_ADDR2MASK 0x1e0 - -/* - * Define the vector mapping bits for the programmable interrupt board - * hardware. These bits encode the interrupt for the board to use - it - * is software selectable (except the EIO-8M). - */ -static unsigned char stl_vecmap[] = { - 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07, - 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03 -}; - -/* - * Lock ordering is that you may not take stallion_lock holding - * brd_lock. - */ - -static spinlock_t brd_lock; /* Guard the board mapping */ -static spinlock_t stallion_lock; /* Guard the tty driver */ - -/* - * Set up enable and disable macros for the ECH boards. They require - * the secondary io address space to be activated and deactivated. - * This way all ECH boards can share their secondary io region. - * If this is an ECH-PCI board then also need to set the page pointer - * to point to the correct page. - */ -#define BRDENABLE(brdnr,pagenr) \ - if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ - outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \ - stl_brds[(brdnr)]->ioctrl); \ - else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \ - outb((pagenr), stl_brds[(brdnr)]->ioctrl); - -#define BRDDISABLE(brdnr) \ - if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ - outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \ - stl_brds[(brdnr)]->ioctrl); - -#define STL_CD1400MAXBAUD 230400 -#define STL_SC26198MAXBAUD 460800 - -#define STL_BAUDBASE 115200 -#define STL_CLOSEDELAY (5 * HZ / 10) - -/*****************************************************************************/ - -/* - * Define the Stallion PCI vendor and device IDs. - */ -#ifndef PCI_VENDOR_ID_STALLION -#define PCI_VENDOR_ID_STALLION 0x124d -#endif -#ifndef PCI_DEVICE_ID_ECHPCI832 -#define PCI_DEVICE_ID_ECHPCI832 0x0000 -#endif -#ifndef PCI_DEVICE_ID_ECHPCI864 -#define PCI_DEVICE_ID_ECHPCI864 0x0002 -#endif -#ifndef PCI_DEVICE_ID_EIOPCI -#define PCI_DEVICE_ID_EIOPCI 0x0003 -#endif - -/* - * Define structure to hold all Stallion PCI boards. - */ - -static struct pci_device_id stl_pcibrds[] = { - { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864), - .driver_data = BRD_ECH64PCI }, - { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI), - .driver_data = BRD_EASYIOPCI }, - { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832), - .driver_data = BRD_ECHPCI }, - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), - .driver_data = BRD_ECHPCI }, - { } -}; -MODULE_DEVICE_TABLE(pci, stl_pcibrds); - -/*****************************************************************************/ - -/* - * Define macros to extract a brd/port number from a minor number. - */ -#define MINOR2BRD(min) (((min) & 0xc0) >> 6) -#define MINOR2PORT(min) ((min) & 0x3f) - -/* - * Define a baud rate table that converts termios baud rate selector - * into the actual baud rate value. All baud rate calculations are - * based on the actual baud rate required. - */ -static unsigned int stl_baudrates[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 -}; - -/*****************************************************************************/ - -/* - * Declare all those functions in this driver! - */ - -static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); -static int stl_brdinit(struct stlbrd *brdp); -static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); -static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); - -/* - * CD1400 uart specific handling functions. - */ -static void stl_cd1400setreg(struct stlport *portp, int regnr, int value); -static int stl_cd1400getreg(struct stlport *portp, int regnr); -static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value); -static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp); -static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); -static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp); -static int stl_cd1400getsignals(struct stlport *portp); -static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts); -static void stl_cd1400ccrwait(struct stlport *portp); -static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx); -static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx); -static void stl_cd1400disableintrs(struct stlport *portp); -static void stl_cd1400sendbreak(struct stlport *portp, int len); -static void stl_cd1400flowctrl(struct stlport *portp, int state); -static void stl_cd1400sendflow(struct stlport *portp, int state); -static void stl_cd1400flush(struct stlport *portp); -static int stl_cd1400datastate(struct stlport *portp); -static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase); -static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase); -static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr); -static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr); -static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr); - -static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr); - -/* - * SC26198 uart specific handling functions. - */ -static void stl_sc26198setreg(struct stlport *portp, int regnr, int value); -static int stl_sc26198getreg(struct stlport *portp, int regnr); -static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value); -static int stl_sc26198getglobreg(struct stlport *portp, int regnr); -static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp); -static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); -static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp); -static int stl_sc26198getsignals(struct stlport *portp); -static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts); -static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx); -static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx); -static void stl_sc26198disableintrs(struct stlport *portp); -static void stl_sc26198sendbreak(struct stlport *portp, int len); -static void stl_sc26198flowctrl(struct stlport *portp, int state); -static void stl_sc26198sendflow(struct stlport *portp, int state); -static void stl_sc26198flush(struct stlport *portp); -static int stl_sc26198datastate(struct stlport *portp); -static void stl_sc26198wait(struct stlport *portp); -static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty); -static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase); -static void stl_sc26198txisr(struct stlport *port); -static void stl_sc26198rxisr(struct stlport *port, unsigned int iack); -static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch); -static void stl_sc26198rxbadchars(struct stlport *portp); -static void stl_sc26198otherisr(struct stlport *port, unsigned int iack); - -/*****************************************************************************/ - -/* - * Generic UART support structure. - */ -typedef struct uart { - int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp); - void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); - void (*setport)(struct stlport *portp, struct ktermios *tiosp); - int (*getsignals)(struct stlport *portp); - void (*setsignals)(struct stlport *portp, int dtr, int rts); - void (*enablerxtx)(struct stlport *portp, int rx, int tx); - void (*startrxtx)(struct stlport *portp, int rx, int tx); - void (*disableintrs)(struct stlport *portp); - void (*sendbreak)(struct stlport *portp, int len); - void (*flowctrl)(struct stlport *portp, int state); - void (*sendflow)(struct stlport *portp, int state); - void (*flush)(struct stlport *portp); - int (*datastate)(struct stlport *portp); - void (*intr)(struct stlpanel *panelp, unsigned int iobase); -} uart_t; - -/* - * Define some macros to make calling these functions nice and clean. - */ -#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit) -#define stl_portinit (* ((uart_t *) portp->uartp)->portinit) -#define stl_setport (* ((uart_t *) portp->uartp)->setport) -#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals) -#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals) -#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx) -#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx) -#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs) -#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak) -#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl) -#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow) -#define stl_flush (* ((uart_t *) portp->uartp)->flush) -#define stl_datastate (* ((uart_t *) portp->uartp)->datastate) - -/*****************************************************************************/ - -/* - * CD1400 UART specific data initialization. - */ -static uart_t stl_cd1400uart = { - stl_cd1400panelinit, - stl_cd1400portinit, - stl_cd1400setport, - stl_cd1400getsignals, - stl_cd1400setsignals, - stl_cd1400enablerxtx, - stl_cd1400startrxtx, - stl_cd1400disableintrs, - stl_cd1400sendbreak, - stl_cd1400flowctrl, - stl_cd1400sendflow, - stl_cd1400flush, - stl_cd1400datastate, - stl_cd1400eiointr -}; - -/* - * Define the offsets within the register bank of a cd1400 based panel. - * These io address offsets are common to the EasyIO board as well. - */ -#define EREG_ADDR 0 -#define EREG_DATA 4 -#define EREG_RXACK 5 -#define EREG_TXACK 6 -#define EREG_MDACK 7 - -#define EREG_BANKSIZE 8 - -#define CD1400_CLK 25000000 -#define CD1400_CLK8M 20000000 - -/* - * Define the cd1400 baud rate clocks. These are used when calculating - * what clock and divisor to use for the required baud rate. Also - * define the maximum baud rate allowed, and the default base baud. - */ -static int stl_cd1400clkdivs[] = { - CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4 -}; - -/*****************************************************************************/ - -/* - * SC26198 UART specific data initization. - */ -static uart_t stl_sc26198uart = { - stl_sc26198panelinit, - stl_sc26198portinit, - stl_sc26198setport, - stl_sc26198getsignals, - stl_sc26198setsignals, - stl_sc26198enablerxtx, - stl_sc26198startrxtx, - stl_sc26198disableintrs, - stl_sc26198sendbreak, - stl_sc26198flowctrl, - stl_sc26198sendflow, - stl_sc26198flush, - stl_sc26198datastate, - stl_sc26198intr -}; - -/* - * Define the offsets within the register bank of a sc26198 based panel. - */ -#define XP_DATA 0 -#define XP_ADDR 1 -#define XP_MODID 2 -#define XP_STATUS 2 -#define XP_IACK 3 - -#define XP_BANKSIZE 4 - -/* - * Define the sc26198 baud rate table. Offsets within the table - * represent the actual baud rate selector of sc26198 registers. - */ -static unsigned int sc26198_baudtable[] = { - 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600, - 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, - 230400, 460800, 921600 -}; - -#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable) - -/*****************************************************************************/ - -/* - * Define the driver info for a user level control device. Used mainly - * to get at port stats - only not using the port device itself. - */ -static const struct file_operations stl_fsiomem = { - .owner = THIS_MODULE, - .unlocked_ioctl = stl_memioctl, - .llseek = noop_llseek, -}; - -static struct class *stallion_class; - -static void stl_cd_change(struct stlport *portp) -{ - unsigned int oldsigs = portp->sigs; - struct tty_struct *tty = tty_port_tty_get(&portp->port); - - if (!tty) - return; - - portp->sigs = stl_getsignals(portp); - - if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) - wake_up_interruptible(&portp->port.open_wait); - - if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) - if (portp->port.flags & ASYNC_CHECK_CD) - tty_hangup(tty); - tty_kref_put(tty); -} - -/* - * Check for any arguments passed in on the module load command line. - */ - -/*****************************************************************************/ - -/* - * Parse the supplied argument string, into the board conf struct. - */ - -static int __init stl_parsebrd(struct stlconf *confp, char **argp) -{ - char *sp; - unsigned int i; - - pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp); - - if ((argp[0] == NULL) || (*argp[0] == 0)) - return 0; - - for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++) - *sp = tolower(*sp); - - for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) - if (strcmp(stl_brdstr[i].name, argp[0]) == 0) - break; - - if (i == ARRAY_SIZE(stl_brdstr)) { - printk("STALLION: unknown board name, %s?\n", argp[0]); - return 0; - } - - confp->brdtype = stl_brdstr[i].type; - - i = 1; - if ((argp[i] != NULL) && (*argp[i] != 0)) - confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0); - i++; - if (confp->brdtype == BRD_ECH) { - if ((argp[i] != NULL) && (*argp[i] != 0)) - confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0); - i++; - } - if ((argp[i] != NULL) && (*argp[i] != 0)) - confp->irq = simple_strtoul(argp[i], NULL, 0); - return 1; -} - -/*****************************************************************************/ - -/* - * Allocate a new board structure. Fill out the basic info in it. - */ - -static struct stlbrd *stl_allocbrd(void) -{ - struct stlbrd *brdp; - - brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL); - if (!brdp) { - printk("STALLION: failed to allocate memory (size=%Zd)\n", - sizeof(struct stlbrd)); - return NULL; - } - - brdp->magic = STL_BOARDMAGIC; - return brdp; -} - -/*****************************************************************************/ - -static int stl_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct stlport *portp = container_of(port, struct stlport, port); - if (!portp->tx.buf) { - portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); - if (!portp->tx.buf) - return -ENOMEM; - portp->tx.head = portp->tx.buf; - portp->tx.tail = portp->tx.buf; - } - stl_setport(portp, tty->termios); - portp->sigs = stl_getsignals(portp); - stl_setsignals(portp, 1, 1); - stl_enablerxtx(portp, 1, 1); - stl_startrxtx(portp, 1, 0); - return 0; -} - -static int stl_open(struct tty_struct *tty, struct file *filp) -{ - struct stlport *portp; - struct stlbrd *brdp; - unsigned int minordev, brdnr, panelnr; - int portnr; - - pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); - - minordev = tty->index; - brdnr = MINOR2BRD(minordev); - if (brdnr >= stl_nrbrds) - return -ENODEV; - brdp = stl_brds[brdnr]; - if (brdp == NULL) - return -ENODEV; - - minordev = MINOR2PORT(minordev); - for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { - if (brdp->panels[panelnr] == NULL) - break; - if (minordev < brdp->panels[panelnr]->nrports) { - portnr = minordev; - break; - } - minordev -= brdp->panels[panelnr]->nrports; - } - if (portnr < 0) - return -ENODEV; - - portp = brdp->panels[panelnr]->ports[portnr]; - if (portp == NULL) - return -ENODEV; - - tty->driver_data = portp; - return tty_port_open(&portp->port, tty, filp); - -} - -/*****************************************************************************/ - -static int stl_carrier_raised(struct tty_port *port) -{ - struct stlport *portp = container_of(port, struct stlport, port); - return (portp->sigs & TIOCM_CD) ? 1 : 0; -} - -static void stl_dtr_rts(struct tty_port *port, int on) -{ - struct stlport *portp = container_of(port, struct stlport, port); - /* Takes brd_lock internally */ - stl_setsignals(portp, on, on); -} - -/*****************************************************************************/ - -static void stl_flushbuffer(struct tty_struct *tty) -{ - struct stlport *portp; - - pr_debug("stl_flushbuffer(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return; - - stl_flush(portp); - tty_wakeup(tty); -} - -/*****************************************************************************/ - -static void stl_waituntilsent(struct tty_struct *tty, int timeout) -{ - struct stlport *portp; - unsigned long tend; - - pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); - - portp = tty->driver_data; - if (portp == NULL) - return; - - if (timeout == 0) - timeout = HZ; - tend = jiffies + timeout; - - while (stl_datastate(portp)) { - if (signal_pending(current)) - break; - msleep_interruptible(20); - if (time_after_eq(jiffies, tend)) - break; - } -} - -/*****************************************************************************/ - -static void stl_shutdown(struct tty_port *port) -{ - struct stlport *portp = container_of(port, struct stlport, port); - stl_disableintrs(portp); - stl_enablerxtx(portp, 0, 0); - stl_flush(portp); - portp->istate = 0; - if (portp->tx.buf != NULL) { - kfree(portp->tx.buf); - portp->tx.buf = NULL; - portp->tx.head = NULL; - portp->tx.tail = NULL; - } -} - -static void stl_close(struct tty_struct *tty, struct file *filp) -{ - struct stlport*portp; - pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); - - portp = tty->driver_data; - if(portp == NULL) - return; - tty_port_close(&portp->port, tty, filp); -} - -/*****************************************************************************/ - -/* - * Write routine. Take data and stuff it in to the TX ring queue. - * If transmit interrupts are not running then start them. - */ - -static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - struct stlport *portp; - unsigned int len, stlen; - unsigned char *chbuf; - char *head, *tail; - - pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count); - - portp = tty->driver_data; - if (portp == NULL) - return 0; - if (portp->tx.buf == NULL) - return 0; - -/* - * If copying direct from user space we must cater for page faults, - * causing us to "sleep" here for a while. To handle this copy in all - * the data we need now, into a local buffer. Then when we got it all - * copy it into the TX buffer. - */ - chbuf = (unsigned char *) buf; - - head = portp->tx.head; - tail = portp->tx.tail; - if (head >= tail) { - len = STL_TXBUFSIZE - (head - tail) - 1; - stlen = STL_TXBUFSIZE - (head - portp->tx.buf); - } else { - len = tail - head - 1; - stlen = len; - } - - len = min(len, (unsigned int)count); - count = 0; - while (len > 0) { - stlen = min(len, stlen); - memcpy(head, chbuf, stlen); - len -= stlen; - chbuf += stlen; - count += stlen; - head += stlen; - if (head >= (portp->tx.buf + STL_TXBUFSIZE)) { - head = portp->tx.buf; - stlen = tail - head; - } - } - portp->tx.head = head; - - clear_bit(ASYI_TXLOW, &portp->istate); - stl_startrxtx(portp, -1, 1); - - return count; -} - -/*****************************************************************************/ - -static int stl_putchar(struct tty_struct *tty, unsigned char ch) -{ - struct stlport *portp; - unsigned int len; - char *head, *tail; - - pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); - - portp = tty->driver_data; - if (portp == NULL) - return -EINVAL; - if (portp->tx.buf == NULL) - return -EINVAL; - - head = portp->tx.head; - tail = portp->tx.tail; - - len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head); - len--; - - if (len > 0) { - *head++ = ch; - if (head >= (portp->tx.buf + STL_TXBUFSIZE)) - head = portp->tx.buf; - } - portp->tx.head = head; - return 0; -} - -/*****************************************************************************/ - -/* - * If there are any characters in the buffer then make sure that TX - * interrupts are on and get'em out. Normally used after the putchar - * routine has been called. - */ - -static void stl_flushchars(struct tty_struct *tty) -{ - struct stlport *portp; - - pr_debug("stl_flushchars(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return; - if (portp->tx.buf == NULL) - return; - - stl_startrxtx(portp, -1, 1); -} - -/*****************************************************************************/ - -static int stl_writeroom(struct tty_struct *tty) -{ - struct stlport *portp; - char *head, *tail; - - pr_debug("stl_writeroom(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return 0; - if (portp->tx.buf == NULL) - return 0; - - head = portp->tx.head; - tail = portp->tx.tail; - return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1); -} - -/*****************************************************************************/ - -/* - * Return number of chars in the TX buffer. Normally we would just - * calculate the number of chars in the buffer and return that, but if - * the buffer is empty and TX interrupts are still on then we return - * that the buffer still has 1 char in it. This way whoever called us - * will not think that ALL chars have drained - since the UART still - * must have some chars in it (we are busy after all). - */ - -static int stl_charsinbuffer(struct tty_struct *tty) -{ - struct stlport *portp; - unsigned int size; - char *head, *tail; - - pr_debug("stl_charsinbuffer(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return 0; - if (portp->tx.buf == NULL) - return 0; - - head = portp->tx.head; - tail = portp->tx.tail; - size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); - if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate)) - size = 1; - return size; -} - -/*****************************************************************************/ - -/* - * Generate the serial struct info. - */ - -static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) -{ - struct serial_struct sio; - struct stlbrd *brdp; - - pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); - - memset(&sio, 0, sizeof(struct serial_struct)); - - mutex_lock(&portp->port.mutex); - sio.line = portp->portnr; - sio.port = portp->ioaddr; - sio.flags = portp->port.flags; - sio.baud_base = portp->baud_base; - sio.close_delay = portp->close_delay; - sio.closing_wait = portp->closing_wait; - sio.custom_divisor = portp->custom_divisor; - sio.hub6 = 0; - if (portp->uartp == &stl_cd1400uart) { - sio.type = PORT_CIRRUS; - sio.xmit_fifo_size = CD1400_TXFIFOSIZE; - } else { - sio.type = PORT_UNKNOWN; - sio.xmit_fifo_size = SC26198_TXFIFOSIZE; - } - - brdp = stl_brds[portp->brdnr]; - if (brdp != NULL) - sio.irq = brdp->irq; - mutex_unlock(&portp->port.mutex); - - return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Set port according to the serial struct info. - * At this point we do not do any auto-configure stuff, so we will - * just quietly ignore any requests to change irq, etc. - */ - -static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp) -{ - struct stlport * portp = tty->driver_data; - struct serial_struct sio; - - pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); - - if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) - return -EFAULT; - mutex_lock(&portp->port.mutex); - if (!capable(CAP_SYS_ADMIN)) { - if ((sio.baud_base != portp->baud_base) || - (sio.close_delay != portp->close_delay) || - ((sio.flags & ~ASYNC_USR_MASK) != - (portp->port.flags & ~ASYNC_USR_MASK))) { - mutex_unlock(&portp->port.mutex); - return -EPERM; - } - } - - portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | - (sio.flags & ASYNC_USR_MASK); - portp->baud_base = sio.baud_base; - portp->close_delay = sio.close_delay; - portp->closing_wait = sio.closing_wait; - portp->custom_divisor = sio.custom_divisor; - mutex_unlock(&portp->port.mutex); - stl_setport(portp, tty->termios); - return 0; -} - -/*****************************************************************************/ - -static int stl_tiocmget(struct tty_struct *tty) -{ - struct stlport *portp; - - portp = tty->driver_data; - if (portp == NULL) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - return stl_getsignals(portp); -} - -static int stl_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct stlport *portp; - int rts = -1, dtr = -1; - - portp = tty->driver_data; - if (portp == NULL) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - if (set & TIOCM_RTS) - rts = 1; - if (set & TIOCM_DTR) - dtr = 1; - if (clear & TIOCM_RTS) - rts = 0; - if (clear & TIOCM_DTR) - dtr = 0; - - stl_setsignals(portp, dtr, rts); - return 0; -} - -static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) -{ - struct stlport *portp; - int rc; - void __user *argp = (void __user *)arg; - - pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg); - - portp = tty->driver_data; - if (portp == NULL) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - rc = 0; - - switch (cmd) { - case TIOCGSERIAL: - rc = stl_getserial(portp, argp); - break; - case TIOCSSERIAL: - rc = stl_setserial(tty, argp); - break; - case COM_GETPORTSTATS: - rc = stl_getportstats(tty, portp, argp); - break; - case COM_CLRPORTSTATS: - rc = stl_clrportstats(portp, argp); - break; - case TIOCSERCONFIG: - case TIOCSERGWILD: - case TIOCSERSWILD: - case TIOCSERGETLSR: - case TIOCSERGSTRUCT: - case TIOCSERGETMULTI: - case TIOCSERSETMULTI: - default: - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -/*****************************************************************************/ - -/* - * Start the transmitter again. Just turn TX interrupts back on. - */ - -static void stl_start(struct tty_struct *tty) -{ - struct stlport *portp; - - pr_debug("stl_start(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return; - stl_startrxtx(portp, -1, 1); -} - -/*****************************************************************************/ - -static void stl_settermios(struct tty_struct *tty, struct ktermios *old) -{ - struct stlport *portp; - struct ktermios *tiosp; - - pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); - - portp = tty->driver_data; - if (portp == NULL) - return; - - tiosp = tty->termios; - if ((tiosp->c_cflag == old->c_cflag) && - (tiosp->c_iflag == old->c_iflag)) - return; - - stl_setport(portp, tiosp); - stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0), - -1); - if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) { - tty->hw_stopped = 0; - stl_start(tty); - } - if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) - wake_up_interruptible(&portp->port.open_wait); -} - -/*****************************************************************************/ - -/* - * Attempt to flow control who ever is sending us data. Based on termios - * settings use software or/and hardware flow control. - */ - -static void stl_throttle(struct tty_struct *tty) -{ - struct stlport *portp; - - pr_debug("stl_throttle(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return; - stl_flowctrl(portp, 0); -} - -/*****************************************************************************/ - -/* - * Unflow control the device sending us data... - */ - -static void stl_unthrottle(struct tty_struct *tty) -{ - struct stlport *portp; - - pr_debug("stl_unthrottle(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return; - stl_flowctrl(portp, 1); -} - -/*****************************************************************************/ - -/* - * Stop the transmitter. Basically to do this we will just turn TX - * interrupts off. - */ - -static void stl_stop(struct tty_struct *tty) -{ - struct stlport *portp; - - pr_debug("stl_stop(tty=%p)\n", tty); - - portp = tty->driver_data; - if (portp == NULL) - return; - stl_startrxtx(portp, -1, 0); -} - -/*****************************************************************************/ - -/* - * Hangup this port. This is pretty much like closing the port, only - * a little more brutal. No waiting for data to drain. Shutdown the - * port and maybe drop signals. - */ - -static void stl_hangup(struct tty_struct *tty) -{ - struct stlport *portp = tty->driver_data; - pr_debug("stl_hangup(tty=%p)\n", tty); - - if (portp == NULL) - return; - tty_port_hangup(&portp->port); -} - -/*****************************************************************************/ - -static int stl_breakctl(struct tty_struct *tty, int state) -{ - struct stlport *portp; - - pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); - - portp = tty->driver_data; - if (portp == NULL) - return -EINVAL; - - stl_sendbreak(portp, ((state == -1) ? 1 : 2)); - return 0; -} - -/*****************************************************************************/ - -static void stl_sendxchar(struct tty_struct *tty, char ch) -{ - struct stlport *portp; - - pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); - - portp = tty->driver_data; - if (portp == NULL) - return; - - if (ch == STOP_CHAR(tty)) - stl_sendflow(portp, 0); - else if (ch == START_CHAR(tty)) - stl_sendflow(portp, 1); - else - stl_putchar(tty, ch); -} - -static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr) -{ - int sigs; - char sep; - - seq_printf(m, "%d: uart:%s tx:%d rx:%d", - portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", - (int) portp->stats.txtotal, (int) portp->stats.rxtotal); - - if (portp->stats.rxframing) - seq_printf(m, " fe:%d", (int) portp->stats.rxframing); - if (portp->stats.rxparity) - seq_printf(m, " pe:%d", (int) portp->stats.rxparity); - if (portp->stats.rxbreaks) - seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks); - if (portp->stats.rxoverrun) - seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun); - - sigs = stl_getsignals(portp); - sep = ' '; - if (sigs & TIOCM_RTS) { - seq_printf(m, "%c%s", sep, "RTS"); - sep = '|'; - } - if (sigs & TIOCM_CTS) { - seq_printf(m, "%c%s", sep, "CTS"); - sep = '|'; - } - if (sigs & TIOCM_DTR) { - seq_printf(m, "%c%s", sep, "DTR"); - sep = '|'; - } - if (sigs & TIOCM_CD) { - seq_printf(m, "%c%s", sep, "DCD"); - sep = '|'; - } - if (sigs & TIOCM_DSR) { - seq_printf(m, "%c%s", sep, "DSR"); - sep = '|'; - } - seq_putc(m, '\n'); -} - -/*****************************************************************************/ - -/* - * Port info, read from the /proc file system. - */ - -static int stl_proc_show(struct seq_file *m, void *v) -{ - struct stlbrd *brdp; - struct stlpanel *panelp; - struct stlport *portp; - unsigned int brdnr, panelnr, portnr; - int totalport; - - totalport = 0; - - seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion); - -/* - * We scan through for each board, panel and port. The offset is - * calculated on the fly, and irrelevant ports are skipped. - */ - for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) { - brdp = stl_brds[brdnr]; - if (brdp == NULL) - continue; - if (brdp->state == 0) - continue; - - totalport = brdnr * STL_MAXPORTS; - for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { - panelp = brdp->panels[panelnr]; - if (panelp == NULL) - continue; - - for (portnr = 0; portnr < panelp->nrports; portnr++, - totalport++) { - portp = panelp->ports[portnr]; - if (portp == NULL) - continue; - stl_portinfo(m, portp, totalport); - } - } - } - return 0; -} - -static int stl_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, stl_proc_show, NULL); -} - -static const struct file_operations stl_proc_fops = { - .owner = THIS_MODULE, - .open = stl_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/*****************************************************************************/ - -/* - * All board interrupts are vectored through here first. This code then - * calls off to the approrpriate board interrupt handlers. - */ - -static irqreturn_t stl_intr(int irq, void *dev_id) -{ - struct stlbrd *brdp = dev_id; - - pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq); - - return IRQ_RETVAL((* brdp->isr)(brdp)); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for EasyIO board types. - */ - -static int stl_eiointr(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int iobase; - int handled = 0; - - spin_lock(&brd_lock); - panelp = brdp->panels[0]; - iobase = panelp->iobase; - while (inb(brdp->iostatus) & EIO_INTRPEND) { - handled = 1; - (* panelp->isr)(panelp, iobase); - } - spin_unlock(&brd_lock); - return handled; -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-AT board types. - */ - -static int stl_echatintr(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int ioaddr, bnknr; - int handled = 0; - - outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); - - while (inb(brdp->iostatus) & ECH_INTRPEND) { - handled = 1; - for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } - - outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); - - return handled; -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-MCA board types. - */ - -static int stl_echmcaintr(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int ioaddr, bnknr; - int handled = 0; - - while (inb(brdp->iostatus) & ECH_INTRPEND) { - handled = 1; - for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } - return handled; -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-PCI board types. - */ - -static int stl_echpciintr(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int ioaddr, bnknr, recheck; - int handled = 0; - - while (1) { - recheck = 0; - for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { - outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl); - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - recheck++; - handled = 1; - } - } - if (! recheck) - break; - } - return handled; -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-8/64-PCI board types. - */ - -static int stl_echpci64intr(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int ioaddr, bnknr; - int handled = 0; - - while (inb(brdp->ioctrl) & 0x1) { - handled = 1; - for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } - - return handled; -} - -/*****************************************************************************/ - -/* - * Initialize all the ports on a panel. - */ - -static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) -{ - struct stlport *portp; - unsigned int i; - int chipmask; - - pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp); - - chipmask = stl_panelinit(brdp, panelp); - -/* - * All UART's are initialized (if found!). Now go through and setup - * each ports data structures. - */ - for (i = 0; i < panelp->nrports; i++) { - portp = kzalloc(sizeof(struct stlport), GFP_KERNEL); - if (!portp) { - printk("STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(struct stlport)); - break; - } - tty_port_init(&portp->port); - portp->port.ops = &stl_port_ops; - portp->magic = STL_PORTMAGIC; - portp->portnr = i; - portp->brdnr = panelp->brdnr; - portp->panelnr = panelp->panelnr; - portp->uartp = panelp->uartp; - portp->clk = brdp->clk; - portp->baud_base = STL_BAUDBASE; - portp->close_delay = STL_CLOSEDELAY; - portp->closing_wait = 30 * HZ; - init_waitqueue_head(&portp->port.open_wait); - init_waitqueue_head(&portp->port.close_wait); - portp->stats.brd = portp->brdnr; - portp->stats.panel = portp->panelnr; - portp->stats.port = portp->portnr; - panelp->ports[i] = portp; - stl_portinit(brdp, panelp, portp); - } - - return 0; -} - -static void stl_cleanup_panels(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - struct stlport *portp; - unsigned int j, k; - struct tty_struct *tty; - - for (j = 0; j < STL_MAXPANELS; j++) { - panelp = brdp->panels[j]; - if (panelp == NULL) - continue; - for (k = 0; k < STL_PORTSPERPANEL; k++) { - portp = panelp->ports[k]; - if (portp == NULL) - continue; - tty = tty_port_tty_get(&portp->port); - if (tty != NULL) { - stl_hangup(tty); - tty_kref_put(tty); - } - kfree(portp->tx.buf); - kfree(portp); - } - kfree(panelp); - } -} - -/*****************************************************************************/ - -/* - * Try to find and initialize an EasyIO board. - */ - -static int __devinit stl_initeio(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int status; - char *name; - int retval; - - pr_debug("stl_initeio(brdp=%p)\n", brdp); - - brdp->ioctrl = brdp->ioaddr1 + 1; - brdp->iostatus = brdp->ioaddr1 + 2; - - status = inb(brdp->iostatus); - if ((status & EIO_IDBITMASK) == EIO_MK3) - brdp->ioctrl++; - -/* - * Handle board specific stuff now. The real difference is PCI - * or not PCI. - */ - if (brdp->brdtype == BRD_EASYIOPCI) { - brdp->iosize1 = 0x80; - brdp->iosize2 = 0x80; - name = "serial(EIO-PCI)"; - outb(0x41, (brdp->ioaddr2 + 0x4c)); - } else { - brdp->iosize1 = 8; - name = "serial(EIO)"; - if ((brdp->irq < 0) || (brdp->irq > 15) || - (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { - printk("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - retval = -EINVAL; - goto err; - } - outb((stl_vecmap[brdp->irq] | EIO_0WS | - ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), - brdp->ioctrl); - } - - retval = -EBUSY; - if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { - printk(KERN_WARNING "STALLION: Warning, board %d I/O address " - "%x conflicts with another device\n", brdp->brdnr, - brdp->ioaddr1); - goto err; - } - - if (brdp->iosize2 > 0) - if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) { - printk(KERN_WARNING "STALLION: Warning, board %d I/O " - "address %x conflicts with another device\n", - brdp->brdnr, brdp->ioaddr2); - printk(KERN_WARNING "STALLION: Warning, also " - "releasing board %d I/O address %x \n", - brdp->brdnr, brdp->ioaddr1); - goto err_rel1; - } - -/* - * Everything looks OK, so let's go ahead and probe for the hardware. - */ - brdp->clk = CD1400_CLK; - brdp->isr = stl_eiointr; - - retval = -ENODEV; - switch (status & EIO_IDBITMASK) { - case EIO_8PORTM: - brdp->clk = CD1400_CLK8M; - /* fall thru */ - case EIO_8PORTRS: - case EIO_8PORTDI: - brdp->nrports = 8; - break; - case EIO_4PORTRS: - brdp->nrports = 4; - break; - case EIO_MK3: - switch (status & EIO_BRDMASK) { - case ID_BRD4: - brdp->nrports = 4; - break; - case ID_BRD8: - brdp->nrports = 8; - break; - case ID_BRD16: - brdp->nrports = 16; - break; - default: - goto err_rel2; - } - break; - default: - goto err_rel2; - } - -/* - * We have verified that the board is actually present, so now we - * can complete the setup. - */ - - panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); - if (!panelp) { - printk(KERN_WARNING "STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(struct stlpanel)); - retval = -ENOMEM; - goto err_rel2; - } - - panelp->magic = STL_PANELMAGIC; - panelp->brdnr = brdp->brdnr; - panelp->panelnr = 0; - panelp->nrports = brdp->nrports; - panelp->iobase = brdp->ioaddr1; - panelp->hwid = status; - if ((status & EIO_IDBITMASK) == EIO_MK3) { - panelp->uartp = &stl_sc26198uart; - panelp->isr = stl_sc26198intr; - } else { - panelp->uartp = &stl_cd1400uart; - panelp->isr = stl_cd1400eiointr; - } - - brdp->panels[0] = panelp; - brdp->nrpanels = 1; - brdp->state |= BRD_FOUND; - brdp->hwid = status; - if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { - printk("STALLION: failed to register interrupt " - "routine for %s irq=%d\n", name, brdp->irq); - retval = -ENODEV; - goto err_fr; - } - - return 0; -err_fr: - stl_cleanup_panels(brdp); -err_rel2: - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); -err_rel1: - release_region(brdp->ioaddr1, brdp->iosize1); -err: - return retval; -} - -/*****************************************************************************/ - -/* - * Try to find an ECH board and initialize it. This code is capable of - * dealing with all types of ECH board. - */ - -static int __devinit stl_initech(struct stlbrd *brdp) -{ - struct stlpanel *panelp; - unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i; - int retval; - char *name; - - pr_debug("stl_initech(brdp=%p)\n", brdp); - - status = 0; - conflict = 0; - -/* - * Set up the initial board register contents for boards. This varies a - * bit between the different board types. So we need to handle each - * separately. Also do a check that the supplied IRQ is good. - */ - switch (brdp->brdtype) { - - case BRD_ECH: - brdp->isr = stl_echatintr; - brdp->ioctrl = brdp->ioaddr1 + 1; - brdp->iostatus = brdp->ioaddr1 + 1; - status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) { - retval = -ENODEV; - goto err; - } - if ((brdp->irq < 0) || (brdp->irq > 15) || - (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { - printk("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - retval = -EINVAL; - goto err; - } - status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); - status |= (stl_vecmap[brdp->irq] << 1); - outb((status | ECH_BRDRESET), brdp->ioaddr1); - brdp->ioctrlval = ECH_INTENABLE | - ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE); - for (i = 0; i < 10; i++) - outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); - brdp->iosize1 = 2; - brdp->iosize2 = 32; - name = "serial(EC8/32)"; - outb(status, brdp->ioaddr1); - break; - - case BRD_ECHMC: - brdp->isr = stl_echmcaintr; - brdp->ioctrl = brdp->ioaddr1 + 0x20; - brdp->iostatus = brdp->ioctrl; - status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) { - retval = -ENODEV; - goto err; - } - if ((brdp->irq < 0) || (brdp->irq > 15) || - (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { - printk("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - retval = -EINVAL; - goto err; - } - outb(ECHMC_BRDRESET, brdp->ioctrl); - outb(ECHMC_INTENABLE, brdp->ioctrl); - brdp->iosize1 = 64; - name = "serial(EC8/32-MC)"; - break; - - case BRD_ECHPCI: - brdp->isr = stl_echpciintr; - brdp->ioctrl = brdp->ioaddr1 + 2; - brdp->iosize1 = 4; - brdp->iosize2 = 8; - name = "serial(EC8/32-PCI)"; - break; - - case BRD_ECH64PCI: - brdp->isr = stl_echpci64intr; - brdp->ioctrl = brdp->ioaddr2 + 0x40; - outb(0x43, (brdp->ioaddr1 + 0x4c)); - brdp->iosize1 = 0x80; - brdp->iosize2 = 0x80; - name = "serial(EC8/64-PCI)"; - break; - - default: - printk("STALLION: unknown board type=%d\n", brdp->brdtype); - retval = -EINVAL; - goto err; - } - -/* - * Check boards for possible IO address conflicts and return fail status - * if an IO conflict found. - */ - retval = -EBUSY; - if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { - printk(KERN_WARNING "STALLION: Warning, board %d I/O address " - "%x conflicts with another device\n", brdp->brdnr, - brdp->ioaddr1); - goto err; - } - - if (brdp->iosize2 > 0) - if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) { - printk(KERN_WARNING "STALLION: Warning, board %d I/O " - "address %x conflicts with another device\n", - brdp->brdnr, brdp->ioaddr2); - printk(KERN_WARNING "STALLION: Warning, also " - "releasing board %d I/O address %x \n", - brdp->brdnr, brdp->ioaddr1); - goto err_rel1; - } - -/* - * Scan through the secondary io address space looking for panels. - * As we find'em allocate and initialize panel structures for each. - */ - brdp->clk = CD1400_CLK; - brdp->hwid = status; - - ioaddr = brdp->ioaddr2; - banknr = 0; - panelnr = 0; - nxtid = 0; - - for (i = 0; i < STL_MAXPANELS; i++) { - if (brdp->brdtype == BRD_ECHPCI) { - outb(nxtid, brdp->ioctrl); - ioaddr = brdp->ioaddr2; - } - status = inb(ioaddr + ECH_PNLSTATUS); - if ((status & ECH_PNLIDMASK) != nxtid) - break; - panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); - if (!panelp) { - printk("STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(struct stlpanel)); - retval = -ENOMEM; - goto err_fr; - } - panelp->magic = STL_PANELMAGIC; - panelp->brdnr = brdp->brdnr; - panelp->panelnr = panelnr; - panelp->iobase = ioaddr; - panelp->pagenr = nxtid; - panelp->hwid = status; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; - - if (status & ECH_PNLXPID) { - panelp->uartp = &stl_sc26198uart; - panelp->isr = stl_sc26198intr; - if (status & ECH_PNL16PORT) { - panelp->nrports = 16; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + 4 + - ECH_PNLSTATUS; - } else - panelp->nrports = 8; - } else { - panelp->uartp = &stl_cd1400uart; - panelp->isr = stl_cd1400echintr; - if (status & ECH_PNL16PORT) { - panelp->nrports = 16; - panelp->ackmask = 0x80; - if (brdp->brdtype != BRD_ECHPCI) - ioaddr += EREG_BANKSIZE; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = ++nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + - ECH_PNLSTATUS; - } else { - panelp->nrports = 8; - panelp->ackmask = 0xc0; - } - } - - nxtid++; - ioaddr += EREG_BANKSIZE; - brdp->nrports += panelp->nrports; - brdp->panels[panelnr++] = panelp; - if ((brdp->brdtype != BRD_ECHPCI) && - (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) { - retval = -EINVAL; - goto err_fr; - } - } - - brdp->nrpanels = panelnr; - brdp->nrbnks = banknr; - if (brdp->brdtype == BRD_ECH) - outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); - - brdp->state |= BRD_FOUND; - if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { - printk("STALLION: failed to register interrupt " - "routine for %s irq=%d\n", name, brdp->irq); - retval = -ENODEV; - goto err_fr; - } - - return 0; -err_fr: - stl_cleanup_panels(brdp); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); -err_rel1: - release_region(brdp->ioaddr1, brdp->iosize1); -err: - return retval; -} - -/*****************************************************************************/ - -/* - * Initialize and configure the specified board. - * Scan through all the boards in the configuration and see what we - * can find. Handle EIO and the ECH boards a little differently here - * since the initial search and setup is very different. - */ - -static int __devinit stl_brdinit(struct stlbrd *brdp) -{ - int i, retval; - - pr_debug("stl_brdinit(brdp=%p)\n", brdp); - - switch (brdp->brdtype) { - case BRD_EASYIO: - case BRD_EASYIOPCI: - retval = stl_initeio(brdp); - if (retval) - goto err; - break; - case BRD_ECH: - case BRD_ECHMC: - case BRD_ECHPCI: - case BRD_ECH64PCI: - retval = stl_initech(brdp); - if (retval) - goto err; - break; - default: - printk("STALLION: board=%d is unknown board type=%d\n", - brdp->brdnr, brdp->brdtype); - retval = -ENODEV; - goto err; - } - - if ((brdp->state & BRD_FOUND) == 0) { - printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", - stl_brdnames[brdp->brdtype], brdp->brdnr, - brdp->ioaddr1, brdp->irq); - goto err_free; - } - - for (i = 0; i < STL_MAXPANELS; i++) - if (brdp->panels[i] != NULL) - stl_initports(brdp, brdp->panels[i]); - - printk("STALLION: %s found, board=%d io=%x irq=%d " - "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], - brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, - brdp->nrports); - - return 0; -err_free: - free_irq(brdp->irq, brdp); - - stl_cleanup_panels(brdp); - - release_region(brdp->ioaddr1, brdp->iosize1); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); -err: - return retval; -} - -/*****************************************************************************/ - -/* - * Find the next available board number that is free. - */ - -static int __devinit stl_getbrdnr(void) -{ - unsigned int i; - - for (i = 0; i < STL_MAXBRDS; i++) - if (stl_brds[i] == NULL) { - if (i >= stl_nrbrds) - stl_nrbrds = i + 1; - return i; - } - - return -1; -} - -/*****************************************************************************/ -/* - * We have a Stallion board. Allocate a board structure and - * initialize it. Read its IO and IRQ resources from PCI - * configuration space. - */ - -static int __devinit stl_pciprobe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct stlbrd *brdp; - unsigned int i, brdtype = ent->driver_data; - int brdnr, retval = -ENODEV; - - if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) - goto err; - - retval = pci_enable_device(pdev); - if (retval) - goto err; - brdp = stl_allocbrd(); - if (brdp == NULL) { - retval = -ENOMEM; - goto err; - } - mutex_lock(&stl_brdslock); - brdnr = stl_getbrdnr(); - if (brdnr < 0) { - dev_err(&pdev->dev, "too many boards found, " - "maximum supported %d\n", STL_MAXBRDS); - mutex_unlock(&stl_brdslock); - retval = -ENODEV; - goto err_fr; - } - brdp->brdnr = (unsigned int)brdnr; - stl_brds[brdp->brdnr] = brdp; - mutex_unlock(&stl_brdslock); - - brdp->brdtype = brdtype; - brdp->state |= STL_PROBED; - -/* - * We have all resources from the board, so let's setup the actual - * board structure now. - */ - switch (brdtype) { - case BRD_ECHPCI: - brdp->ioaddr2 = pci_resource_start(pdev, 0); - brdp->ioaddr1 = pci_resource_start(pdev, 1); - break; - case BRD_ECH64PCI: - brdp->ioaddr2 = pci_resource_start(pdev, 2); - brdp->ioaddr1 = pci_resource_start(pdev, 1); - break; - case BRD_EASYIOPCI: - brdp->ioaddr1 = pci_resource_start(pdev, 2); - brdp->ioaddr2 = pci_resource_start(pdev, 1); - break; - default: - dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype); - break; - } - - brdp->irq = pdev->irq; - retval = stl_brdinit(brdp); - if (retval) - goto err_null; - - pci_set_drvdata(pdev, brdp); - - for (i = 0; i < brdp->nrports; i++) - tty_register_device(stl_serial, - brdp->brdnr * STL_MAXPORTS + i, &pdev->dev); - - return 0; -err_null: - stl_brds[brdp->brdnr] = NULL; -err_fr: - kfree(brdp); -err: - return retval; -} - -static void __devexit stl_pciremove(struct pci_dev *pdev) -{ - struct stlbrd *brdp = pci_get_drvdata(pdev); - unsigned int i; - - free_irq(brdp->irq, brdp); - - stl_cleanup_panels(brdp); - - release_region(brdp->ioaddr1, brdp->iosize1); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); - - for (i = 0; i < brdp->nrports; i++) - tty_unregister_device(stl_serial, - brdp->brdnr * STL_MAXPORTS + i); - - stl_brds[brdp->brdnr] = NULL; - kfree(brdp); -} - -static struct pci_driver stl_pcidriver = { - .name = "stallion", - .id_table = stl_pcibrds, - .probe = stl_pciprobe, - .remove = __devexit_p(stl_pciremove) -}; - -/*****************************************************************************/ - -/* - * Return the board stats structure to user app. - */ - -static int stl_getbrdstats(combrd_t __user *bp) -{ - combrd_t stl_brdstats; - struct stlbrd *brdp; - struct stlpanel *panelp; - unsigned int i; - - if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t))) - return -EFAULT; - if (stl_brdstats.brd >= STL_MAXBRDS) - return -ENODEV; - brdp = stl_brds[stl_brdstats.brd]; - if (brdp == NULL) - return -ENODEV; - - memset(&stl_brdstats, 0, sizeof(combrd_t)); - stl_brdstats.brd = brdp->brdnr; - stl_brdstats.type = brdp->brdtype; - stl_brdstats.hwid = brdp->hwid; - stl_brdstats.state = brdp->state; - stl_brdstats.ioaddr = brdp->ioaddr1; - stl_brdstats.ioaddr2 = brdp->ioaddr2; - stl_brdstats.irq = brdp->irq; - stl_brdstats.nrpanels = brdp->nrpanels; - stl_brdstats.nrports = brdp->nrports; - for (i = 0; i < brdp->nrpanels; i++) { - panelp = brdp->panels[i]; - stl_brdstats.panels[i].panel = i; - stl_brdstats.panels[i].hwid = panelp->hwid; - stl_brdstats.panels[i].nrports = panelp->nrports; - } - - return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Resolve the referenced port number into a port struct pointer. - */ - -static struct stlport *stl_getport(int brdnr, int panelnr, int portnr) -{ - struct stlbrd *brdp; - struct stlpanel *panelp; - - if (brdnr < 0 || brdnr >= STL_MAXBRDS) - return NULL; - brdp = stl_brds[brdnr]; - if (brdp == NULL) - return NULL; - if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels) - return NULL; - panelp = brdp->panels[panelnr]; - if (panelp == NULL) - return NULL; - if (portnr < 0 || (unsigned int)portnr >= panelp->nrports) - return NULL; - return panelp->ports[portnr]; -} - -/*****************************************************************************/ - -/* - * Return the port stats structure to user app. A NULL port struct - * pointer passed in means that we need to find out from the app - * what port to get stats for (used through board control device). - */ - -static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp) -{ - comstats_t stl_comstats; - unsigned char *head, *tail; - unsigned long flags; - - if (!portp) { - if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) - return -EFAULT; - portp = stl_getport(stl_comstats.brd, stl_comstats.panel, - stl_comstats.port); - if (portp == NULL) - return -ENODEV; - } - - mutex_lock(&portp->port.mutex); - portp->stats.state = portp->istate; - portp->stats.flags = portp->port.flags; - portp->stats.hwid = portp->hwid; - - portp->stats.ttystate = 0; - portp->stats.cflags = 0; - portp->stats.iflags = 0; - portp->stats.oflags = 0; - portp->stats.lflags = 0; - portp->stats.rxbuffered = 0; - - spin_lock_irqsave(&stallion_lock, flags); - if (tty != NULL && portp->port.tty == tty) { - portp->stats.ttystate = tty->flags; - /* No longer available as a statistic */ - portp->stats.rxbuffered = 1; /*tty->flip.count; */ - if (tty->termios != NULL) { - portp->stats.cflags = tty->termios->c_cflag; - portp->stats.iflags = tty->termios->c_iflag; - portp->stats.oflags = tty->termios->c_oflag; - portp->stats.lflags = tty->termios->c_lflag; - } - } - spin_unlock_irqrestore(&stallion_lock, flags); - - head = portp->tx.head; - tail = portp->tx.tail; - portp->stats.txbuffered = (head >= tail) ? (head - tail) : - (STL_TXBUFSIZE - (tail - head)); - - portp->stats.signals = (unsigned long) stl_getsignals(portp); - mutex_unlock(&portp->port.mutex); - - return copy_to_user(cp, &portp->stats, - sizeof(comstats_t)) ? -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Clear the port stats structure. We also return it zeroed out... - */ - -static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) -{ - comstats_t stl_comstats; - - if (!portp) { - if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) - return -EFAULT; - portp = stl_getport(stl_comstats.brd, stl_comstats.panel, - stl_comstats.port); - if (portp == NULL) - return -ENODEV; - } - - mutex_lock(&portp->port.mutex); - memset(&portp->stats, 0, sizeof(comstats_t)); - portp->stats.brd = portp->brdnr; - portp->stats.panel = portp->panelnr; - portp->stats.port = portp->portnr; - mutex_unlock(&portp->port.mutex); - return copy_to_user(cp, &portp->stats, - sizeof(comstats_t)) ? -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Return the entire driver ports structure to a user app. - */ - -static int stl_getportstruct(struct stlport __user *arg) -{ - struct stlport stl_dummyport; - struct stlport *portp; - - if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport))) - return -EFAULT; - portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, - stl_dummyport.portnr); - if (!portp) - return -ENODEV; - return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * Return the entire driver board structure to a user app. - */ - -static int stl_getbrdstruct(struct stlbrd __user *arg) -{ - struct stlbrd stl_dummybrd; - struct stlbrd *brdp; - - if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd))) - return -EFAULT; - if (stl_dummybrd.brdnr >= STL_MAXBRDS) - return -ENODEV; - brdp = stl_brds[stl_dummybrd.brdnr]; - if (!brdp) - return -ENODEV; - return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0; -} - -/*****************************************************************************/ - -/* - * The "staliomem" device is also required to do some special operations - * on the board and/or ports. In this driver it is mostly used for stats - * collection. - */ - -static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) -{ - int brdnr, rc; - void __user *argp = (void __user *)arg; - - pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); - - brdnr = iminor(fp->f_dentry->d_inode); - if (brdnr >= STL_MAXBRDS) - return -ENODEV; - rc = 0; - - switch (cmd) { - case COM_GETPORTSTATS: - rc = stl_getportstats(NULL, NULL, argp); - break; - case COM_CLRPORTSTATS: - rc = stl_clrportstats(NULL, argp); - break; - case COM_GETBRDSTATS: - rc = stl_getbrdstats(argp); - break; - case COM_READPORT: - rc = stl_getportstruct(argp); - break; - case COM_READBOARD: - rc = stl_getbrdstruct(argp); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - return rc; -} - -static const struct tty_operations stl_ops = { - .open = stl_open, - .close = stl_close, - .write = stl_write, - .put_char = stl_putchar, - .flush_chars = stl_flushchars, - .write_room = stl_writeroom, - .chars_in_buffer = stl_charsinbuffer, - .ioctl = stl_ioctl, - .set_termios = stl_settermios, - .throttle = stl_throttle, - .unthrottle = stl_unthrottle, - .stop = stl_stop, - .start = stl_start, - .hangup = stl_hangup, - .flush_buffer = stl_flushbuffer, - .break_ctl = stl_breakctl, - .wait_until_sent = stl_waituntilsent, - .send_xchar = stl_sendxchar, - .tiocmget = stl_tiocmget, - .tiocmset = stl_tiocmset, - .proc_fops = &stl_proc_fops, -}; - -static const struct tty_port_operations stl_port_ops = { - .carrier_raised = stl_carrier_raised, - .dtr_rts = stl_dtr_rts, - .activate = stl_activate, - .shutdown = stl_shutdown, -}; - -/*****************************************************************************/ -/* CD1400 HARDWARE FUNCTIONS */ -/*****************************************************************************/ - -/* - * These functions get/set/update the registers of the cd1400 UARTs. - * Access to the cd1400 registers is via an address/data io port pair. - * (Maybe should make this inline...) - */ - -static int stl_cd1400getreg(struct stlport *portp, int regnr) -{ - outb((regnr + portp->uartaddr), portp->ioaddr); - return inb(portp->ioaddr + EREG_DATA); -} - -static void stl_cd1400setreg(struct stlport *portp, int regnr, int value) -{ - outb(regnr + portp->uartaddr, portp->ioaddr); - outb(value, portp->ioaddr + EREG_DATA); -} - -static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value) -{ - outb(regnr + portp->uartaddr, portp->ioaddr); - if (inb(portp->ioaddr + EREG_DATA) != value) { - outb(value, portp->ioaddr + EREG_DATA); - return 1; - } - return 0; -} - -/*****************************************************************************/ - -/* - * Inbitialize the UARTs in a panel. We don't care what sort of board - * these ports are on - since the port io registers are almost - * identical when dealing with ports. - */ - -static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp) -{ - unsigned int gfrcr; - int chipmask, i, j; - int nrchips, uartaddr, ioaddr; - unsigned long flags; - - pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(panelp->brdnr, panelp->pagenr); - -/* - * Check that each chip is present and started up OK. - */ - chipmask = 0; - nrchips = panelp->nrports / CD1400_PORTS; - for (i = 0; i < nrchips; i++) { - if (brdp->brdtype == BRD_ECHPCI) { - outb((panelp->pagenr + (i >> 1)), brdp->ioctrl); - ioaddr = panelp->iobase; - } else - ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1)); - uartaddr = (i & 0x01) ? 0x080 : 0; - outb((GFRCR + uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); - outb((CCR + uartaddr), ioaddr); - outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); - outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); - outb((GFRCR + uartaddr), ioaddr); - for (j = 0; j < CCR_MAXWAIT; j++) - if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) - break; - - if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { - printk("STALLION: cd1400 not responding, " - "brd=%d panel=%d chip=%d\n", - panelp->brdnr, panelp->panelnr, i); - continue; - } - chipmask |= (0x1 << i); - outb((PPR + uartaddr), ioaddr); - outb(PPR_SCALAR, (ioaddr + EREG_DATA)); - } - - BRDDISABLE(panelp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - return chipmask; -} - -/*****************************************************************************/ - -/* - * Initialize hardware specific port registers. - */ - -static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) -{ - unsigned long flags; - pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, - panelp, portp); - - if ((brdp == NULL) || (panelp == NULL) || - (portp == NULL)) - return; - - spin_lock_irqsave(&brd_lock, flags); - portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) || - (portp->portnr < 8)) ? 0 : EREG_BANKSIZE); - portp->uartaddr = (portp->portnr & 0x04) << 5; - portp->pagenr = panelp->pagenr + (portp->portnr >> 3); - - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, LIVR, (portp->portnr << 3)); - portp->hwid = stl_cd1400getreg(portp, GFRCR); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Wait for the command register to be ready. We will poll this, - * since it won't usually take too long to be ready. - */ - -static void stl_cd1400ccrwait(struct stlport *portp) -{ - int i; - - for (i = 0; i < CCR_MAXWAIT; i++) - if (stl_cd1400getreg(portp, CCR) == 0) - return; - - printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n", - portp->portnr, portp->panelnr, portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Set up the cd1400 registers for a port based on the termios port - * settings. - */ - -static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp) -{ - struct stlbrd *brdp; - unsigned long flags; - unsigned int clkdiv, baudrate; - unsigned char cor1, cor2, cor3; - unsigned char cor4, cor5, ccr; - unsigned char srer, sreron, sreroff; - unsigned char mcor1, mcor2, rtpr; - unsigned char clk, div; - - cor1 = 0; - cor2 = 0; - cor3 = 0; - cor4 = 0; - cor5 = 0; - ccr = 0; - rtpr = 0; - clk = 0; - div = 0; - mcor1 = 0; - mcor2 = 0; - sreron = 0; - sreroff = 0; - - brdp = stl_brds[portp->brdnr]; - if (brdp == NULL) - return; - -/* - * Set up the RX char ignore mask with those RX error types we - * can ignore. We can get the cd1400 to help us out a little here, - * it will ignore parity errors and breaks for us. - */ - portp->rxignoremsk = 0; - if (tiosp->c_iflag & IGNPAR) { - portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN); - cor1 |= COR1_PARIGNORE; - } - if (tiosp->c_iflag & IGNBRK) { - portp->rxignoremsk |= ST_BREAK; - cor4 |= COR4_IGNBRK; - } - - portp->rxmarkmsk = ST_OVERRUN; - if (tiosp->c_iflag & (INPCK | PARMRK)) - portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING); - if (tiosp->c_iflag & BRKINT) - portp->rxmarkmsk |= ST_BREAK; - -/* - * Go through the char size, parity and stop bits and set all the - * option register appropriately. - */ - switch (tiosp->c_cflag & CSIZE) { - case CS5: - cor1 |= COR1_CHL5; - break; - case CS6: - cor1 |= COR1_CHL6; - break; - case CS7: - cor1 |= COR1_CHL7; - break; - default: - cor1 |= COR1_CHL8; - break; - } - - if (tiosp->c_cflag & CSTOPB) - cor1 |= COR1_STOP2; - else - cor1 |= COR1_STOP1; - - if (tiosp->c_cflag & PARENB) { - if (tiosp->c_cflag & PARODD) - cor1 |= (COR1_PARENB | COR1_PARODD); - else - cor1 |= (COR1_PARENB | COR1_PAREVEN); - } else { - cor1 |= COR1_PARNONE; - } - -/* - * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing - * space for hardware flow control and the like. This should be set to - * VMIN. Also here we will set the RX data timeout to 10ms - this should - * really be based on VTIME. - */ - cor3 |= FIFO_RXTHRESHOLD; - rtpr = 2; - -/* - * Calculate the baud rate timers. For now we will just assume that - * the input and output baud are the same. Could have used a baud - * table here, but this way we can generate virtually any baud rate - * we like! - */ - baudrate = tiosp->c_cflag & CBAUD; - if (baudrate & CBAUDEX) { - baudrate &= ~CBAUDEX; - if ((baudrate < 1) || (baudrate > 4)) - tiosp->c_cflag &= ~CBAUDEX; - else - baudrate += 15; - } - baudrate = stl_baudrates[baudrate]; - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baudrate = 57600; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baudrate = 115200; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baudrate = 230400; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baudrate = 460800; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - baudrate = (portp->baud_base / portp->custom_divisor); - } - if (baudrate > STL_CD1400MAXBAUD) - baudrate = STL_CD1400MAXBAUD; - - if (baudrate > 0) { - for (clk = 0; clk < CD1400_NUMCLKS; clk++) { - clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate; - if (clkdiv < 0x100) - break; - } - div = (unsigned char) clkdiv; - } - -/* - * Check what form of modem signaling is required and set it up. - */ - if ((tiosp->c_cflag & CLOCAL) == 0) { - mcor1 |= MCOR1_DCD; - mcor2 |= MCOR2_DCD; - sreron |= SRER_MODEM; - portp->port.flags |= ASYNC_CHECK_CD; - } else - portp->port.flags &= ~ASYNC_CHECK_CD; - -/* - * Setup cd1400 enhanced modes if we can. In particular we want to - * handle as much of the flow control as possible automatically. As - * well as saving a few CPU cycles it will also greatly improve flow - * control reliability. - */ - if (tiosp->c_iflag & IXON) { - cor2 |= COR2_TXIBE; - cor3 |= COR3_SCD12; - if (tiosp->c_iflag & IXANY) - cor2 |= COR2_IXM; - } - - if (tiosp->c_cflag & CRTSCTS) { - cor2 |= COR2_CTSAE; - mcor1 |= FIFO_RTSTHRESHOLD; - } - -/* - * All cd1400 register values calculated so go through and set - * them all up. - */ - - pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", - portp->portnr, portp->panelnr, portp->brdnr); - pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", - cor1, cor2, cor3, cor4, cor5); - pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", - mcor1, mcor2, rtpr, sreron, sreroff); - pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); - pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - srer = stl_cd1400getreg(portp, SRER); - stl_cd1400setreg(portp, SRER, 0); - if (stl_cd1400updatereg(portp, COR1, cor1)) - ccr = 1; - if (stl_cd1400updatereg(portp, COR2, cor2)) - ccr = 1; - if (stl_cd1400updatereg(portp, COR3, cor3)) - ccr = 1; - if (ccr) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_CORCHANGE); - } - stl_cd1400setreg(portp, COR4, cor4); - stl_cd1400setreg(portp, COR5, cor5); - stl_cd1400setreg(portp, MCOR1, mcor1); - stl_cd1400setreg(portp, MCOR2, mcor2); - if (baudrate > 0) { - stl_cd1400setreg(portp, TCOR, clk); - stl_cd1400setreg(portp, TBPR, div); - stl_cd1400setreg(portp, RCOR, clk); - stl_cd1400setreg(portp, RBPR, div); - } - stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]); - stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]); - stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]); - stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]); - stl_cd1400setreg(portp, RTPR, rtpr); - mcor1 = stl_cd1400getreg(portp, MSVR1); - if (mcor1 & MSVR1_DCD) - portp->sigs |= TIOCM_CD; - else - portp->sigs &= ~TIOCM_CD; - stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron)); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Set the state of the DTR and RTS signals. - */ - -static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts) -{ - unsigned char msvr1, msvr2; - unsigned long flags; - - pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n", - portp, dtr, rts); - - msvr1 = 0; - msvr2 = 0; - if (dtr > 0) - msvr1 = MSVR1_DTR; - if (rts > 0) - msvr2 = MSVR2_RTS; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - if (rts >= 0) - stl_cd1400setreg(portp, MSVR2, msvr2); - if (dtr >= 0) - stl_cd1400setreg(portp, MSVR1, msvr1); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Return the state of the signals. - */ - -static int stl_cd1400getsignals(struct stlport *portp) -{ - unsigned char msvr1, msvr2; - unsigned long flags; - int sigs; - - pr_debug("stl_cd1400getsignals(portp=%p)\n", portp); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - msvr1 = stl_cd1400getreg(portp, MSVR1); - msvr2 = stl_cd1400getreg(portp, MSVR2); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - - sigs = 0; - sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0; - sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0; - sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0; - sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0; -#if 0 - sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0; - sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0; -#else - sigs |= TIOCM_DSR; -#endif - return sigs; -} - -/*****************************************************************************/ - -/* - * Enable/Disable the Transmitter and/or Receiver. - */ - -static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx) -{ - unsigned char ccr; - unsigned long flags; - - pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); - - ccr = 0; - - if (tx == 0) - ccr |= CCR_TXDISABLE; - else if (tx > 0) - ccr |= CCR_TXENABLE; - if (rx == 0) - ccr |= CCR_RXDISABLE; - else if (rx > 0) - ccr |= CCR_RXENABLE; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, ccr); - stl_cd1400ccrwait(portp); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Start/stop the Transmitter and/or Receiver. - */ - -static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx) -{ - unsigned char sreron, sreroff; - unsigned long flags; - - pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); - - sreron = 0; - sreroff = 0; - if (tx == 0) - sreroff |= (SRER_TXDATA | SRER_TXEMPTY); - else if (tx == 1) - sreron |= SRER_TXDATA; - else if (tx >= 2) - sreron |= SRER_TXEMPTY; - if (rx == 0) - sreroff |= SRER_RXDATA; - else if (rx > 0) - sreron |= SRER_RXDATA; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, SRER, - ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron)); - BRDDISABLE(portp->brdnr); - if (tx > 0) - set_bit(ASYI_TXBUSY, &portp->istate); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Disable all interrupts from this port. - */ - -static void stl_cd1400disableintrs(struct stlport *portp) -{ - unsigned long flags; - - pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, SRER, 0); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -static void stl_cd1400sendbreak(struct stlport *portp, int len) -{ - unsigned long flags; - - pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, SRER, - ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) | - SRER_TXEMPTY)); - BRDDISABLE(portp->brdnr); - portp->brklen = len; - if (len == 1) - portp->stats.txbreaks++; - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Take flow control actions... - */ - -static void stl_cd1400flowctrl(struct stlport *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - - pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state); - - if (portp == NULL) - return; - tty = tty_port_tty_get(&portp->port); - if (tty == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - - if (state) { - if (tty->termios->c_iflag & IXOFF) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); - portp->stats.rxxon++; - stl_cd1400ccrwait(portp); - } -/* - * Question: should we return RTS to what it was before? It may - * have been set by an ioctl... Suppose not, since if you have - * hardware flow control set then it is pretty silly to go and - * set the RTS line by hand. - */ - if (tty->termios->c_cflag & CRTSCTS) { - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) | - FIFO_RTSTHRESHOLD)); - stl_cd1400setreg(portp, MSVR2, MSVR2_RTS); - portp->stats.rxrtson++; - } - } else { - if (tty->termios->c_iflag & IXOFF) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); - portp->stats.rxxoff++; - stl_cd1400ccrwait(portp); - } - if (tty->termios->c_cflag & CRTSCTS) { - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) & 0xf0)); - stl_cd1400setreg(portp, MSVR2, 0); - portp->stats.rxrtsoff++; - } - } - - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - tty_kref_put(tty); -} - -/*****************************************************************************/ - -/* - * Send a flow control character... - */ - -static void stl_cd1400sendflow(struct stlport *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - - pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state); - - if (portp == NULL) - return; - tty = tty_port_tty_get(&portp->port); - if (tty == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - if (state) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); - portp->stats.rxxon++; - stl_cd1400ccrwait(portp); - } else { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); - portp->stats.rxxoff++; - stl_cd1400ccrwait(portp); - } - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - tty_kref_put(tty); -} - -/*****************************************************************************/ - -static void stl_cd1400flush(struct stlport *portp) -{ - unsigned long flags; - - pr_debug("stl_cd1400flush(portp=%p)\n", portp); - - if (portp == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO); - stl_cd1400ccrwait(portp); - portp->tx.tail = portp->tx.head; - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Return the current state of data flow on this port. This is only - * really interesting when determining if data has fully completed - * transmission or not... This is easy for the cd1400, it accurately - * maintains the busy port flag. - */ - -static int stl_cd1400datastate(struct stlport *portp) -{ - pr_debug("stl_cd1400datastate(portp=%p)\n", portp); - - if (portp == NULL) - return 0; - - return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0; -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for cd1400 EasyIO boards. - */ - -static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase) -{ - unsigned char svrtype; - - pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase); - - spin_lock(&brd_lock); - outb(SVRR, iobase); - svrtype = inb(iobase + EREG_DATA); - if (panelp->nrports > 4) { - outb((SVRR + 0x80), iobase); - svrtype |= inb(iobase + EREG_DATA); - } - - if (svrtype & SVRR_RX) - stl_cd1400rxisr(panelp, iobase); - else if (svrtype & SVRR_TX) - stl_cd1400txisr(panelp, iobase); - else if (svrtype & SVRR_MDM) - stl_cd1400mdmisr(panelp, iobase); - - spin_unlock(&brd_lock); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for cd1400 panels. - */ - -static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase) -{ - unsigned char svrtype; - - pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase); - - outb(SVRR, iobase); - svrtype = inb(iobase + EREG_DATA); - outb((SVRR + 0x80), iobase); - svrtype |= inb(iobase + EREG_DATA); - if (svrtype & SVRR_RX) - stl_cd1400rxisr(panelp, iobase); - else if (svrtype & SVRR_TX) - stl_cd1400txisr(panelp, iobase); - else if (svrtype & SVRR_MDM) - stl_cd1400mdmisr(panelp, iobase); -} - - -/*****************************************************************************/ - -/* - * Unfortunately we need to handle breaks in the TX data stream, since - * this is the only way to generate them on the cd1400. - */ - -static int stl_cd1400breakisr(struct stlport *portp, int ioaddr) -{ - if (portp->brklen == 1) { - outb((COR2 + portp->uartaddr), ioaddr); - outb((inb(ioaddr + EREG_DATA) | COR2_ETC), - (ioaddr + EREG_DATA)); - outb((TDR + portp->uartaddr), ioaddr); - outb(ETC_CMD, (ioaddr + EREG_DATA)); - outb(ETC_STARTBREAK, (ioaddr + EREG_DATA)); - outb((SRER + portp->uartaddr), ioaddr); - outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)), - (ioaddr + EREG_DATA)); - return 1; - } else if (portp->brklen > 1) { - outb((TDR + portp->uartaddr), ioaddr); - outb(ETC_CMD, (ioaddr + EREG_DATA)); - outb(ETC_STOPBREAK, (ioaddr + EREG_DATA)); - portp->brklen = -1; - return 1; - } else { - outb((COR2 + portp->uartaddr), ioaddr); - outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC), - (ioaddr + EREG_DATA)); - portp->brklen = 0; - } - return 0; -} - -/*****************************************************************************/ - -/* - * Transmit interrupt handler. This has gotta be fast! Handling TX - * chars is pretty simple, stuff as many as possible from the TX buffer - * into the cd1400 FIFO. Must also handle TX breaks here, since they - * are embedded as commands in the data stream. Oh no, had to use a goto! - * This could be optimized more, will do when I get time... - * In practice it is possible that interrupts are enabled but that the - * port has been hung up. Need to handle not having any TX buffer here, - * this is done by using the side effect that head and tail will also - * be NULL if the buffer has been freed. - */ - -static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) -{ - struct stlport *portp; - int len, stlen; - char *head, *tail; - unsigned char ioack, srer; - struct tty_struct *tty; - - pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); - - ioack = inb(ioaddr + EREG_TXACK); - if (((ioack & panelp->ackmask) != 0) || - ((ioack & ACK_TYPMASK) != ACK_TYPTX)) { - printk("STALLION: bad TX interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - -/* - * Unfortunately we need to handle breaks in the data stream, since - * this is the only way to generate them on the cd1400. Do it now if - * a break is to be sent. - */ - if (portp->brklen != 0) - if (stl_cd1400breakisr(portp, ioaddr)) - goto stl_txalldone; - - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); - if ((len == 0) || ((len < STL_TXBUFLOW) && - (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { - set_bit(ASYI_TXLOW, &portp->istate); - tty = tty_port_tty_get(&portp->port); - if (tty) { - tty_wakeup(tty); - tty_kref_put(tty); - } - } - - if (len == 0) { - outb((SRER + portp->uartaddr), ioaddr); - srer = inb(ioaddr + EREG_DATA); - if (srer & SRER_TXDATA) { - srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY; - } else { - srer &= ~(SRER_TXDATA | SRER_TXEMPTY); - clear_bit(ASYI_TXBUSY, &portp->istate); - } - outb(srer, (ioaddr + EREG_DATA)); - } else { - len = min(len, CD1400_TXFIFOSIZE); - portp->stats.txtotal += len; - stlen = min_t(unsigned int, len, - (portp->tx.buf + STL_TXBUFSIZE) - tail); - outb((TDR + portp->uartaddr), ioaddr); - outsb((ioaddr + EREG_DATA), tail, stlen); - len -= stlen; - tail += stlen; - if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) - tail = portp->tx.buf; - if (len > 0) { - outsb((ioaddr + EREG_DATA), tail, len); - tail += len; - } - portp->tx.tail = tail; - } - -stl_txalldone: - outb((EOSRR + portp->uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ - -/* - * Receive character interrupt handler. Determine if we have good chars - * or bad chars and then process appropriately. Good chars are easy - * just shove the lot into the RX buffer and set all status byte to 0. - * If a bad RX char then process as required. This routine needs to be - * fast! In practice it is possible that we get an interrupt on a port - * that is closed. This can happen on hangups - since they completely - * shutdown a port not in user context. Need to handle this case. - */ - -static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) -{ - struct stlport *portp; - struct tty_struct *tty; - unsigned int ioack, len, buflen; - unsigned char status; - char ch; - - pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); - - ioack = inb(ioaddr + EREG_RXACK); - if ((ioack & panelp->ackmask) != 0) { - printk("STALLION: bad RX interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - tty = tty_port_tty_get(&portp->port); - - if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) { - outb((RDCR + portp->uartaddr), ioaddr); - len = inb(ioaddr + EREG_DATA); - if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { - len = min_t(unsigned int, len, sizeof(stl_unwanted)); - outb((RDSR + portp->uartaddr), ioaddr); - insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); - portp->stats.rxlost += len; - portp->stats.rxtotal += len; - } else { - len = min(len, buflen); - if (len > 0) { - unsigned char *ptr; - outb((RDSR + portp->uartaddr), ioaddr); - tty_prepare_flip_string(tty, &ptr, len); - insb((ioaddr + EREG_DATA), ptr, len); - tty_schedule_flip(tty); - portp->stats.rxtotal += len; - } - } - } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) { - outb((RDSR + portp->uartaddr), ioaddr); - status = inb(ioaddr + EREG_DATA); - ch = inb(ioaddr + EREG_DATA); - if (status & ST_PARITY) - portp->stats.rxparity++; - if (status & ST_FRAMING) - portp->stats.rxframing++; - if (status & ST_OVERRUN) - portp->stats.rxoverrun++; - if (status & ST_BREAK) - portp->stats.rxbreaks++; - if (status & ST_SCHARMASK) { - if ((status & ST_SCHARMASK) == ST_SCHAR1) - portp->stats.txxon++; - if ((status & ST_SCHARMASK) == ST_SCHAR2) - portp->stats.txxoff++; - goto stl_rxalldone; - } - if (tty != NULL && (portp->rxignoremsk & status) == 0) { - if (portp->rxmarkmsk & status) { - if (status & ST_BREAK) { - status = TTY_BREAK; - if (portp->port.flags & ASYNC_SAK) { - do_SAK(tty); - BRDENABLE(portp->brdnr, portp->pagenr); - } - } else if (status & ST_PARITY) - status = TTY_PARITY; - else if (status & ST_FRAMING) - status = TTY_FRAME; - else if(status & ST_OVERRUN) - status = TTY_OVERRUN; - else - status = 0; - } else - status = 0; - tty_insert_flip_char(tty, ch, status); - tty_schedule_flip(tty); - } - } else { - printk("STALLION: bad RX interrupt ack value=%x\n", ioack); - tty_kref_put(tty); - return; - } - -stl_rxalldone: - tty_kref_put(tty); - outb((EOSRR + portp->uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ - -/* - * Modem interrupt handler. The is called when the modem signal line - * (DCD) has changed state. Leave most of the work to the off-level - * processing routine. - */ - -static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr) -{ - struct stlport *portp; - unsigned int ioack; - unsigned char misr; - - pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp); - - ioack = inb(ioaddr + EREG_MDACK); - if (((ioack & panelp->ackmask) != 0) || - ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) { - printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - - outb((MISR + portp->uartaddr), ioaddr); - misr = inb(ioaddr + EREG_DATA); - if (misr & MISR_DCD) { - stl_cd_change(portp); - portp->stats.modem++; - } - - outb((EOSRR + portp->uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ -/* SC26198 HARDWARE FUNCTIONS */ -/*****************************************************************************/ - -/* - * These functions get/set/update the registers of the sc26198 UARTs. - * Access to the sc26198 registers is via an address/data io port pair. - * (Maybe should make this inline...) - */ - -static int stl_sc26198getreg(struct stlport *portp, int regnr) -{ - outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - return inb(portp->ioaddr + XP_DATA); -} - -static void stl_sc26198setreg(struct stlport *portp, int regnr, int value) -{ - outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - outb(value, (portp->ioaddr + XP_DATA)); -} - -static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value) -{ - outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - if (inb(portp->ioaddr + XP_DATA) != value) { - outb(value, (portp->ioaddr + XP_DATA)); - return 1; - } - return 0; -} - -/*****************************************************************************/ - -/* - * Functions to get and set the sc26198 global registers. - */ - -static int stl_sc26198getglobreg(struct stlport *portp, int regnr) -{ - outb(regnr, (portp->ioaddr + XP_ADDR)); - return inb(portp->ioaddr + XP_DATA); -} - -#if 0 -static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value) -{ - outb(regnr, (portp->ioaddr + XP_ADDR)); - outb(value, (portp->ioaddr + XP_DATA)); -} -#endif - -/*****************************************************************************/ - -/* - * Inbitialize the UARTs in a panel. We don't care what sort of board - * these ports are on - since the port io registers are almost - * identical when dealing with ports. - */ - -static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp) -{ - int chipmask, i; - int nrchips, ioaddr; - - pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); - - BRDENABLE(panelp->brdnr, panelp->pagenr); - -/* - * Check that each chip is present and started up OK. - */ - chipmask = 0; - nrchips = (panelp->nrports + 4) / SC26198_PORTS; - if (brdp->brdtype == BRD_ECHPCI) - outb(panelp->pagenr, brdp->ioctrl); - - for (i = 0; i < nrchips; i++) { - ioaddr = panelp->iobase + (i * 4); - outb(SCCR, (ioaddr + XP_ADDR)); - outb(CR_RESETALL, (ioaddr + XP_DATA)); - outb(TSTR, (ioaddr + XP_ADDR)); - if (inb(ioaddr + XP_DATA) != 0) { - printk("STALLION: sc26198 not responding, " - "brd=%d panel=%d chip=%d\n", - panelp->brdnr, panelp->panelnr, i); - continue; - } - chipmask |= (0x1 << i); - outb(GCCR, (ioaddr + XP_ADDR)); - outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA)); - outb(WDTRCR, (ioaddr + XP_ADDR)); - outb(0xff, (ioaddr + XP_DATA)); - } - - BRDDISABLE(panelp->brdnr); - return chipmask; -} - -/*****************************************************************************/ - -/* - * Initialize hardware specific port registers. - */ - -static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) -{ - pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, - panelp, portp); - - if ((brdp == NULL) || (panelp == NULL) || - (portp == NULL)) - return; - - portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); - portp->uartaddr = (portp->portnr & 0x07) << 4; - portp->pagenr = panelp->pagenr; - portp->hwid = 0x1; - - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS); - BRDDISABLE(portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Set up the sc26198 registers for a port based on the termios port - * settings. - */ - -static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp) -{ - struct stlbrd *brdp; - unsigned long flags; - unsigned int baudrate; - unsigned char mr0, mr1, mr2, clk; - unsigned char imron, imroff, iopr, ipr; - - mr0 = 0; - mr1 = 0; - mr2 = 0; - clk = 0; - iopr = 0; - imron = 0; - imroff = 0; - - brdp = stl_brds[portp->brdnr]; - if (brdp == NULL) - return; - -/* - * Set up the RX char ignore mask with those RX error types we - * can ignore. - */ - portp->rxignoremsk = 0; - if (tiosp->c_iflag & IGNPAR) - portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING | - SR_RXOVERRUN); - if (tiosp->c_iflag & IGNBRK) - portp->rxignoremsk |= SR_RXBREAK; - - portp->rxmarkmsk = SR_RXOVERRUN; - if (tiosp->c_iflag & (INPCK | PARMRK)) - portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING); - if (tiosp->c_iflag & BRKINT) - portp->rxmarkmsk |= SR_RXBREAK; - -/* - * Go through the char size, parity and stop bits and set all the - * option register appropriately. - */ - switch (tiosp->c_cflag & CSIZE) { - case CS5: - mr1 |= MR1_CS5; - break; - case CS6: - mr1 |= MR1_CS6; - break; - case CS7: - mr1 |= MR1_CS7; - break; - default: - mr1 |= MR1_CS8; - break; - } - - if (tiosp->c_cflag & CSTOPB) - mr2 |= MR2_STOP2; - else - mr2 |= MR2_STOP1; - - if (tiosp->c_cflag & PARENB) { - if (tiosp->c_cflag & PARODD) - mr1 |= (MR1_PARENB | MR1_PARODD); - else - mr1 |= (MR1_PARENB | MR1_PAREVEN); - } else - mr1 |= MR1_PARNONE; - - mr1 |= MR1_ERRBLOCK; - -/* - * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing - * space for hardware flow control and the like. This should be set to - * VMIN. - */ - mr2 |= MR2_RXFIFOHALF; - -/* - * Calculate the baud rate timers. For now we will just assume that - * the input and output baud are the same. The sc26198 has a fixed - * baud rate table, so only discrete baud rates possible. - */ - baudrate = tiosp->c_cflag & CBAUD; - if (baudrate & CBAUDEX) { - baudrate &= ~CBAUDEX; - if ((baudrate < 1) || (baudrate > 4)) - tiosp->c_cflag &= ~CBAUDEX; - else - baudrate += 15; - } - baudrate = stl_baudrates[baudrate]; - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baudrate = 57600; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baudrate = 115200; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baudrate = 230400; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baudrate = 460800; - else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - baudrate = (portp->baud_base / portp->custom_divisor); - } - if (baudrate > STL_SC26198MAXBAUD) - baudrate = STL_SC26198MAXBAUD; - - if (baudrate > 0) - for (clk = 0; clk < SC26198_NRBAUDS; clk++) - if (baudrate <= sc26198_baudtable[clk]) - break; - -/* - * Check what form of modem signaling is required and set it up. - */ - if (tiosp->c_cflag & CLOCAL) { - portp->port.flags &= ~ASYNC_CHECK_CD; - } else { - iopr |= IOPR_DCDCOS; - imron |= IR_IOPORT; - portp->port.flags |= ASYNC_CHECK_CD; - } - -/* - * Setup sc26198 enhanced modes if we can. In particular we want to - * handle as much of the flow control as possible automatically. As - * well as saving a few CPU cycles it will also greatly improve flow - * control reliability. - */ - if (tiosp->c_iflag & IXON) { - mr0 |= MR0_SWFTX | MR0_SWFT; - imron |= IR_XONXOFF; - } else - imroff |= IR_XONXOFF; - - if (tiosp->c_iflag & IXOFF) - mr0 |= MR0_SWFRX; - - if (tiosp->c_cflag & CRTSCTS) { - mr2 |= MR2_AUTOCTS; - mr1 |= MR1_AUTORTS; - } - -/* - * All sc26198 register values calculated so go through and set - * them all up. - */ - - pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", - portp->portnr, portp->panelnr, portp->brdnr); - pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); - pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); - pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IMR, 0); - stl_sc26198updatereg(portp, MR0, mr0); - stl_sc26198updatereg(portp, MR1, mr1); - stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK); - stl_sc26198updatereg(portp, MR2, mr2); - stl_sc26198updatereg(portp, IOPIOR, - ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr)); - - if (baudrate > 0) { - stl_sc26198setreg(portp, TXCSR, clk); - stl_sc26198setreg(portp, RXCSR, clk); - } - - stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]); - stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); - - ipr = stl_sc26198getreg(portp, IPR); - if (ipr & IPR_DCD) - portp->sigs &= ~TIOCM_CD; - else - portp->sigs |= TIOCM_CD; - - portp->imr = (portp->imr & ~imroff) | imron; - stl_sc26198setreg(portp, IMR, portp->imr); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Set the state of the DTR and RTS signals. - */ - -static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts) -{ - unsigned char iopioron, iopioroff; - unsigned long flags; - - pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp, - dtr, rts); - - iopioron = 0; - iopioroff = 0; - if (dtr == 0) - iopioroff |= IPR_DTR; - else if (dtr > 0) - iopioron |= IPR_DTR; - if (rts == 0) - iopioroff |= IPR_RTS; - else if (rts > 0) - iopioron |= IPR_RTS; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IOPIOR, - ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron)); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Return the state of the signals. - */ - -static int stl_sc26198getsignals(struct stlport *portp) -{ - unsigned char ipr; - unsigned long flags; - int sigs; - - pr_debug("stl_sc26198getsignals(portp=%p)\n", portp); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - ipr = stl_sc26198getreg(portp, IPR); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - - sigs = 0; - sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD; - sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS; - sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR; - sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS; - sigs |= TIOCM_DSR; - return sigs; -} - -/*****************************************************************************/ - -/* - * Enable/Disable the Transmitter and/or Receiver. - */ - -static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx) -{ - unsigned char ccr; - unsigned long flags; - - pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx); - - ccr = portp->crenable; - if (tx == 0) - ccr &= ~CR_TXENABLE; - else if (tx > 0) - ccr |= CR_TXENABLE; - if (rx == 0) - ccr &= ~CR_RXENABLE; - else if (rx > 0) - ccr |= CR_RXENABLE; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, SCCR, ccr); - BRDDISABLE(portp->brdnr); - portp->crenable = ccr; - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Start/stop the Transmitter and/or Receiver. - */ - -static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx) -{ - unsigned char imr; - unsigned long flags; - - pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); - - imr = portp->imr; - if (tx == 0) - imr &= ~IR_TXRDY; - else if (tx == 1) - imr |= IR_TXRDY; - if (rx == 0) - imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG); - else if (rx > 0) - imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IMR, imr); - BRDDISABLE(portp->brdnr); - portp->imr = imr; - if (tx > 0) - set_bit(ASYI_TXBUSY, &portp->istate); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Disable all interrupts from this port. - */ - -static void stl_sc26198disableintrs(struct stlport *portp) -{ - unsigned long flags; - - pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - portp->imr = 0; - stl_sc26198setreg(portp, IMR, 0); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -static void stl_sc26198sendbreak(struct stlport *portp, int len) -{ - unsigned long flags; - - pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len); - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - if (len == 1) { - stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); - portp->stats.txbreaks++; - } else - stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); - - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Take flow control actions... - */ - -static void stl_sc26198flowctrl(struct stlport *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - unsigned char mr0; - - pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state); - - if (portp == NULL) - return; - tty = tty_port_tty_get(&portp->port); - if (tty == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - - if (state) { - if (tty->termios->c_iflag & IXOFF) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); - mr0 |= MR0_SWFRX; - portp->stats.rxxon++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } -/* - * Question: should we return RTS to what it was before? It may - * have been set by an ioctl... Suppose not, since if you have - * hardware flow control set then it is pretty silly to go and - * set the RTS line by hand. - */ - if (tty->termios->c_cflag & CRTSCTS) { - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS)); - portp->stats.rxrtson++; - } - } else { - if (tty->termios->c_iflag & IXOFF) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); - mr0 &= ~MR0_SWFRX; - portp->stats.rxxoff++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } - if (tty->termios->c_cflag & CRTSCTS) { - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS)); - portp->stats.rxrtsoff++; - } - } - - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - tty_kref_put(tty); -} - -/*****************************************************************************/ - -/* - * Send a flow control character. - */ - -static void stl_sc26198sendflow(struct stlport *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - unsigned char mr0; - - pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state); - - if (portp == NULL) - return; - tty = tty_port_tty_get(&portp->port); - if (tty == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - if (state) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); - mr0 |= MR0_SWFRX; - portp->stats.rxxon++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } else { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); - mr0 &= ~MR0_SWFRX; - portp->stats.rxxoff++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - tty_kref_put(tty); -} - -/*****************************************************************************/ - -static void stl_sc26198flush(struct stlport *portp) -{ - unsigned long flags; - - pr_debug("stl_sc26198flush(portp=%p)\n", portp); - - if (portp == NULL) - return; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, SCCR, CR_TXRESET); - stl_sc26198setreg(portp, SCCR, portp->crenable); - BRDDISABLE(portp->brdnr); - portp->tx.tail = portp->tx.head; - spin_unlock_irqrestore(&brd_lock, flags); -} - -/*****************************************************************************/ - -/* - * Return the current state of data flow on this port. This is only - * really interesting when determining if data has fully completed - * transmission or not... The sc26198 interrupt scheme cannot - * determine when all data has actually drained, so we need to - * check the port statusy register to be sure. - */ - -static int stl_sc26198datastate(struct stlport *portp) -{ - unsigned long flags; - unsigned char sr; - - pr_debug("stl_sc26198datastate(portp=%p)\n", portp); - - if (portp == NULL) - return 0; - if (test_bit(ASYI_TXBUSY, &portp->istate)) - return 1; - - spin_lock_irqsave(&brd_lock, flags); - BRDENABLE(portp->brdnr, portp->pagenr); - sr = stl_sc26198getreg(portp, SR); - BRDDISABLE(portp->brdnr); - spin_unlock_irqrestore(&brd_lock, flags); - - return (sr & SR_TXEMPTY) ? 0 : 1; -} - -/*****************************************************************************/ - -/* - * Delay for a small amount of time, to give the sc26198 a chance - * to process a command... - */ - -static void stl_sc26198wait(struct stlport *portp) -{ - int i; - - pr_debug("stl_sc26198wait(portp=%p)\n", portp); - - if (portp == NULL) - return; - - for (i = 0; i < 20; i++) - stl_sc26198getglobreg(portp, TSTR); -} - -/*****************************************************************************/ - -/* - * If we are TX flow controlled and in IXANY mode then we may - * need to unflow control here. We gotta do this because of the - * automatic flow control modes of the sc26198. - */ - -static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty) -{ - unsigned char mr0; - - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_HOSTXON); - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - clear_bit(ASYI_TXFLOWED, &portp->istate); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for sc26198 panels. - */ - -static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase) -{ - struct stlport *portp; - unsigned int iack; - - spin_lock(&brd_lock); - -/* - * Work around bug in sc26198 chip... Cannot have A6 address - * line of UART high, else iack will be returned as 0. - */ - outb(0, (iobase + 1)); - - iack = inb(iobase + XP_IACK); - portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)]; - - if (iack & IVR_RXDATA) - stl_sc26198rxisr(portp, iack); - else if (iack & IVR_TXDATA) - stl_sc26198txisr(portp); - else - stl_sc26198otherisr(portp, iack); - - spin_unlock(&brd_lock); -} - -/*****************************************************************************/ - -/* - * Transmit interrupt handler. This has gotta be fast! Handling TX - * chars is pretty simple, stuff as many as possible from the TX buffer - * into the sc26198 FIFO. - * In practice it is possible that interrupts are enabled but that the - * port has been hung up. Need to handle not having any TX buffer here, - * this is done by using the side effect that head and tail will also - * be NULL if the buffer has been freed. - */ - -static void stl_sc26198txisr(struct stlport *portp) -{ - struct tty_struct *tty; - unsigned int ioaddr; - unsigned char mr0; - int len, stlen; - char *head, *tail; - - pr_debug("stl_sc26198txisr(portp=%p)\n", portp); - - ioaddr = portp->ioaddr; - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); - if ((len == 0) || ((len < STL_TXBUFLOW) && - (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { - set_bit(ASYI_TXLOW, &portp->istate); - tty = tty_port_tty_get(&portp->port); - if (tty) { - tty_wakeup(tty); - tty_kref_put(tty); - } - } - - if (len == 0) { - outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR)); - mr0 = inb(ioaddr + XP_DATA); - if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) { - portp->imr &= ~IR_TXRDY; - outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR)); - outb(portp->imr, (ioaddr + XP_DATA)); - clear_bit(ASYI_TXBUSY, &portp->istate); - } else { - mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY); - outb(mr0, (ioaddr + XP_DATA)); - } - } else { - len = min(len, SC26198_TXFIFOSIZE); - portp->stats.txtotal += len; - stlen = min_t(unsigned int, len, - (portp->tx.buf + STL_TXBUFSIZE) - tail); - outb(GTXFIFO, (ioaddr + XP_ADDR)); - outsb((ioaddr + XP_DATA), tail, stlen); - len -= stlen; - tail += stlen; - if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) - tail = portp->tx.buf; - if (len > 0) { - outsb((ioaddr + XP_DATA), tail, len); - tail += len; - } - portp->tx.tail = tail; - } -} - -/*****************************************************************************/ - -/* - * Receive character interrupt handler. Determine if we have good chars - * or bad chars and then process appropriately. Good chars are easy - * just shove the lot into the RX buffer and set all status byte to 0. - * If a bad RX char then process as required. This routine needs to be - * fast! In practice it is possible that we get an interrupt on a port - * that is closed. This can happen on hangups - since they completely - * shutdown a port not in user context. Need to handle this case. - */ - -static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) -{ - struct tty_struct *tty; - unsigned int len, buflen, ioaddr; - - pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); - - tty = tty_port_tty_get(&portp->port); - ioaddr = portp->ioaddr; - outb(GIBCR, (ioaddr + XP_ADDR)); - len = inb(ioaddr + XP_DATA) + 1; - - if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { - if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { - len = min_t(unsigned int, len, sizeof(stl_unwanted)); - outb(GRXFIFO, (ioaddr + XP_ADDR)); - insb((ioaddr + XP_DATA), &stl_unwanted[0], len); - portp->stats.rxlost += len; - portp->stats.rxtotal += len; - } else { - len = min(len, buflen); - if (len > 0) { - unsigned char *ptr; - outb(GRXFIFO, (ioaddr + XP_ADDR)); - tty_prepare_flip_string(tty, &ptr, len); - insb((ioaddr + XP_DATA), ptr, len); - tty_schedule_flip(tty); - portp->stats.rxtotal += len; - } - } - } else { - stl_sc26198rxbadchars(portp); - } - -/* - * If we are TX flow controlled and in IXANY mode then we may need - * to unflow control here. We gotta do this because of the automatic - * flow control modes of the sc26198. - */ - if (test_bit(ASYI_TXFLOWED, &portp->istate)) { - if ((tty != NULL) && - (tty->termios != NULL) && - (tty->termios->c_iflag & IXANY)) { - stl_sc26198txunflow(portp, tty); - } - } - tty_kref_put(tty); -} - -/*****************************************************************************/ - -/* - * Process an RX bad character. - */ - -static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch) -{ - struct tty_struct *tty; - unsigned int ioaddr; - - tty = tty_port_tty_get(&portp->port); - ioaddr = portp->ioaddr; - - if (status & SR_RXPARITY) - portp->stats.rxparity++; - if (status & SR_RXFRAMING) - portp->stats.rxframing++; - if (status & SR_RXOVERRUN) - portp->stats.rxoverrun++; - if (status & SR_RXBREAK) - portp->stats.rxbreaks++; - - if ((tty != NULL) && - ((portp->rxignoremsk & status) == 0)) { - if (portp->rxmarkmsk & status) { - if (status & SR_RXBREAK) { - status = TTY_BREAK; - if (portp->port.flags & ASYNC_SAK) { - do_SAK(tty); - BRDENABLE(portp->brdnr, portp->pagenr); - } - } else if (status & SR_RXPARITY) - status = TTY_PARITY; - else if (status & SR_RXFRAMING) - status = TTY_FRAME; - else if(status & SR_RXOVERRUN) - status = TTY_OVERRUN; - else - status = 0; - } else - status = 0; - - tty_insert_flip_char(tty, ch, status); - tty_schedule_flip(tty); - - if (status == 0) - portp->stats.rxtotal++; - } - tty_kref_put(tty); -} - -/*****************************************************************************/ - -/* - * Process all characters in the RX FIFO of the UART. Check all char - * status bytes as well, and process as required. We need to check - * all bytes in the FIFO, in case some more enter the FIFO while we - * are here. To get the exact character error type we need to switch - * into CHAR error mode (that is why we need to make sure we empty - * the FIFO). - */ - -static void stl_sc26198rxbadchars(struct stlport *portp) -{ - unsigned char status, mr1; - char ch; - -/* - * To get the precise error type for each character we must switch - * back into CHAR error mode. - */ - mr1 = stl_sc26198getreg(portp, MR1); - stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); - - while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { - stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR); - ch = stl_sc26198getreg(portp, RXFIFO); - stl_sc26198rxbadch(portp, status, ch); - } - -/* - * To get correct interrupt class we must switch back into BLOCK - * error mode. - */ - stl_sc26198setreg(portp, MR1, mr1); -} - -/*****************************************************************************/ - -/* - * Other interrupt handler. This includes modem signals, flow - * control actions, etc. Most stuff is left to off-level interrupt - * processing time. - */ - -static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) -{ - unsigned char cir, ipr, xisr; - - pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack); - - cir = stl_sc26198getglobreg(portp, CIR); - - switch (cir & CIR_SUBTYPEMASK) { - case CIR_SUBCOS: - ipr = stl_sc26198getreg(portp, IPR); - if (ipr & IPR_DCDCHANGE) { - stl_cd_change(portp); - portp->stats.modem++; - } - break; - case CIR_SUBXONXOFF: - xisr = stl_sc26198getreg(portp, XISR); - if (xisr & XISR_RXXONGOT) { - set_bit(ASYI_TXFLOWED, &portp->istate); - portp->stats.txxoff++; - } - if (xisr & XISR_RXXOFFGOT) { - clear_bit(ASYI_TXFLOWED, &portp->istate); - portp->stats.txxon++; - } - break; - case CIR_SUBBREAK: - stl_sc26198setreg(portp, SCCR, CR_BREAKRESET); - stl_sc26198rxbadchars(portp); - break; - default: - break; - } -} - -static void stl_free_isabrds(void) -{ - struct stlbrd *brdp; - unsigned int i; - - for (i = 0; i < stl_nrbrds; i++) { - if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) - continue; - - free_irq(brdp->irq, brdp); - - stl_cleanup_panels(brdp); - - release_region(brdp->ioaddr1, brdp->iosize1); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); - - kfree(brdp); - stl_brds[i] = NULL; - } -} - -/* - * Loadable module initialization stuff. - */ -static int __init stallion_module_init(void) -{ - struct stlbrd *brdp; - struct stlconf conf; - unsigned int i, j; - int retval; - - printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); - - spin_lock_init(&stallion_lock); - spin_lock_init(&brd_lock); - - stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); - if (!stl_serial) { - retval = -ENOMEM; - goto err; - } - - stl_serial->owner = THIS_MODULE; - stl_serial->driver_name = stl_drvname; - stl_serial->name = "ttyE"; - stl_serial->major = STL_SERIALMAJOR; - stl_serial->minor_start = 0; - stl_serial->type = TTY_DRIVER_TYPE_SERIAL; - stl_serial->subtype = SERIAL_TYPE_NORMAL; - stl_serial->init_termios = stl_deftermios; - stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - tty_set_operations(stl_serial, &stl_ops); - - retval = tty_register_driver(stl_serial); - if (retval) { - printk("STALLION: failed to register serial driver\n"); - goto err_frtty; - } - -/* - * Find any dynamically supported boards. That is via module load - * line options. - */ - for (i = stl_nrbrds; i < stl_nargs; i++) { - memset(&conf, 0, sizeof(conf)); - if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) - continue; - if ((brdp = stl_allocbrd()) == NULL) - continue; - brdp->brdnr = i; - brdp->brdtype = conf.brdtype; - brdp->ioaddr1 = conf.ioaddr1; - brdp->ioaddr2 = conf.ioaddr2; - brdp->irq = conf.irq; - brdp->irqtype = conf.irqtype; - stl_brds[brdp->brdnr] = brdp; - if (stl_brdinit(brdp)) { - stl_brds[brdp->brdnr] = NULL; - kfree(brdp); - } else { - for (j = 0; j < brdp->nrports; j++) - tty_register_device(stl_serial, - brdp->brdnr * STL_MAXPORTS + j, NULL); - stl_nrbrds = i + 1; - } - } - - /* this has to be _after_ isa finding because of locking */ - retval = pci_register_driver(&stl_pcidriver); - if (retval && stl_nrbrds == 0) { - printk(KERN_ERR "STALLION: can't register pci driver\n"); - goto err_unrtty; - } - -/* - * Set up a character driver for per board stuff. This is mainly used - * to do stats ioctls on the ports. - */ - if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) - printk("STALLION: failed to register serial board device\n"); - - stallion_class = class_create(THIS_MODULE, "staliomem"); - if (IS_ERR(stallion_class)) - printk("STALLION: failed to create class\n"); - for (i = 0; i < 4; i++) - device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), - NULL, "staliomem%d", i); - - return 0; -err_unrtty: - tty_unregister_driver(stl_serial); -err_frtty: - put_tty_driver(stl_serial); -err: - return retval; -} - -static void __exit stallion_module_exit(void) -{ - struct stlbrd *brdp; - unsigned int i, j; - - pr_debug("cleanup_module()\n"); - - printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, - stl_drvversion); - -/* - * Free up all allocated resources used by the ports. This includes - * memory and interrupts. As part of this process we will also do - * a hangup on every open port - to try to flush out any processes - * hanging onto ports. - */ - for (i = 0; i < stl_nrbrds; i++) { - if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) - continue; - for (j = 0; j < brdp->nrports; j++) - tty_unregister_device(stl_serial, - brdp->brdnr * STL_MAXPORTS + j); - } - - for (i = 0; i < 4; i++) - device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); - unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); - class_destroy(stallion_class); - - pci_unregister_driver(&stl_pcidriver); - - stl_free_isabrds(); - - tty_unregister_driver(stl_serial); - put_tty_driver(stl_serial); -} - -module_init(stallion_module_init); -module_exit(stallion_module_exit); - -MODULE_AUTHOR("Greg Ungerer"); -MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 5c8fcfc42c3e..fb1fc4e5a8cb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -41,6 +41,8 @@ config STAGING_EXCLUDE_BUILD if !STAGING_EXCLUDE_BUILD +source "drivers/staging/tty/Kconfig" + source "drivers/staging/et131x/Kconfig" source "drivers/staging/slicoss/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index d53886317826..f498e345a01d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -3,6 +3,7 @@ # fix for build system bug... obj-$(CONFIG_STAGING) += staging.o +obj-y += tty/ obj-$(CONFIG_ET131X) += et131x/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ diff --git a/drivers/staging/tty/Kconfig b/drivers/staging/tty/Kconfig new file mode 100644 index 000000000000..77103a07abbd --- /dev/null +++ b/drivers/staging/tty/Kconfig @@ -0,0 +1,87 @@ +config STALLION + tristate "Stallion EasyIO or EC8/32 support" + depends on STALDRV && (ISA || EISA || PCI) + help + If you have an EasyIO or EasyConnection 8/32 multiport Stallion + card, then this is for you; say Y. Make sure to read + . + + To compile this driver as a module, choose M here: the + module will be called stallion. + +config ISTALLION + tristate "Stallion EC8/64, ONboard, Brumby support" + depends on STALDRV && (ISA || EISA || PCI) + help + If you have an EasyConnection 8/64, ONboard, Brumby or Stallion + serial multiport card, say Y here. Make sure to read + . + + To compile this driver as a module, choose M here: the + module will be called istallion. + +config DIGIEPCA + tristate "Digiboard Intelligent Async Support" + depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + ---help--- + This is a driver for Digi International's Xx, Xeve, and Xem series + of cards which provide multiple serial ports. You would need + something like this to connect more than two modems to your Linux + box, for instance in order to become a dial-in server. This driver + supports the original PC (ISA) boards as well as PCI, and EISA. If + you have a card like this, say Y here and read the file + . + + To compile this driver as a module, choose M here: the + module will be called epca. + +config RISCOM8 + tristate "SDL RISCom/8 card support" + depends on SERIAL_NONSTANDARD + help + This is a driver for the SDL Communications RISCom/8 multiport card, + which gives you many serial ports. You would need something like + this to connect more than two modems to your Linux box, for instance + in order to become a dial-in server. If you have a card like that, + say Y here and read the file . + + Also it's possible to say M here and compile this driver as kernel + loadable module; the module will be called riscom8. + +config SPECIALIX + tristate "Specialix IO8+ card support" + depends on SERIAL_NONSTANDARD + help + This is a driver for the Specialix IO8+ multiport card (both the + ISA and the PCI version) which gives you many serial ports. You + would need something like this to connect more than two modems to + your Linux box, for instance in order to become a dial-in server. + + If you have a card like that, say Y here and read the file + . Also it's possible to say + M here and compile this driver as kernel loadable module which will be + called specialix. + +config COMPUTONE + tristate "Computone IntelliPort Plus serial support" + depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + ---help--- + This driver supports the entire family of Intelliport II/Plus + controllers with the exception of the MicroChannel controllers and + products previous to the Intelliport II. These are multiport cards, + which give you many serial ports. You would need something like this + to connect more than two modems to your Linux box, for instance in + order to become a dial-in server. If you have a card like that, say + Y here and read . + + To compile this driver as module, choose M here: the + module will be called ip2. + +config SERIAL167 + bool "CD2401 support for MVME166/7 serial ports" + depends on MVME16x + help + This is the driver for the serial ports on the Motorola MVME166, + 167, and 172 boards. Everyone using one of these boards should say + Y here. + diff --git a/drivers/staging/tty/Makefile b/drivers/staging/tty/Makefile new file mode 100644 index 000000000000..ac57c105611b --- /dev/null +++ b/drivers/staging/tty/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_STALLION) += stallion.o +obj-$(CONFIG_ISTALLION) += istallion.o +obj-$(CONFIG_DIGIEPCA) += epca.o +obj-$(CONFIG_SERIAL167) += serial167.o +obj-$(CONFIG_SPECIALIX) += specialix.o +obj-$(CONFIG_RISCOM8) += riscom8.o +obj-$(CONFIG_COMPUTONE) += ip2/ diff --git a/drivers/staging/tty/TODO b/drivers/staging/tty/TODO new file mode 100644 index 000000000000..88756453ac6c --- /dev/null +++ b/drivers/staging/tty/TODO @@ -0,0 +1,6 @@ +These are a few tty/serial drivers that either do not build, +or work if they do build, or if they seem to work, are for obsolete +hardware, or are full of unfixable races and no one uses them anymore. + +If no one steps up to adopt any of these drivers, they will be removed +in the 2.6.41 release. diff --git a/drivers/staging/tty/epca.c b/drivers/staging/tty/epca.c new file mode 100644 index 000000000000..7ad3638967ae --- /dev/null +++ b/drivers/staging/tty/epca.c @@ -0,0 +1,2784 @@ +/* + Copyright (C) 1996 Digi International. + + For technical support please email digiLinux@dgii.com or + call Digi tech support at (612) 912-3456 + + ** This driver is no longer supported by Digi ** + + Much of this design and code came from epca.c which was + copyright (C) 1994, 1995 Troy De Jongh, and subsquently + modified by David Nugent, Christoph Lameter, Mike McLagan. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* See README.epca for change history --DAT*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "digiPCI.h" + + +#include "digi1.h" +#include "digiFep1.h" +#include "epca.h" +#include "epcaconfig.h" + +#define VERSION "1.3.0.1-LK2.6" + +/* This major needs to be submitted to Linux to join the majors list */ +#define DIGIINFOMAJOR 35 /* For Digi specific ioctl */ + + +#define MAXCARDS 7 +#define epcaassert(x, msg) if (!(x)) epca_error(__LINE__, msg) + +#define PFX "epca: " + +static int nbdevs, num_cards, liloconfig; +static int digi_poller_inhibited = 1 ; + +static int setup_error_code; +static int invalid_lilo_config; + +/* + * The ISA boards do window flipping into the same spaces so its only sane with + * a single lock. It's still pretty efficient. This lock guards the hardware + * and the tty_port lock guards the kernel side stuff like use counts. Take + * this lock inside the port lock if you must take both. + */ +static DEFINE_SPINLOCK(epca_lock); + +/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted + to 7 below. */ +static struct board_info boards[MAXBOARDS]; + +static struct tty_driver *pc_driver; +static struct tty_driver *pc_info; + +/* ------------------ Begin Digi specific structures -------------------- */ + +/* + * digi_channels represents an array of structures that keep track of each + * channel of the Digi product. Information such as transmit and receive + * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored + * here. This structure is NOT used to overlay the cards physical channel + * structure. + */ +static struct channel digi_channels[MAX_ALLOC]; + +/* + * card_ptr is an array used to hold the address of the first channel structure + * of each card. This array will hold the addresses of various channels located + * in digi_channels. + */ +static struct channel *card_ptr[MAXCARDS]; + +static struct timer_list epca_timer; + +/* + * Begin generic memory functions. These functions will be alias (point at) + * more specific functions dependent on the board being configured. + */ +static void memwinon(struct board_info *b, unsigned int win); +static void memwinoff(struct board_info *b, unsigned int win); +static void globalwinon(struct channel *ch); +static void rxwinon(struct channel *ch); +static void txwinon(struct channel *ch); +static void memoff(struct channel *ch); +static void assertgwinon(struct channel *ch); +static void assertmemoff(struct channel *ch); + +/* ---- Begin more 'specific' memory functions for cx_like products --- */ + +static void pcxem_memwinon(struct board_info *b, unsigned int win); +static void pcxem_memwinoff(struct board_info *b, unsigned int win); +static void pcxem_globalwinon(struct channel *ch); +static void pcxem_rxwinon(struct channel *ch); +static void pcxem_txwinon(struct channel *ch); +static void pcxem_memoff(struct channel *ch); + +/* ------ Begin more 'specific' memory functions for the pcxe ------- */ + +static void pcxe_memwinon(struct board_info *b, unsigned int win); +static void pcxe_memwinoff(struct board_info *b, unsigned int win); +static void pcxe_globalwinon(struct channel *ch); +static void pcxe_rxwinon(struct channel *ch); +static void pcxe_txwinon(struct channel *ch); +static void pcxe_memoff(struct channel *ch); + +/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ +/* Note : pc64xe and pcxi share the same windowing routines */ + +static void pcxi_memwinon(struct board_info *b, unsigned int win); +static void pcxi_memwinoff(struct board_info *b, unsigned int win); +static void pcxi_globalwinon(struct channel *ch); +static void pcxi_rxwinon(struct channel *ch); +static void pcxi_txwinon(struct channel *ch); +static void pcxi_memoff(struct channel *ch); + +/* - Begin 'specific' do nothing memory functions needed for some cards - */ + +static void dummy_memwinon(struct board_info *b, unsigned int win); +static void dummy_memwinoff(struct board_info *b, unsigned int win); +static void dummy_globalwinon(struct channel *ch); +static void dummy_rxwinon(struct channel *ch); +static void dummy_txwinon(struct channel *ch); +static void dummy_memoff(struct channel *ch); +static void dummy_assertgwinon(struct channel *ch); +static void dummy_assertmemoff(struct channel *ch); + +static struct channel *verifyChannel(struct tty_struct *); +static void pc_sched_event(struct channel *, int); +static void epca_error(int, char *); +static void pc_close(struct tty_struct *, struct file *); +static void shutdown(struct channel *, struct tty_struct *tty); +static void pc_hangup(struct tty_struct *); +static int pc_write_room(struct tty_struct *); +static int pc_chars_in_buffer(struct tty_struct *); +static void pc_flush_buffer(struct tty_struct *); +static void pc_flush_chars(struct tty_struct *); +static int pc_open(struct tty_struct *, struct file *); +static void post_fep_init(unsigned int crd); +static void epcapoll(unsigned long); +static void doevent(int); +static void fepcmd(struct channel *, int, int, int, int, int); +static unsigned termios2digi_h(struct channel *ch, unsigned); +static unsigned termios2digi_i(struct channel *ch, unsigned); +static unsigned termios2digi_c(struct channel *ch, unsigned); +static void epcaparam(struct tty_struct *, struct channel *); +static void receive_data(struct channel *, struct tty_struct *tty); +static int pc_ioctl(struct tty_struct *, + unsigned int, unsigned long); +static int info_ioctl(struct tty_struct *, + unsigned int, unsigned long); +static void pc_set_termios(struct tty_struct *, struct ktermios *); +static void do_softint(struct work_struct *work); +static void pc_stop(struct tty_struct *); +static void pc_start(struct tty_struct *); +static void pc_throttle(struct tty_struct *tty); +static void pc_unthrottle(struct tty_struct *tty); +static int pc_send_break(struct tty_struct *tty, int msec); +static void setup_empty_event(struct tty_struct *tty, struct channel *ch); + +static int pc_write(struct tty_struct *, const unsigned char *, int); +static int pc_init(void); +static int init_PCI(void); + +/* + * Table of functions for each board to handle memory. Mantaining parallelism + * is a *very* good idea here. The idea is for the runtime code to blindly call + * these functions, not knowing/caring about the underlying hardware. This + * stuff should contain no conditionals; if more functionality is needed a + * different entry should be established. These calls are the interface calls + * and are the only functions that should be accessed. Anyone caught making + * direct calls deserves what they get. + */ +static void memwinon(struct board_info *b, unsigned int win) +{ + b->memwinon(b, win); +} + +static void memwinoff(struct board_info *b, unsigned int win) +{ + b->memwinoff(b, win); +} + +static void globalwinon(struct channel *ch) +{ + ch->board->globalwinon(ch); +} + +static void rxwinon(struct channel *ch) +{ + ch->board->rxwinon(ch); +} + +static void txwinon(struct channel *ch) +{ + ch->board->txwinon(ch); +} + +static void memoff(struct channel *ch) +{ + ch->board->memoff(ch); +} +static void assertgwinon(struct channel *ch) +{ + ch->board->assertgwinon(ch); +} + +static void assertmemoff(struct channel *ch) +{ + ch->board->assertmemoff(ch); +} + +/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */ +static void pcxem_memwinon(struct board_info *b, unsigned int win) +{ + outb_p(FEPWIN | win, b->port + 1); +} + +static void pcxem_memwinoff(struct board_info *b, unsigned int win) +{ + outb_p(0, b->port + 1); +} + +static void pcxem_globalwinon(struct channel *ch) +{ + outb_p(FEPWIN, (int)ch->board->port + 1); +} + +static void pcxem_rxwinon(struct channel *ch) +{ + outb_p(ch->rxwin, (int)ch->board->port + 1); +} + +static void pcxem_txwinon(struct channel *ch) +{ + outb_p(ch->txwin, (int)ch->board->port + 1); +} + +static void pcxem_memoff(struct channel *ch) +{ + outb_p(0, (int)ch->board->port + 1); +} + +/* ----------------- Begin pcxe memory window stuff ------------------ */ +static void pcxe_memwinon(struct board_info *b, unsigned int win) +{ + outb_p(FEPWIN | win, b->port + 1); +} + +static void pcxe_memwinoff(struct board_info *b, unsigned int win) +{ + outb_p(inb(b->port) & ~FEPMEM, b->port + 1); + outb_p(0, b->port + 1); +} + +static void pcxe_globalwinon(struct channel *ch) +{ + outb_p(FEPWIN, (int)ch->board->port + 1); +} + +static void pcxe_rxwinon(struct channel *ch) +{ + outb_p(ch->rxwin, (int)ch->board->port + 1); +} + +static void pcxe_txwinon(struct channel *ch) +{ + outb_p(ch->txwin, (int)ch->board->port + 1); +} + +static void pcxe_memoff(struct channel *ch) +{ + outb_p(0, (int)ch->board->port); + outb_p(0, (int)ch->board->port + 1); +} + +/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ +static void pcxi_memwinon(struct board_info *b, unsigned int win) +{ + outb_p(inb(b->port) | FEPMEM, b->port); +} + +static void pcxi_memwinoff(struct board_info *b, unsigned int win) +{ + outb_p(inb(b->port) & ~FEPMEM, b->port); +} + +static void pcxi_globalwinon(struct channel *ch) +{ + outb_p(FEPMEM, ch->board->port); +} + +static void pcxi_rxwinon(struct channel *ch) +{ + outb_p(FEPMEM, ch->board->port); +} + +static void pcxi_txwinon(struct channel *ch) +{ + outb_p(FEPMEM, ch->board->port); +} + +static void pcxi_memoff(struct channel *ch) +{ + outb_p(0, ch->board->port); +} + +static void pcxi_assertgwinon(struct channel *ch) +{ + epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off"); +} + +static void pcxi_assertmemoff(struct channel *ch) +{ + epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on"); +} + +/* + * Not all of the cards need specific memory windowing routines. Some cards + * (Such as PCI) needs no windowing routines at all. We provide these do + * nothing routines so that the same code base can be used. The driver will + * ALWAYS call a windowing routine if it thinks it needs to; regardless of the + * card. However, dependent on the card the routine may or may not do anything. + */ +static void dummy_memwinon(struct board_info *b, unsigned int win) +{ +} + +static void dummy_memwinoff(struct board_info *b, unsigned int win) +{ +} + +static void dummy_globalwinon(struct channel *ch) +{ +} + +static void dummy_rxwinon(struct channel *ch) +{ +} + +static void dummy_txwinon(struct channel *ch) +{ +} + +static void dummy_memoff(struct channel *ch) +{ +} + +static void dummy_assertgwinon(struct channel *ch) +{ +} + +static void dummy_assertmemoff(struct channel *ch) +{ +} + +static struct channel *verifyChannel(struct tty_struct *tty) +{ + /* + * This routine basically provides a sanity check. It insures that the + * channel returned is within the proper range of addresses as well as + * properly initialized. If some bogus info gets passed in + * through tty->driver_data this should catch it. + */ + if (tty) { + struct channel *ch = tty->driver_data; + if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { + if (ch->magic == EPCA_MAGIC) + return ch; + } + } + return NULL; +} + +static void pc_sched_event(struct channel *ch, int event) +{ + /* + * We call this to schedule interrupt processing on some event. The + * kernel sees our request and calls the related routine in OUR driver. + */ + ch->event |= 1 << event; + schedule_work(&ch->tqueue); +} + +static void epca_error(int line, char *msg) +{ + printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg); +} + +static void pc_close(struct tty_struct *tty, struct file *filp) +{ + struct channel *ch; + struct tty_port *port; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch == NULL) + return; + port = &ch->port; + + if (tty_port_close_start(port, tty, filp) == 0) + return; + + pc_flush_buffer(tty); + shutdown(ch, tty); + + tty_port_close_end(port, tty); + ch->event = 0; /* FIXME: review ch->event locking */ + tty_port_tty_set(port, NULL); +} + +static void shutdown(struct channel *ch, struct tty_struct *tty) +{ + unsigned long flags; + struct board_chan __iomem *bc; + struct tty_port *port = &ch->port; + + if (!(port->flags & ASYNC_INITIALIZED)) + return; + + spin_lock_irqsave(&epca_lock, flags); + + globalwinon(ch); + bc = ch->brdchan; + + /* + * In order for an event to be generated on the receipt of data the + * idata flag must be set. Since we are shutting down, this is not + * necessary clear this flag. + */ + if (bc) + writeb(0, &bc->idata); + + /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */ + if (tty->termios->c_cflag & HUPCL) { + ch->omodem &= ~(ch->m_rts | ch->m_dtr); + fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); + } + memoff(ch); + + /* + * The channel has officialy been closed. The next time it is opened it + * will have to reinitialized. Set a flag to indicate this. + */ + /* Prevent future Digi programmed interrupts from coming active */ + port->flags &= ~ASYNC_INITIALIZED; + spin_unlock_irqrestore(&epca_lock, flags); +} + +static void pc_hangup(struct tty_struct *tty) +{ + struct channel *ch; + + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + pc_flush_buffer(tty); + tty_ldisc_flush(tty); + shutdown(ch, tty); + + ch->event = 0; /* FIXME: review locking of ch->event */ + tty_port_hangup(&ch->port); + } +} + +static int pc_write(struct tty_struct *tty, + const unsigned char *buf, int bytesAvailable) +{ + unsigned int head, tail; + int dataLen; + int size; + int amountCopied; + struct channel *ch; + unsigned long flags; + int remain; + struct board_chan __iomem *bc; + + /* + * pc_write is primarily called directly by the kernel routine + * tty_write (Though it can also be called by put_char) found in + * tty_io.c. pc_write is passed a line discipline buffer where the data + * to be written out is stored. The line discipline implementation + * itself is done at the kernel level and is not brought into the + * driver. + */ + + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch == NULL) + return 0; + + /* Make a pointer to the channel data structure found on the board. */ + bc = ch->brdchan; + size = ch->txbufsize; + amountCopied = 0; + + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + + head = readw(&bc->tin) & (size - 1); + tail = readw(&bc->tout); + + if (tail != readw(&bc->tout)) + tail = readw(&bc->tout); + tail &= (size - 1); + + if (head >= tail) { + /* head has not wrapped */ + /* + * remain (much like dataLen above) represents the total amount + * of space available on the card for data. Here dataLen + * represents the space existing between the head pointer and + * the end of buffer. This is important because a memcpy cannot + * be told to automatically wrap around when it hits the buffer + * end. + */ + dataLen = size - head; + remain = size - (head - tail) - 1; + } else { + /* head has wrapped around */ + remain = tail - head - 1; + dataLen = remain; + } + /* + * Check the space on the card. If we have more data than space; reduce + * the amount of data to fit the space. + */ + bytesAvailable = min(remain, bytesAvailable); + txwinon(ch); + while (bytesAvailable > 0) { + /* there is data to copy onto card */ + + /* + * If head is not wrapped, the below will make sure the first + * data copy fills to the end of card buffer. + */ + dataLen = min(bytesAvailable, dataLen); + memcpy_toio(ch->txptr + head, buf, dataLen); + buf += dataLen; + head += dataLen; + amountCopied += dataLen; + bytesAvailable -= dataLen; + + if (head >= size) { + head = 0; + dataLen = tail; + } + } + ch->statusflags |= TXBUSY; + globalwinon(ch); + writew(head, &bc->tin); + + if ((ch->statusflags & LOWWAIT) == 0) { + ch->statusflags |= LOWWAIT; + writeb(1, &bc->ilow); + } + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + return amountCopied; +} + +static int pc_write_room(struct tty_struct *tty) +{ + int remain = 0; + struct channel *ch; + unsigned long flags; + unsigned int head, tail; + struct board_chan __iomem *bc; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + + bc = ch->brdchan; + head = readw(&bc->tin) & (ch->txbufsize - 1); + tail = readw(&bc->tout); + + if (tail != readw(&bc->tout)) + tail = readw(&bc->tout); + /* Wrap tail if necessary */ + tail &= (ch->txbufsize - 1); + remain = tail - head - 1; + if (remain < 0) + remain += ch->txbufsize; + + if (remain && (ch->statusflags & LOWWAIT) == 0) { + ch->statusflags |= LOWWAIT; + writeb(1, &bc->ilow); + } + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + } + /* Return how much room is left on card */ + return remain; +} + +static int pc_chars_in_buffer(struct tty_struct *tty) +{ + int chars; + unsigned int ctail, head, tail; + int remain; + unsigned long flags; + struct channel *ch; + struct board_chan __iomem *bc; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch == NULL) + return 0; + + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + + bc = ch->brdchan; + tail = readw(&bc->tout); + head = readw(&bc->tin); + ctail = readw(&ch->mailbox->cout); + + if (tail == head && readw(&ch->mailbox->cin) == ctail && + readb(&bc->tbusy) == 0) + chars = 0; + else { /* Begin if some space on the card has been used */ + head = readw(&bc->tin) & (ch->txbufsize - 1); + tail &= (ch->txbufsize - 1); + /* + * The logic here is basically opposite of the above + * pc_write_room here we are finding the amount of bytes in the + * buffer filled. Not the amount of bytes empty. + */ + remain = tail - head - 1; + if (remain < 0) + remain += ch->txbufsize; + chars = (int)(ch->txbufsize - remain); + /* + * Make it possible to wakeup anything waiting for output in + * tty_ioctl.c, etc. + * + * If not already set. Setup an event to indicate when the + * transmit buffer empties. + */ + if (!(ch->statusflags & EMPTYWAIT)) + setup_empty_event(tty, ch); + } /* End if some space on the card has been used */ + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + /* Return number of characters residing on card. */ + return chars; +} + +static void pc_flush_buffer(struct tty_struct *tty) +{ + unsigned int tail; + unsigned long flags; + struct channel *ch; + struct board_chan __iomem *bc; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch == NULL) + return; + + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + bc = ch->brdchan; + tail = readw(&bc->tout); + /* Have FEP move tout pointer; effectively flushing transmit buffer */ + fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + tty_wakeup(tty); +} + +static void pc_flush_chars(struct tty_struct *tty) +{ + struct channel *ch; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + unsigned long flags; + spin_lock_irqsave(&epca_lock, flags); + /* + * If not already set and the transmitter is busy setup an + * event to indicate when the transmit empties. + */ + if ((ch->statusflags & TXBUSY) && + !(ch->statusflags & EMPTYWAIT)) + setup_empty_event(tty, ch); + spin_unlock_irqrestore(&epca_lock, flags); + } +} + +static int epca_carrier_raised(struct tty_port *port) +{ + struct channel *ch = container_of(port, struct channel, port); + if (ch->imodem & ch->dcd) + return 1; + return 0; +} + +static void epca_dtr_rts(struct tty_port *port, int onoff) +{ +} + +static int pc_open(struct tty_struct *tty, struct file *filp) +{ + struct channel *ch; + struct tty_port *port; + unsigned long flags; + int line, retval, boardnum; + struct board_chan __iomem *bc; + unsigned int head; + + line = tty->index; + if (line < 0 || line >= nbdevs) + return -ENODEV; + + ch = &digi_channels[line]; + port = &ch->port; + boardnum = ch->boardnum; + + /* Check status of board configured in system. */ + + /* + * I check to see if the epca_setup routine detected a user error. It + * might be better to put this in pc_init, but for the moment it goes + * here. + */ + if (invalid_lilo_config) { + if (setup_error_code & INVALID_BOARD_TYPE) + printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n"); + if (setup_error_code & INVALID_NUM_PORTS) + printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n"); + if (setup_error_code & INVALID_MEM_BASE) + printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n"); + if (setup_error_code & INVALID_PORT_BASE) + printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n"); + if (setup_error_code & INVALID_BOARD_STATUS) + printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n"); + if (setup_error_code & INVALID_ALTPIN) + printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n"); + tty->driver_data = NULL; /* Mark this device as 'down' */ + return -ENODEV; + } + if (boardnum >= num_cards || boards[boardnum].status == DISABLED) { + tty->driver_data = NULL; /* Mark this device as 'down' */ + return(-ENODEV); + } + + bc = ch->brdchan; + if (bc == NULL) { + tty->driver_data = NULL; + return -ENODEV; + } + + spin_lock_irqsave(&port->lock, flags); + /* + * Every time a channel is opened, increment a counter. This is + * necessary because we do not wish to flush and shutdown the channel + * until the last app holding the channel open, closes it. + */ + port->count++; + /* + * Set a kernel structures pointer to our local channel structure. This + * way we can get to it when passed only a tty struct. + */ + tty->driver_data = ch; + port->tty = tty; + /* + * If this is the first time the channel has been opened, initialize + * the tty->termios struct otherwise let pc_close handle it. + */ + spin_lock(&epca_lock); + globalwinon(ch); + ch->statusflags = 0; + + /* Save boards current modem status */ + ch->imodem = readb(&bc->mstat); + + /* + * Set receive head and tail ptrs to each other. This indicates no data + * available to read. + */ + head = readw(&bc->rin); + writew(head, &bc->rout); + + /* Set the channels associated tty structure */ + + /* + * The below routine generally sets up parity, baud, flow control + * issues, etc.... It effect both control flags and input flags. + */ + epcaparam(tty, ch); + memoff(ch); + spin_unlock(&epca_lock); + port->flags |= ASYNC_INITIALIZED; + spin_unlock_irqrestore(&port->lock, flags); + + retval = tty_port_block_til_ready(port, tty, filp); + if (retval) + return retval; + /* + * Set this again in case a hangup set it to zero while this open() was + * waiting for the line... + */ + spin_lock_irqsave(&port->lock, flags); + port->tty = tty; + spin_lock(&epca_lock); + globalwinon(ch); + /* Enable Digi Data events */ + writeb(1, &bc->idata); + memoff(ch); + spin_unlock(&epca_lock); + spin_unlock_irqrestore(&port->lock, flags); + return 0; +} + +static int __init epca_module_init(void) +{ + return pc_init(); +} +module_init(epca_module_init); + +static struct pci_driver epca_driver; + +static void __exit epca_module_exit(void) +{ + int count, crd; + struct board_info *bd; + struct channel *ch; + + del_timer_sync(&epca_timer); + + if (tty_unregister_driver(pc_driver) || + tty_unregister_driver(pc_info)) { + printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); + return; + } + put_tty_driver(pc_driver); + put_tty_driver(pc_info); + + for (crd = 0; crd < num_cards; crd++) { + bd = &boards[crd]; + if (!bd) { /* sanity check */ + printk(KERN_ERR " - Digi : cleanup_module failed\n"); + return; + } + ch = card_ptr[crd]; + for (count = 0; count < bd->numports; count++, ch++) { + struct tty_struct *tty = tty_port_tty_get(&ch->port); + if (tty) { + tty_hangup(tty); + tty_kref_put(tty); + } + } + } + pci_unregister_driver(&epca_driver); +} +module_exit(epca_module_exit); + +static const struct tty_operations pc_ops = { + .open = pc_open, + .close = pc_close, + .write = pc_write, + .write_room = pc_write_room, + .flush_buffer = pc_flush_buffer, + .chars_in_buffer = pc_chars_in_buffer, + .flush_chars = pc_flush_chars, + .ioctl = pc_ioctl, + .set_termios = pc_set_termios, + .stop = pc_stop, + .start = pc_start, + .throttle = pc_throttle, + .unthrottle = pc_unthrottle, + .hangup = pc_hangup, + .break_ctl = pc_send_break +}; + +static const struct tty_port_operations epca_port_ops = { + .carrier_raised = epca_carrier_raised, + .dtr_rts = epca_dtr_rts, +}; + +static int info_open(struct tty_struct *tty, struct file *filp) +{ + return 0; +} + +static const struct tty_operations info_ops = { + .open = info_open, + .ioctl = info_ioctl, +}; + +static int __init pc_init(void) +{ + int crd; + struct board_info *bd; + unsigned char board_id = 0; + int err = -ENOMEM; + + int pci_boards_found, pci_count; + + pci_count = 0; + + pc_driver = alloc_tty_driver(MAX_ALLOC); + if (!pc_driver) + goto out1; + + pc_info = alloc_tty_driver(MAX_ALLOC); + if (!pc_info) + goto out2; + + /* + * If epca_setup has not been ran by LILO set num_cards to defaults; + * copy board structure defined by digiConfig into drivers board + * structure. Note : If LILO has ran epca_setup then epca_setup will + * handle defining num_cards as well as copying the data into the board + * structure. + */ + if (!liloconfig) { + /* driver has been configured via. epcaconfig */ + nbdevs = NBDEVS; + num_cards = NUMCARDS; + memcpy(&boards, &static_boards, + sizeof(struct board_info) * NUMCARDS); + } + + /* + * Note : If lilo was used to configure the driver and the ignore + * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards + * will equal 0 at this point. This is okay; PCI cards will still be + * picked up if detected. + */ + + /* + * Set up interrupt, we will worry about memory allocation in + * post_fep_init. + */ + printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION); + + /* + * NOTE : This code assumes that the number of ports found in the + * boards array is correct. This could be wrong if the card in question + * is PCI (And therefore has no ports entry in the boards structure.) + * The rest of the information will be valid for PCI because the + * beginning of pc_init scans for PCI and determines i/o and base + * memory addresses. I am not sure if it is possible to read the number + * of ports supported by the card prior to it being booted (Since that + * is the state it is in when pc_init is run). Because it is not + * possible to query the number of supported ports until after the card + * has booted; we are required to calculate the card_ptrs as the card + * is initialized (Inside post_fep_init). The negative thing about this + * approach is that digiDload's call to GET_INFO will have a bad port + * value. (Since this is called prior to post_fep_init.) + */ + pci_boards_found = 0; + if (num_cards < MAXBOARDS) + pci_boards_found += init_PCI(); + num_cards += pci_boards_found; + + pc_driver->owner = THIS_MODULE; + pc_driver->name = "ttyD"; + pc_driver->major = DIGI_MAJOR; + pc_driver->minor_start = 0; + pc_driver->type = TTY_DRIVER_TYPE_SERIAL; + pc_driver->subtype = SERIAL_TYPE_NORMAL; + pc_driver->init_termios = tty_std_termios; + pc_driver->init_termios.c_iflag = 0; + pc_driver->init_termios.c_oflag = 0; + pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; + pc_driver->init_termios.c_lflag = 0; + pc_driver->init_termios.c_ispeed = 9600; + pc_driver->init_termios.c_ospeed = 9600; + pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; + tty_set_operations(pc_driver, &pc_ops); + + pc_info->owner = THIS_MODULE; + pc_info->name = "digi_ctl"; + pc_info->major = DIGIINFOMAJOR; + pc_info->minor_start = 0; + pc_info->type = TTY_DRIVER_TYPE_SERIAL; + pc_info->subtype = SERIAL_TYPE_INFO; + pc_info->init_termios = tty_std_termios; + pc_info->init_termios.c_iflag = 0; + pc_info->init_termios.c_oflag = 0; + pc_info->init_termios.c_lflag = 0; + pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + pc_info->init_termios.c_ispeed = 9600; + pc_info->init_termios.c_ospeed = 9600; + pc_info->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(pc_info, &info_ops); + + + for (crd = 0; crd < num_cards; crd++) { + /* + * This is where the appropriate memory handlers for the + * hardware is set. Everything at runtime blindly jumps through + * these vectors. + */ + + /* defined in epcaconfig.h */ + bd = &boards[crd]; + + switch (bd->type) { + case PCXEM: + case EISAXEM: + bd->memwinon = pcxem_memwinon; + bd->memwinoff = pcxem_memwinoff; + bd->globalwinon = pcxem_globalwinon; + bd->txwinon = pcxem_txwinon; + bd->rxwinon = pcxem_rxwinon; + bd->memoff = pcxem_memoff; + bd->assertgwinon = dummy_assertgwinon; + bd->assertmemoff = dummy_assertmemoff; + break; + + case PCIXEM: + case PCIXRJ: + case PCIXR: + bd->memwinon = dummy_memwinon; + bd->memwinoff = dummy_memwinoff; + bd->globalwinon = dummy_globalwinon; + bd->txwinon = dummy_txwinon; + bd->rxwinon = dummy_rxwinon; + bd->memoff = dummy_memoff; + bd->assertgwinon = dummy_assertgwinon; + bd->assertmemoff = dummy_assertmemoff; + break; + + case PCXE: + case PCXEVE: + bd->memwinon = pcxe_memwinon; + bd->memwinoff = pcxe_memwinoff; + bd->globalwinon = pcxe_globalwinon; + bd->txwinon = pcxe_txwinon; + bd->rxwinon = pcxe_rxwinon; + bd->memoff = pcxe_memoff; + bd->assertgwinon = dummy_assertgwinon; + bd->assertmemoff = dummy_assertmemoff; + break; + + case PCXI: + case PC64XE: + bd->memwinon = pcxi_memwinon; + bd->memwinoff = pcxi_memwinoff; + bd->globalwinon = pcxi_globalwinon; + bd->txwinon = pcxi_txwinon; + bd->rxwinon = pcxi_rxwinon; + bd->memoff = pcxi_memoff; + bd->assertgwinon = pcxi_assertgwinon; + bd->assertmemoff = pcxi_assertmemoff; + break; + + default: + break; + } + + /* + * Some cards need a memory segment to be defined for use in + * transmit and receive windowing operations. These boards are + * listed in the below switch. In the case of the XI the amount + * of memory on the board is variable so the memory_seg is also + * variable. This code determines what they segment should be. + */ + switch (bd->type) { + case PCXE: + case PCXEVE: + case PC64XE: + bd->memory_seg = 0xf000; + break; + + case PCXI: + board_id = inb((int)bd->port); + if ((board_id & 0x1) == 0x1) { + /* it's an XI card */ + /* Is it a 64K board */ + if ((board_id & 0x30) == 0) + bd->memory_seg = 0xf000; + + /* Is it a 128K board */ + if ((board_id & 0x30) == 0x10) + bd->memory_seg = 0xe000; + + /* Is is a 256K board */ + if ((board_id & 0x30) == 0x20) + bd->memory_seg = 0xc000; + + /* Is it a 512K board */ + if ((board_id & 0x30) == 0x30) + bd->memory_seg = 0x8000; + } else + printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port); + break; + } + } + + err = tty_register_driver(pc_driver); + if (err) { + printk(KERN_ERR "Couldn't register Digi PC/ driver"); + goto out3; + } + + err = tty_register_driver(pc_info); + if (err) { + printk(KERN_ERR "Couldn't register Digi PC/ info "); + goto out4; + } + + /* Start up the poller to check for events on all enabled boards */ + init_timer(&epca_timer); + epca_timer.function = epcapoll; + mod_timer(&epca_timer, jiffies + HZ/25); + return 0; + +out4: + tty_unregister_driver(pc_driver); +out3: + put_tty_driver(pc_info); +out2: + put_tty_driver(pc_driver); +out1: + return err; +} + +static void post_fep_init(unsigned int crd) +{ + int i; + void __iomem *memaddr; + struct global_data __iomem *gd; + struct board_info *bd; + struct board_chan __iomem *bc; + struct channel *ch; + int shrinkmem = 0, lowwater; + + /* + * This call is made by the user via. the ioctl call DIGI_INIT. It is + * responsible for setting up all the card specific stuff. + */ + bd = &boards[crd]; + + /* + * If this is a PCI board, get the port info. Remember PCI cards do not + * have entries into the epcaconfig.h file, so we can't get the number + * of ports from it. Unfortunetly, this means that anyone doing a + * DIGI_GETINFO before the board has booted will get an invalid number + * of ports returned (It should return 0). Calls to DIGI_GETINFO after + * DIGI_INIT has been called will return the proper values. + */ + if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */ + /* + * Below we use XEMPORTS as a memory offset regardless of which + * PCI card it is. This is because all of the supported PCI + * cards have the same memory offset for the channel data. This + * will have to be changed if we ever develop a PCI/XE card. + * NOTE : The FEP manual states that the port offset is 0xC22 + * as opposed to 0xC02. This is only true for PC/XE, and PC/XI + * cards; not for the XEM, or CX series. On the PCI cards the + * number of ports is determined by reading a ID PROM located + * in the box attached to the card. The card can then determine + * the index the id to determine the number of ports available. + * (FYI - The id should be located at 0x1ac (And may use up to + * 4 bytes if the box in question is a XEM or CX)). + */ + /* PCI cards are already remapped at this point ISA are not */ + bd->numports = readw(bd->re_map_membase + XEMPORTS); + epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports"); + nbdevs += (bd->numports); + } else { + /* Fix up the mappings for ISA/EISA etc */ + /* FIXME: 64K - can we be smarter ? */ + bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000); + } + + if (crd != 0) + card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; + else + card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ + + ch = card_ptr[crd]; + epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); + + memaddr = bd->re_map_membase; + + /* + * The below assignment will set bc to point at the BEGINING of the + * cards channel structures. For 1 card there will be between 8 and 64 + * of these structures. + */ + bc = memaddr + CHANSTRUCT; + + /* + * The below assignment will set gd to point at the BEGINING of global + * memory address 0xc00. The first data in that global memory actually + * starts at address 0xc1a. The command in pointer begins at 0xd10. + */ + gd = memaddr + GLOBAL; + + /* + * XEPORTS (address 0xc22) points at the number of channels the card + * supports. (For 64XE, XI, XEM, and XR use 0xc02) + */ + if ((bd->type == PCXEVE || bd->type == PCXE) && + (readw(memaddr + XEPORTS) < 3)) + shrinkmem = 1; + if (bd->type < PCIXEM) + if (!request_region((int)bd->port, 4, board_desc[bd->type])) + return; + memwinon(bd, 0); + + /* + * Remember ch is the main drivers channels structure, while bc is the + * cards channel structure. + */ + for (i = 0; i < bd->numports; i++, ch++, bc++) { + unsigned long flags; + u16 tseg, rseg; + + tty_port_init(&ch->port); + ch->port.ops = &epca_port_ops; + ch->brdchan = bc; + ch->mailbox = gd; + INIT_WORK(&ch->tqueue, do_softint); + ch->board = &boards[crd]; + + spin_lock_irqsave(&epca_lock, flags); + switch (bd->type) { + /* + * Since some of the boards use different bitmaps for + * their control signals we cannot hard code these + * values and retain portability. We virtualize this + * data here. + */ + case EISAXEM: + case PCXEM: + case PCIXEM: + case PCIXRJ: + case PCIXR: + ch->m_rts = 0x02; + ch->m_dcd = 0x80; + ch->m_dsr = 0x20; + ch->m_cts = 0x10; + ch->m_ri = 0x40; + ch->m_dtr = 0x01; + break; + + case PCXE: + case PCXEVE: + case PCXI: + case PC64XE: + ch->m_rts = 0x02; + ch->m_dcd = 0x08; + ch->m_dsr = 0x10; + ch->m_cts = 0x20; + ch->m_ri = 0x40; + ch->m_dtr = 0x80; + break; + } + + if (boards[crd].altpin) { + ch->dsr = ch->m_dcd; + ch->dcd = ch->m_dsr; + ch->digiext.digi_flags |= DIGI_ALTPIN; + } else { + ch->dcd = ch->m_dcd; + ch->dsr = ch->m_dsr; + } + + ch->boardnum = crd; + ch->channelnum = i; + ch->magic = EPCA_MAGIC; + tty_port_tty_set(&ch->port, NULL); + + if (shrinkmem) { + fepcmd(ch, SETBUFFER, 32, 0, 0, 0); + shrinkmem = 0; + } + + tseg = readw(&bc->tseg); + rseg = readw(&bc->rseg); + + switch (bd->type) { + case PCIXEM: + case PCIXRJ: + case PCIXR: + /* Cover all the 2MEG cards */ + ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); + ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); + ch->txwin = FEPWIN | (tseg >> 11); + ch->rxwin = FEPWIN | (rseg >> 11); + break; + + case PCXEM: + case EISAXEM: + /* Cover all the 32K windowed cards */ + /* Mask equal to window size - 1 */ + ch->txptr = memaddr + ((tseg << 4) & 0x7fff); + ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); + ch->txwin = FEPWIN | (tseg >> 11); + ch->rxwin = FEPWIN | (rseg >> 11); + break; + + case PCXEVE: + case PCXE: + ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) + & 0x1fff); + ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); + ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) + & 0x1fff); + ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9); + break; + + case PCXI: + case PC64XE: + ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); + ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); + ch->txwin = ch->rxwin = 0; + break; + } + + ch->txbufhead = 0; + ch->txbufsize = readw(&bc->tmax) + 1; + + ch->rxbufhead = 0; + ch->rxbufsize = readw(&bc->rmax) + 1; + + lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); + + /* Set transmitter low water mark */ + fepcmd(ch, STXLWATER, lowwater, 0, 10, 0); + + /* Set receiver low water mark */ + fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0); + + /* Set receiver high water mark */ + fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); + + writew(100, &bc->edelay); + writeb(1, &bc->idata); + + ch->startc = readb(&bc->startc); + ch->stopc = readb(&bc->stopc); + ch->startca = readb(&bc->startca); + ch->stopca = readb(&bc->stopca); + + ch->fepcflag = 0; + ch->fepiflag = 0; + ch->fepoflag = 0; + ch->fepstartc = 0; + ch->fepstopc = 0; + ch->fepstartca = 0; + ch->fepstopca = 0; + + ch->port.close_delay = 50; + + spin_unlock_irqrestore(&epca_lock, flags); + } + + printk(KERN_INFO + "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", + VERSION, board_desc[bd->type], (long)bd->port, + (long)bd->membase, bd->numports); + memwinoff(bd, 0); +} + +static void epcapoll(unsigned long ignored) +{ + unsigned long flags; + int crd; + unsigned int head, tail; + struct channel *ch; + struct board_info *bd; + + /* + * This routine is called upon every timer interrupt. Even though the + * Digi series cards are capable of generating interrupts this method + * of non-looping polling is more efficient. This routine checks for + * card generated events (Such as receive data, are transmit buffer + * empty) and acts on those events. + */ + for (crd = 0; crd < num_cards; crd++) { + bd = &boards[crd]; + ch = card_ptr[crd]; + + if ((bd->status == DISABLED) || digi_poller_inhibited) + continue; + + /* + * assertmemoff is not needed here; indeed it is an empty + * subroutine. It is being kept because future boards may need + * this as well as some legacy boards. + */ + spin_lock_irqsave(&epca_lock, flags); + + assertmemoff(ch); + + globalwinon(ch); + + /* + * In this case head and tail actually refer to the event queue + * not the transmit or receive queue. + */ + head = readw(&ch->mailbox->ein); + tail = readw(&ch->mailbox->eout); + + /* If head isn't equal to tail we have an event */ + if (head != tail) + doevent(crd); + memoff(ch); + + spin_unlock_irqrestore(&epca_lock, flags); + } /* End for each card */ + mod_timer(&epca_timer, jiffies + (HZ / 25)); +} + +static void doevent(int crd) +{ + void __iomem *eventbuf; + struct channel *ch, *chan0; + static struct tty_struct *tty; + struct board_info *bd; + struct board_chan __iomem *bc; + unsigned int tail, head; + int event, channel; + int mstat, lstat; + + /* + * This subroutine is called by epcapoll when an event is detected + * in the event queue. This routine responds to those events. + */ + bd = &boards[crd]; + + chan0 = card_ptr[crd]; + epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); + assertgwinon(chan0); + while ((tail = readw(&chan0->mailbox->eout)) != + (head = readw(&chan0->mailbox->ein))) { + /* Begin while something in event queue */ + assertgwinon(chan0); + eventbuf = bd->re_map_membase + tail + ISTART; + /* Get the channel the event occurred on */ + channel = readb(eventbuf); + /* Get the actual event code that occurred */ + event = readb(eventbuf + 1); + /* + * The two assignments below get the current modem status + * (mstat) and the previous modem status (lstat). These are + * useful becuase an event could signal a change in modem + * signals itself. + */ + mstat = readb(eventbuf + 2); + lstat = readb(eventbuf + 3); + + ch = chan0 + channel; + if ((unsigned)channel >= bd->numports || !ch) { + if (channel >= bd->numports) + ch = chan0; + bc = ch->brdchan; + goto next; + } + + bc = ch->brdchan; + if (bc == NULL) + goto next; + + tty = tty_port_tty_get(&ch->port); + if (event & DATA_IND) { /* Begin DATA_IND */ + receive_data(ch, tty); + assertgwinon(ch); + } /* End DATA_IND */ + /* else *//* Fix for DCD transition missed bug */ + if (event & MODEMCHG_IND) { + /* A modem signal change has been indicated */ + ch->imodem = mstat; + if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) { + /* We are now receiving dcd */ + if (mstat & ch->dcd) + wake_up_interruptible(&ch->port.open_wait); + else /* No dcd; hangup */ + pc_sched_event(ch, EPCA_EVENT_HANGUP); + } + } + if (tty) { + if (event & BREAK_IND) { + /* A break has been indicated */ + tty_insert_flip_char(tty, 0, TTY_BREAK); + tty_schedule_flip(tty); + } else if (event & LOWTX_IND) { + if (ch->statusflags & LOWWAIT) { + ch->statusflags &= ~LOWWAIT; + tty_wakeup(tty); + } + } else if (event & EMPTYTX_IND) { + /* This event is generated by + setup_empty_event */ + ch->statusflags &= ~TXBUSY; + if (ch->statusflags & EMPTYWAIT) { + ch->statusflags &= ~EMPTYWAIT; + tty_wakeup(tty); + } + } + tty_kref_put(tty); + } +next: + globalwinon(ch); + BUG_ON(!bc); + writew(1, &bc->idata); + writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout); + globalwinon(chan0); + } /* End while something in event queue */ +} + +static void fepcmd(struct channel *ch, int cmd, int word_or_byte, + int byte2, int ncmds, int bytecmd) +{ + unchar __iomem *memaddr; + unsigned int head, cmdTail, cmdStart, cmdMax; + long count; + int n; + + /* This is the routine in which commands may be passed to the card. */ + + if (ch->board->status == DISABLED) + return; + assertgwinon(ch); + /* Remember head (As well as max) is just an offset not a base addr */ + head = readw(&ch->mailbox->cin); + /* cmdStart is a base address */ + cmdStart = readw(&ch->mailbox->cstart); + /* + * We do the addition below because we do not want a max pointer + * relative to cmdStart. We want a max pointer that points at the + * physical end of the command queue. + */ + cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax)); + memaddr = ch->board->re_map_membase; + + if (head >= (cmdMax - cmdStart) || (head & 03)) { + printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", + __LINE__, cmd, head); + printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", + __LINE__, cmdMax, cmdStart); + return; + } + if (bytecmd) { + writeb(cmd, memaddr + head + cmdStart + 0); + writeb(ch->channelnum, memaddr + head + cmdStart + 1); + /* Below word_or_byte is bits to set */ + writeb(word_or_byte, memaddr + head + cmdStart + 2); + /* Below byte2 is bits to reset */ + writeb(byte2, memaddr + head + cmdStart + 3); + } else { + writeb(cmd, memaddr + head + cmdStart + 0); + writeb(ch->channelnum, memaddr + head + cmdStart + 1); + writeb(word_or_byte, memaddr + head + cmdStart + 2); + } + head = (head + 4) & (cmdMax - cmdStart - 4); + writew(head, &ch->mailbox->cin); + count = FEPTIMEOUT; + + for (;;) { + count--; + if (count == 0) { + printk(KERN_ERR " - Fep not responding in fepcmd()\n"); + return; + } + head = readw(&ch->mailbox->cin); + cmdTail = readw(&ch->mailbox->cout); + n = (head - cmdTail) & (cmdMax - cmdStart - 4); + /* + * Basically this will break when the FEP acknowledges the + * command by incrementing cmdTail (Making it equal to head). + */ + if (n <= ncmds * (sizeof(short) * 4)) + break; + } +} + +/* + * Digi products use fields in their channels structures that are very similar + * to the c_cflag and c_iflag fields typically found in UNIX termios + * structures. The below three routines allow mappings between these hardware + * "flags" and their respective Linux flags. + */ +static unsigned termios2digi_h(struct channel *ch, unsigned cflag) +{ + unsigned res = 0; + + if (cflag & CRTSCTS) { + ch->digiext.digi_flags |= (RTSPACE | CTSPACE); + res |= ((ch->m_cts) | (ch->m_rts)); + } + + if (ch->digiext.digi_flags & RTSPACE) + res |= ch->m_rts; + + if (ch->digiext.digi_flags & DTRPACE) + res |= ch->m_dtr; + + if (ch->digiext.digi_flags & CTSPACE) + res |= ch->m_cts; + + if (ch->digiext.digi_flags & DSRPACE) + res |= ch->dsr; + + if (ch->digiext.digi_flags & DCDPACE) + res |= ch->dcd; + + if (res & (ch->m_rts)) + ch->digiext.digi_flags |= RTSPACE; + + if (res & (ch->m_cts)) + ch->digiext.digi_flags |= CTSPACE; + + return res; +} + +static unsigned termios2digi_i(struct channel *ch, unsigned iflag) +{ + unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | + INPCK | ISTRIP | IXON | IXANY | IXOFF); + if (ch->digiext.digi_flags & DIGI_AIXON) + res |= IAIXON; + return res; +} + +static unsigned termios2digi_c(struct channel *ch, unsigned cflag) +{ + unsigned res = 0; + if (cflag & CBAUDEX) { + ch->digiext.digi_flags |= DIGI_FAST; + /* + * HUPCL bit is used by FEP to indicate fast baud table is to + * be used. + */ + res |= FEP_HUPCL; + } else + ch->digiext.digi_flags &= ~DIGI_FAST; + /* + * CBAUD has bit position 0x1000 set these days to indicate Linux + * baud rate remap. Digi hardware can't handle the bit assignment. + * (We use a different bit assignment for high speed.). Clear this + * bit out. + */ + res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); + /* + * This gets a little confusing. The Digi cards have their own + * representation of c_cflags controlling baud rate. For the most part + * this is identical to the Linux implementation. However; Digi + * supports one rate (76800) that Linux doesn't. This means that the + * c_cflag entry that would normally mean 76800 for Digi actually means + * 115200 under Linux. Without the below mapping, a stty 115200 would + * only drive the board at 76800. Since the rate 230400 is also found + * after 76800, the same problem afflicts us when we choose a rate of + * 230400. Without the below modificiation stty 230400 would actually + * give us 115200. + * + * There are two additional differences. The Linux value for CLOCAL + * (0x800; 0004000) has no meaning to the Digi hardware. Also in later + * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000) + * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be + * checked for a screened out prior to termios2digi_c returning. Since + * CLOCAL isn't used by the board this can be ignored as long as the + * returned value is used only by Digi hardware. + */ + if (cflag & CBAUDEX) { + /* + * The below code is trying to guarantee that only baud rates + * 115200 and 230400 are remapped. We use exclusive or because + * the various baud rates share common bit positions and + * therefore can't be tested for easily. + */ + if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || + (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) + res += 1; + } + return res; +} + +/* Caller must hold the locks */ +static void epcaparam(struct tty_struct *tty, struct channel *ch) +{ + unsigned int cmdHead; + struct ktermios *ts; + struct board_chan __iomem *bc; + unsigned mval, hflow, cflag, iflag; + + bc = ch->brdchan; + epcaassert(bc != NULL, "bc out of range"); + + assertgwinon(ch); + ts = tty->termios; + if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ + cmdHead = readw(&bc->rin); + writew(cmdHead, &bc->rout); + cmdHead = readw(&bc->tin); + /* Changing baud in mid-stream transmission can be wonderful */ + /* + * Flush current transmit buffer by setting cmdTail pointer + * (tout) to cmdHead pointer (tin). Hopefully the transmit + * buffer is empty. + */ + fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); + mval = 0; + } else { /* Begin CBAUD not detected */ + /* + * c_cflags have changed but that change had nothing to do with + * BAUD. Propagate the change to the card. + */ + cflag = termios2digi_c(ch, ts->c_cflag); + if (cflag != ch->fepcflag) { + ch->fepcflag = cflag; + /* Set baud rate, char size, stop bits, parity */ + fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); + } + /* + * If the user has not forced CLOCAL and if the device is not a + * CALLOUT device (Which is always CLOCAL) we set flags such + * that the driver will wait on carrier detect. + */ + if (ts->c_cflag & CLOCAL) + clear_bit(ASYNCB_CHECK_CD, &ch->port.flags); + else + set_bit(ASYNCB_CHECK_CD, &ch->port.flags); + mval = ch->m_dtr | ch->m_rts; + } /* End CBAUD not detected */ + iflag = termios2digi_i(ch, ts->c_iflag); + /* Check input mode flags */ + if (iflag != ch->fepiflag) { + ch->fepiflag = iflag; + /* + * Command sets channels iflag structure on the board. Such + * things as input soft flow control, handling of parity + * errors, and break handling are all set here. + * + * break handling, parity handling, input stripping, + * flow control chars + */ + fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); + } + /* + * Set the board mint value for this channel. This will cause hardware + * events to be generated each time the DCD signal (Described in mint) + * changes. + */ + writeb(ch->dcd, &bc->mint); + if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) + if (ch->digiext.digi_flags & DIGI_FORCEDCD) + writeb(0, &bc->mint); + ch->imodem = readb(&bc->mstat); + hflow = termios2digi_h(ch, ts->c_cflag); + if (hflow != ch->hflow) { + ch->hflow = hflow; + /* + * Hard flow control has been selected but the board is not + * using it. Activate hard flow control now. + */ + fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); + } + mval ^= ch->modemfake & (mval ^ ch->modem); + + if (ch->omodem ^ mval) { + ch->omodem = mval; + /* + * The below command sets the DTR and RTS mstat structure. If + * hard flow control is NOT active these changes will drive the + * output of the actual DTR and RTS lines. If hard flow control + * is active, the changes will be saved in the mstat structure + * and only asserted when hard flow control is turned off. + */ + + /* First reset DTR & RTS; then set them */ + fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); + fepcmd(ch, SETMODEM, mval, 0, 0, 1); + } + if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) { + ch->fepstartc = ch->startc; + ch->fepstopc = ch->stopc; + /* + * The XON / XOFF characters have changed; propagate these + * changes to the card. + */ + fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); + } + if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) { + ch->fepstartca = ch->startca; + ch->fepstopca = ch->stopca; + /* + * Similar to the above, this time the auxilarly XON / XOFF + * characters have changed; propagate these changes to the card. + */ + fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); + } +} + +/* Caller holds lock */ +static void receive_data(struct channel *ch, struct tty_struct *tty) +{ + unchar *rptr; + struct ktermios *ts = NULL; + struct board_chan __iomem *bc; + int dataToRead, wrapgap, bytesAvailable; + unsigned int tail, head; + unsigned int wrapmask; + + /* + * This routine is called by doint when a receive data event has taken + * place. + */ + globalwinon(ch); + if (ch->statusflags & RXSTOPPED) + return; + if (tty) + ts = tty->termios; + bc = ch->brdchan; + BUG_ON(!bc); + wrapmask = ch->rxbufsize - 1; + + /* + * Get the head and tail pointers to the receiver queue. Wrap the head + * pointer if it has reached the end of the buffer. + */ + head = readw(&bc->rin); + head &= wrapmask; + tail = readw(&bc->rout) & wrapmask; + + bytesAvailable = (head - tail) & wrapmask; + if (bytesAvailable == 0) + return; + + /* If CREAD bit is off or device not open, set TX tail to head */ + if (!tty || !ts || !(ts->c_cflag & CREAD)) { + writew(head, &bc->rout); + return; + } + + if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0) + return; + + if (readb(&bc->orun)) { + writeb(0, &bc->orun); + printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n", + tty->name); + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + rxwinon(ch); + while (bytesAvailable > 0) { + /* Begin while there is data on the card */ + wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; + /* + * Even if head has wrapped around only report the amount of + * data to be equal to the size - tail. Remember memcpy can't + * automaticly wrap around the receive buffer. + */ + dataToRead = (wrapgap < bytesAvailable) ? wrapgap + : bytesAvailable; + /* Make sure we don't overflow the buffer */ + dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead); + if (dataToRead == 0) + break; + /* + * Move data read from our card into the line disciplines + * buffer for translation if necessary. + */ + memcpy_fromio(rptr, ch->rxptr + tail, dataToRead); + tail = (tail + dataToRead) & wrapmask; + bytesAvailable -= dataToRead; + } /* End while there is data on the card */ + globalwinon(ch); + writew(tail, &bc->rout); + /* Must be called with global data */ + tty_schedule_flip(tty); +} + +static int info_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case DIGI_GETINFO: + { + struct digi_info di; + int brd; + + if (get_user(brd, (unsigned int __user *)arg)) + return -EFAULT; + if (brd < 0 || brd >= num_cards || num_cards == 0) + return -ENODEV; + + memset(&di, 0, sizeof(di)); + + di.board = brd; + di.status = boards[brd].status; + di.type = boards[brd].type ; + di.numports = boards[brd].numports ; + /* Legacy fixups - just move along nothing to see */ + di.port = (unsigned char *)boards[brd].port ; + di.membase = (unsigned char *)boards[brd].membase ; + + if (copy_to_user((void __user *)arg, &di, sizeof(di))) + return -EFAULT; + break; + + } + + case DIGI_POLLER: + { + int brd = arg & 0xff000000 >> 16; + unsigned char state = arg & 0xff; + + if (brd < 0 || brd >= num_cards) { + printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n"); + return -ENODEV; + } + digi_poller_inhibited = state; + break; + } + + case DIGI_INIT: + { + /* + * This call is made by the apps to complete the + * initialization of the board(s). This routine is + * responsible for setting the card to its initial + * state and setting the drivers control fields to the + * sutianle settings for the card in question. + */ + int crd; + for (crd = 0; crd < num_cards; crd++) + post_fep_init(crd); + break; + } + default: + return -ENOTTY; + } + return 0; +} + +static int pc_tiocmget(struct tty_struct *tty) +{ + struct channel *ch = tty->driver_data; + struct board_chan __iomem *bc; + unsigned int mstat, mflag = 0; + unsigned long flags; + + if (ch) + bc = ch->brdchan; + else + return -EINVAL; + + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + mstat = readb(&bc->mstat); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + + if (mstat & ch->m_dtr) + mflag |= TIOCM_DTR; + if (mstat & ch->m_rts) + mflag |= TIOCM_RTS; + if (mstat & ch->m_cts) + mflag |= TIOCM_CTS; + if (mstat & ch->dsr) + mflag |= TIOCM_DSR; + if (mstat & ch->m_ri) + mflag |= TIOCM_RI; + if (mstat & ch->dcd) + mflag |= TIOCM_CD; + return mflag; +} + +static int pc_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct channel *ch = tty->driver_data; + unsigned long flags; + + if (!ch) + return -EINVAL; + + spin_lock_irqsave(&epca_lock, flags); + /* + * I think this modemfake stuff is broken. It doesn't correctly reflect + * the behaviour desired by the TIOCM* ioctls. Therefore this is + * probably broken. + */ + if (set & TIOCM_RTS) { + ch->modemfake |= ch->m_rts; + ch->modem |= ch->m_rts; + } + if (set & TIOCM_DTR) { + ch->modemfake |= ch->m_dtr; + ch->modem |= ch->m_dtr; + } + if (clear & TIOCM_RTS) { + ch->modemfake |= ch->m_rts; + ch->modem &= ~ch->m_rts; + } + if (clear & TIOCM_DTR) { + ch->modemfake |= ch->m_dtr; + ch->modem &= ~ch->m_dtr; + } + globalwinon(ch); + /* + * The below routine generally sets up parity, baud, flow control + * issues, etc.... It effect both control flags and input flags. + */ + epcaparam(tty, ch); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + return 0; +} + +static int pc_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + digiflow_t dflow; + unsigned long flags; + unsigned int mflag, mstat; + unsigned char startc, stopc; + struct board_chan __iomem *bc; + struct channel *ch = tty->driver_data; + void __user *argp = (void __user *)arg; + + if (ch) + bc = ch->brdchan; + else + return -EINVAL; + switch (cmd) { + case TIOCMODG: + mflag = pc_tiocmget(tty); + if (put_user(mflag, (unsigned long __user *)argp)) + return -EFAULT; + break; + case TIOCMODS: + if (get_user(mstat, (unsigned __user *)argp)) + return -EFAULT; + return pc_tiocmset(tty, mstat, ~mstat); + case TIOCSDTR: + spin_lock_irqsave(&epca_lock, flags); + ch->omodem |= ch->m_dtr; + globalwinon(ch); + fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + break; + + case TIOCCDTR: + spin_lock_irqsave(&epca_lock, flags); + ch->omodem &= ~ch->m_dtr; + globalwinon(ch); + fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + break; + case DIGI_GETA: + if (copy_to_user(argp, &ch->digiext, sizeof(digi_t))) + return -EFAULT; + break; + case DIGI_SETAW: + case DIGI_SETAF: + if (cmd == DIGI_SETAW) { + /* Setup an event to indicate when the transmit + buffer empties */ + spin_lock_irqsave(&epca_lock, flags); + setup_empty_event(tty, ch); + spin_unlock_irqrestore(&epca_lock, flags); + tty_wait_until_sent(tty, 0); + } else { + /* ldisc lock already held in ioctl */ + if (tty->ldisc->ops->flush_buffer) + tty->ldisc->ops->flush_buffer(tty); + } + /* Fall Thru */ + case DIGI_SETA: + if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) + return -EFAULT; + + if (ch->digiext.digi_flags & DIGI_ALTPIN) { + ch->dcd = ch->m_dsr; + ch->dsr = ch->m_dcd; + } else { + ch->dcd = ch->m_dcd; + ch->dsr = ch->m_dsr; + } + + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + + /* + * The below routine generally sets up parity, baud, flow + * control issues, etc.... It effect both control flags and + * input flags. + */ + epcaparam(tty, ch); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + break; + + case DIGI_GETFLOW: + case DIGI_GETAFLOW: + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + if (cmd == DIGI_GETFLOW) { + dflow.startc = readb(&bc->startc); + dflow.stopc = readb(&bc->stopc); + } else { + dflow.startc = readb(&bc->startca); + dflow.stopc = readb(&bc->stopca); + } + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + + if (copy_to_user(argp, &dflow, sizeof(dflow))) + return -EFAULT; + break; + + case DIGI_SETAFLOW: + case DIGI_SETFLOW: + if (cmd == DIGI_SETFLOW) { + startc = ch->startc; + stopc = ch->stopc; + } else { + startc = ch->startca; + stopc = ch->stopca; + } + + if (copy_from_user(&dflow, argp, sizeof(dflow))) + return -EFAULT; + + if (dflow.startc != startc || dflow.stopc != stopc) { + /* Begin if setflow toggled */ + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + + if (cmd == DIGI_SETFLOW) { + ch->fepstartc = ch->startc = dflow.startc; + ch->fepstopc = ch->stopc = dflow.stopc; + fepcmd(ch, SONOFFC, ch->fepstartc, + ch->fepstopc, 0, 1); + } else { + ch->fepstartca = ch->startca = dflow.startc; + ch->fepstopca = ch->stopca = dflow.stopc; + fepcmd(ch, SAUXONOFFC, ch->fepstartca, + ch->fepstopca, 0, 1); + } + + if (ch->statusflags & TXSTOPPED) + pc_start(tty); + + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + } /* End if setflow toggled */ + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct channel *ch; + unsigned long flags; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + + if (ch != NULL) { /* Begin if channel valid */ + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + epcaparam(tty, ch); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + + if ((old_termios->c_cflag & CRTSCTS) && + ((tty->termios->c_cflag & CRTSCTS) == 0)) + tty->hw_stopped = 0; + + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&ch->port.open_wait); + + } /* End if channel valid */ +} + +static void do_softint(struct work_struct *work) +{ + struct channel *ch = container_of(work, struct channel, tqueue); + /* Called in response to a modem change event */ + if (ch && ch->magic == EPCA_MAGIC) { + struct tty_struct *tty = tty_port_tty_get(&ch->port); + + if (tty && tty->driver_data) { + if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { + tty_hangup(tty); + wake_up_interruptible(&ch->port.open_wait); + clear_bit(ASYNCB_NORMAL_ACTIVE, + &ch->port.flags); + } + } + tty_kref_put(tty); + } +} + +/* + * pc_stop and pc_start provide software flow control to the routine and the + * pc_ioctl routine. + */ +static void pc_stop(struct tty_struct *tty) +{ + struct channel *ch; + unsigned long flags; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + spin_lock_irqsave(&epca_lock, flags); + if ((ch->statusflags & TXSTOPPED) == 0) { + /* Begin if transmit stop requested */ + globalwinon(ch); + /* STOP transmitting now !! */ + fepcmd(ch, PAUSETX, 0, 0, 0, 0); + ch->statusflags |= TXSTOPPED; + memoff(ch); + } /* End if transmit stop requested */ + spin_unlock_irqrestore(&epca_lock, flags); + } +} + +static void pc_start(struct tty_struct *tty) +{ + struct channel *ch; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + unsigned long flags; + spin_lock_irqsave(&epca_lock, flags); + /* Just in case output was resumed because of a change + in Digi-flow */ + if (ch->statusflags & TXSTOPPED) { + /* Begin transmit resume requested */ + struct board_chan __iomem *bc; + globalwinon(ch); + bc = ch->brdchan; + if (ch->statusflags & LOWWAIT) + writeb(1, &bc->ilow); + /* Okay, you can start transmitting again... */ + fepcmd(ch, RESUMETX, 0, 0, 0, 0); + ch->statusflags &= ~TXSTOPPED; + memoff(ch); + } /* End transmit resume requested */ + spin_unlock_irqrestore(&epca_lock, flags); + } +} + +/* + * The below routines pc_throttle and pc_unthrottle are used to slow (And + * resume) the receipt of data into the kernels receive buffers. The exact + * occurrence of this depends on the size of the kernels receive buffer and + * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for + * more details. + */ +static void pc_throttle(struct tty_struct *tty) +{ + struct channel *ch; + unsigned long flags; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + spin_lock_irqsave(&epca_lock, flags); + if ((ch->statusflags & RXSTOPPED) == 0) { + globalwinon(ch); + fepcmd(ch, PAUSERX, 0, 0, 0, 0); + ch->statusflags |= RXSTOPPED; + memoff(ch); + } + spin_unlock_irqrestore(&epca_lock, flags); + } +} + +static void pc_unthrottle(struct tty_struct *tty) +{ + struct channel *ch; + unsigned long flags; + /* + * verifyChannel returns the channel from the tty struct if it is + * valid. This serves as a sanity check. + */ + ch = verifyChannel(tty); + if (ch != NULL) { + /* Just in case output was resumed because of a change + in Digi-flow */ + spin_lock_irqsave(&epca_lock, flags); + if (ch->statusflags & RXSTOPPED) { + globalwinon(ch); + fepcmd(ch, RESUMERX, 0, 0, 0, 0); + ch->statusflags &= ~RXSTOPPED; + memoff(ch); + } + spin_unlock_irqrestore(&epca_lock, flags); + } +} + +static int pc_send_break(struct tty_struct *tty, int msec) +{ + struct channel *ch = tty->driver_data; + unsigned long flags; + + if (msec == -1) + msec = 0xFFFF; + else if (msec > 0xFFFE) + msec = 0xFFFE; + else if (msec < 1) + msec = 1; + + spin_lock_irqsave(&epca_lock, flags); + globalwinon(ch); + /* + * Maybe I should send an infinite break here, schedule() for msec + * amount of time, and then stop the break. This way, the user can't + * screw up the FEP by causing digi_send_break() to be called (i.e. via + * an ioctl()) more than once in msec amount of time. + * Try this for now... + */ + fepcmd(ch, SENDBREAK, msec, 0, 10, 0); + memoff(ch); + spin_unlock_irqrestore(&epca_lock, flags); + return 0; +} + +/* Caller MUST hold the lock */ +static void setup_empty_event(struct tty_struct *tty, struct channel *ch) +{ + struct board_chan __iomem *bc = ch->brdchan; + + globalwinon(ch); + ch->statusflags |= EMPTYWAIT; + /* + * When set the iempty flag request a event to be generated when the + * transmit buffer is empty (If there is no BREAK in progress). + */ + writeb(1, &bc->iempty); + memoff(ch); +} + +#ifndef MODULE +static void __init epca_setup(char *str, int *ints) +{ + struct board_info board; + int index, loop, last; + char *temp, *t2; + unsigned len; + + /* + * If this routine looks a little strange it is because it is only + * called if a LILO append command is given to boot the kernel with + * parameters. In this way, we can provide the user a method of + * changing his board configuration without rebuilding the kernel. + */ + if (!liloconfig) + liloconfig = 1; + + memset(&board, 0, sizeof(board)); + + /* Assume the data is int first, later we can change it */ + /* I think that array position 0 of ints holds the number of args */ + for (last = 0, index = 1; index <= ints[0]; index++) + switch (index) { /* Begin parse switch */ + case 1: + board.status = ints[index]; + /* + * We check for 2 (As opposed to 1; because 2 is a flag + * instructing the driver to ignore epcaconfig.) For + * this reason we check for 2. + */ + if (board.status == 2) { + /* Begin ignore epcaconfig as well as lilo cmd line */ + nbdevs = 0; + num_cards = 0; + return; + } /* End ignore epcaconfig as well as lilo cmd line */ + + if (board.status > 2) { + printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", + board.status); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_STATUS; + return; + } + last = index; + break; + case 2: + board.type = ints[index]; + if (board.type >= PCIXEM) { + printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_TYPE; + return; + } + last = index; + break; + case 3: + board.altpin = ints[index]; + if (board.altpin > 1) { + printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin); + invalid_lilo_config = 1; + setup_error_code |= INVALID_ALTPIN; + return; + } + last = index; + break; + + case 4: + board.numports = ints[index]; + if (board.numports < 2 || board.numports > 256) { + printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports); + invalid_lilo_config = 1; + setup_error_code |= INVALID_NUM_PORTS; + return; + } + nbdevs += board.numports; + last = index; + break; + + case 5: + board.port = ints[index]; + if (ints[index] <= 0) { + printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); + invalid_lilo_config = 1; + setup_error_code |= INVALID_PORT_BASE; + return; + } + last = index; + break; + + case 6: + board.membase = ints[index]; + if (ints[index] <= 0) { + printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n", + (unsigned int)board.membase); + invalid_lilo_config = 1; + setup_error_code |= INVALID_MEM_BASE; + return; + } + last = index; + break; + + default: + printk(KERN_ERR " - epca_setup: Too many integer parms\n"); + return; + + } /* End parse switch */ + + while (str && *str) { /* Begin while there is a string arg */ + /* find the next comma or terminator */ + temp = str; + /* While string is not null, and a comma hasn't been found */ + while (*temp && (*temp != ',')) + temp++; + if (!*temp) + temp = NULL; + else + *temp++ = 0; + /* Set index to the number of args + 1 */ + index = last + 1; + + switch (index) { + case 1: + len = strlen(str); + if (strncmp("Disable", str, len) == 0) + board.status = 0; + else if (strncmp("Enable", str, len) == 0) + board.status = 1; + else { + printk(KERN_ERR "epca_setup: Invalid status %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_STATUS; + return; + } + last = index; + break; + + case 2: + for (loop = 0; loop < EPCA_NUM_TYPES; loop++) + if (strcmp(board_desc[loop], str) == 0) + break; + /* + * If the index incremented above refers to a + * legitamate board type set it here. + */ + if (index < EPCA_NUM_TYPES) + board.type = loop; + else { + printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_TYPE; + return; + } + last = index; + break; + + case 3: + len = strlen(str); + if (strncmp("Disable", str, len) == 0) + board.altpin = 0; + else if (strncmp("Enable", str, len) == 0) + board.altpin = 1; + else { + printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_ALTPIN; + return; + } + last = index; + break; + + case 4: + t2 = str; + while (isdigit(*t2)) + t2++; + + if (*t2) { + printk(KERN_ERR "epca_setup: Invalid port count %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_NUM_PORTS; + return; + } + + /* + * There is not a man page for simple_strtoul but the + * code can be found in vsprintf.c. The first argument + * is the string to translate (To an unsigned long + * obviously), the second argument can be the address + * of any character variable or a NULL. If a variable + * is given, the end pointer of the string will be + * stored in that variable; if a NULL is given the end + * pointer will not be returned. The last argument is + * the base to use. If a 0 is indicated, the routine + * will attempt to determine the proper base by looking + * at the values prefix (A '0' for octal, a 'x' for + * hex, etc ... If a value is given it will use that + * value as the base. + */ + board.numports = simple_strtoul(str, NULL, 0); + nbdevs += board.numports; + last = index; + break; + + case 5: + t2 = str; + while (isxdigit(*t2)) + t2++; + + if (*t2) { + printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_PORT_BASE; + return; + } + + board.port = simple_strtoul(str, NULL, 16); + last = index; + break; + + case 6: + t2 = str; + while (isxdigit(*t2)) + t2++; + + if (*t2) { + printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_MEM_BASE; + return; + } + board.membase = simple_strtoul(str, NULL, 16); + last = index; + break; + default: + printk(KERN_ERR "epca: Too many string parms\n"); + return; + } + str = temp; + } /* End while there is a string arg */ + + if (last < 6) { + printk(KERN_ERR "epca: Insufficient parms specified\n"); + return; + } + + /* I should REALLY validate the stuff here */ + /* Copies our local copy of board into boards */ + memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board)); + /* Does this get called once per lilo arg are what ? */ + printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", + num_cards, board_desc[board.type], + board.numports, (int)board.port, (unsigned int) board.membase); + num_cards++; +} + +static int __init epca_real_setup(char *str) +{ + int ints[11]; + + epca_setup(get_options(str, 11, ints), ints); + return 1; +} + +__setup("digiepca", epca_real_setup); +#endif + +enum epic_board_types { + brd_xr = 0, + brd_xem, + brd_cx, + brd_xrj, +}; + +/* indexed directly by epic_board_types enum */ +static struct { + unsigned char board_type; + unsigned bar_idx; /* PCI base address region */ +} epca_info_tbl[] = { + { PCIXR, 0, }, + { PCIXEM, 0, }, + { PCICX, 0, }, + { PCIXRJ, 2, }, +}; + +static int __devinit epca_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + static int board_num = -1; + int board_idx, info_idx = ent->driver_data; + unsigned long addr; + + if (pci_enable_device(pdev)) + return -EIO; + + board_num++; + board_idx = board_num + num_cards; + if (board_idx >= MAXBOARDS) + goto err_out; + + addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx); + if (!addr) { + printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n", + epca_info_tbl[info_idx].bar_idx); + goto err_out; + } + + boards[board_idx].status = ENABLED; + boards[board_idx].type = epca_info_tbl[info_idx].board_type; + boards[board_idx].numports = 0x0; + boards[board_idx].port = addr + PCI_IO_OFFSET; + boards[board_idx].membase = addr; + + if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) { + printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", + 0x200000, addr + PCI_IO_OFFSET); + goto err_out; + } + + boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET, + 0x200000); + if (!boards[board_idx].re_map_port) { + printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", + 0x200000, addr + PCI_IO_OFFSET); + goto err_out_free_pciio; + } + + if (!request_mem_region(addr, 0x200000, "epca")) { + printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", + 0x200000, addr); + goto err_out_free_iounmap; + } + + boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000); + if (!boards[board_idx].re_map_membase) { + printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", + 0x200000, addr + PCI_IO_OFFSET); + goto err_out_free_memregion; + } + + /* + * I don't know what the below does, but the hardware guys say its + * required on everything except PLX (In this case XRJ). + */ + if (info_idx != brd_xrj) { + pci_write_config_byte(pdev, 0x40, 0); + pci_write_config_byte(pdev, 0x46, 0); + } + + return 0; + +err_out_free_memregion: + release_mem_region(addr, 0x200000); +err_out_free_iounmap: + iounmap(boards[board_idx].re_map_port); +err_out_free_pciio: + release_mem_region(addr + PCI_IO_OFFSET, 0x200000); +err_out: + return -ENODEV; +} + + +static struct pci_device_id epca_pci_tbl[] = { + { PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr }, + { PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem }, + { PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx }, + { PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, epca_pci_tbl); + +static int __init init_PCI(void) +{ + memset(&epca_driver, 0, sizeof(epca_driver)); + epca_driver.name = "epca"; + epca_driver.id_table = epca_pci_tbl; + epca_driver.probe = epca_init_one; + + return pci_register_driver(&epca_driver); +} + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/tty/epca.h b/drivers/staging/tty/epca.h new file mode 100644 index 000000000000..d414bf2dbf7c --- /dev/null +++ b/drivers/staging/tty/epca.h @@ -0,0 +1,158 @@ +#define XEMPORTS 0xC02 +#define XEPORTS 0xC22 + +#define MAX_ALLOC 0x100 + +#define MAXBOARDS 12 +#define FEPCODESEG 0x0200L +#define FEPCODE 0x2000L +#define BIOSCODE 0xf800L + +#define MISCGLOBAL 0x0C00L +#define NPORT 0x0C22L +#define MBOX 0x0C40L +#define PORTBASE 0x0C90L + +/* Begin code defines used for epca_setup */ + +#define INVALID_BOARD_TYPE 0x1 +#define INVALID_NUM_PORTS 0x2 +#define INVALID_MEM_BASE 0x4 +#define INVALID_PORT_BASE 0x8 +#define INVALID_BOARD_STATUS 0x10 +#define INVALID_ALTPIN 0x20 + +/* End code defines used for epca_setup */ + + +#define FEPCLR 0x00 +#define FEPMEM 0x02 +#define FEPRST 0x04 +#define FEPINT 0x08 +#define FEPMASK 0x0e +#define FEPWIN 0x80 + +#define PCXE 0 +#define PCXEVE 1 +#define PCXEM 2 +#define EISAXEM 3 +#define PC64XE 4 +#define PCXI 5 +#define PCIXEM 7 +#define PCICX 8 +#define PCIXR 9 +#define PCIXRJ 10 +#define EPCA_NUM_TYPES 6 + + +static char *board_desc[] = +{ + "PC/Xe", + "PC/Xeve", + "PC/Xem", + "EISA/Xem", + "PC/64Xe", + "PC/Xi", + "unknown", + "PCI/Xem", + "PCI/CX", + "PCI/Xr", + "PCI/Xrj", +}; + +#define STARTC 021 +#define STOPC 023 +#define IAIXON 0x2000 + + +#define TXSTOPPED 0x1 +#define LOWWAIT 0x2 +#define EMPTYWAIT 0x4 +#define RXSTOPPED 0x8 +#define TXBUSY 0x10 + +#define DISABLED 0 +#define ENABLED 1 +#define OFF 0 +#define ON 1 + +#define FEPTIMEOUT 200000 +#define SERIAL_TYPE_INFO 3 +#define EPCA_EVENT_HANGUP 1 +#define EPCA_MAGIC 0x5c6df104L + +struct channel +{ + long magic; + struct tty_port port; + unsigned char boardnum; + unsigned char channelnum; + unsigned char omodem; /* FEP output modem status */ + unsigned char imodem; /* FEP input modem status */ + unsigned char modemfake; /* Modem values to be forced */ + unsigned char modem; /* Force values */ + unsigned char hflow; + unsigned char dsr; + unsigned char dcd; + unsigned char m_rts ; /* The bits used in whatever FEP */ + unsigned char m_dcd ; /* is indiginous to this board to */ + unsigned char m_dsr ; /* represent each of the physical */ + unsigned char m_cts ; /* handshake lines */ + unsigned char m_ri ; + unsigned char m_dtr ; + unsigned char stopc; + unsigned char startc; + unsigned char stopca; + unsigned char startca; + unsigned char fepstopc; + unsigned char fepstartc; + unsigned char fepstopca; + unsigned char fepstartca; + unsigned char txwin; + unsigned char rxwin; + unsigned short fepiflag; + unsigned short fepcflag; + unsigned short fepoflag; + unsigned short txbufhead; + unsigned short txbufsize; + unsigned short rxbufhead; + unsigned short rxbufsize; + int close_delay; + unsigned long event; + uint dev; + unsigned long statusflags; + unsigned long c_iflag; + unsigned long c_cflag; + unsigned long c_lflag; + unsigned long c_oflag; + unsigned char __iomem *txptr; + unsigned char __iomem *rxptr; + struct board_info *board; + struct board_chan __iomem *brdchan; + struct digi_struct digiext; + struct work_struct tqueue; + struct global_data __iomem *mailbox; +}; + +struct board_info +{ + unsigned char status; + unsigned char type; + unsigned char altpin; + unsigned short numports; + unsigned long port; + unsigned long membase; + void __iomem *re_map_port; + void __iomem *re_map_membase; + unsigned long memory_seg; + void ( * memwinon ) (struct board_info *, unsigned int) ; + void ( * memwinoff ) (struct board_info *, unsigned int) ; + void ( * globalwinon ) (struct channel *) ; + void ( * txwinon ) (struct channel *) ; + void ( * rxwinon ) (struct channel *) ; + void ( * memoff ) (struct channel *) ; + void ( * assertgwinon ) (struct channel *) ; + void ( * assertmemoff ) (struct channel *) ; + unsigned char poller_inhibited ; +}; + diff --git a/drivers/staging/tty/epcaconfig.h b/drivers/staging/tty/epcaconfig.h new file mode 100644 index 000000000000..55dec067078e --- /dev/null +++ b/drivers/staging/tty/epcaconfig.h @@ -0,0 +1,7 @@ +#define NUMCARDS 0 +#define NBDEVS 0 + +struct board_info static_boards[NUMCARDS]={ +}; + +/* DO NOT HAND EDIT THIS FILE! */ diff --git a/drivers/staging/tty/ip2/Makefile b/drivers/staging/tty/ip2/Makefile new file mode 100644 index 000000000000..7b78e0dfc5b0 --- /dev/null +++ b/drivers/staging/tty/ip2/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Computone IntelliPort Plus Driver +# + +obj-$(CONFIG_COMPUTONE) += ip2.o + +ip2-y := ip2main.o + diff --git a/drivers/staging/tty/ip2/i2cmd.c b/drivers/staging/tty/ip2/i2cmd.c new file mode 100644 index 000000000000..e7af647800b6 --- /dev/null +++ b/drivers/staging/tty/ip2/i2cmd.c @@ -0,0 +1,210 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Definition table for In-line and Bypass commands. Applicable +* only when the standard loadware is active. (This is included +* source code, not a separate compilation module.) +* +*******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Revision History: +// +// 10 October 1991 MAG First Draft +// 7 November 1991 MAG Reflects additional commands. +// 24 February 1992 MAG Additional commands for 1.4.x loadware +// 11 March 1992 MAG Additional commands +// 30 March 1992 MAG Additional command: CMD_DSS_NOW +// 18 May 1992 MAG Discovered commands 39 & 40 must be at the end of a +// packet: affects implementation. +//------------------------------------------------------------------------------ + +//************ +//* Includes * +//************ + +#include "i2cmd.h" /* To get some bit-defines */ + +//------------------------------------------------------------------------------ +// Here is the table of global arrays which represent each type of command +// supported in the IntelliPort standard loadware. See also i2cmd.h +// for a more complete explanation of what is going on. +//------------------------------------------------------------------------------ + +// Here are the various globals: note that the names are not used except through +// the macros defined in i2cmd.h. Also note that although they are character +// arrays here (for extendability) they are cast to structure pointers in the +// i2cmd.h macros. See i2cmd.h for flags definitions. + +// Length Flags Command +static UCHAR ct02[] = { 1, BTH, 0x02 }; // DTR UP +static UCHAR ct03[] = { 1, BTH, 0x03 }; // DTR DN +static UCHAR ct04[] = { 1, BTH, 0x04 }; // RTS UP +static UCHAR ct05[] = { 1, BTH, 0x05 }; // RTS DN +static UCHAR ct06[] = { 1, BYP, 0x06 }; // START FL +static UCHAR ct07[] = { 2, BTH, 0x07,0 }; // BAUD +static UCHAR ct08[] = { 2, BTH, 0x08,0 }; // BITS +static UCHAR ct09[] = { 2, BTH, 0x09,0 }; // STOP +static UCHAR ct10[] = { 2, BTH, 0x0A,0 }; // PARITY +static UCHAR ct11[] = { 2, BTH, 0x0B,0 }; // XON +static UCHAR ct12[] = { 2, BTH, 0x0C,0 }; // XOFF +static UCHAR ct13[] = { 1, BTH, 0x0D }; // STOP FL +static UCHAR ct14[] = { 1, BYP|VIP, 0x0E }; // ACK HOTK +//static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0 }; // IRQ SET +static UCHAR ct16[] = { 2, INL, 0x10,0 }; // IXONOPTS +static UCHAR ct17[] = { 2, INL, 0x11,0 }; // OXONOPTS +static UCHAR ct18[] = { 1, INL, 0x12 }; // CTSENAB +static UCHAR ct19[] = { 1, BTH, 0x13 }; // CTSDSAB +static UCHAR ct20[] = { 1, INL, 0x14 }; // DCDENAB +static UCHAR ct21[] = { 1, BTH, 0x15 }; // DCDDSAB +static UCHAR ct22[] = { 1, BTH, 0x16 }; // DSRENAB +static UCHAR ct23[] = { 1, BTH, 0x17 }; // DSRDSAB +static UCHAR ct24[] = { 1, BTH, 0x18 }; // RIENAB +static UCHAR ct25[] = { 1, BTH, 0x19 }; // RIDSAB +static UCHAR ct26[] = { 2, BTH, 0x1A,0 }; // BRKENAB +static UCHAR ct27[] = { 1, BTH, 0x1B }; // BRKDSAB +//static UCHAR ct28[]={ 2, BTH, 0x1C,0 }; // MAXBLOKSIZE +//static UCHAR ct29[]={ 2, 0, 0x1D,0 }; // reserved +static UCHAR ct30[] = { 1, INL, 0x1E }; // CTSFLOWENAB +static UCHAR ct31[] = { 1, INL, 0x1F }; // CTSFLOWDSAB +static UCHAR ct32[] = { 1, INL, 0x20 }; // RTSFLOWENAB +static UCHAR ct33[] = { 1, INL, 0x21 }; // RTSFLOWDSAB +static UCHAR ct34[] = { 2, BTH, 0x22,0 }; // ISTRIPMODE +static UCHAR ct35[] = { 2, BTH|END, 0x23,0 }; // SENDBREAK +static UCHAR ct36[] = { 2, BTH, 0x24,0 }; // SETERRMODE +//static UCHAR ct36a[]={ 3, INL, 0x24,0,0 }; // SET_REPLACE + +// The following is listed for completeness, but should never be sent directly +// by user-level code. It is sent only by library routines in response to data +// movement. +//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0 }; // FLOW PACKET + +// Back to normal +//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ +//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0 }; // OPOSTON +//static UCHAR ct40[]={ 1, BTH|END, 0x28 }; // OPOSTOFF +static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME +//static UCHAR ct42[]={ 2, BTH, 0x2A,0 }; // TXBAUD +//static UCHAR ct43[]={ 2, BTH, 0x2B,0 }; // RXBAUD +//static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING +//static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB +//static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB +//static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS +//static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB +//static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB +//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB +//static UCHAR ct51[]={ 1, BTH, 0x33 }; // DTRFLOWDSAB +//static UCHAR ct52[]={ 1, BTH, 0x34 }; // BAUDTABRESET +//static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP +static UCHAR ct54[] = { 3, BTH, 0x36,0,0 }; // CUSTOMBAUD1 +static UCHAR ct55[] = { 3, BTH, 0x37,0,0 }; // CUSTOMBAUD2 +static UCHAR ct56[] = { 2, BTH|END, 0x38,0 }; // PAUSE +static UCHAR ct57[] = { 1, BYP, 0x39 }; // SUSPEND +static UCHAR ct58[] = { 1, BYP, 0x3A }; // UNSUSPEND +static UCHAR ct59[] = { 2, BTH, 0x3B,0 }; // PARITYCHK +static UCHAR ct60[] = { 1, INL|VIP, 0x3C }; // BOOKMARKREQ +//static UCHAR ct61[]={ 2, BTH, 0x3D,0 }; // INTERNALLOOP +//static UCHAR ct62[]={ 2, BTH, 0x3E,0 }; // HOTKTIMEOUT +static UCHAR ct63[] = { 2, INL, 0x3F,0 }; // SETTXON +static UCHAR ct64[] = { 2, INL, 0x40,0 }; // SETTXOFF +//static UCHAR ct65[]={ 2, BTH, 0x41,0 }; // SETAUTORTS +//static UCHAR ct66[]={ 2, BTH, 0x42,0 }; // SETHIGHWAT +//static UCHAR ct67[]={ 2, BYP, 0x43,0 }; // STARTSELFL +//static UCHAR ct68[]={ 2, INL, 0x44,0 }; // ENDSELFL +//static UCHAR ct69[]={ 1, BYP, 0x45 }; // HWFLOW_OFF +//static UCHAR ct70[]={ 1, BTH, 0x46 }; // ODSRFL_ENAB +//static UCHAR ct71[]={ 1, BTH, 0x47 }; // ODSRFL_DSAB +//static UCHAR ct72[]={ 1, BTH, 0x48 }; // ODCDFL_ENAB +//static UCHAR ct73[]={ 1, BTH, 0x49 }; // ODCDFL_DSAB +//static UCHAR ct74[]={ 2, BTH, 0x4A,0 }; // LOADLEVEL +//static UCHAR ct75[]={ 2, BTH, 0x4B,0 }; // STATDATA +//static UCHAR ct76[]={ 1, BYP, 0x4C }; // BREAK_ON +//static UCHAR ct77[]={ 1, BYP, 0x4D }; // BREAK_OFF +//static UCHAR ct78[]={ 1, BYP, 0x4E }; // GETFC +static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW +//static UCHAR ct80[]={ 4, BTH, 0x50,0,0,0 }; // DIVISOR_LATCH +//static UCHAR ct81[]={ 1, BYP, 0x51 }; // GET_STATUS +//static UCHAR ct82[]={ 1, BYP, 0x52 }; // GET_TXCNT +//static UCHAR ct83[]={ 1, BYP, 0x53 }; // GET_RXCNT +//static UCHAR ct84[]={ 1, BYP, 0x54 }; // GET_BOXIDS +//static UCHAR ct85[]={10, BYP, 0x55,0,0,0,0,0,0,0,0,0 }; // ENAB_MULT +//static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE +static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST +//static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD +//static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO +//static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break + +// Some composite commands as well +//static UCHAR cc01[]={ 2, BTH, 0x02,0x04 }; // DTR & RTS UP +//static UCHAR cc02[]={ 2, BTH, 0x03,0x05 }; // DTR & RTS DN + +//******** +//* Code * +//******** + +//****************************************************************************** +// Function: i2cmdUnixFlags(iflag, cflag, lflag) +// Parameters: Unix tty flags +// +// Returns: Pointer to command structure +// +// Description: +// +// This routine sets the parameters of command 47 and returns a pointer to the +// appropriate structure. +//****************************************************************************** +#if 0 +cmdSyntaxPtr +i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) +{ + cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47; + + pCM->cmd[1] = (unsigned char) iflag; + pCM->cmd[2] = (unsigned char) (iflag >> 8); + pCM->cmd[3] = (unsigned char) cflag; + pCM->cmd[4] = (unsigned char) (cflag >> 8); + pCM->cmd[5] = (unsigned char) lflag; + pCM->cmd[6] = (unsigned char) (lflag >> 8); + return pCM; +} +#endif /* 0 */ + +//****************************************************************************** +// Function: i2cmdBaudDef(which, rate) +// Parameters: ? +// +// Returns: Pointer to command structure +// +// Description: +// +// This routine sets the parameters of commands 54 or 55 (according to the +// argument which), and returns a pointer to the appropriate structure. +//****************************************************************************** +static cmdSyntaxPtr +i2cmdBaudDef(int which, unsigned short rate) +{ + cmdSyntaxPtr pCM; + + switch(which) + { + case 1: + pCM = (cmdSyntaxPtr) ct54; + break; + default: + case 2: + pCM = (cmdSyntaxPtr) ct55; + break; + } + pCM->cmd[1] = (unsigned char) rate; + pCM->cmd[2] = (unsigned char) (rate >> 8); + return pCM; +} + diff --git a/drivers/staging/tty/ip2/i2cmd.h b/drivers/staging/tty/ip2/i2cmd.h new file mode 100644 index 000000000000..29277ec6b8ed --- /dev/null +++ b/drivers/staging/tty/ip2/i2cmd.h @@ -0,0 +1,630 @@ +/******************************************************************************* +* +* (c) 1999 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Definitions and support for In-line and Bypass commands. +* Applicable only when the standard loadware is active. +* +*******************************************************************************/ +//------------------------------------------------------------------------------ +// Revision History: +// +// 10 October 1991 MAG First Draft +// 7 November 1991 MAG Reflects some new commands +// 20 February 1992 MAG CMD_HOTACK corrected: no argument. +// 24 February 1992 MAG Support added for new commands for 1.4.x loadware. +// 11 March 1992 MAG Additional commands. +// 16 March 1992 MAG Additional commands. +// 30 March 1992 MAG Additional command: CMD_DSS_NOW +// 18 May 1992 MAG Changed CMD_OPOST +// +//------------------------------------------------------------------------------ +#ifndef I2CMD_H // To prevent multiple includes +#define I2CMD_H 1 + +#include "ip2types.h" + +// This module is designed to provide a uniform method of sending commands to +// the board through command packets. The difficulty is, some commands take +// parameters, others do not. Furthermore, it is often useful to send several +// commands to the same channel as part of the same packet. (See also i2pack.h.) +// +// This module is designed so that the caller should not be responsible for +// remembering the exact syntax of each command, or at least so that the +// compiler could check things somewhat. I'll explain as we go... +// +// First, a structure which can embody the syntax of each type of command. +// +typedef struct _cmdSyntax +{ + UCHAR length; // Number of bytes in the command + UCHAR flags; // Information about the command (see below) + + // The command and its parameters, which may be of arbitrary length. Don't + // worry yet how the parameters will be initialized; macros later take care + // of it. Also, don't worry about the arbitrary length issue; this structure + // is never used to allocate space (see i2cmd.c). + UCHAR cmd[2]; +} cmdSyntax, *cmdSyntaxPtr; + +// Bit assignments for flags + +#define INL 1 // Set if suitable for inline commands +#define BYP 2 // Set if suitable for bypass commands +#define BTH (INL|BYP) // suitable for either! +#define END 4 // Set if this must be the last command in a block +#define VIP 8 // Set if this command is special in some way and really + // should only be sent from the library-level and not + // directly from user-level +#define VAR 0x10 // This command is of variable length! + +// Declarations for the global arrays used to bear the commands and their +// arguments. +// +// Note: Since these are globals and the arguments might change, it is important +// that the library routine COPY these into buffers from whence they would be +// sent, rather than merely storing the pointers. In multi-threaded +// environments, important that the copy should obtain before any context switch +// is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND +// MORE THAN ONCE WITH THE SAME PARAMETERS in the same call. +// +static UCHAR ct02[]; +static UCHAR ct03[]; +static UCHAR ct04[]; +static UCHAR ct05[]; +static UCHAR ct06[]; +static UCHAR ct07[]; +static UCHAR ct08[]; +static UCHAR ct09[]; +static UCHAR ct10[]; +static UCHAR ct11[]; +static UCHAR ct12[]; +static UCHAR ct13[]; +static UCHAR ct14[]; +static UCHAR ct15[]; +static UCHAR ct16[]; +static UCHAR ct17[]; +static UCHAR ct18[]; +static UCHAR ct19[]; +static UCHAR ct20[]; +static UCHAR ct21[]; +static UCHAR ct22[]; +static UCHAR ct23[]; +static UCHAR ct24[]; +static UCHAR ct25[]; +static UCHAR ct26[]; +static UCHAR ct27[]; +static UCHAR ct28[]; +static UCHAR ct29[]; +static UCHAR ct30[]; +static UCHAR ct31[]; +static UCHAR ct32[]; +static UCHAR ct33[]; +static UCHAR ct34[]; +static UCHAR ct35[]; +static UCHAR ct36[]; +static UCHAR ct36a[]; +static UCHAR ct41[]; +static UCHAR ct42[]; +static UCHAR ct43[]; +static UCHAR ct44[]; +static UCHAR ct45[]; +static UCHAR ct46[]; +static UCHAR ct48[]; +static UCHAR ct49[]; +static UCHAR ct50[]; +static UCHAR ct51[]; +static UCHAR ct52[]; +static UCHAR ct56[]; +static UCHAR ct57[]; +static UCHAR ct58[]; +static UCHAR ct59[]; +static UCHAR ct60[]; +static UCHAR ct61[]; +static UCHAR ct62[]; +static UCHAR ct63[]; +static UCHAR ct64[]; +static UCHAR ct65[]; +static UCHAR ct66[]; +static UCHAR ct67[]; +static UCHAR ct68[]; +static UCHAR ct69[]; +static UCHAR ct70[]; +static UCHAR ct71[]; +static UCHAR ct72[]; +static UCHAR ct73[]; +static UCHAR ct74[]; +static UCHAR ct75[]; +static UCHAR ct76[]; +static UCHAR ct77[]; +static UCHAR ct78[]; +static UCHAR ct79[]; +static UCHAR ct80[]; +static UCHAR ct81[]; +static UCHAR ct82[]; +static UCHAR ct83[]; +static UCHAR ct84[]; +static UCHAR ct85[]; +static UCHAR ct86[]; +static UCHAR ct87[]; +static UCHAR ct88[]; +static UCHAR ct89[]; +static UCHAR ct90[]; +static UCHAR ct91[]; +static UCHAR cc01[]; +static UCHAR cc02[]; + +// Now, refer to i2cmd.c, and see the character arrays defined there. They are +// cast here to cmdSyntaxPtr. +// +// There are library functions for issuing bypass or inline commands. These +// functions take one or more arguments of the type cmdSyntaxPtr. The routine +// then can figure out how long each command is supposed to be and easily add it +// to the list. +// +// For ease of use, we define manifests which return pointers to appropriate +// cmdSyntaxPtr things. But some commands also take arguments. If a single +// argument is used, we define a macro which performs the single assignment and +// (through the expedient of a comma expression) references the appropriate +// pointer. For commands requiring several arguments, we actually define a +// function to perform the assignments. + +#define CMD_DTRUP (cmdSyntaxPtr)(ct02) // Raise DTR +#define CMD_DTRDN (cmdSyntaxPtr)(ct03) // Lower DTR +#define CMD_RTSUP (cmdSyntaxPtr)(ct04) // Raise RTS +#define CMD_RTSDN (cmdSyntaxPtr)(ct05) // Lower RTS +#define CMD_STARTFL (cmdSyntaxPtr)(ct06) // Start Flushing Data + +#define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01) // Raise DTR and RTS +#define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02) // Lower DTR and RTS + +// Set Baud Rate for transmit and receive +#define CMD_SETBAUD(arg) \ + (((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07)) + +#define CBR_50 1 +#define CBR_75 2 +#define CBR_110 3 +#define CBR_134 4 +#define CBR_150 5 +#define CBR_200 6 +#define CBR_300 7 +#define CBR_600 8 +#define CBR_1200 9 +#define CBR_1800 10 +#define CBR_2400 11 +#define CBR_4800 12 +#define CBR_9600 13 +#define CBR_19200 14 +#define CBR_38400 15 +#define CBR_2000 16 +#define CBR_3600 17 +#define CBR_7200 18 +#define CBR_56000 19 +#define CBR_57600 20 +#define CBR_64000 21 +#define CBR_76800 22 +#define CBR_115200 23 +#define CBR_C1 24 // Custom baud rate 1 +#define CBR_C2 25 // Custom baud rate 2 +#define CBR_153600 26 +#define CBR_230400 27 +#define CBR_307200 28 +#define CBR_460800 29 +#define CBR_921600 30 + +// Set Character size +// +#define CMD_SETBITS(arg) \ + (((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08)) + +#define CSZ_5 0 +#define CSZ_6 1 +#define CSZ_7 2 +#define CSZ_8 3 + +// Set number of stop bits +// +#define CMD_SETSTOP(arg) \ + (((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09)) + +#define CST_1 0 +#define CST_15 1 // 1.5 stop bits +#define CST_2 2 + +// Set parity option +// +#define CMD_SETPAR(arg) \ + (((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10)) + +#define CSP_NP 0 // no parity +#define CSP_OD 1 // odd parity +#define CSP_EV 2 // Even parity +#define CSP_SP 3 // Space parity +#define CSP_MK 4 // Mark parity + +// Define xon char for transmitter flow control +// +#define CMD_DEF_IXON(arg) \ + (((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11)) + +// Define xoff char for transmitter flow control +// +#define CMD_DEF_IXOFF(arg) \ + (((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12)) + +#define CMD_STOPFL (cmdSyntaxPtr)(ct13) // Stop Flushing data + +// Acknowledge receipt of hotkey signal +// +#define CMD_HOTACK (cmdSyntaxPtr)(ct14) + +// Define irq level to use. Should actually be sent by library-level code, not +// directly from user... +// +#define CMDVALUE_IRQ 15 // For library use at initialization. Until this command + // is sent, board processing doesn't really start. +#define CMD_SET_IRQ(arg) \ + (((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15)) + +#define CIR_POLL 0 // No IRQ - Poll +#define CIR_3 3 // IRQ 3 +#define CIR_4 4 // IRQ 4 +#define CIR_5 5 // IRQ 5 +#define CIR_7 7 // IRQ 7 +#define CIR_10 10 // IRQ 10 +#define CIR_11 11 // IRQ 11 +#define CIR_12 12 // IRQ 12 +#define CIR_15 15 // IRQ 15 + +// Select transmit flow xon/xoff options +// +#define CMD_IXON_OPT(arg) \ + (((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16)) + +#define CIX_NONE 0 // Incoming Xon/Xoff characters not special +#define CIX_XON 1 // Xoff disable, Xon enable +#define CIX_XANY 2 // Xoff disable, any key enable + +// Select receive flow xon/xoff options +// +#define CMD_OXON_OPT(arg) \ + (((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17)) + +#define COX_NONE 0 // Don't send Xon/Xoff +#define COX_XON 1 // Send xon/xoff to start/stop incoming data + + +#define CMD_CTS_REP (cmdSyntaxPtr)(ct18) // Enable CTS reporting +#define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting + +#define CMD_DCD_REP (cmdSyntaxPtr)(ct20) // Enable DCD reporting +#define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting + +#define CMD_DSR_REP (cmdSyntaxPtr)(ct22) // Enable DSR reporting +#define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting + +#define CMD_RI_REP (cmdSyntaxPtr)(ct24) // Enable RI reporting +#define CMD_RI_NREP (cmdSyntaxPtr)(ct25) // Disable RI reporting + +// Enable break reporting and select style +// +#define CMD_BRK_REP(arg) \ + (((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26)) + +#define CBK_STAT 0x00 // Report breaks as a status (exception,irq) +#define CBK_NULL 0x01 // Report breaks as a good null +#define CBK_STAT_SEQ 0x02 // Report breaks as a status AND as in-band character + // sequence FFh, 01h, 10h +#define CBK_SEQ 0x03 // Report breaks as the in-band + //sequence FFh, 01h, 10h ONLY. +#define CBK_FLSH 0x04 // if this bit set also flush input data +#define CBK_POSIX 0x08 // if this bit set report as FF,0,0 sequence +#define CBK_SINGLE 0x10 // if this bit set with CBK_SEQ or CBK_STAT_SEQ + //then reports single null instead of triple + +#define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting + +// Specify maximum block size for received data +// +#define CMD_MAX_BLOCK(arg) \ + (((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28)) + +// -- COMMAND 29 is reserved -- + +#define CMD_CTSFL_ENAB (cmdSyntaxPtr)(ct30) // Enable CTS flow control +#define CMD_CTSFL_DSAB (cmdSyntaxPtr)(ct31) // Disable CTS flow control +#define CMD_RTSFL_ENAB (cmdSyntaxPtr)(ct32) // Enable RTS flow control +#define CMD_RTSFL_DSAB (cmdSyntaxPtr)(ct33) // Disable RTS flow control + +// Specify istrip option +// +#define CMD_ISTRIP_OPT(arg) \ + (((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34)) + +#define CIS_NOSTRIP 0 // Strip characters to character size +#define CIS_STRIP 1 // Strip any 8-bit characters to 7 bits + +// Send a break of arg milliseconds +// +#define CMD_SEND_BRK(arg) \ + (((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35)) + +// Set error reporting mode +// +#define CMD_SET_ERROR(arg) \ + (((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36)) + +#define CSE_ESTAT 0 // Report error in a status packet +#define CSE_NOREP 1 // Treat character as though it were good +#define CSE_DROP 2 // Discard the character +#define CSE_NULL 3 // Replace with a null +#define CSE_MARK 4 // Replace with a 3-character sequence (as Unix) + +#define CSE_REPLACE 0x8 // Replace the errored character with the + // replacement character defined here + +#define CSE_STAT_REPLACE 0x18 // Replace the errored character with the + // replacement character defined here AND + // report the error as a status packet (as in + // CSE_ESTAT). + + +// COMMAND 37, to send flow control packets, is handled only by low-level +// library code in response to data movement and shouldn't ever be sent by the +// user code. See i2pack.h and the body of i2lib.c for details. + +// Enable on-board post-processing, using options given in oflag argument. +// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command +// because the loadware does not permit sending back-to-back CMD_OPOST_ON +// commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that +// CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a +// solo packet). This means the caller must specify separately CMD_OPOST_OFF, +// CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure +// each gets a separate packet. Extra CMD_OPOST_OFF's are always ok. +// +#define CMD_OPOST_ON(oflag) \ + (*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \ + (cmdSyntaxPtr)(ct39)) + +#define CMD_OPOST_OFF (cmdSyntaxPtr)(ct40) // Disable on-board post-proc + +#define CMD_RESUME (cmdSyntaxPtr)(ct41) // Resume: behave as though an XON + // were received; + +// Set Transmit baud rate (see command 7 for arguments) +// +#define CMD_SETBAUD_TX(arg) \ + (((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42)) + +// Set Receive baud rate (see command 7 for arguments) +// +#define CMD_SETBAUD_RX(arg) \ + (((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43)) + +// Request interrupt from board each arg milliseconds. Interrupt will specify +// "received data", even though there may be no data present. If arg == 0, +// disables any such interrupts. +// +#define CMD_PING_REQ(arg) \ + (((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44)) + +#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking +#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking + +#if 0 +// COMMAND 47: Send Protocol info via Unix flags: +// iflag = Unix tty t_iflag +// cflag = Unix tty t_cflag +// lflag = Unix tty t_lflag +// See System V Unix/Xenix documentation for the meanings of the bit fields +// within these flags +// +#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag) +#endif /* 0 */ + +#define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl +#define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl +#define CMD_DTRFL_ENAB (cmdSyntaxPtr)(ct50) // Enable DTR flow control +#define CMD_DTRFL_DSAB (cmdSyntaxPtr)(ct51) // Disable DTR flow control +#define CMD_BAUD_RESET (cmdSyntaxPtr)(ct52) // Reset baudrate table + +// COMMAND 54: Define custom rate #1 +// rate = (short) 1/10 of the desired baud rate +// +#define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate) + +// COMMAND 55: Define custom rate #2 +// rate = (short) 1/10 of the desired baud rate +// +#define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate) + +// Pause arg hundredths of seconds. (Note, this is NOT milliseconds.) +// +#define CMD_PAUSE(arg) \ + (((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56)) + +#define CMD_SUSPEND (cmdSyntaxPtr)(ct57) // Suspend output +#define CMD_UNSUSPEND (cmdSyntaxPtr)(ct58) // Un-Suspend output + +// Set parity-checking options +// +#define CMD_PARCHK(arg) \ + (((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59)) + +#define CPK_ENAB 0 // Enable parity checking on input +#define CPK_DSAB 1 // Disable parity checking on input + +#define CMD_BMARK_REQ (cmdSyntaxPtr)(ct60) // Bookmark request + + +// Enable/Disable internal loopback mode +// +#define CMD_INLOOP(arg) \ + (((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61)) + +#define CIN_DISABLE 0 // Normal operation (default) +#define CIN_ENABLE 1 // Internal (local) loopback +#define CIN_REMOTE 2 // Remote loopback + +// Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0 +// --> no timeout: wait forever. +// +#define CMD_HOT_TIME(arg) \ + (((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62)) + + +// Define (outgoing) xon for receive flow control +// +#define CMD_DEF_OXON(arg) \ + (((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63)) + +// Define (outgoing) xoff for receiver flow control +// +#define CMD_DEF_OXOFF(arg) \ + (((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64)) + +// Enable/Disable RTS on transmit (1/2 duplex-style) +// +#define CMD_RTS_XMIT(arg) \ + (((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65)) + +#define CHD_DISABLE 0 +#define CHD_ENABLE 1 + +// Set high-water-mark level (debugging use only) +// +#define CMD_SETHIGHWAT(arg) \ + (((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66)) + +// Start flushing tagged data (tag = 0-14) +// +#define CMD_START_SELFL(tag) \ + (((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67)) + +// End flushing tagged data (tag = 0-14) +// +#define CMD_END_SELFL(tag) \ + (((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68)) + +#define CMD_HWFLOW_OFF (cmdSyntaxPtr)(ct69) // Disable HW TX flow control +#define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c +#define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c +#define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c +#define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c + +// Set transmit interrupt load level. Count should be an even value 2-12 +// +#define CMD_LOADLEVEL(count) \ + (((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74)) + +// If reporting DSS changes, map to character sequence FFh, 2, MSR +// +#define CMD_STATDATA(arg) \ + (((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75)) + +#define CSTD_DISABLE// Report DSS changes as status packets only (default) +#define CSTD_ENABLE // Report DSS changes as in-band data sequence as well as + // by status packet. + +#define CMD_BREAK_ON (cmdSyntaxPtr)(ct76)// Set break and stop xmit +#define CMD_BREAK_OFF (cmdSyntaxPtr)(ct77)// End break and restart xmit +#define CMD_GETFC (cmdSyntaxPtr)(ct78)// Request for flow control packet + // from board. + +// Transmit this character immediately +// +#define CMD_XMIT_NOW(ch) \ + (((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79)) + +// Set baud rate via "divisor latch" +// +#define CMD_DIVISOR_LATCH(which,value) \ + (((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \ + *(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \ + (cmdSyntaxPtr)(ct80)) + +#define CDL_RX 1 // Set receiver rate +#define CDL_TX 2 // Set transmit rate + // (CDL_TX | CDL_RX) Set both rates + +// Request for special diagnostic status pkt from the board. +// +#define CMD_GET_STATUS (cmdSyntaxPtr)(ct81) + +// Request time-stamped transmit character count packet. +// +#define CMD_GET_TXCNT (cmdSyntaxPtr)(ct82) + +// Request time-stamped receive character count packet. +// +#define CMD_GET_RXCNT (cmdSyntaxPtr)(ct83) + +// Request for box/board I.D. packet. +#define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84) + +// Enable or disable multiple channels according to bit-mapped ushorts box 1-4 +// +#define CMD_ENAB_MULT(enable, box1, box2, box3, box4) \ + (((cmdSytaxPtr)(ct85))->cmd[1] = (enable), \ + *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \ + *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \ + *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \ + *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \ + (cmdSyntaxPtr)(ct85)) + +#define CEM_DISABLE 0 +#define CEM_ENABLE 1 + +// Enable or disable receiver or receiver interrupts (default both enabled) +// +#define CMD_RCV_ENABLE(ch) \ + (((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86)) + +#define CRE_OFF 0 // Disable the receiver +#define CRE_ON 1 // Enable the receiver +#define CRE_INTOFF 2 // Disable receiver interrupts (to loadware) +#define CRE_INTON 3 // Enable receiver interrupts (to loadware) + +// Starts up a hardware test process, which runs transparently, and sends a +// STAT_HWFAIL packet in case a hardware failure is detected. +// +#define CMD_HW_TEST (cmdSyntaxPtr)(ct87) + +// Change receiver threshold and timeout value: +// Defaults: timeout = 20mS +// threshold count = 8 when DTRflow not in use, +// threshold count = 5 when DTRflow in use. +// +#define CMD_RCV_THRESHOLD(count,ms) \ + (((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \ + ((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \ + (cmdSyntaxPtr)(ct88)) + +// Makes the loadware report DSS signals for this channel immediately. +// +#define CMD_DSS_NOW (cmdSyntaxPtr)(ct89) + +// Set the receive silo parameters +// timeout is ms idle wait until delivery (~VTIME) +// threshold is max characters cause interrupt (~VMIN) +// +#define CMD_SET_SILO(timeout,threshold) \ + (((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \ + ((cmdSyntaxPtr)(ct90))->cmd[2] = (threshold), \ + (cmdSyntaxPtr)(ct90)) + +// Set timed break in decisecond (1/10s) +// +#define CMD_LBREAK(ds) \ + (((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66)) + + + +#endif // I2CMD_H diff --git a/drivers/staging/tty/ip2/i2ellis.c b/drivers/staging/tty/ip2/i2ellis.c new file mode 100644 index 000000000000..29db44de399f --- /dev/null +++ b/drivers/staging/tty/ip2/i2ellis.c @@ -0,0 +1,1403 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Low-level interface code for the device driver +* (This is included source code, not a separate compilation +* module.) +* +*******************************************************************************/ +//--------------------------------------------- +// Function declarations private to this module +//--------------------------------------------- +// Functions called only indirectly through i2eBordStr entries. + +static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int); +static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int); +static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int); +static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int); + +static unsigned short iiReadWord16(i2eBordStrPtr); +static unsigned short iiReadWord8(i2eBordStrPtr); +static void iiWriteWord16(i2eBordStrPtr, unsigned short); +static void iiWriteWord8(i2eBordStrPtr, unsigned short); + +static int iiWaitForTxEmptyII(i2eBordStrPtr, int); +static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int); +static int iiTxMailEmptyII(i2eBordStrPtr); +static int iiTxMailEmptyIIEX(i2eBordStrPtr); +static int iiTrySendMailII(i2eBordStrPtr, unsigned char); +static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char); + +static unsigned short iiGetMailII(i2eBordStrPtr); +static unsigned short iiGetMailIIEX(i2eBordStrPtr); + +static void iiEnableMailIrqII(i2eBordStrPtr); +static void iiEnableMailIrqIIEX(i2eBordStrPtr); +static void iiWriteMaskII(i2eBordStrPtr, unsigned char); +static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); + +static void ii2Nop(void); + +//*************** +//* Static Data * +//*************** + +static int ii2Safe; // Safe I/O address for delay routine + +static int iiDelayed; // Set when the iiResetDelay function is + // called. Cleared when ANY board is reset. +static DEFINE_RWLOCK(Dl_spinlock); + +//******** +//* Code * +//******** + +//======================================================= +// Initialization Routines +// +// iiSetAddress +// iiReset +// iiResetDelay +// iiInitialize +//======================================================= + +//****************************************************************************** +// Function: iiSetAddress(pB, address, delay) +// Parameters: pB - pointer to the board structure +// address - the purported I/O address of the board +// delay - pointer to the 1-ms delay function to use +// in this and any future operations to this board +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// This routine (roughly) checks for address validity, sets the i2eValid OK and +// sets the state to II_STATE_COLD which means that we haven't even sent a reset +// yet. +// +//****************************************************************************** +static int +iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay ) +{ + // Should any failure occur before init is finished... + pB->i2eValid = I2E_INCOMPLETE; + + // Cannot check upper limit except extremely: Might be microchannel + // Address must be on an 8-byte boundary + + if ((unsigned int)address <= 0x100 + || (unsigned int)address >= 0xfff8 + || (address & 0x7) + ) + { + I2_COMPLETE(pB, I2EE_BADADDR); + } + + // Initialize accelerators + pB->i2eBase = address; + pB->i2eData = address + FIFO_DATA; + pB->i2eStatus = address + FIFO_STATUS; + pB->i2ePointer = address + FIFO_PTR; + pB->i2eXMail = address + FIFO_MAIL; + pB->i2eXMask = address + FIFO_MASK; + + // Initialize i/o address for ii2DelayIO + ii2Safe = address + FIFO_NOP; + + // Initialize the delay routine + pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop); + + pB->i2eValid = I2E_MAGIC; + pB->i2eState = II_STATE_COLD; + + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiReset(pB) +// Parameters: pB - pointer to the board structure +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Attempts to reset the board (see also i2hw.h). Normally, we would use this to +// reset a board immediately after iiSetAddress(), but it is valid to reset a +// board from any state, say, in order to change or re-load loadware. (Under +// such circumstances, no reason to re-run iiSetAddress(), which is why it is a +// separate routine and not included in this routine. +// +//****************************************************************************** +static int +iiReset(i2eBordStrPtr pB) +{ + // Magic number should be set, else even the address is suspect + if (pB->i2eValid != I2E_MAGIC) + { + I2_COMPLETE(pB, I2EE_BADMAGIC); + } + + outb(0, pB->i2eBase + FIFO_RESET); /* Any data will do */ + iiDelay(pB, 50); // Pause between resets + outb(0, pB->i2eBase + FIFO_RESET); /* Second reset */ + + // We must wait before even attempting to read anything from the FIFO: the + // board's P.O.S.T may actually attempt to read and write its end of the + // FIFO in order to check flags, loop back (where supported), etc. On + // completion of this testing it would reset the FIFO, and on completion + // of all // P.O.S.T., write the message. We must not mistake data which + // might have been sent for testing as part of the reset message. To + // better utilize time, say, when resetting several boards, we allow the + // delay to be performed externally; in this way the caller can reset + // several boards, delay a single time, then call the initialization + // routine for all. + + pB->i2eState = II_STATE_RESET; + + iiDelayed = 0; // i.e., the delay routine hasn't been called since the most + // recent reset. + + // Ensure anything which would have been of use to standard loadware is + // blanked out, since board has now forgotten everything!. + + pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */ + pB->i2eWaitingForEmptyFifo = 0; + pB->i2eOutMailWaiting = 0; + pB->i2eChannelPtr = NULL; + pB->i2eChannelCnt = 0; + + pB->i2eLeadoffWord[0] = 0; + pB->i2eFifoInInts = 0; + pB->i2eFifoOutInts = 0; + pB->i2eFatalTrap = NULL; + pB->i2eFatal = 0; + + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiResetDelay(pB) +// Parameters: pB - pointer to the board structure +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Using the delay defined in board structure, waits two seconds (for board to +// reset). +// +//****************************************************************************** +static int +iiResetDelay(i2eBordStrPtr pB) +{ + if (pB->i2eValid != I2E_MAGIC) { + I2_COMPLETE(pB, I2EE_BADMAGIC); + } + if (pB->i2eState != II_STATE_RESET) { + I2_COMPLETE(pB, I2EE_BADSTATE); + } + iiDelay(pB,2000); /* Now we wait for two seconds. */ + iiDelayed = 1; /* Delay has been called: ok to initialize */ + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiInitialize(pB) +// Parameters: pB - pointer to the board structure +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Attempts to read the Power-on reset message. Initializes any remaining fields +// in the pB structure. +// +// This should be called as the third step of a process beginning with +// iiReset(), then iiResetDelay(). This routine checks to see that the structure +// is "valid" and in the reset state, also confirms that the delay routine has +// been called since the latest reset (to any board! overly strong!). +// +//****************************************************************************** +static int +iiInitialize(i2eBordStrPtr pB) +{ + int itemp; + unsigned char c; + unsigned short utemp; + unsigned int ilimit; + + if (pB->i2eValid != I2E_MAGIC) + { + I2_COMPLETE(pB, I2EE_BADMAGIC); + } + + if (pB->i2eState != II_STATE_RESET || !iiDelayed) + { + I2_COMPLETE(pB, I2EE_BADSTATE); + } + + // In case there is a failure short of our completely reading the power-up + // message. + pB->i2eValid = I2E_INCOMPLETE; + + + // Now attempt to read the message. + + for (itemp = 0; itemp < sizeof(porStr); itemp++) + { + // We expect the entire message is ready. + if (!I2_HAS_INPUT(pB)) { + pB->i2ePomSize = itemp; + I2_COMPLETE(pB, I2EE_PORM_SHORT); + } + + pB->i2ePom.c[itemp] = c = inb(pB->i2eData); + + // We check the magic numbers as soon as they are supposed to be read + // (rather than after) to minimize effect of reading something we + // already suspect can't be "us". + if ( (itemp == POR_1_INDEX && c != POR_MAGIC_1) || + (itemp == POR_2_INDEX && c != POR_MAGIC_2)) + { + pB->i2ePomSize = itemp+1; + I2_COMPLETE(pB, I2EE_BADMAGIC); + } + } + + pB->i2ePomSize = itemp; + + // Ensure that this was all the data... + if (I2_HAS_INPUT(pB)) + I2_COMPLETE(pB, I2EE_PORM_LONG); + + // For now, we'll fail to initialize if P.O.S.T reports bad chip mapper: + // Implying we will not be able to download any code either: That's ok: the + // condition is pretty explicit. + if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER) + { + I2_COMPLETE(pB, I2EE_POSTERR); + } + + // Determine anything which must be done differently depending on the family + // of boards! + switch (pB->i2ePom.e.porID & POR_ID_FAMILY) + { + case POR_ID_FII: // IntelliPort-II + + pB->i2eFifoStyle = FIFO_II; + pB->i2eFifoSize = 512; // 512 bytes, always + pB->i2eDataWidth16 = false; + + pB->i2eMaxIrq = 15; // Because board cannot tell us it is in an 8-bit + // slot, we do allow it to be done (documentation!) + + pB->i2eGoodMap[1] = + pB->i2eGoodMap[2] = + pB->i2eGoodMap[3] = + pB->i2eChannelMap[1] = + pB->i2eChannelMap[2] = + pB->i2eChannelMap[3] = 0; + + switch (pB->i2ePom.e.porID & POR_ID_SIZE) + { + case POR_ID_II_4: + pB->i2eGoodMap[0] = + pB->i2eChannelMap[0] = 0x0f; // four-port + + // Since porPorts1 is based on the Hardware ID register, the numbers + // should always be consistent for IntelliPort-II. Ditto below... + if (pB->i2ePom.e.porPorts1 != 4) + { + I2_COMPLETE(pB, I2EE_INCONSIST); + } + break; + + case POR_ID_II_8: + case POR_ID_II_8R: + pB->i2eGoodMap[0] = + pB->i2eChannelMap[0] = 0xff; // Eight port + if (pB->i2ePom.e.porPorts1 != 8) + { + I2_COMPLETE(pB, I2EE_INCONSIST); + } + break; + + case POR_ID_II_6: + pB->i2eGoodMap[0] = + pB->i2eChannelMap[0] = 0x3f; // Six Port + if (pB->i2ePom.e.porPorts1 != 6) + { + I2_COMPLETE(pB, I2EE_INCONSIST); + } + break; + } + + // Fix up the "good channel list based on any errors reported. + if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1) + { + pB->i2eGoodMap[0] &= ~0x0f; + } + + if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2) + { + pB->i2eGoodMap[0] &= ~0xf0; + } + + break; // POR_ID_FII case + + case POR_ID_FIIEX: // IntelliPort-IIEX + + pB->i2eFifoStyle = FIFO_IIEX; + + itemp = pB->i2ePom.e.porFifoSize; + + // Implicit assumption that fifo would not grow beyond 32k, + // nor would ever be less than 256. + + if (itemp < 8 || itemp > 15) + { + I2_COMPLETE(pB, I2EE_INCONSIST); + } + pB->i2eFifoSize = (1 << itemp); + + // These are based on what P.O.S.T thinks should be there, based on + // box ID registers + ilimit = pB->i2ePom.e.porNumBoxes; + if (ilimit > ABS_MAX_BOXES) + { + ilimit = ABS_MAX_BOXES; + } + + // For as many boxes as EXIST, gives the type of box. + // Added 8/6/93: check for the ISA-4 (asic) which looks like an + // expandable but for whom "8 or 16?" is not the right question. + + utemp = pB->i2ePom.e.porFlags; + if (utemp & POR_CEX4) + { + pB->i2eChannelMap[0] = 0x000f; + } else { + utemp &= POR_BOXES; + for (itemp = 0; itemp < ilimit; itemp++) + { + pB->i2eChannelMap[itemp] = + ((utemp & POR_BOX_16) ? 0xffff : 0x00ff); + utemp >>= 1; + } + } + + // These are based on what P.O.S.T actually found. + + utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1; + + for (itemp = 0; itemp < ilimit; itemp++) + { + pB->i2eGoodMap[itemp] = 0; + if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f; + if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0; + if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00; + if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000; + utemp >>= 4; + } + + // Now determine whether we should transfer in 8 or 16-bit mode. + switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) ) + { + case POR_BUS_SLOT16 | POR_BUS_DIP16: + pB->i2eDataWidth16 = true; + pB->i2eMaxIrq = 15; + break; + + case POR_BUS_SLOT16: + pB->i2eDataWidth16 = false; + pB->i2eMaxIrq = 15; + break; + + case 0: + case POR_BUS_DIP16: // In an 8-bit slot, DIP switch don't care. + default: + pB->i2eDataWidth16 = false; + pB->i2eMaxIrq = 7; + break; + } + break; // POR_ID_FIIEX case + + default: // Unknown type of board + I2_COMPLETE(pB, I2EE_BAD_FAMILY); + break; + } // End the switch based on family + + // Temporarily, claim there is no room in the outbound fifo. + // We will maintain this whenever we check for an empty outbound FIFO. + pB->i2eFifoRemains = 0; + + // Now, based on the bus type, should we expect to be able to re-configure + // interrupts (say, for testing purposes). + switch (pB->i2ePom.e.porBus & POR_BUS_TYPE) + { + case POR_BUS_T_ISA: + case POR_BUS_T_UNK: // If the type of bus is undeclared, assume ok. + case POR_BUS_T_MCA: + case POR_BUS_T_EISA: + break; + default: + I2_COMPLETE(pB, I2EE_BADBUS); + } + + if (pB->i2eDataWidth16) + { + pB->i2eWriteBuf = iiWriteBuf16; + pB->i2eReadBuf = iiReadBuf16; + pB->i2eWriteWord = iiWriteWord16; + pB->i2eReadWord = iiReadWord16; + } else { + pB->i2eWriteBuf = iiWriteBuf8; + pB->i2eReadBuf = iiReadBuf8; + pB->i2eWriteWord = iiWriteWord8; + pB->i2eReadWord = iiReadWord8; + } + + switch(pB->i2eFifoStyle) + { + case FIFO_II: + pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII; + pB->i2eTxMailEmpty = iiTxMailEmptyII; + pB->i2eTrySendMail = iiTrySendMailII; + pB->i2eGetMail = iiGetMailII; + pB->i2eEnableMailIrq = iiEnableMailIrqII; + pB->i2eWriteMask = iiWriteMaskII; + + break; + + case FIFO_IIEX: + pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX; + pB->i2eTxMailEmpty = iiTxMailEmptyIIEX; + pB->i2eTrySendMail = iiTrySendMailIIEX; + pB->i2eGetMail = iiGetMailIIEX; + pB->i2eEnableMailIrq = iiEnableMailIrqIIEX; + pB->i2eWriteMask = iiWriteMaskIIEX; + + break; + + default: + I2_COMPLETE(pB, I2EE_INCONSIST); + } + + // Initialize state information. + pB->i2eState = II_STATE_READY; // Ready to load loadware. + + // Some Final cleanup: + // For some boards, the bootstrap firmware may perform some sort of test + // resulting in a stray character pending in the incoming mailbox. If one is + // there, it should be read and discarded, especially since for the standard + // firmware, it's the mailbox that interrupts the host. + + pB->i2eStartMail = iiGetMail(pB); + + // Throw it away and clear the mailbox structure element + pB->i2eStartMail = NO_MAIL_HERE; + + // Everything is ok now, return with good status/ + + pB->i2eValid = I2E_MAGIC; + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: ii2DelayTimer(mseconds) +// Parameters: mseconds - number of milliseconds to delay +// +// Returns: Nothing +// +// Description: +// +// This routine delays for approximately mseconds milliseconds and is intended +// to be called indirectly through i2Delay field in i2eBordStr. It uses the +// Linux timer_list mechanism. +// +// The Linux timers use a unit called "jiffies" which are 10mS in the Intel +// architecture. This function rounds the delay period up to the next "jiffy". +// In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended +// for Alpha platforms at this time. +// +//****************************************************************************** +static void +ii2DelayTimer(unsigned int mseconds) +{ + msleep_interruptible(mseconds); +} + +#if 0 +//static void ii2DelayIO(unsigned int); +//****************************************************************************** +// !!! Not Used, this is DOS crap, some of you young folks may be interested in +// in how things were done in the stone age of caculating machines !!! +// Function: ii2DelayIO(mseconds) +// Parameters: mseconds - number of milliseconds to delay +// +// Returns: Nothing +// +// Description: +// +// This routine delays for approximately mseconds milliseconds and is intended +// to be called indirectly through i2Delay field in i2eBordStr. It is intended +// for use where a clock-based function is impossible: for example, DOS drivers. +// +// This function uses the IN instruction to place bounds on the timing and +// assumes that ii2Safe has been set. This is because I/O instructions are not +// subject to caching and will therefore take a certain minimum time. To ensure +// the delay is at least long enough on fast machines, it is based on some +// fastest-case calculations. On slower machines this may cause VERY long +// delays. (3 x fastest case). In the fastest case, everything is cached except +// the I/O instruction itself. +// +// Timing calculations: +// The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O +// operation in question is a byte operation to an odd address. For 8-bit +// operations, the architecture generally enforces two wait states. At 10 MHz, a +// single cycle time is 100nS. A read operation at two wait states takes 6 +// cycles for a total time of 600nS. Therefore approximately 1666 iterations +// would be required to generate a single millisecond delay. The worst +// (reasonable) case would be an 8MHz system with no cacheing. In this case, the +// I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code +// fetch of other instructions in the loop would take time (zero wait states, +// however) and would be hard to estimate. This is minimized by using in-line +// assembler for the in inner loop of IN instructions. This consists of just a +// few bytes. So we'll guess about four code fetches per loop. Each code fetch +// should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is +// that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS. +// +// So much for theoretical timings: results using 1666 value on some actual +// machines: +// IBM 286 6MHz 3.15 mS +// Zenith 386 33MHz 2.45 mS +// (brandX) 386 33MHz 1.90 mS (has cache) +// (brandY) 486 33MHz 2.35 mS +// NCR 486 ?? 1.65 mS (microchannel) +// +// For most machines, it is probably safe to scale this number back (remember, +// for robust operation use an actual timed delay if possible), so we are using +// a value of 1190. This yields 1.17 mS for the fastest machine in our sample, +// 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine. +// +// 1/29/93: +// The above timings are too slow. Actual cycle times might be faster. ISA cycle +// times could approach 500 nS, and ... +// The IBM model 77 being microchannel has no wait states for 8-bit reads and +// seems to be accessing the I/O at 440 nS per access (from start of one to +// start of next). This would imply we need 1000/.440 = 2272 iterations to +// guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in +// fact enough. For diagnostics, we keep the level at 1190, but developers note +// this needs tuning. +// +// Safe assumption: 2270 i/o reads = 1 millisecond +// +//****************************************************************************** + + +static int ii2DelValue = 1190; // See timing calculations below + // 1666 for fastest theoretical machine + // 1190 safe for most fast 386 machines + // 1000 for fastest machine tested here + // 540 (sic) for AT286/6Mhz +static void +ii2DelayIO(unsigned int mseconds) +{ + if (!ii2Safe) + return; /* Do nothing if this variable uninitialized */ + + while(mseconds--) { + int i = ii2DelValue; + while ( i-- ) { + inb(ii2Safe); + } + } +} +#endif + +//****************************************************************************** +// Function: ii2Nop() +// Parameters: None +// +// Returns: Nothing +// +// Description: +// +// iiInitialize will set i2eDelay to this if the delay parameter is NULL. This +// saves checking for a NULL pointer at every call. +//****************************************************************************** +static void +ii2Nop(void) +{ + return; // no mystery here +} + +//======================================================= +// Routines which are available in 8/16-bit versions, or +// in different fifo styles. These are ALL called +// indirectly through the board structure. +//======================================================= + +//****************************************************************************** +// Function: iiWriteBuf16(pB, address, count) +// Parameters: pB - pointer to board structure +// address - address of data to write +// count - number of data bytes to write +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Writes 'count' bytes from 'address' to the data fifo specified by the board +// structure pointer pB. Should count happen to be odd, an extra pad byte is +// sent (identity unknown...). Uses 16-bit (word) operations. Is called +// indirectly through pB->i2eWriteBuf. +// +//****************************************************************************** +static int +iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count) +{ + // Rudimentary sanity checking here. + if (pB->i2eValid != I2E_MAGIC) + I2_COMPLETE(pB, I2EE_INVALID); + + I2_OUTSW(pB->i2eData, address, count); + + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiWriteBuf8(pB, address, count) +// Parameters: pB - pointer to board structure +// address - address of data to write +// count - number of data bytes to write +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Writes 'count' bytes from 'address' to the data fifo specified by the board +// structure pointer pB. Should count happen to be odd, an extra pad byte is +// sent (identity unknown...). This is to be consistent with the 16-bit version. +// Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf. +// +//****************************************************************************** +static int +iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count) +{ + /* Rudimentary sanity checking here */ + if (pB->i2eValid != I2E_MAGIC) + I2_COMPLETE(pB, I2EE_INVALID); + + I2_OUTSB(pB->i2eData, address, count); + + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiReadBuf16(pB, address, count) +// Parameters: pB - pointer to board structure +// address - address to put data read +// count - number of data bytes to read +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Reads 'count' bytes into 'address' from the data fifo specified by the board +// structure pointer pB. Should count happen to be odd, an extra pad byte is +// received (identity unknown...). Uses 16-bit (word) operations. Is called +// indirectly through pB->i2eReadBuf. +// +//****************************************************************************** +static int +iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count) +{ + // Rudimentary sanity checking here. + if (pB->i2eValid != I2E_MAGIC) + I2_COMPLETE(pB, I2EE_INVALID); + + I2_INSW(pB->i2eData, address, count); + + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiReadBuf8(pB, address, count) +// Parameters: pB - pointer to board structure +// address - address to put data read +// count - number of data bytes to read +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Reads 'count' bytes into 'address' from the data fifo specified by the board +// structure pointer pB. Should count happen to be odd, an extra pad byte is +// received (identity unknown...). This to match the 16-bit behaviour. Uses +// 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf. +// +//****************************************************************************** +static int +iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count) +{ + // Rudimentary sanity checking here. + if (pB->i2eValid != I2E_MAGIC) + I2_COMPLETE(pB, I2EE_INVALID); + + I2_INSB(pB->i2eData, address, count); + + I2_COMPLETE(pB, I2EE_GOOD); +} + +//****************************************************************************** +// Function: iiReadWord16(pB) +// Parameters: pB - pointer to board structure +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Returns the word read from the data fifo specified by the board-structure +// pointer pB. Uses a 16-bit operation. Is called indirectly through +// pB->i2eReadWord. +// +//****************************************************************************** +static unsigned short +iiReadWord16(i2eBordStrPtr pB) +{ + return inw(pB->i2eData); +} + +//****************************************************************************** +// Function: iiReadWord8(pB) +// Parameters: pB - pointer to board structure +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Returns the word read from the data fifo specified by the board-structure +// pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is +// called indirectly through pB->i2eReadWord. +// +//****************************************************************************** +static unsigned short +iiReadWord8(i2eBordStrPtr pB) +{ + unsigned short urs; + + urs = inb(pB->i2eData); + + return (inb(pB->i2eData) << 8) | urs; +} + +//****************************************************************************** +// Function: iiWriteWord16(pB, value) +// Parameters: pB - pointer to board structure +// value - data to write +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Writes the word 'value' to the data fifo specified by the board-structure +// pointer pB. Uses 16-bit operation. Is called indirectly through +// pB->i2eWriteWord. +// +//****************************************************************************** +static void +iiWriteWord16(i2eBordStrPtr pB, unsigned short value) +{ + outw((int)value, pB->i2eData); +} + +//****************************************************************************** +// Function: iiWriteWord8(pB, value) +// Parameters: pB - pointer to board structure +// value - data to write +// +// Returns: True if everything appears copacetic. +// False if there is any error: the pB->i2eError field has the error +// +// Description: +// +// Writes the word 'value' to the data fifo specified by the board-structure +// pointer pB. Uses two 8-bit operations (writes LSB first). Is called +// indirectly through pB->i2eWriteWord. +// +//****************************************************************************** +static void +iiWriteWord8(i2eBordStrPtr pB, unsigned short value) +{ + outb((char)value, pB->i2eData); + outb((char)(value >> 8), pB->i2eData); +} + +//****************************************************************************** +// Function: iiWaitForTxEmptyII(pB, mSdelay) +// Parameters: pB - pointer to board structure +// mSdelay - period to wait before returning +// +// Returns: True if the FIFO is empty. +// False if it not empty in the required time: the pB->i2eError +// field has the error. +// +// Description: +// +// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if +// not empty by the required time, returns false and error in pB->i2eError, +// otherwise returns true. +// +// mSdelay == 0 is taken to mean must be empty on the first test. +// +// This version operates on IntelliPort-II - style FIFO's +// +// Note this routine is organized so that if status is ok there is no delay at +// all called either before or after the test. Is called indirectly through +// pB->i2eWaitForTxEmpty. +// +//****************************************************************************** +static int +iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay) +{ + unsigned long flags; + int itemp; + + for (;;) + { + // This routine hinges on being able to see the "other" status register + // (as seen by the local processor). His incoming fifo is our outgoing + // FIFO. + // + // By the nature of this routine, you would be using this as part of a + // larger atomic context: i.e., you would use this routine to ensure the + // fifo empty, then act on this information. Between these two halves, + // you will generally not want to service interrupts or in any way + // disrupt the assumptions implicit in the larger context. + // + // Even worse, however, this routine "shifts" the status register to + // point to the local status register which is not the usual situation. + // Therefore for extra safety, we force the critical section to be + // completely atomic, and pick up after ourselves before allowing any + // interrupts of any kind. + + + write_lock_irqsave(&Dl_spinlock, flags); + outb(SEL_COMMAND, pB->i2ePointer); + outb(SEL_CMD_SH, pB->i2ePointer); + + itemp = inb(pB->i2eStatus); + + outb(SEL_COMMAND, pB->i2ePointer); + outb(SEL_CMD_UNSH, pB->i2ePointer); + + if (itemp & ST_IN_EMPTY) + { + I2_UPDATE_FIFO_ROOM(pB); + write_unlock_irqrestore(&Dl_spinlock, flags); + I2_COMPLETE(pB, I2EE_GOOD); + } + + write_unlock_irqrestore(&Dl_spinlock, flags); + + if (mSdelay-- == 0) + break; + + iiDelay(pB, 1); /* 1 mS granularity on checking condition */ + } + I2_COMPLETE(pB, I2EE_TXE_TIME); +} + +//****************************************************************************** +// Function: iiWaitForTxEmptyIIEX(pB, mSdelay) +// Parameters: pB - pointer to board structure +// mSdelay - period to wait before returning +// +// Returns: True if the FIFO is empty. +// False if it not empty in the required time: the pB->i2eError +// field has the error. +// +// Description: +// +// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if +// not empty by the required time, returns false and error in pB->i2eError, +// otherwise returns true. +// +// mSdelay == 0 is taken to mean must be empty on the first test. +// +// This version operates on IntelliPort-IIEX - style FIFO's +// +// Note this routine is organized so that if status is ok there is no delay at +// all called either before or after the test. Is called indirectly through +// pB->i2eWaitForTxEmpty. +// +//****************************************************************************** +static int +iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay) +{ + unsigned long flags; + + for (;;) + { + // By the nature of this routine, you would be using this as part of a + // larger atomic context: i.e., you would use this routine to ensure the + // fifo empty, then act on this information. Between these two halves, + // you will generally not want to service interrupts or in any way + // disrupt the assumptions implicit in the larger context. + + write_lock_irqsave(&Dl_spinlock, flags); + + if (inb(pB->i2eStatus) & STE_OUT_MT) { + I2_UPDATE_FIFO_ROOM(pB); + write_unlock_irqrestore(&Dl_spinlock, flags); + I2_COMPLETE(pB, I2EE_GOOD); + } + write_unlock_irqrestore(&Dl_spinlock, flags); + + if (mSdelay-- == 0) + break; + + iiDelay(pB, 1); // 1 mS granularity on checking condition + } + I2_COMPLETE(pB, I2EE_TXE_TIME); +} + +//****************************************************************************** +// Function: iiTxMailEmptyII(pB) +// Parameters: pB - pointer to board structure +// +// Returns: True if the transmit mailbox is empty. +// False if it not empty. +// +// Description: +// +// Returns true or false according to whether the transmit mailbox is empty (and +// therefore able to accept more mail) +// +// This version operates on IntelliPort-II - style FIFO's +// +//****************************************************************************** +static int +iiTxMailEmptyII(i2eBordStrPtr pB) +{ + int port = pB->i2ePointer; + outb(SEL_OUTMAIL, port); + return inb(port) == 0; +} + +//****************************************************************************** +// Function: iiTxMailEmptyIIEX(pB) +// Parameters: pB - pointer to board structure +// +// Returns: True if the transmit mailbox is empty. +// False if it not empty. +// +// Description: +// +// Returns true or false according to whether the transmit mailbox is empty (and +// therefore able to accept more mail) +// +// This version operates on IntelliPort-IIEX - style FIFO's +// +//****************************************************************************** +static int +iiTxMailEmptyIIEX(i2eBordStrPtr pB) +{ + return !(inb(pB->i2eStatus) & STE_OUT_MAIL); +} + +//****************************************************************************** +// Function: iiTrySendMailII(pB,mail) +// Parameters: pB - pointer to board structure +// mail - value to write to mailbox +// +// Returns: True if the transmit mailbox is empty, and mail is sent. +// False if it not empty. +// +// Description: +// +// If outgoing mailbox is empty, sends mail and returns true. If outgoing +// mailbox is not empty, returns false. +// +// This version operates on IntelliPort-II - style FIFO's +// +//****************************************************************************** +static int +iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail) +{ + int port = pB->i2ePointer; + + outb(SEL_OUTMAIL, port); + if (inb(port) == 0) { + outb(SEL_OUTMAIL, port); + outb(mail, port); + return 1; + } + return 0; +} + +//****************************************************************************** +// Function: iiTrySendMailIIEX(pB,mail) +// Parameters: pB - pointer to board structure +// mail - value to write to mailbox +// +// Returns: True if the transmit mailbox is empty, and mail is sent. +// False if it not empty. +// +// Description: +// +// If outgoing mailbox is empty, sends mail and returns true. If outgoing +// mailbox is not empty, returns false. +// +// This version operates on IntelliPort-IIEX - style FIFO's +// +//****************************************************************************** +static int +iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail) +{ + if (inb(pB->i2eStatus) & STE_OUT_MAIL) + return 0; + outb(mail, pB->i2eXMail); + return 1; +} + +//****************************************************************************** +// Function: iiGetMailII(pB,mail) +// Parameters: pB - pointer to board structure +// +// Returns: Mailbox data or NO_MAIL_HERE. +// +// Description: +// +// If no mail available, returns NO_MAIL_HERE otherwise returns the data from +// the mailbox, which is guaranteed != NO_MAIL_HERE. +// +// This version operates on IntelliPort-II - style FIFO's +// +//****************************************************************************** +static unsigned short +iiGetMailII(i2eBordStrPtr pB) +{ + if (I2_HAS_MAIL(pB)) { + outb(SEL_INMAIL, pB->i2ePointer); + return inb(pB->i2ePointer); + } else { + return NO_MAIL_HERE; + } +} + +//****************************************************************************** +// Function: iiGetMailIIEX(pB,mail) +// Parameters: pB - pointer to board structure +// +// Returns: Mailbox data or NO_MAIL_HERE. +// +// Description: +// +// If no mail available, returns NO_MAIL_HERE otherwise returns the data from +// the mailbox, which is guaranteed != NO_MAIL_HERE. +// +// This version operates on IntelliPort-IIEX - style FIFO's +// +//****************************************************************************** +static unsigned short +iiGetMailIIEX(i2eBordStrPtr pB) +{ + if (I2_HAS_MAIL(pB)) + return inb(pB->i2eXMail); + else + return NO_MAIL_HERE; +} + +//****************************************************************************** +// Function: iiEnableMailIrqII(pB) +// Parameters: pB - pointer to board structure +// +// Returns: Nothing +// +// Description: +// +// Enables board to interrupt host (only) by writing to host's in-bound mailbox. +// +// This version operates on IntelliPort-II - style FIFO's +// +//****************************************************************************** +static void +iiEnableMailIrqII(i2eBordStrPtr pB) +{ + outb(SEL_MASK, pB->i2ePointer); + outb(ST_IN_MAIL, pB->i2ePointer); +} + +//****************************************************************************** +// Function: iiEnableMailIrqIIEX(pB) +// Parameters: pB - pointer to board structure +// +// Returns: Nothing +// +// Description: +// +// Enables board to interrupt host (only) by writing to host's in-bound mailbox. +// +// This version operates on IntelliPort-IIEX - style FIFO's +// +//****************************************************************************** +static void +iiEnableMailIrqIIEX(i2eBordStrPtr pB) +{ + outb(MX_IN_MAIL, pB->i2eXMask); +} + +//****************************************************************************** +// Function: iiWriteMaskII(pB) +// Parameters: pB - pointer to board structure +// +// Returns: Nothing +// +// Description: +// +// Writes arbitrary value to the mask register. +// +// This version operates on IntelliPort-II - style FIFO's +// +//****************************************************************************** +static void +iiWriteMaskII(i2eBordStrPtr pB, unsigned char value) +{ + outb(SEL_MASK, pB->i2ePointer); + outb(value, pB->i2ePointer); +} + +//****************************************************************************** +// Function: iiWriteMaskIIEX(pB) +// Parameters: pB - pointer to board structure +// +// Returns: Nothing +// +// Description: +// +// Writes arbitrary value to the mask register. +// +// This version operates on IntelliPort-IIEX - style FIFO's +// +//****************************************************************************** +static void +iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value) +{ + outb(value, pB->i2eXMask); +} + +//****************************************************************************** +// Function: iiDownloadBlock(pB, pSource, isStandard) +// Parameters: pB - pointer to board structure +// pSource - loadware block to download +// isStandard - True if "standard" loadware, else false. +// +// Returns: Success or Failure +// +// Description: +// +// Downloads a single block (at pSource)to the board referenced by pB. Caller +// sets isStandard to true/false according to whether the "standard" loadware is +// what's being loaded. The normal process, then, is to perform an iiInitialize +// to the board, then perform some number of iiDownloadBlocks using the returned +// state to determine when download is complete. +// +// Possible return values: (see I2ELLIS.H) +// II_DOWN_BADVALID +// II_DOWN_BADFILE +// II_DOWN_CONTINUING +// II_DOWN_GOOD +// II_DOWN_BAD +// II_DOWN_BADSTATE +// II_DOWN_TIMEOUT +// +// Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to +// determine whether this is the first block, whether to check for magic +// numbers, how many blocks there are to go... +// +//****************************************************************************** +static int +iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard) +{ + int itemp; + int loadedFirst; + + if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID; + + switch(pB->i2eState) + { + case II_STATE_READY: + + // Loading the first block after reset. Must check the magic number of the + // loadfile, store the number of blocks we expect to load. + if (pSource->e.loadMagic != MAGIC_LOADFILE) + { + return II_DOWN_BADFILE; + } + + // Next we store the total number of blocks to load, including this one. + pB->i2eToLoad = 1 + pSource->e.loadBlocksMore; + + // Set the state, store the version numbers. ('Cause this may have come + // from a file - we might want to report these versions and revisions in + // case of an error! + pB->i2eState = II_STATE_LOADING; + pB->i2eLVersion = pSource->e.loadVersion; + pB->i2eLRevision = pSource->e.loadRevision; + pB->i2eLSub = pSource->e.loadSubRevision; + + // The time and date of compilation is also available but don't bother + // storing it for normal purposes. + loadedFirst = 1; + break; + + case II_STATE_LOADING: + loadedFirst = 0; + break; + + default: + return II_DOWN_BADSTATE; + } + + // Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad + // must be positive still, because otherwise we would have cleaned up last + // time and set the state to II_STATE_LOADED. + if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { + return II_DOWN_TIMEOUT; + } + + if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) { + return II_DOWN_BADVALID; + } + + // If we just loaded the first block, wait for the fifo to empty an extra + // long time to allow for any special startup code in the firmware, like + // sending status messages to the LCD's. + + if (loadedFirst) { + if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) { + return II_DOWN_TIMEOUT; + } + } + + // Determine whether this was our last block! + if (--(pB->i2eToLoad)) { + return II_DOWN_CONTINUING; // more to come... + } + + // It WAS our last block: Clean up operations... + // ...Wait for last buffer to drain from the board... + if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { + return II_DOWN_TIMEOUT; + } + // If there were only a single block written, this would come back + // immediately and be harmless, though not strictly necessary. + itemp = MAX_DLOAD_ACK_TIME/10; + while (--itemp) { + if (I2_HAS_INPUT(pB)) { + switch (inb(pB->i2eData)) { + case LOADWARE_OK: + pB->i2eState = + isStandard ? II_STATE_STDLOADED :II_STATE_LOADED; + + // Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2) + // will, // if there is a debug port attached, require some + // time to send information to the debug port now. It will do + // this before // executing any of the code we just downloaded. + // It may take up to 700 milliseconds. + if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) { + iiDelay(pB, 700); + } + + return II_DOWN_GOOD; + + case LOADWARE_BAD: + default: + return II_DOWN_BAD; + } + } + + iiDelay(pB, 10); // 10 mS granularity on checking condition + } + + // Drop-through --> timed out waiting for firmware confirmation + + pB->i2eState = II_STATE_BADLOAD; + return II_DOWN_TIMEOUT; +} + +//****************************************************************************** +// Function: iiDownloadAll(pB, pSource, isStandard, size) +// Parameters: pB - pointer to board structure +// pSource - loadware block to download +// isStandard - True if "standard" loadware, else false. +// size - size of data to download (in bytes) +// +// Returns: Success or Failure +// +// Description: +// +// Given a pointer to a board structure, a pointer to the beginning of some +// loadware, whether it is considered the "standard loadware", and the size of +// the array in bytes loads the entire array to the board as loadware. +// +// Assumes the board has been freshly reset and the power-up reset message read. +// (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be +// too much or too little data to load, or if iiDownloadBlock complains. +//****************************************************************************** +static int +iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size) +{ + int status; + + // We know (from context) board should be ready for the first block of + // download. Complain if not. + if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE; + + while (size > 0) { + size -= LOADWARE_BLOCK_SIZE; // How much data should there be left to + // load after the following operation ? + + // Note we just bump pSource by "one", because its size is actually that + // of an entire block, same as LOADWARE_BLOCK_SIZE. + status = iiDownloadBlock(pB, pSource++, isStandard); + + switch(status) + { + case II_DOWN_GOOD: + return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD); + + case II_DOWN_CONTINUING: + break; + + default: + return status; + } + } + + // We shouldn't drop out: it means "while" caught us with nothing left to + // download, yet the previous DownloadBlock did not return complete. Ergo, + // not enough data to match the size byte in the header. + return II_DOWN_UNDER; +} diff --git a/drivers/staging/tty/ip2/i2ellis.h b/drivers/staging/tty/ip2/i2ellis.h new file mode 100644 index 000000000000..fb6df2456018 --- /dev/null +++ b/drivers/staging/tty/ip2/i2ellis.h @@ -0,0 +1,566 @@ +/******************************************************************************* +* +* (c) 1999 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Mainline code for the device driver +* +*******************************************************************************/ +//------------------------------------------------------------------------------ +// i2ellis.h +// +// IntelliPort-II and IntelliPort-IIEX +// +// Extremely +// Low +// Level +// Interface +// Services +// +// Structure Definitions and declarations for "ELLIS" service routines found in +// i2ellis.c +// +// These routines are based on properties of the IntelliPort-II and -IIEX +// hardware and bootstrap firmware, and are not sensitive to particular +// conventions of any particular loadware. +// +// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material +// here and in i2ellis.c is intended to provice a useful, but not required, +// layer of insulation from the hardware specifics. +//------------------------------------------------------------------------------ +#ifndef I2ELLIS_H /* To prevent multiple includes */ +#define I2ELLIS_H 1 +//------------------------------------------------ +// Revision History: +// +// 30 September 1991 MAG First Draft Started +// 12 October 1991 ...continued... +// +// 20 December 1996 AKM Linux version +//------------------------------------------------- + +//---------------------- +// Mandatory Includes: +//---------------------- +#include "ip2types.h" +#include "i2hw.h" // The hardware definitions + +//------------------------------------------ +// STAT_BOXIDS packets +//------------------------------------------ +#define MAX_BOX 4 + +typedef struct _bidStat +{ + unsigned char bid_value[MAX_BOX]; +} bidStat, *bidStatPtr; + +// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX +// boards, reports the hardware-specific "asynchronous resource register" on +// each expansion box. Boxes not present report 0xff. For -II boards, the first +// element contains 0x80 for 8-port, 0x40 for 4-port boards. + +// Box IDs aka ARR or Async Resource Register (more than you want to know) +// 7 6 5 4 3 2 1 0 +// F F N N L S S S +// ============================= +// F F - Product Family Designator +// =====+++++++++++++++++++++++++++++++ +// 0 0 - Intelliport II EX / ISA-8 +// 1 0 - IntelliServer +// 0 1 - SAC - Port Device (Intelliport III ??? ) +// =====+++++++++++++++++++++++++++++++++++++++ +// N N - Number of Ports +// 0 0 - 8 (eight) +// 0 1 - 4 (four) +// 1 0 - 12 (twelve) +// 1 1 - 16 (sixteen) +// =++++++++++++++++++++++++++++++++++ +// L - LCD Display Module Present +// 0 - No +// 1 - LCD module present +// =========+++++++++++++++++++++++++++++++++++++ +// S S S - Async Signals Supported Designator +// 0 0 0 - 8dss, Mod DCE DB25 Female +// 0 0 1 - 6dss, RJ-45 +// 0 1 0 - RS-232/422 dss, DB25 Female +// 0 1 1 - RS-232/422 dss, separate 232/422 DB25 Female +// 1 0 0 - 6dss, 921.6 I/F with ST654's +// 1 0 1 - RS-423/232 8dss, RJ-45 10Pin +// 1 1 0 - 6dss, Mod DCE DB25 Female +// 1 1 1 - NO BOX PRESENT + +#define FF(c) ((c & 0xC0) >> 6) +#define NN(c) ((c & 0x30) >> 4) +#define L(c) ((c & 0x08) >> 3) +#define SSS(c) (c & 0x07) + +#define BID_HAS_654(x) (SSS(x) == 0x04) +#define BID_NO_BOX 0xff /* no box */ +#define BID_8PORT 0x80 /* IP2-8 port */ +#define BID_4PORT 0x81 /* IP2-4 port */ +#define BID_EXP_MASK 0x30 /* IP2-EX */ +#define BID_EXP_8PORT 0x00 /* 8, */ +#define BID_EXP_4PORT 0x10 /* 4, */ +#define BID_EXP_UNDEF 0x20 /* UNDEF, */ +#define BID_EXP_16PORT 0x30 /* 16, */ +#define BID_LCD_CTRL 0x08 /* LCD Controller */ +#define BID_LCD_NONE 0x00 /* - no controller present */ +#define BID_LCD_PRES 0x08 /* - controller present */ +#define BID_CON_MASK 0x07 /* - connector pinouts */ +#define BID_CON_DB25 0x00 /* - DB-25 F */ +#define BID_CON_RJ45 0x01 /* - rj45 */ + +//------------------------------------------------------------------------------ +// i2eBordStr +// +// This structure contains all the information the ELLIS routines require in +// dealing with a particular board. +//------------------------------------------------------------------------------ +// There are some queues here which are guaranteed to never contain the entry +// for a single channel twice. So they must be slightly larger to allow +// unambiguous full/empty management +// +#define CH_QUEUE_SIZE ABS_MOST_PORTS+2 + +typedef struct _i2eBordStr +{ + porStr i2ePom; // Structure containing the power-on message. + + unsigned short i2ePomSize; + // The number of bytes actually read if + // different from sizeof i2ePom, indicates + // there is an error! + + unsigned short i2eStartMail; + // Contains whatever inbound mailbox data + // present at startup. NO_MAIL_HERE indicates + // nothing was present. No special + // significance as of this writing, but may be + // useful for diagnostic reasons. + + unsigned short i2eValid; + // Indicates validity of the structure; if + // i2eValid == I2E_MAGIC, then we can trust + // the other fields. Some (especially + // initialization) functions are good about + // checking for validity. Many functions do + // not, it being assumed that the larger + // context assures we are using a valid + // i2eBordStrPtr. + + unsigned short i2eError; + // Used for returning an error condition from + // several functions which use i2eBordStrPtr + // as an argument. + + // Accelerators to characterize separate features of a board, derived from a + // number of sources. + + unsigned short i2eFifoSize; + // Always, the size of the FIFO. For + // IntelliPort-II, always the same, for -IIEX + // taken from the Power-On reset message. + + volatile + unsigned short i2eFifoRemains; + // Used during normal operation to indicate a + // lower bound on the amount of data which + // might be in the outbound fifo. + + unsigned char i2eFifoStyle; + // Accelerator which tells which style (-II or + // -IIEX) FIFO we are using. + + unsigned char i2eDataWidth16; + // Accelerator which tells whether we should + // do 8 or 16-bit data transfers. + + unsigned char i2eMaxIrq; + // The highest allowable IRQ, based on the + // slot size. + + // Accelerators for various addresses on the board + int i2eBase; // I/O Address of the Board + int i2eData; // From here data transfers happen + int i2eStatus; // From here status reads happen + int i2ePointer; // (IntelliPort-II: pointer/commands) + int i2eXMail; // (IntelliPOrt-IIEX: mailboxes + int i2eXMask; // (IntelliPort-IIEX: mask write + + //------------------------------------------------------- + // Information presented in a common format across boards + // For each box, bit map of the channels present. Box closest to + // the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable) + // is taken to be box 0. These are derived from product i.d. registers. + + unsigned short i2eChannelMap[ABS_MAX_BOXES]; + + // Same as above, except each is derived from firmware attempting to detect + // the uart presence (by reading a valid GFRCR register). If bits are set in + // i2eChannelMap and not in i2eGoodMap, there is a potential problem. + + unsigned short i2eGoodMap[ABS_MAX_BOXES]; + + // --------------------------- + // For indirect function calls + + // Routine to cause an N-millisecond delay: Patched by the ii2Initialize + // function. + + void (*i2eDelay)(unsigned int); + + // Routine to write N bytes to the board through the FIFO. Returns true if + // all copacetic, otherwise returns false and error is in i2eError field. + // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. + + int (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int); + + // Routine to read N bytes from the board through the FIFO. Returns true if + // copacetic, otherwise returns false and error in i2eError. + // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. + + int (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int); + + // Returns a word from FIFO. Will use 2 byte operations if needed. + + unsigned short (*i2eReadWord)(struct _i2eBordStr *); + + // Writes a word to FIFO. Will use 2 byte operations if needed. + + void (*i2eWriteWord)(struct _i2eBordStr *, unsigned short); + + // Waits specified time for the Transmit FIFO to go empty. Returns true if + // ok, otherwise returns false and error in i2eError. + + int (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int); + + // Returns true or false according to whether the outgoing mailbox is empty. + + int (*i2eTxMailEmpty)(struct _i2eBordStr *); + + // Checks whether outgoing mailbox is empty. If so, sends mail and returns + // true. Otherwise returns false. + + int (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char); + + // If no mail available, returns NO_MAIL_HERE, else returns the value in the + // mailbox (guaranteed can't be NO_MAIL_HERE). + + unsigned short (*i2eGetMail)(struct _i2eBordStr *); + + // Enables the board to interrupt the host when it writes to the mailbox. + // Irqs will not occur, however, until the loadware separately enables + // interrupt generation to the host. The standard loadware does this in + // response to a command packet sent by the host. (Also, disables + // any other potential interrupt sources from the board -- other than the + // inbound mailbox). + + void (*i2eEnableMailIrq)(struct _i2eBordStr *); + + // Writes an arbitrary value to the mask register. + + void (*i2eWriteMask)(struct _i2eBordStr *, unsigned char); + + + // State information + + // During downloading, indicates the number of blocks remaining to download + // to the board. + + short i2eToLoad; + + // State of board (see manifests below) (e.g., whether in reset condition, + // whether standard loadware is installed, etc. + + unsigned char i2eState; + + // These three fields are only valid when there is loadware running on the + // board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED ) + + unsigned char i2eLVersion; // Loadware version + unsigned char i2eLRevision; // Loadware revision + unsigned char i2eLSub; // Loadware subrevision + + // Flags which only have meaning in the context of the standard loadware. + // Somewhat violates the layering concept, but there is so little additional + // needed at the board level (while much additional at the channel level), + // that this beats maintaining two different per-board structures. + + // Indicates which IRQ the board has been initialized (from software) to use + // For MicroChannel boards, any value different from IRQ_UNDEFINED means + // that the software command has been sent to enable interrupts (or specify + // they are disabled). Special value: IRQ_UNDEFINED indicates that the + // software command to select the interrupt has not yet been sent, therefore + // (since the standard loadware insists that it be sent before any other + // packets are sent) no other packets should be sent yet. + + unsigned short i2eUsingIrq; + + // This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us + // putting more in the mailbox until an appropriate mailbox message is + // received. + + unsigned char i2eWaitingForEmptyFifo; + + // Any mailbox bits waiting to be sent to the board are OR'ed in here. + + unsigned char i2eOutMailWaiting; + + // The head of any incoming packet is read into here, is then examined and + // we dispatch accordingly. + + unsigned short i2eLeadoffWord[1]; + + // Running counter of interrupts where the mailbox indicated incoming data. + + unsigned short i2eFifoInInts; + + // Running counter of interrupts where the mailbox indicated outgoing data + // had been stripped. + + unsigned short i2eFifoOutInts; + + // If not void, gives the address of a routine to call if fatal board error + // is found (only applies to standard l/w). + + void (*i2eFatalTrap)(struct _i2eBordStr *); + + // Will point to an array of some sort of channel structures (whose format + // is unknown at this level, being a function of what loadware is + // installed and the code configuration (max sizes of buffers, etc.)). + + void *i2eChannelPtr; + + // Set indicates that the board has gone fatal. + + unsigned short i2eFatal; + + // The number of elements pointed to by i2eChannelPtr. + + unsigned short i2eChannelCnt; + + // Ring-buffers of channel structures whose channels have particular needs. + + rwlock_t Fbuf_spinlock; + volatile + unsigned short i2Fbuf_strip; // Strip index + volatile + unsigned short i2Fbuf_stuff; // Stuff index + void *i2Fbuf[CH_QUEUE_SIZE]; // An array of channel pointers + // of channels who need to send + // flow control packets. + rwlock_t Dbuf_spinlock; + volatile + unsigned short i2Dbuf_strip; // Strip index + volatile + unsigned short i2Dbuf_stuff; // Stuff index + void *i2Dbuf[CH_QUEUE_SIZE]; // An array of channel pointers + // of channels who need to send + // data or in-line command packets. + rwlock_t Bbuf_spinlock; + volatile + unsigned short i2Bbuf_strip; // Strip index + volatile + unsigned short i2Bbuf_stuff; // Stuff index + void *i2Bbuf[CH_QUEUE_SIZE]; // An array of channel pointers + // of channels who need to send + // bypass command packets. + + /* + * A set of flags to indicate that certain events have occurred on at least + * one of the ports on this board. We use this to decide whether to spin + * through the channels looking for breaks, etc. + */ + int got_input; + int status_change; + bidStat channelBtypes; + + /* + * Debugging counters, etc. + */ + unsigned long debugFlowQueued; + unsigned long debugInlineQueued; + unsigned long debugDataQueued; + unsigned long debugBypassQueued; + unsigned long debugFlowCount; + unsigned long debugInlineCount; + unsigned long debugBypassCount; + + rwlock_t read_fifo_spinlock; + rwlock_t write_fifo_spinlock; + +// For queuing interrupt bottom half handlers. /\/\|=mhw=|\/\/ + struct work_struct tqueue_interrupt; + + struct timer_list SendPendingTimer; // Used by iiSendPending + unsigned int SendPendingRetry; +} i2eBordStr, *i2eBordStrPtr; + +//------------------------------------------------------------------- +// Macro Definitions for the indirect calls defined in the i2eBordStr +//------------------------------------------------------------------- +// +#define iiDelay(a,b) (*(a)->i2eDelay)(b) +#define iiWriteBuf(a,b,c) (*(a)->i2eWriteBuf)(a,b,c) +#define iiReadBuf(a,b,c) (*(a)->i2eReadBuf)(a,b,c) + +#define iiWriteWord(a,b) (*(a)->i2eWriteWord)(a,b) +#define iiReadWord(a) (*(a)->i2eReadWord)(a) + +#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b) + +#define iiTxMailEmpty(a) (*(a)->i2eTxMailEmpty)(a) +#define iiTrySendMail(a,b) (*(a)->i2eTrySendMail)(a,b) + +#define iiGetMail(a) (*(a)->i2eGetMail)(a) +#define iiEnableMailIrq(a) (*(a)->i2eEnableMailIrq)(a) +#define iiDisableMailIrq(a) (*(a)->i2eWriteMask)(a,0) +#define iiWriteMask(a,b) (*(a)->i2eWriteMask)(a,b) + +//------------------------------------------- +// Manifests for i2eBordStr: +//------------------------------------------- + +typedef void (*delayFunc_t)(unsigned int); + +// i2eValid +// +#define I2E_MAGIC 0x4251 // Structure is valid. +#define I2E_INCOMPLETE 0x1122 // Structure failed during init. + + +// i2eError +// +#define I2EE_GOOD 0 // Operation successful +#define I2EE_BADADDR 1 // Address out of range +#define I2EE_BADSTATE 2 // Attempt to perform a function when the board + // structure was in the incorrect state +#define I2EE_BADMAGIC 3 // Bad magic number from Power On test (i2ePomSize + // reflects what was read +#define I2EE_PORM_SHORT 4 // Power On message too short +#define I2EE_PORM_LONG 5 // Power On message too long +#define I2EE_BAD_FAMILY 6 // Un-supported board family type +#define I2EE_INCONSIST 7 // Firmware reports something impossible, + // e.g. unexpected number of ports... Almost no + // excuse other than bad FIFO... +#define I2EE_POSTERR 8 // Power-On self test reported a bad error +#define I2EE_BADBUS 9 // Unknown Bus type declared in message +#define I2EE_TXE_TIME 10 // Timed out waiting for TX Fifo to empty +#define I2EE_INVALID 11 // i2eValid field does not indicate a valid and + // complete board structure (for functions which + // require this be so.) +#define I2EE_BAD_PORT 12 // Discrepancy between channels actually found and + // what the product is supposed to have. Check + // i2eGoodMap vs i2eChannelMap for details. +#define I2EE_BAD_IRQ 13 // Someone specified an unsupported IRQ +#define I2EE_NOCHANNELS 14 // No channel structures have been defined (for + // functions requiring this). + +// i2eFifoStyle +// +#define FIFO_II 0 /* IntelliPort-II style: see also i2hw.h */ +#define FIFO_IIEX 1 /* IntelliPort-IIEX style */ + +// i2eGetMail +// +#define NO_MAIL_HERE 0x1111 // Since mail is unsigned char, cannot possibly + // promote to 0x1111. +// i2eState +// +#define II_STATE_COLD 0 // Addresses have been defined, but board not even + // reset yet. +#define II_STATE_RESET 1 // Board,if it exists, has just been reset +#define II_STATE_READY 2 // Board ready for its first block +#define II_STATE_LOADING 3 // Board continuing load +#define II_STATE_LOADED 4 // Board has finished load: status ok +#define II_STATE_BADLOAD 5 // Board has finished load: failed! +#define II_STATE_STDLOADED 6 // Board has finished load: standard firmware + +// i2eUsingIrq +// +#define I2_IRQ_UNDEFINED 0x1352 /* No valid irq (or polling = 0) can + * ever promote to this! */ +//------------------------------------------ +// Handy Macros for i2ellis.c and others +// Note these are common to -II and -IIEX +//------------------------------------------ + +// Given a pointer to the board structure, does the input FIFO have any data or +// not? +// +#define I2_HAS_INPUT(pB) !(inb(pB->i2eStatus) & ST_IN_EMPTY) + +// Given a pointer to the board structure, is there anything in the incoming +// mailbox? +// +#define I2_HAS_MAIL(pB) (inb(pB->i2eStatus) & ST_IN_MAIL) + +#define I2_UPDATE_FIFO_ROOM(pB) ((pB)->i2eFifoRemains = (pB)->i2eFifoSize) + +//------------------------------------------ +// Function Declarations for i2ellis.c +//------------------------------------------ +// +// Functions called directly +// +// Initialization of a board & structure is in four (five!) parts: +// +// 1) iiSetAddress() - Define the board address & delay function for a board. +// 2) iiReset() - Reset the board (provided it exists) +// -- Note you may do this to several boards -- +// 3) iiResetDelay() - Delay for 2 seconds (once for all boards) +// 4) iiInitialize() - Attempt to read Power-up message; further initialize +// accelerators +// +// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write +// loadware. To change loadware, you must begin again with step 2, resetting +// the board again (step 1 not needed). + +static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t ); +static int iiReset(i2eBordStrPtr); +static int iiResetDelay(i2eBordStrPtr); +static int iiInitialize(i2eBordStrPtr); + +// Routine to validate that all channels expected are there. +// +extern int iiValidateChannels(i2eBordStrPtr); + +// Routine used to download a block of loadware. +// +static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int); + +// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile: +// +#define II_DOWN_BADVALID 0 // board structure is invalid +#define II_DOWN_CONTINUING 1 // So far, so good, firmware expects more +#define II_DOWN_GOOD 2 // Download complete, CRC good +#define II_DOWN_BAD 3 // Download complete, but CRC bad +#define II_DOWN_BADFILE 4 // Bad magic number in loadware file +#define II_DOWN_BADSTATE 5 // Board is in an inappropriate state for + // downloading loadware. (see i2eState) +#define II_DOWN_TIMEOUT 6 // Timeout waiting for firmware +#define II_DOWN_OVER 7 // Too much data +#define II_DOWN_UNDER 8 // Not enough data +#define II_DOWN_NOFILE 9 // Loadware file not found + +// Routine to download an entire loadware module: Return values are a subset of +// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING +// +static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int); + +// Many functions defined here return True if good, False otherwise, with an +// error code in i2eError field. Here is a handy macro for setting the error +// code and returning. +// +#define I2_COMPLETE(pB,code) do { \ + pB->i2eError = code; \ + return (code == I2EE_GOOD);\ + } while (0) + +#endif // I2ELLIS_H diff --git a/drivers/staging/tty/ip2/i2hw.h b/drivers/staging/tty/ip2/i2hw.h new file mode 100644 index 000000000000..c0ba6c05f0cd --- /dev/null +++ b/drivers/staging/tty/ip2/i2hw.h @@ -0,0 +1,652 @@ +/******************************************************************************* +* +* (c) 1999 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Definitions limited to properties of the hardware or the +* bootstrap firmware. As such, they are applicable regardless of +* operating system or loadware (standard or diagnostic). +* +*******************************************************************************/ +#ifndef I2HW_H +#define I2HW_H 1 +//------------------------------------------------------------------------------ +// Revision History: +// +// 23 September 1991 MAG First Draft Started...through... +// 11 October 1991 ... Continuing development... +// 6 August 1993 Added support for ISA-4 (asic) which is architected +// as an ISA-CEX with a single 4-port box. +// +// 20 December 1996 AKM Version for Linux +// +//------------------------------------------------------------------------------ +/*------------------------------------------------------------------------------ + +HARDWARE DESCRIPTION: + +Introduction: + +The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8) +addresses in the host's I/O space. + +Some addresses are used to transfer data to/from the board, some to transfer +so-called "mailbox" messages, and some to read bit-mapped status information. +While all the products in the line are functionally similar, some use a 16-bit +data path to transfer data while others use an 8-bit path. Also, the use of +command /status/mailbox registers differs slightly between the II and IIEX +branches of the family. + +The host determines what type of board it is dealing with by reading a string of +sixteen characters from the board. These characters are always placed in the +fifo by the board's local processor whenever the board is reset (either from +power-on or under software control) and are known as the "Power-on Reset +Message." In order that this message can be read from either type of board, the +hardware registers used in reading this message are the same. Once this message +has been read by the host, then it has the information required to operate. + +General Differences between boards: + +The greatest structural difference is between the -II and -IIEX families of +product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support +the data path, mailbox registers, and status registers. This chip contains some +features which are not used in the IntelliPort-II products; a description of +these is omitted here. Because of these many features, it contains many +registers, too many to access directly within a small address space. They are +accessed by first writing a value to a "pointer" register. This value selects +the register to be accessed. The next read or write to that address accesses +the selected register rather than the pointer register. + +The -IIEX boards use a proprietary design similar to the Am4701 in function. But +because of a simpler, more streamlined design it doesn't require so many +registers. This means they can be accessed directly in single operations rather +than through a pointer register. + +Besides these differences, there are differences in whether 8-bit or 16-bit +transfers are used to move data to the board. + +The -II boards are capable only of 8-bit data transfers, while the -IIEX boards +may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP +switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit +transfers are supported (and will be expected by the standard loadware). The +on-board firmware can determine the position of the switch, and whether the +board is installed in a 16-bit slot; it supplies this information to the host as +part of the power-up reset message. + +The configuration switch (#8) and slot selection do not directly configure the +hardware. It is up to the on-board loadware and host-based drivers to act +according to the selected options. That is, loadware and drivers could be +written to perform 8-bit transfers regardless of the state of the DIP switch or +slot (and in a diagnostic environment might well do so). Likewise, 16-bit +transfers could be performed as long as the card is in a 16-bit slot. + +Note the slot selection and DIP switch selection are provided separately: a +board running in 8-bit mode in a 16-bit slot has a greater range of possible +interrupts to choose from; information of potential use to the host. + +All 8-bit data transfers are done in the same way, regardless of whether on a +-II board or a -IIEX board. + +The host must consider two things then: 1) whether a -II or -IIEX product is +being used, and 2) whether an 8-bit or 16-bit data path is used. + +A further difference is that -II boards always have a 512-byte fifo operating in +each direction. -IIEX boards may use fifos of varying size; this size is +reported as part of the power-up message. + +I/O Map Of IntelliPort-II and IntelliPort-IIEX boards: +(Relative to the chosen base address) + +Addr R/W IntelliPort-II IntelliPort-IIEX +---- --- -------------- ---------------- +0 R/W Data Port (byte) Data Port (byte or word) +1 R/W (Not used) (MSB of word-wide data written to Data Port) +2 R Status Register Status Register +2 W Pointer Register Interrupt Mask Register +3 R/W (Not used) Mailbox Registers (6 bits: 11111100) +4,5 -- Reserved for future products +6 -- Reserved for future products +7 R Guaranteed to have no effect +7 W Hardware reset of board. + + +Rules: +All data transfers are performed using the even i/o address. If byte-wide data +transfers are being used, do INB/OUTB operations on the data port. If word-wide +transfers are used, do INW/OUTW operations. In some circumstances (such as +reading the power-up message) you will do INB from the data port, but in this +case the MSB of each word read is lost. When accessing all other unreserved +registers, use byte operations only. +------------------------------------------------------------------------------*/ + +//------------------------------------------------ +// Mandatory Includes: +//------------------------------------------------ +// +#include "ip2types.h" + +//------------------------------------------------------------------------- +// Manifests for the I/O map: +//------------------------------------------------------------------------- +// R/W: Data port (byte) for IntelliPort-II, +// R/W: Data port (byte or word) for IntelliPort-IIEX +// Incoming or outgoing data passes through a FIFO, the status of which is +// available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is +// the primary means of transferring data, commands, flow-control, and status +// information between the host and board. +// +#define FIFO_DATA 0 + +// Another way of passing information between the board and the host is +// through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of +// data. Writing data to the mailbox causes a status bit to be set, and +// potentially interrupting the intended receiver. The sender has some way to +// determine whether the data has been read yet; as soon as it has, it may send +// more. The mailboxes are handled differently on -II and -IIEX products, as +// suggested below. +//------------------------------------------------------------------------------ +// Read: Status Register for IntelliPort-II or -IIEX +// The presence of any bit set here will cause an interrupt to the host, +// provided the corresponding bit has been unmasked in the interrupt mask +// register. Furthermore, interrupts to the host are disabled globally until the +// loadware selects the irq line to use. With the exception of STN_MR, the bits +// remain set so long as the associated condition is true. +// +#define FIFO_STATUS 2 + +// Bit map of status bits which are identical for -II and -IIEX +// +#define ST_OUT_FULL 0x40 // Outbound FIFO full +#define ST_IN_EMPTY 0x20 // Inbound FIFO empty +#define ST_IN_MAIL 0x04 // Inbound Mailbox full + +// The following exists only on the Intelliport-IIEX, and indicates that the +// board has not read the last outgoing mailbox data yet. In the IntelliPort-II, +// the outgoing mailbox may be read back: a zero indicates the board has read +// the data. +// +#define STE_OUT_MAIL 0x80 // Outbound mailbox full (!) + +// The following bits are defined differently for -II and -IIEX boards. Code +// which relies on these bits will need to be functionally different for the two +// types of boards and should be generally avoided because of the additional +// complexity this creates: + +// Bit map of status bits only on -II + +// Fifo has been RESET (cleared when the status register is read). Note that +// this condition cannot be masked and would always interrupt the host, except +// that the hardware reset also disables interrupts globally from the board +// until re-enabled by loadware. This could also arise from the +// Am4701-supported command to reset the chip, but this command is generally not +// used here. +// +#define STN_MR 0x80 + +// See the AMD Am4701 data sheet for details on the following four bits. They +// are not presently used by Computone drivers. +// +#define STN_OUT_AF 0x10 // Outbound FIFO almost full (programmable) +#define STN_IN_AE 0x08 // Inbound FIFO almost empty (programmable) +#define STN_BD 0x02 // Inbound byte detected +#define STN_PE 0x01 // Parity/Framing condition detected + +// Bit-map of status bits only on -IIEX +// +#define STE_OUT_HF 0x10 // Outbound FIFO half full +#define STE_IN_HF 0x08 // Inbound FIFO half full +#define STE_IN_FULL 0x02 // Inbound FIFO full +#define STE_OUT_MT 0x01 // Outbound FIFO empty + +//------------------------------------------------------------------------------ + +// Intelliport-II -- Write Only: the pointer register. +// Values are written to this register to select the Am4701 internal register to +// be accessed on the next operation. +// +#define FIFO_PTR 0x02 + +// Values for the pointer register +// +#define SEL_COMMAND 0x1 // Selects the Am4701 command register + +// Some possible commands: +// +#define SEL_CMD_MR 0x80 // Am4701 command to reset the chip +#define SEL_CMD_SH 0x40 // Am4701 command to map the "other" port into the + // status register. +#define SEL_CMD_UNSH 0 // Am4701 command to "unshift": port maps into its + // own status register. +#define SEL_MASK 0x2 // Selects the Am4701 interrupt mask register. The + // interrupt mask register is bit-mapped to match + // the status register (FIFO_STATUS) except for + // STN_MR. (See above.) +#define SEL_BYTE_DET 0x3 // Selects the Am4701 byte-detect register. (Not + // normally used except in diagnostics.) +#define SEL_OUTMAIL 0x4 // Selects the outbound mailbox (R/W). Reading back + // a value of zero indicates that the mailbox has + // been read by the board and is available for more + // data./ Writing to the mailbox optionally + // interrupts the board, depending on the loadware's + // setting of its interrupt mask register. +#define SEL_AEAF 0x5 // Selects AE/AF threshold register. +#define SEL_INMAIL 0x6 // Selects the inbound mailbox (Read) + +//------------------------------------------------------------------------------ +// IntelliPort-IIEX -- Write Only: interrupt mask (and misc flags) register: +// Unlike IntelliPort-II, bit assignments do NOT match those of the status +// register. +// +#define FIFO_MASK 0x2 + +// Mailbox readback select: +// If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If +// clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox. +// This is the normal situation. The clearing of a mailbox is determined on +// -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback +// capability is provided for diagnostic purposes only. +// +#define MX_OUTMAIL_RSEL 0x80 + +#define MX_IN_MAIL 0x40 // Enables interrupts when incoming mailbox goes + // full (ST_IN_MAIL set). +#define MX_IN_FULL 0x20 // Enables interrupts when incoming FIFO goes full + // (STE_IN_FULL). +#define MX_IN_MT 0x08 // Enables interrupts when incoming FIFO goes empty + // (ST_IN_MT). +#define MX_OUT_FULL 0x04 // Enables interrupts when outgoing FIFO goes full + // (ST_OUT_FULL). +#define MX_OUT_MT 0x01 // Enables interrupts when outgoing FIFO goes empty + // (STE_OUT_MT). + +// Any remaining bits are reserved, and should be written to ZERO for +// compatibility with future Computone products. + +//------------------------------------------------------------------------------ +// IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two +// bits always read back 0). +// Read: One of the mailboxes, usually Inbound. +// Inbound Mailbox (MX_OUTMAIL_RSEL = 0) +// Outbound Mailbox (MX_OUTMAIL_RSEL = 1) +// Write: Outbound Mailbox +// For the IntelliPort-II boards, the outbound mailbox is read back to determine +// whether the board has read the data (0 --> data has been read). For the +// IntelliPort-IIEX, this is done by reading a status register. To determine +// whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit +// in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by +// setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the +// case with the -II boards. For this reason, FIFO_MAIL is normally used to read +// the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for +// MX_OUTMAIL_RSEL description.) +// +#define FIFO_MAIL 0x3 + +//------------------------------------------------------------------------------ +// WRITE ONLY: Resets the board. (Data doesn't matter). +// +#define FIFO_RESET 0x7 + +//------------------------------------------------------------------------------ +// READ ONLY: Will have no effect. (Data is undefined.) +// Actually, there will be an effect, in that the operation is sure to generate +// a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short +// delays when no comparable time constant is available. +// +#define FIFO_NOP 0x7 + +//------------------------------------------------------------------------------ +// RESET & POWER-ON RESET MESSAGE +/*------------------------------------------------------------------------------ +RESET: + +The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel +reset, and via a write to the reset register described above. For products using +the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses, +the Power-up and channel reset sources cause additional hardware initialization +which should only occur at system startup time. + +The third type of reset, called a "command reset", is done by writing any data +to the FIFO_RESET address described above. This resets the on-board processor, +FIFO, UARTS, and associated hardware. + +This passes control of the board to the bootstrap firmware, which performs a +Power-On Self Test and which detects its current configuration. For example, +-IIEX products determine the size of FIFO which has been installed, and the +number and type of expansion boxes attached. + +This and other information is then written to the FIFO in a 16-byte data block +to be read by the host. This block is guaranteed to be present within two (2) +seconds of having received the command reset. The firmware is now ready to +receive loadware from the host. + +It is good practice to perform a command reset to the board explicitly as part +of your software initialization. This allows your code to properly restart from +a soft boot. (Many systems do not issue channel reset on soft boot). + +Because of a hardware reset problem on some of the Cirrus Logic 1400's which are +used on the product, it is recommended that you reset the board twice, separated +by an approximately 50 milliseconds delay. (VERY approximately: probably ok to +be off by a factor of five. The important point is that the first command reset +in fact generates a reset pulse on the board. This pulse is guaranteed to last +less than 10 milliseconds. The additional delay ensures the 1400 has had the +chance to respond sufficiently to the first reset. Why not a longer delay? Much +more than 50 milliseconds gets to be noticable, but the board would still work. + +Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap +firmware is ready to receive loadware. + +Note on Power-on Reset Message format: +The various fields have been designed with future expansion in view. +Combinations of bitfields and values have been defined which define products +which may not currently exist. This has been done to allow drivers to anticipate +the possible introduction of products in a systematic fashion. This is not +intended to suggest that each potential product is actually under consideration. +------------------------------------------------------------------------------*/ + +//---------------------------------------- +// Format of Power-on Reset Message +//---------------------------------------- + +typedef union _porStr // "por" stands for Power On Reset +{ + unsigned char c[16]; // array used when considering the message as a + // string of undifferentiated characters + + struct // Elements used when considering values + { + // The first two bytes out of the FIFO are two magic numbers. These are + // intended to establish that there is indeed a member of the + // IntelliPort-II(EX) family present. The remaining bytes may be + // expected // to be valid. When reading the Power-on Reset message, + // if the magic numbers do not match it is probably best to stop + // reading immediately. You are certainly not reading our board (unless + // hardware is faulty), and may in fact be reading some other piece of + // hardware. + + unsigned char porMagic1; // magic number: first byte == POR_MAGIC_1 + unsigned char porMagic2; // magic number: second byte == POR_MAGIC_2 + + // The Version, Revision, and Subrevision are stored as absolute numbers + // and would normally be displayed in the format V.R.S (e.g. 1.0.2) + + unsigned char porVersion; // Bootstrap firmware version number + unsigned char porRevision; // Bootstrap firmware revision number + unsigned char porSubRev; // Bootstrap firmware sub-revision number + + unsigned char porID; // Product ID: Bit-mapped according to + // conventions described below. Among other + // things, this allows us to distinguish + // IntelliPort-II boards from IntelliPort-IIEX + // boards. + + unsigned char porBus; // IntelliPort-II: Unused + // IntelliPort-IIEX: Bus Information: + // Bit-mapped below + + unsigned char porMemory; // On-board DRAM size: in 32k blocks + + // porPorts1 (and porPorts2) are used to determine the ports which are + // available to the board. For non-expandable product, a single number + // is sufficient. For expandable product, the board may be connected + // to as many as four boxes. Each box may be (so far) either a 16-port + // or an 8-port size. Whenever an 8-port box is used, the remaining 8 + // ports leave gaps between existing channels. For that reason, + // expandable products must report a MAP of available channels. Since + // each UART supports four ports, we represent each UART found by a + // single bit. Using two bytes to supply the mapping information we + // report the presense or absense of up to 16 UARTS, or 64 ports in + // steps of 4 ports. For -IIEX products, the ports are numbered + // starting at the box closest to the controller in the "chain". + + // Interpreted Differently for IntelliPort-II and -IIEX. + // -II: Number of ports (Derived actually from product ID). See + // Diag1&2 to indicate if uart was actually detected. + // -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This + // bitmap is based on detecting the uarts themselves; + // see porFlags for information from the box i.d's. + unsigned char porPorts1; + + unsigned char porDiag1; // Results of on-board P.O.S.T, 1st byte + unsigned char porDiag2; // Results of on-board P.O.S.T, 2nd byte + unsigned char porSpeed; // Speed of local CPU: given as MHz x10 + // e.g., 16.0 MHz CPU is reported as 160 + unsigned char porFlags; // Misc information (see manifests below) + // Bit-mapped: CPU type, UART's present + + unsigned char porPorts2; // -II: Undefined + // -IIEX: Bit-map of UARTS found, MSB (see + // above for LSB) + + // IntelliPort-II: undefined + // IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the + // host interface FIFO, in each direction. When running the -IIEX in + // 8-bit mode, fifo capacity is halved. The bootstrap firmware will + // have already accounted for this fact in generating this number. + unsigned char porFifoSize; + + // IntelliPort-II: undefined + // IntelliPort-IIEX: The number of boxes connected. (Presently 1-4) + unsigned char porNumBoxes; + } e; +} porStr, *porStrPtr; + +//-------------------------- +// Values for porStr fields +//-------------------------- + +//--------------------- +// porMagic1, porMagic2 +//---------------------- +// +#define POR_MAGIC_1 0x96 // The only valid value for porMagic1 +#define POR_MAGIC_2 0x35 // The only valid value for porMagic2 +#define POR_1_INDEX 0 // Byte position of POR_MAGIC_1 +#define POR_2_INDEX 1 // Ditto for POR_MAGIC_2 + +//---------------------- +// porID +//---------------------- +// +#define POR_ID_FAMILY 0xc0 // These bits indicate the general family of + // product. +#define POR_ID_FII 0x00 // Family is "IntelliPort-II" +#define POR_ID_FIIEX 0x40 // Family is "IntelliPort-IIEX" + +// These bits are reserved, presently zero. May be used at a later date to +// convey other product information. +// +#define POR_ID_RESERVED 0x3c + +#define POR_ID_SIZE 0x03 // Remaining bits indicate number of ports & + // Connector information. +#define POR_ID_II_8 0x00 // For IntelliPort-II, indicates 8-port using + // standard brick. +#define POR_ID_II_8R 0x01 // For IntelliPort-II, indicates 8-port using + // RJ11's (no CTS) +#define POR_ID_II_6 0x02 // For IntelliPort-II, indicates 6-port using + // RJ45's +#define POR_ID_II_4 0x03 // For IntelliPort-II, indicates 4-port using + // 4xRJ45 connectors +#define POR_ID_EX 0x00 // For IntelliPort-IIEX, indicates standard + // expandable controller (other values reserved) + +//---------------------- +// porBus +//---------------------- + +// IntelliPort-IIEX only: Board is installed in a 16-bit slot +// +#define POR_BUS_SLOT16 0x20 + +// IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface +// operation. +// +#define POR_BUS_DIP16 0x10 + +// Bits 0-2 indicate type of bus: This information is stored in the bootstrap +// loadware, different loadware being used on different products for different +// buses. For most situations, the drivers do not need this information; but it +// is handy in a diagnostic environment. For example, on microchannel boards, +// you would not want to try to test several interrupts, only the one for which +// you were configured. +// +#define POR_BUS_TYPE 0x07 + +// Unknown: this product doesn't know what bus it is running in. (e.g. if same +// bootstrap firmware were wanted for two different buses.) +// +#define POR_BUS_T_UNK 0 + +// Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK +// state, since the same bootstrap firmware is used for each. + +#define POR_BUS_T_MCA 1 // MCA BUS */ +#define POR_BUS_T_EISA 2 // EISA BUS */ +#define POR_BUS_T_ISA 3 // ISA BUS */ + +// Values 4-7 Reserved + +// Remaining bits are reserved + +//---------------------- +// porDiag1 +//---------------------- + +#define POR_BAD_MAPPER 0x80 // HW failure on P.O.S.T: Chip mapper failed + +// These two bits valid only for the IntelliPort-II +// +#define POR_BAD_UART1 0x01 // First 1400 bad +#define POR_BAD_UART2 0x02 // Second 1400 bad + +//---------------------- +// porDiag2 +//---------------------- + +#define POR_DEBUG_PORT 0x80 // debug port was detected by the P.O.S.T +#define POR_DIAG_OK 0x00 // Indicates passage: Failure codes not yet + // available. + // Other bits undefined. +//---------------------- +// porFlags +//---------------------- + +#define POR_CPU 0x03 // These bits indicate supposed CPU type +#define POR_CPU_8 0x01 // Board uses an 80188 (no such thing yet) +#define POR_CPU_6 0x02 // Board uses an 80186 (all existing products) +#define POR_CEX4 0x04 // If set, this is an ISA-CEX/4: An ISA-4 (asic) + // which is architected like an ISA-CEX connected + // to a (hitherto impossible) 4-port box. +#define POR_BOXES 0xf0 // Valid for IntelliPort-IIEX only: Map of Box + // sizes based on box I.D. +#define POR_BOX_16 0x10 // Set indicates 16-port, clear 8-port + +//------------------------------------- +// LOADWARE and DOWNLOADING CODE +//------------------------------------- + +/* +Loadware may be sent to the board in two ways: +1) It may be read from a (binary image) data file block by block as each block + is sent to the board. This is only possible when the initialization is + performed by code which can access your file system. This is most suitable + for diagnostics and appications which use the interface library directly. + +2) It may be hard-coded into your source by including a .h file (typically + supplied by Computone), which declares a data array and initializes every + element. This achieves the same result as if an entire loadware file had + been read into the array. + + This requires more data space in your program, but access to the file system + is not required. This method is more suited to driver code, which typically + is running at a level too low to access the file system directly. + +At present, loadware can only be generated at Computone. + +All Loadware begins with a header area which has a particular format. This +includes a magic number which identifies the file as being (purportedly) +loadware, CRC (for the loader), and version information. +*/ + + +//----------------------------------------------------------------------------- +// Format of loadware block +// +// This is defined as a union so we can pass a pointer to one of these items +// and (if it is the first block) pick out the version information, etc. +// +// Otherwise, to deal with this as a simple character array +//------------------------------------------------------------------------------ + +#define LOADWARE_BLOCK_SIZE 512 // Number of bytes in each block of loadware + +typedef union _loadHdrStr +{ + unsigned char c[LOADWARE_BLOCK_SIZE]; // Valid for every block + + struct // These fields are valid for only the first block of loadware. + { + unsigned char loadMagic; // Magic number: see below + unsigned char loadBlocksMore; // How many more blocks? + unsigned char loadCRC[2]; // Two CRC bytes: used by loader + unsigned char loadVersion; // Version number + unsigned char loadRevision; // Revision number + unsigned char loadSubRevision; // Sub-revision number + unsigned char loadSpares[9]; // Presently unused + unsigned char loadDates[32]; // Null-terminated string which can give + // date and time of compilation + } e; +} loadHdrStr, *loadHdrStrPtr; + +//------------------------------------ +// Defines for downloading code: +//------------------------------------ + +// The loadMagic field in the first block of the loadfile must be this, else the +// file is not valid. +// +#define MAGIC_LOADFILE 0x3c + +// How do we know the load was successful? On completion of the load, the +// bootstrap firmware returns a code to indicate whether it thought the download +// was valid and intends to execute it. These are the only possible valid codes: +// +#define LOADWARE_OK 0xc3 // Download was ok +#define LOADWARE_BAD 0x5a // Download was bad (CRC error) + +// Constants applicable to writing blocks of loadware: +// The first block of loadware might take 600 mS to load, in extreme cases. +// (Expandable board: worst case for sending startup messages to the LCD's). +// The 600mS figure is not really a calculation, but a conservative +// guess/guarantee. Usually this will be within 100 mS, like subsequent blocks. +// +#define MAX_DLOAD_START_TIME 1000 // 1000 mS +#define MAX_DLOAD_READ_TIME 100 // 100 mS + +// Firmware should respond with status (see above) within this long of host +// having sent the final block. +// +#define MAX_DLOAD_ACK_TIME 100 // 100 mS, again! + +//------------------------------------------------------ +// MAXIMUM NUMBER OF PORTS PER BOARD: +// This is fixed for now (with the expandable), but may +// be expanding according to even newer products. +//------------------------------------------------------ +// +#define ABS_MAX_BOXES 4 // Absolute most boxes per board +#define ABS_BIGGEST_BOX 16 // Absolute the most ports per box +#define ABS_MOST_PORTS (ABS_MAX_BOXES * ABS_BIGGEST_BOX) + +#define I2_OUTSW(port, addr, count) outsw((port), (addr), (((count)+1)/2)) +#define I2_OUTSB(port, addr, count) outsb((port), (addr), (((count)+1))&-2) +#define I2_INSW(port, addr, count) insw((port), (addr), (((count)+1)/2)) +#define I2_INSB(port, addr, count) insb((port), (addr), (((count)+1))&-2) + +#endif // I2HW_H + diff --git a/drivers/staging/tty/ip2/i2lib.c b/drivers/staging/tty/ip2/i2lib.c new file mode 100644 index 000000000000..0d10b89218ed --- /dev/null +++ b/drivers/staging/tty/ip2/i2lib.c @@ -0,0 +1,2214 @@ +/******************************************************************************* +* +* (c) 1999 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport +* serial I/O controllers. +* +* DESCRIPTION: High-level interface code for the device driver. Uses the +* Extremely Low Level Interface Support (i2ellis.c). Provides an +* interface to the standard loadware, to support drivers or +* application code. (This is included source code, not a separate +* compilation module.) +* +*******************************************************************************/ +//------------------------------------------------------------------------------ +// Note on Strategy: +// Once the board has been initialized, it will interrupt us when: +// 1) It has something in the fifo for us to read (incoming data, flow control +// packets, or whatever). +// 2) It has stripped whatever we have sent last time in the FIFO (and +// consequently is ready for more). +// +// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This +// worsens performance considerably, but is done so that a great many channels +// might use only a little memory. +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Revision History: +// +// 0.00 - 4/16/91 --- First Draft +// 0.01 - 4/29/91 --- 1st beta release +// 0.02 - 6/14/91 --- Changes to allow small model compilation +// 0.03 - 6/17/91 MAG Break reporting protected from interrupts routines with +// in-line asm added for moving data to/from ring buffers, +// replacing a variety of methods used previously. +// 0.04 - 6/21/91 MAG Initial flow-control packets not queued until +// i2_enable_interrupts time. Former versions would enqueue +// them at i2_init_channel time, before we knew how many +// channels were supposed to exist! +// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now; +// supports new 16-bit protocol and expandable boards. +// - 10/24/91 MAG Most changes in place and stable. +// 0.06 - 2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no +// argument. +// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt +// level (mostly responses to specific commands.) +// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet +// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE +// turning on the interrupt. +// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check +// some incoming. +// +// 1.1 - 12/25/96 AKM Linux version. +// - 10/09/98 DMC Revised Linux version. +//------------------------------------------------------------------------------ + +//************ +//* Includes * +//************ + +#include +#include "i2lib.h" + + +//*********************** +//* Function Prototypes * +//*********************** +static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int); +static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int ); +static void i2StripFifo(i2eBordStrPtr); +static void i2StuffFifoBypass(i2eBordStrPtr); +static void i2StuffFifoFlow(i2eBordStrPtr); +static void i2StuffFifoInline(i2eBordStrPtr); +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 void serviceOutgoingFifo(i2eBordStrPtr); + +// Functions defined in ip2.c as part of interrupt handling +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); + +//*************** +//* Debug Data * +//*************** +#ifdef DEBUG_FIFO + +unsigned char DBGBuf[0x4000]; +unsigned short I = 0; + +static void +WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) +{ + char *p = src; + + // XXX: We need a spin lock here if we ever use this again + + while (*s) { // copy label + DBGBuf[I] = *s++; + I = I++ & 0x3fff; + } + while (n--) { // copy data + DBGBuf[I] = *p++; + I = I++ & 0x3fff; + } +} + +static void +fatality(i2eBordStrPtr pB ) +{ + int i; + + for (i=0;i= ' ' && DBGBuf[i] <= '~') { + printk(" %c ",DBGBuf[i]); + } else { + printk(" . "); + } + } + printk("\n"); + printk("Last index %x\n",I); +} +#endif /* DEBUG_FIFO */ + +//******** +//* Code * +//******** + +static inline int +i2Validate ( i2ChanStrPtr pCh ) +{ + //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity, + // (CHANNEL_MAGIC | CHANNEL_SUPPORT)); + return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) + == (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 +// Returns: Nothing +// +// Description: +// If any outgoing mail bits are set and there is outgoing mailbox is empty, +// send the mail and clear the bits. +//****************************************************************************** +static void +iiSendPendingMail(i2eBordStrPtr pB) +{ + if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) ) + { + if (iiTrySendMail(pB, pB->i2eOutMailWaiting)) + { + /* If we were already waiting for fifo to empty, + * or just sent MB_OUT_STUFFED, then we are + * still waiting for it to empty, until we should + * receive an MB_IN_STRIPPED from the board. + */ + pB->i2eWaitingForEmptyFifo |= + (pB->i2eOutMailWaiting & MB_OUT_STUFFED); + pB->i2eOutMailWaiting = 0; + pB->SendPendingRetry = 0; + } else { +/* The only time we hit this area is when "iiTrySendMail" has + failed. That only occurs when the outbound mailbox is + still busy with the last message. We take a short breather + to let the board catch up with itself and then try again. + 16 Retries is the limit - then we got a borked board. + /\/\|=mhw=|\/\/ */ + + if( ++pB->SendPendingRetry < 16 ) { + 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" ); + } + } + } +} + +//****************************************************************************** +// Function: i2InitChannels(pB, nChannels, pCh) +// Parameters: Pointer to Ellis Board structure +// Number of channels to initialize +// Pointer to first element in an array of channel structures +// Returns: Success or failure +// +// Description: +// +// This function patches pointers, back-pointers, and initializes all the +// elements in the channel structure array. +// +// This should be run after the board structure is initialized, through having +// loaded the standard loadware (otherwise it complains). +// +// In any case, it must be done before any serious work begins initializing the +// irq's or sending commands... +// +//****************************************************************************** +static int +i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) +{ + int index, stuffIndex; + i2ChanStrPtr *ppCh; + + if (pB->i2eValid != I2E_MAGIC) { + I2_COMPLETE(pB, I2EE_BADMAGIC); + } + if (pB->i2eState != II_STATE_STDLOADED) { + I2_COMPLETE(pB, I2EE_BADSTATE); + } + + rwlock_init(&pB->read_fifo_spinlock); + rwlock_init(&pB->write_fifo_spinlock); + rwlock_init(&pB->Dbuf_spinlock); + rwlock_init(&pB->Bbuf_spinlock); + rwlock_init(&pB->Fbuf_spinlock); + + // NO LOCK needed yet - this is init + + pB->i2eChannelPtr = pCh; + pB->i2eChannelCnt = nChannels; + + pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0; + pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0; + pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0; + + pB->SendPendingRetry = 0; + + memset ( pCh, 0, sizeof (i2ChanStr) * nChannels ); + + for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf); + nChannels && index < ABS_MOST_PORTS; + index++) + { + if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) { + continue; + } + rwlock_init(&pCh->Ibuf_spinlock); + rwlock_init(&pCh->Obuf_spinlock); + rwlock_init(&pCh->Cbuf_spinlock); + rwlock_init(&pCh->Pbuf_spinlock); + // NO LOCK needed yet - this is init + // Set up validity flag according to support level + if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) { + pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT; + } else { + pCh->validity = CHANNEL_MAGIC; + } + pCh->pMyBord = pB; /* Back-pointer */ + + // Prepare an outgoing flow-control packet to send as soon as the chance + // occurs. + if ( pCh->validity & CHANNEL_SUPPORT ) { + pCh->infl.hd.i2sChannel = index; + pCh->infl.hd.i2sCount = 5; + pCh->infl.hd.i2sType = PTYPE_BYPASS; + pCh->infl.fcmd = 37; + pCh->infl.asof = 0; + pCh->infl.room = IBUF_SIZE - 1; + + pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full + + // The following is similar to calling i2QueueNeeds, except that this + // is done in longhand, since we are setting up initial conditions on + // many channels at once. + pCh->channelNeeds = NEED_FLOW; // Since starting from scratch + pCh->sinceLastFlow = 0; // No bytes received since last flow + // control packet was queued + stuffIndex++; + *ppCh++ = pCh; // List this channel as needing + // initial flow control packet sent + } + + // Don't allow anything to be sent until the status packets come in from + // the board. + + pCh->outfl.asof = 0; + pCh->outfl.room = 0; + + // Initialize all the ring buffers + + pCh->Ibuf_stuff = pCh->Ibuf_strip = 0; + pCh->Obuf_stuff = pCh->Obuf_strip = 0; + pCh->Cbuf_stuff = pCh->Cbuf_strip = 0; + + memset( &pCh->icount, 0, sizeof (struct async_icount) ); + pCh->hotKeyIn = HOT_CLEAR; + pCh->channelOptions = 0; + pCh->bookMarks = 0; + init_waitqueue_head(&pCh->pBookmarkWait); + + init_waitqueue_head(&pCh->open_wait); + init_waitqueue_head(&pCh->close_wait); + init_waitqueue_head(&pCh->delta_msr_wait); + + // Set base and divisor so default custom rate is 9600 + pCh->BaudBase = 921600; // MAX for ST654, changed after we get + pCh->BaudDivisor = 96; // the boxids (UART types) later + + pCh->dataSetIn = 0; + pCh->dataSetOut = 0; + + pCh->wopen = 0; + pCh->throttled = 0; + + pCh->speed = CBR_9600; + + pCh->flags = 0; + + pCh->ClosingDelay = 5*HZ/10; + pCh->ClosingWaitTime = 30*HZ; + + // Initialize task queue objects + INIT_WORK(&pCh->tqueue_input, do_input); + INIT_WORK(&pCh->tqueue_status, do_status); + +#ifdef IP2DEBUG_TRACE + pCh->trace = ip2trace; +#endif + + ++pCh; + --nChannels; + } + // No need to check for wrap here; this is initialization. + pB->i2Fbuf_stuff = stuffIndex; + I2_COMPLETE(pB, I2EE_GOOD); + +} + +//****************************************************************************** +// Function: i2DeQueueNeeds(pB, type) +// Parameters: Pointer to a board structure +// type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW +// Returns: +// Pointer to a channel structure +// +// Description: Returns pointer struct of next channel that needs service of +// the type specified. Otherwise returns a NULL reference. +// +//****************************************************************************** +static i2ChanStrPtr +i2DeQueueNeeds(i2eBordStrPtr pB, int type) +{ + unsigned short queueIndex; + unsigned long flags; + + i2ChanStrPtr pCh = NULL; + + switch(type) { + + case NEED_INLINE: + + write_lock_irqsave(&pB->Dbuf_spinlock, flags); + if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip) + { + queueIndex = pB->i2Dbuf_strip; + pCh = pB->i2Dbuf[queueIndex]; + queueIndex++; + if (queueIndex >= CH_QUEUE_SIZE) { + queueIndex = 0; + } + pB->i2Dbuf_strip = queueIndex; + pCh->channelNeeds &= ~NEED_INLINE; + } + write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); + break; + + case NEED_BYPASS: + + write_lock_irqsave(&pB->Bbuf_spinlock, flags); + if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip) + { + queueIndex = pB->i2Bbuf_strip; + pCh = pB->i2Bbuf[queueIndex]; + queueIndex++; + if (queueIndex >= CH_QUEUE_SIZE) { + queueIndex = 0; + } + pB->i2Bbuf_strip = queueIndex; + pCh->channelNeeds &= ~NEED_BYPASS; + } + write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); + break; + + case NEED_FLOW: + + write_lock_irqsave(&pB->Fbuf_spinlock, flags); + if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip) + { + queueIndex = pB->i2Fbuf_strip; + pCh = pB->i2Fbuf[queueIndex]; + queueIndex++; + if (queueIndex >= CH_QUEUE_SIZE) { + queueIndex = 0; + } + pB->i2Fbuf_strip = queueIndex; + pCh->channelNeeds &= ~NEED_FLOW; + } + write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); + break; + default: + printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type); + break; + } + return pCh; +} + +//****************************************************************************** +// Function: i2QueueNeeds(pB, pCh, type) +// Parameters: Pointer to a board structure +// Pointer to a channel structure +// type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW +// Returns: Nothing +// +// Description: +// For each type of need selected, if the given channel is not already in the +// queue, adds it, and sets the flag indicating it is in the queue. +//****************************************************************************** +static void +i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type) +{ + unsigned short queueIndex; + unsigned long flags; + + // We turn off all the interrupts during this brief process, since the + // interrupt-level code might want to put things on the queue as well. + + switch (type) { + + case NEED_INLINE: + + write_lock_irqsave(&pB->Dbuf_spinlock, flags); + if ( !(pCh->channelNeeds & NEED_INLINE) ) + { + pCh->channelNeeds |= NEED_INLINE; + queueIndex = pB->i2Dbuf_stuff; + pB->i2Dbuf[queueIndex++] = pCh; + if (queueIndex >= CH_QUEUE_SIZE) + queueIndex = 0; + pB->i2Dbuf_stuff = queueIndex; + } + write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); + break; + + case NEED_BYPASS: + + write_lock_irqsave(&pB->Bbuf_spinlock, flags); + if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS)) + { + pCh->channelNeeds |= NEED_BYPASS; + queueIndex = pB->i2Bbuf_stuff; + pB->i2Bbuf[queueIndex++] = pCh; + if (queueIndex >= CH_QUEUE_SIZE) + queueIndex = 0; + pB->i2Bbuf_stuff = queueIndex; + } + write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); + break; + + case NEED_FLOW: + + write_lock_irqsave(&pB->Fbuf_spinlock, flags); + if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW)) + { + pCh->channelNeeds |= NEED_FLOW; + queueIndex = pB->i2Fbuf_stuff; + pB->i2Fbuf[queueIndex++] = pCh; + if (queueIndex >= CH_QUEUE_SIZE) + queueIndex = 0; + pB->i2Fbuf_stuff = queueIndex; + } + write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); + break; + + case NEED_CREDIT: + pCh->channelNeeds |= NEED_CREDIT; + break; + default: + printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type); + break; + } + return; +} + +//****************************************************************************** +// Function: i2QueueCommands(type, pCh, timeout, nCommands, pCs,...) +// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE +// pointer to the channel structure +// maximum period to wait +// number of commands (n) +// n commands +// Returns: Number of commands sent, or -1 for error +// +// get board lock before calling +// +// Description: +// Queues up some commands to be sent to a channel. To send possibly several +// bypass or inline commands to the given channel. The timeout parameter +// indicates how many HUNDREDTHS OF SECONDS to wait until there is room: +// 0 = return immediately if no room, -ive = wait forever, +ive = number of +// 1/100 seconds to wait. Return values: +// -1 Some kind of nasty error: bad channel structure or invalid arguments. +// 0 No room to send all the commands +// (+) Number of commands sent +//****************************************************************************** +static int +i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands, + cmdSyntaxPtr pCs0,...) +{ + int totalsize = 0; + int blocksize; + int lastended; + cmdSyntaxPtr *ppCs; + cmdSyntaxPtr pCs; + int count; + int flag; + i2eBordStrPtr pB; + + unsigned short maxBlock; + unsigned short maxBuff; + short bufroom; + unsigned short stuffIndex; + unsigned char *pBuf; + unsigned char *pInsert; + unsigned char *pDest, *pSource; + unsigned short channel; + int cnt; + unsigned long flags = 0; + rwlock_t *lock_var_p = NULL; + + // Make sure the channel exists, otherwise do nothing + if ( !i2Validate ( pCh ) ) { + return -1; + } + + ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 ); + + pB = pCh->pMyBord; + + // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT + if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED) + return -2; + // If the board has gone fatal, return bad, and also hit the trap routine if + // it exists. + if (pB->i2eFatal) { + if ( pB->i2eFatalTrap ) { + (*(pB)->i2eFatalTrap)(pB); + } + return -3; + } + // Set up some variables, Which buffers are we using? How big are they? + switch(type) + { + case PTYPE_INLINE: + flag = INL; + maxBlock = MAX_OBUF_BLOCK; + maxBuff = OBUF_SIZE; + pBuf = pCh->Obuf; + break; + case PTYPE_BYPASS: + flag = BYP; + maxBlock = MAX_CBUF_BLOCK; + maxBuff = CBUF_SIZE; + pBuf = pCh->Cbuf; + break; + default: + return -4; + } + // Determine the total size required for all the commands + totalsize = blocksize = sizeof(i2CmdHeader); + lastended = 0; + ppCs = &pCs0; + for ( count = nCommands; count; count--, ppCs++) + { + pCs = *ppCs; + cnt = pCs->length; + // Will a new block be needed for this one? + // Two possible reasons: too + // big or previous command has to be at the end of a packet. + if ((blocksize + cnt > maxBlock) || lastended) { + blocksize = sizeof(i2CmdHeader); + totalsize += sizeof(i2CmdHeader); + } + totalsize += cnt; + blocksize += cnt; + + // If this command had to end a block, then we will make sure to + // account for it should there be any more blocks. + lastended = pCs->flags & END; + } + for (;;) { + // Make sure any pending flush commands go out before we add more data. + if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) { + // How much room (this time through) ? + switch(type) { + case PTYPE_INLINE: + lock_var_p = &pCh->Obuf_spinlock; + write_lock_irqsave(lock_var_p, flags); + stuffIndex = pCh->Obuf_stuff; + bufroom = pCh->Obuf_strip - stuffIndex; + break; + case PTYPE_BYPASS: + lock_var_p = &pCh->Cbuf_spinlock; + write_lock_irqsave(lock_var_p, flags); + stuffIndex = pCh->Cbuf_stuff; + bufroom = pCh->Cbuf_strip - stuffIndex; + break; + default: + return -5; + } + if (--bufroom < 0) { + bufroom += maxBuff; + } + + ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom ); + + // Check for overflow + if (totalsize <= bufroom) { + // Normal Expected path - We still hold LOCK + break; /* from for()- Enough room: goto proceed */ + } + ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); + write_unlock_irqrestore(lock_var_p, flags); + } else + ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); + + /* Prepare to wait for buffers to empty */ + serviceOutgoingFifo(pB); // Dump what we got + + if (timeout == 0) { + return 0; // Tired of waiting + } + if (timeout > 0) + timeout--; // So negative values == forever + + if (!in_interrupt()) { + schedule_timeout_interruptible(1); // short nap + } else { + // we cannot sched/sleep in interrupt silly + return 0; + } + if (signal_pending(current)) { + return 0; // Wake up! Time to die!!! + } + + ip2trace (CHANN, ITRC_QUEUE, 4, 0 ); + + } // end of for(;;) + + // At this point we have room and the lock - stick them in. + channel = pCh->infl.hd.i2sChannel; + pInsert = &pBuf[stuffIndex]; // Pointer to start of packet + pDest = CMD_OF(pInsert); // Pointer to start of command + + // When we start counting, the block is the size of the header + for (blocksize = sizeof(i2CmdHeader), count = nCommands, + lastended = 0, ppCs = &pCs0; + count; + count--, ppCs++) + { + pCs = *ppCs; // Points to command protocol structure + + // If this is a bookmark request command, post the fact that a bookmark + // request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ + // has no parameters! The more general solution would be to reference + // pCs->cmd[0]. + if (pCs == CMD_BMARK_REQ) { + pCh->bookMarks++; + + ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks ); + + } + cnt = pCs->length; + + // If this command would put us over the maximum block size or + // if the last command had to be at the end of a block, we end + // the existing block here and start a new one. + if ((blocksize + cnt > maxBlock) || lastended) { + + ip2trace (CHANN, ITRC_QUEUE, 5, 0 ); + + PTYPE_OF(pInsert) = type; + CHANNEL_OF(pInsert) = channel; + // count here does not include the header + CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); + stuffIndex += blocksize; + if(stuffIndex >= maxBuff) { + stuffIndex = 0; + pInsert = pBuf; + } + pInsert = &pBuf[stuffIndex]; // Pointer to start of next pkt + pDest = CMD_OF(pInsert); + blocksize = sizeof(i2CmdHeader); + } + // Now we know there is room for this one in the current block + + blocksize += cnt; // Total bytes in this command + pSource = pCs->cmd; // Copy the command into the buffer + while (cnt--) { + *pDest++ = *pSource++; + } + // If this command had to end a block, then we will make sure to account + // for it should there be any more blocks. + lastended = pCs->flags & END; + } // end for + // Clean up the final block by writing header, etc + + PTYPE_OF(pInsert) = type; + CHANNEL_OF(pInsert) = channel; + // count here does not include the header + CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); + stuffIndex += blocksize; + if(stuffIndex >= maxBuff) { + stuffIndex = 0; + pInsert = pBuf; + } + // Updates the index, and post the need for service. When adding these to + // the queue of channels, we turn off the interrupt while doing so, + // because at interrupt level we might want to push a channel back to the + // end of the queue. + switch(type) + { + case PTYPE_INLINE: + pCh->Obuf_stuff = stuffIndex; // Store buffer pointer + write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); + + pB->debugInlineQueued++; + // Add the channel pointer to list of channels needing service (first + // come...), if it's not already there. + i2QueueNeeds(pB, pCh, NEED_INLINE); + break; + + case PTYPE_BYPASS: + pCh->Cbuf_stuff = stuffIndex; // Store buffer pointer + write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); + + pB->debugBypassQueued++; + // Add the channel pointer to list of channels needing service (first + // come...), if it's not already there. + i2QueueNeeds(pB, pCh, NEED_BYPASS); + break; + } + + ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands ); + + return nCommands; // Good status: number of commands sent +} + +//****************************************************************************** +// Function: i2GetStatus(pCh,resetBits) +// Parameters: Pointer to a channel structure +// Bit map of status bits to clear +// Returns: Bit map of current status bits +// +// Description: +// Returns the state of data set signals, and whether a break has been received, +// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status +// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared +// AFTER the condition is passed. If pCh does not point to a valid channel, +// returns -1 (which would be impossible otherwise. +//****************************************************************************** +static int +i2GetStatus(i2ChanStrPtr pCh, int resetBits) +{ + unsigned short status; + i2eBordStrPtr pB; + + ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits ); + + // Make sure the channel exists, otherwise do nothing */ + if ( !i2Validate ( pCh ) ) + return -1; + + pB = pCh->pMyBord; + + status = pCh->dataSetIn; + + // Clear any specified error bits: but note that only actual error bits can + // be cleared, regardless of the value passed. + if (resetBits) + { + pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR)); + pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI); + } + + ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn ); + + return status; +} + +//****************************************************************************** +// Function: i2Input(pChpDest,count) +// Parameters: Pointer to a channel structure +// Pointer to data buffer +// Number of bytes to read +// Returns: Number of bytes read, or -1 for error +// +// Description: +// Strips data from the input buffer and writes it to pDest. If there is a +// collosal blunder, (invalid structure pointers or the like), returns -1. +// Otherwise, returns the number of bytes read. +//****************************************************************************** +static int +i2Input(i2ChanStrPtr pCh) +{ + int amountToMove; + unsigned short stripIndex; + int count; + unsigned long flags = 0; + + ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0); + + // Ensure channel structure seems real + if ( !i2Validate( pCh ) ) { + count = -1; + goto i2Input_exit; + } + write_lock_irqsave(&pCh->Ibuf_spinlock, flags); + + // initialize some accelerators and private copies + stripIndex = pCh->Ibuf_strip; + + count = pCh->Ibuf_stuff - stripIndex; + + // If buffer is empty or requested data count was 0, (trivial case) return + // without any further thought. + if ( count == 0 ) { + write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + goto i2Input_exit; + } + // Adjust for buffer wrap + if ( count < 0 ) { + count += IBUF_SIZE; + } + // Don't give more than can be taken by the line discipline + amountToMove = pCh->pTTY->receive_room; + if (count > amountToMove) { + count = amountToMove; + } + // How much could we copy without a wrap? + amountToMove = IBUF_SIZE - stripIndex; + + if (amountToMove > count) { + amountToMove = count; + } + // Move the first block + pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, + &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); + // If we needed to wrap, do the second data move + if (count > amountToMove) { + pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, + pCh->Ibuf, NULL, count - amountToMove ); + } + // Bump and wrap the stripIndex all at once by the amount of data read. This + // method is good regardless of whether the data was in one or two pieces. + stripIndex += count; + if (stripIndex >= IBUF_SIZE) { + stripIndex -= IBUF_SIZE; + } + pCh->Ibuf_strip = stripIndex; + + // Update our flow control information and possibly queue ourselves to send + // it, depending on how much data has been stripped since the last time a + // packet was sent. + pCh->infl.asof += count; + + if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) { + pCh->sinceLastFlow -= pCh->whenSendFlow; + write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); + } else { + write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + } + +i2Input_exit: + + ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count); + + return count; +} + +//****************************************************************************** +// Function: i2InputFlush(pCh) +// Parameters: Pointer to a channel structure +// Returns: Number of bytes stripped, or -1 for error +// +// Description: +// Strips any data from the input buffer. If there is a collosal blunder, +// (invalid structure pointers or the like), returns -1. Otherwise, returns the +// number of bytes stripped. +//****************************************************************************** +static int +i2InputFlush(i2ChanStrPtr pCh) +{ + int count; + unsigned long flags; + + // Ensure channel structure seems real + if ( !i2Validate ( pCh ) ) + return -1; + + ip2trace (CHANN, ITRC_INPUT, 10, 0); + + write_lock_irqsave(&pCh->Ibuf_spinlock, flags); + count = pCh->Ibuf_stuff - pCh->Ibuf_strip; + + // Adjust for buffer wrap + if (count < 0) { + count += IBUF_SIZE; + } + + // Expedient way to zero out the buffer + pCh->Ibuf_strip = pCh->Ibuf_stuff; + + + // Update our flow control information and possibly queue ourselves to send + // it, depending on how much data has been stripped since the last time a + // packet was sent. + + pCh->infl.asof += count; + + if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow ) + { + pCh->sinceLastFlow -= pCh->whenSendFlow; + write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); + } else { + write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + } + + ip2trace (CHANN, ITRC_INPUT, 19, 1, count); + + return count; +} + +//****************************************************************************** +// Function: i2InputAvailable(pCh) +// Parameters: Pointer to a channel structure +// Returns: Number of bytes available, or -1 for error +// +// Description: +// If there is a collosal blunder, (invalid structure pointers or the like), +// returns -1. Otherwise, returns the number of bytes stripped. Otherwise, +// returns the number of bytes available in the buffer. +//****************************************************************************** +#if 0 +static int +i2InputAvailable(i2ChanStrPtr pCh) +{ + int count; + + // Ensure channel structure seems real + if ( !i2Validate ( pCh ) ) return -1; + + + // initialize some accelerators and private copies + read_lock_irqsave(&pCh->Ibuf_spinlock, flags); + count = pCh->Ibuf_stuff - pCh->Ibuf_strip; + read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + + // Adjust for buffer wrap + if (count < 0) + { + count += IBUF_SIZE; + } + + return count; +} +#endif + +//****************************************************************************** +// Function: i2Output(pCh, pSource, count) +// Parameters: Pointer to channel structure +// Pointer to source data +// Number of bytes to send +// Returns: Number of bytes sent, or -1 for error +// +// Description: +// Queues the data at pSource to be sent as data packets to the board. If there +// is a collosal blunder, (invalid structure pointers or the like), returns -1. +// Otherwise, returns the number of bytes written. What if there is not enough +// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then +// we transfer as many characters as we can now, then return. If this bit is +// clear (default), routine will spin along until all the data is buffered. +// Should this occur, the 1-ms delay routine is called while waiting to avoid +// applications that one cannot break out of. +//****************************************************************************** +static int +i2Output(i2ChanStrPtr pCh, const char *pSource, int count) +{ + i2eBordStrPtr pB; + unsigned char *pInsert; + int amountToMove; + int countOriginal = count; + unsigned short channel; + unsigned short stuffIndex; + unsigned long flags; + + int bailout = 10; + + ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 ); + + // Ensure channel structure seems real + if ( !i2Validate ( pCh ) ) + return -1; + + // initialize some accelerators and private copies + pB = pCh->pMyBord; + channel = pCh->infl.hd.i2sChannel; + + // If the board has gone fatal, return bad, and also hit the trap routine if + // it exists. + if (pB->i2eFatal) { + if (pB->i2eFatalTrap) { + (*(pB)->i2eFatalTrap)(pB); + } + return -1; + } + // Proceed as though we would do everything + while ( count > 0 ) { + + // How much room in output buffer is there? + read_lock_irqsave(&pCh->Obuf_spinlock, flags); + amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; + read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); + if (amountToMove < 0) { + amountToMove += OBUF_SIZE; + } + // Subtract off the headers size and see how much room there is for real + // data. If this is negative, we will discover later. + amountToMove -= sizeof (i2DataHeader); + + // Don't move more (now) than can go in a single packet + if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) { + amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader); + } + // Don't move more than the count we were given + if (amountToMove > count) { + amountToMove = count; + } + // Now we know how much we must move: NB because the ring buffers have + // an overflow area at the end, we needn't worry about wrapping in the + // middle of a packet. + +// Small WINDOW here with no LOCK but I can't call Flush with LOCK +// We would be flushing (or ending flush) anyway + + ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove ); + + if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) + && amountToMove > 0 ) + { + write_lock_irqsave(&pCh->Obuf_spinlock, flags); + stuffIndex = pCh->Obuf_stuff; + + // Had room to move some data: don't know whether the block size, + // buffer space, or what was the limiting factor... + pInsert = &(pCh->Obuf[stuffIndex]); + + // Set up the header + CHANNEL_OF(pInsert) = channel; + PTYPE_OF(pInsert) = PTYPE_DATA; + TAG_OF(pInsert) = 0; + ID_OF(pInsert) = ID_ORDINARY_DATA; + DATA_COUNT_OF(pInsert) = amountToMove; + + // Move the data + memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); + // Adjust pointers and indices + pSource += amountToMove; + pCh->Obuf_char_count += amountToMove; + stuffIndex += amountToMove + sizeof(i2DataHeader); + count -= amountToMove; + + if (stuffIndex >= OBUF_SIZE) { + stuffIndex = 0; + } + pCh->Obuf_stuff = stuffIndex; + + write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); + + ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex ); + + } else { + + // Cannot move data + // becuz we need to stuff a flush + // or amount to move is <= 0 + + ip2trace(CHANN, ITRC_OUTPUT, 14, 3, + amountToMove, pB->i2eFifoRemains, + pB->i2eWaitingForEmptyFifo ); + + // Put this channel back on queue + // this ultimatly gets more data or wakes write output + i2QueueNeeds(pB, pCh, NEED_INLINE); + + if ( pB->i2eWaitingForEmptyFifo ) { + + ip2trace (CHANN, ITRC_OUTPUT, 16, 0 ); + + // or schedule + if (!in_interrupt()) { + + ip2trace (CHANN, ITRC_OUTPUT, 61, 0 ); + + schedule_timeout_interruptible(2); + if (signal_pending(current)) { + break; + } + continue; + } else { + + ip2trace (CHANN, ITRC_OUTPUT, 62, 0 ); + + // let interrupt in = WAS restore_flags() + // We hold no lock nor is irq off anymore??? + + break; + } + break; // from while(count) + } + else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) ) + { + ip2trace (CHANN, ITRC_OUTPUT, 19, 2, + pB->i2eFifoRemains, + pB->i2eTxMailEmpty ); + + break; // from while(count) + } else if ( pCh->channelNeeds & NEED_CREDIT ) { + + ip2trace (CHANN, ITRC_OUTPUT, 22, 0 ); + + break; // from while(count) + } else if ( --bailout) { + + // Try to throw more things (maybe not us) in the fifo if we're + // not already waiting for it. + + ip2trace (CHANN, ITRC_OUTPUT, 20, 0 ); + + serviceOutgoingFifo(pB); + //break; CONTINUE; + } else { + ip2trace (CHANN, ITRC_OUTPUT, 21, 3, + pB->i2eFifoRemains, + pB->i2eOutMailWaiting, + pB->i2eWaitingForEmptyFifo ); + + break; // from while(count) + } + } + } // End of while(count) + + i2QueueNeeds(pB, pCh, NEED_INLINE); + + // We drop through either when the count expires, or when there is some + // count left, but there was a non-blocking write. + if (countOriginal > count) { + + ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count ); + + serviceOutgoingFifo( pB ); + } + + ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count ); + + return countOriginal - count; +} + +//****************************************************************************** +// Function: i2FlushOutput(pCh) +// Parameters: Pointer to a channel structure +// Returns: Nothing +// +// Description: +// Sends bypass command to start flushing (waiting possibly forever until there +// is room), then sends inline command to stop flushing output, (again waiting +// possibly forever). +//****************************************************************************** +static inline void +i2FlushOutput(i2ChanStrPtr pCh) +{ + + ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags ); + + if (pCh->flush_flags) + return; + + if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { + pCh->flush_flags = STARTFL_FLAG; // Failed - flag for later + + ip2trace (CHANN, ITRC_FLUSH, 2, 0 ); + + } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) { + pCh->flush_flags = STOPFL_FLAG; // Failed - flag for later + + ip2trace (CHANN, ITRC_FLUSH, 3, 0 ); + } +} + +static int +i2RetryFlushOutput(i2ChanStrPtr pCh) +{ + int old_flags = pCh->flush_flags; + + ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags ); + + pCh->flush_flags = 0; // Clear flag so we can avoid recursion + // and queue the commands + + if ( old_flags & STARTFL_FLAG ) { + if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { + old_flags = STOPFL_FLAG; //Success - send stop flush + } else { + old_flags = STARTFL_FLAG; //Failure - Flag for retry later + } + + ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags ); + + } + if ( old_flags & STOPFL_FLAG ) { + if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) { + old_flags = 0; // Success - clear flags + } + + ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags ); + } + pCh->flush_flags = old_flags; + + ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags ); + + return old_flags; +} + +//****************************************************************************** +// Function: i2DrainOutput(pCh,timeout) +// Parameters: Pointer to a channel structure +// Maximum period to wait +// Returns: ? +// +// Description: +// Uses the bookmark request command to ask the board to send a bookmark back as +// soon as all the data is completely sent. +//****************************************************************************** +static void +i2DrainWakeup(unsigned long d) +{ + i2ChanStrPtr pCh = (i2ChanStrPtr)d; + + ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); + + pCh->BookmarkTimer.expires = 0; + wake_up_interruptible( &pCh->pBookmarkWait ); +} + +static void +i2DrainOutput(i2ChanStrPtr pCh, int timeout) +{ + wait_queue_t wait; + i2eBordStrPtr pB; + + ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires); + + pB = pCh->pMyBord; + // If the board has gone fatal, return bad, + // and also hit the trap routine if it exists. + if (pB->i2eFatal) { + if (pB->i2eFatalTrap) { + (*(pB)->i2eFatalTrap)(pB); + } + return; + } + if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { + // One per customer (channel) + setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, + (unsigned long)pCh); + + ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); + + mod_timer(&pCh->BookmarkTimer, jiffies + timeout); + } + + i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); + + init_waitqueue_entry(&wait, current); + add_wait_queue(&(pCh->pBookmarkWait), &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + serviceOutgoingFifo( pB ); + + schedule(); // Now we take our interruptible sleep on + + // Clean up the queue + set_current_state( TASK_RUNNING ); + remove_wait_queue(&(pCh->pBookmarkWait), &wait); + + // if expires == 0 then timer poped, then do not need to del_timer + if ((timeout > 0) && pCh->BookmarkTimer.expires && + time_before(jiffies, pCh->BookmarkTimer.expires)) { + del_timer( &(pCh->BookmarkTimer) ); + pCh->BookmarkTimer.expires = 0; + + ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires ); + + } + ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires ); + return; +} + +//****************************************************************************** +// Function: i2OutputFree(pCh) +// Parameters: Pointer to a channel structure +// Returns: Space in output buffer +// +// Description: +// Returns -1 if very gross error. Otherwise returns the amount of bytes still +// free in the output buffer. +//****************************************************************************** +static int +i2OutputFree(i2ChanStrPtr pCh) +{ + int amountToMove; + unsigned long flags; + + // Ensure channel structure seems real + if ( !i2Validate ( pCh ) ) { + return -1; + } + read_lock_irqsave(&pCh->Obuf_spinlock, flags); + amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; + read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); + + if (amountToMove < 0) { + amountToMove += OBUF_SIZE; + } + // If this is negative, we will discover later + amountToMove -= sizeof(i2DataHeader); + + return (amountToMove < 0) ? 0 : amountToMove; +} +static void + +ip2_owake( PTTY tp) +{ + i2ChanStrPtr pCh; + + if (tp == NULL) return; + + pCh = tp->driver_data; + + ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, + (1 << TTY_DO_WRITE_WAKEUP) ); + + tty_wakeup(tp); +} + +static inline void +set_baud_params(i2eBordStrPtr pB) +{ + int i,j; + i2ChanStrPtr *pCh; + + pCh = (i2ChanStrPtr *) pB->i2eChannelPtr; + + for (i = 0; i < ABS_MAX_BOXES; i++) { + if (pB->channelBtypes.bid_value[i]) { + if (BID_HAS_654(pB->channelBtypes.bid_value[i])) { + for (j = 0; j < ABS_BIGGEST_BOX; j++) { + if (pCh[i*16+j] == NULL) + break; + (pCh[i*16+j])->BaudBase = 921600; // MAX for ST654 + (pCh[i*16+j])->BaudDivisor = 96; + } + } else { // has cirrus cd1400 + for (j = 0; j < ABS_BIGGEST_BOX; j++) { + if (pCh[i*16+j] == NULL) + break; + (pCh[i*16+j])->BaudBase = 115200; // MAX for CD1400 + (pCh[i*16+j])->BaudDivisor = 12; + } + } + } + } +} + +//****************************************************************************** +// Function: i2StripFifo(pB) +// Parameters: Pointer to a board structure +// Returns: ? +// +// Description: +// Strips all the available data from the incoming FIFO, identifies the type of +// packet, and either buffers the data or does what needs to be done. +// +// Note there is no overflow checking here: if the board sends more data than it +// ought to, we will not detect it here, but blindly overflow... +//****************************************************************************** + +// A buffer for reading in blocks for unknown channels +static unsigned char junkBuffer[IBUF_SIZE]; + +// A buffer to read in a status packet. Because of the size of the count field +// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE +static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4]; + +// This table changes the bit order from MSR order given by STAT_MODEM packet to +// status bits used in our library. +static char xlatDss[16] = { +0 | 0 | 0 | 0 , +0 | 0 | 0 | I2_CTS , +0 | 0 | I2_DSR | 0 , +0 | 0 | I2_DSR | I2_CTS , +0 | I2_RI | 0 | 0 , +0 | I2_RI | 0 | I2_CTS , +0 | I2_RI | I2_DSR | 0 , +0 | I2_RI | I2_DSR | I2_CTS , +I2_DCD | 0 | 0 | 0 , +I2_DCD | 0 | 0 | I2_CTS , +I2_DCD | 0 | I2_DSR | 0 , +I2_DCD | 0 | I2_DSR | I2_CTS , +I2_DCD | I2_RI | 0 | 0 , +I2_DCD | I2_RI | 0 | I2_CTS , +I2_DCD | I2_RI | I2_DSR | 0 , +I2_DCD | I2_RI | I2_DSR | I2_CTS }; + +static inline void +i2StripFifo(i2eBordStrPtr pB) +{ + i2ChanStrPtr pCh; + int channel; + int count; + unsigned short stuffIndex; + int amountToRead; + unsigned char *pc, *pcLimit; + unsigned char uc; + unsigned char dss_change; + unsigned long bflags,cflags; + +// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 ); + + while (I2_HAS_INPUT(pB)) { +// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 ); + + // Process packet from fifo a one atomic unit + write_lock_irqsave(&pB->read_fifo_spinlock, bflags); + + // The first word (or two bytes) will have channel number and type of + // packet, possibly other information + pB->i2eLeadoffWord[0] = iiReadWord(pB); + + switch(PTYPE_OF(pB->i2eLeadoffWord)) + { + case PTYPE_DATA: + pB->got_input = 1; + +// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 ); + + channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */ + count = iiReadWord(pB); /* Count is in the next word */ + +// NEW: Check the count for sanity! Should the hardware fail, our death +// is more pleasant. While an oversize channel is acceptable (just more +// than the driver supports), an over-length count clearly means we are +// sick! + if ( ((unsigned int)count) > IBUF_SIZE ) { + pB->i2eFatal = 2; + write_unlock_irqrestore(&pB->read_fifo_spinlock, + bflags); + return; /* Bail out ASAP */ + } + // Channel is illegally big ? + if ((channel >= pB->i2eChannelCnt) || + (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel]))) + { + iiReadBuf(pB, junkBuffer, count); + write_unlock_irqrestore(&pB->read_fifo_spinlock, + bflags); + break; /* From switch: ready for next packet */ + } + + // Channel should be valid, then + + // If this is a hot-key, merely post its receipt for now. These are + // always supposed to be 1-byte packets, so we won't even check the + // count. Also we will post an acknowledgement to the board so that + // more data can be forthcoming. Note that we are not trying to use + // these sequences in this driver, merely to robustly ignore them. + if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY) + { + pCh->hotKeyIn = iiReadWord(pB) & 0xff; + write_unlock_irqrestore(&pB->read_fifo_spinlock, + bflags); + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK); + break; /* From the switch: ready for next packet */ + } + + // Normal data! We crudely assume there is room for the data in our + // buffer because the board wouldn't have exceeded his credit limit. + write_lock_irqsave(&pCh->Ibuf_spinlock, cflags); + // We have 2 locks now + stuffIndex = pCh->Ibuf_stuff; + amountToRead = IBUF_SIZE - stuffIndex; + if (amountToRead > count) + amountToRead = count; + + // stuffIndex would have been already adjusted so there would + // always be room for at least one, and count is always at least + // one. + + iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); + pCh->icount.rx += amountToRead; + + // Update the stuffIndex by the amount of data moved. Note we could + // never ask for more data than would just fit. However, we might + // have read in one more byte than we wanted because the read + // rounds up to even bytes. If this byte is on the end of the + // packet, and is padding, we ignore it. If the byte is part of + // the actual data, we need to move it. + + stuffIndex += amountToRead; + + if (stuffIndex >= IBUF_SIZE) { + if ((amountToRead & 1) && (count > amountToRead)) { + pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE]; + amountToRead++; + stuffIndex = 1; + } else { + stuffIndex = 0; + } + } + + // If there is anything left over, read it as well + if (count > amountToRead) { + amountToRead = count - amountToRead; + iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); + pCh->icount.rx += amountToRead; + stuffIndex += amountToRead; + } + + // Update stuff index + pCh->Ibuf_stuff = stuffIndex; + write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags); + write_unlock_irqrestore(&pB->read_fifo_spinlock, + bflags); + +#ifdef USE_IQ + schedule_work(&pCh->tqueue_input); +#else + do_input(&pCh->tqueue_input); +#endif + + // Note we do not need to maintain any flow-control credits at this + // time: if we were to increment .asof and decrement .room, there + // would be no net effect. Instead, when we strip data, we will + // increment .asof and leave .room unchanged. + + break; // From switch: ready for next packet + + case PTYPE_STATUS: + ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 ); + + count = CMD_COUNT_OF(pB->i2eLeadoffWord); + + iiReadBuf(pB, cmdBuffer, count); + // We can release early with buffer grab + write_unlock_irqrestore(&pB->read_fifo_spinlock, + bflags); + + pc = cmdBuffer; + pcLimit = &(cmdBuffer[count]); + + while (pc < pcLimit) { + channel = *pc++; + + ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc ); + + /* check for valid channel */ + if (channel < pB->i2eChannelCnt + && + (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL + ) + { + dss_change = 0; + + switch (uc = *pc++) + { + /* Breaks and modem signals are easy: just update status */ + case STAT_CTS_UP: + if ( !(pCh->dataSetIn & I2_CTS) ) + { + pCh->dataSetIn |= I2_DCTS; + pCh->icount.cts++; + dss_change = 1; + } + pCh->dataSetIn |= I2_CTS; + break; + + case STAT_CTS_DN: + if ( pCh->dataSetIn & I2_CTS ) + { + pCh->dataSetIn |= I2_DCTS; + pCh->icount.cts++; + dss_change = 1; + } + pCh->dataSetIn &= ~I2_CTS; + break; + + case STAT_DCD_UP: + ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn ); + + if ( !(pCh->dataSetIn & I2_DCD) ) + { + ip2trace (CHANN, ITRC_MODEM, 2, 0 ); + pCh->dataSetIn |= I2_DDCD; + pCh->icount.dcd++; + dss_change = 1; + } + pCh->dataSetIn |= I2_DCD; + + ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn ); + break; + + case STAT_DCD_DN: + ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn ); + if ( pCh->dataSetIn & I2_DCD ) + { + ip2trace (channel, ITRC_MODEM, 5, 0 ); + pCh->dataSetIn |= I2_DDCD; + pCh->icount.dcd++; + dss_change = 1; + } + pCh->dataSetIn &= ~I2_DCD; + + ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn ); + break; + + case STAT_DSR_UP: + if ( !(pCh->dataSetIn & I2_DSR) ) + { + pCh->dataSetIn |= I2_DDSR; + pCh->icount.dsr++; + dss_change = 1; + } + pCh->dataSetIn |= I2_DSR; + break; + + case STAT_DSR_DN: + if ( pCh->dataSetIn & I2_DSR ) + { + pCh->dataSetIn |= I2_DDSR; + pCh->icount.dsr++; + dss_change = 1; + } + pCh->dataSetIn &= ~I2_DSR; + break; + + case STAT_RI_UP: + if ( !(pCh->dataSetIn & I2_RI) ) + { + pCh->dataSetIn |= I2_DRI; + pCh->icount.rng++; + dss_change = 1; + } + pCh->dataSetIn |= I2_RI ; + break; + + case STAT_RI_DN: + // to be compat with serial.c + //if ( pCh->dataSetIn & I2_RI ) + //{ + // pCh->dataSetIn |= I2_DRI; + // pCh->icount.rng++; + // dss_change = 1; + //} + pCh->dataSetIn &= ~I2_RI ; + break; + + case STAT_BRK_DET: + pCh->dataSetIn |= I2_BRK; + pCh->icount.brk++; + dss_change = 1; + break; + + // Bookmarks? one less request we're waiting for + case STAT_BMARK: + pCh->bookMarks--; + if (pCh->bookMarks <= 0 ) { + pCh->bookMarks = 0; + wake_up_interruptible( &pCh->pBookmarkWait ); + + ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires ); + } + break; + + // Flow control packets? Update the new credits, and if + // someone was waiting for output, queue him up again. + case STAT_FLOW: + pCh->outfl.room = + ((flowStatPtr)pc)->room - + (pCh->outfl.asof - ((flowStatPtr)pc)->asof); + + ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room ); + + if (pCh->channelNeeds & NEED_CREDIT) + { + ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds); + + pCh->channelNeeds &= ~NEED_CREDIT; + i2QueueNeeds(pB, pCh, NEED_INLINE); + if ( pCh->pTTY ) + ip2_owake(pCh->pTTY); + } + + ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds); + + pc += sizeof(flowStat); + break; + + /* Special packets: */ + /* Just copy the information into the channel structure */ + + case STAT_STATUS: + + pCh->channelStatus = *((debugStatPtr)pc); + pc += sizeof(debugStat); + break; + + case STAT_TXCNT: + + pCh->channelTcount = *((cntStatPtr)pc); + pc += sizeof(cntStat); + break; + + case STAT_RXCNT: + + pCh->channelRcount = *((cntStatPtr)pc); + pc += sizeof(cntStat); + break; + + case STAT_BOXIDS: + pB->channelBtypes = *((bidStatPtr)pc); + pc += sizeof(bidStat); + set_baud_params(pB); + break; + + case STAT_HWFAIL: + i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST); + pCh->channelFail = *((failStatPtr)pc); + pc += sizeof(failStat); + break; + + /* No explicit match? then + * Might be an error packet... + */ + default: + switch (uc & STAT_MOD_ERROR) + { + case STAT_ERROR: + if (uc & STAT_E_PARITY) { + pCh->dataSetIn |= I2_PAR; + pCh->icount.parity++; + } + if (uc & STAT_E_FRAMING){ + pCh->dataSetIn |= I2_FRA; + pCh->icount.frame++; + } + if (uc & STAT_E_OVERRUN){ + pCh->dataSetIn |= I2_OVR; + pCh->icount.overrun++; + } + break; + + case STAT_MODEM: + // the answer to DSS_NOW request (not change) + pCh->dataSetIn = (pCh->dataSetIn + & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) ) + | xlatDss[uc & 0xf]; + wake_up_interruptible ( &pCh->dss_now_wait ); + default: + break; + } + } /* End of switch on status type */ + if (dss_change) { +#ifdef USE_IQ + schedule_work(&pCh->tqueue_status); +#else + do_status(&pCh->tqueue_status); +#endif + } + } + else /* Or else, channel is invalid */ + { + // Even though the channel is invalid, we must test the + // status to see how much additional data it has (to be + // skipped) + switch (*pc++) + { + case STAT_FLOW: + pc += 4; /* Skip the data */ + break; + + default: + break; + } + } + } // End of while (there is still some status packet left) + break; + + default: // Neither packet? should be impossible + ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1, + PTYPE_OF(pB->i2eLeadoffWord) ); + write_unlock_irqrestore(&pB->read_fifo_spinlock, + bflags); + + break; + } // End of switch on type of packets + } /*while(board I2_HAS_INPUT)*/ + + ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 ); + + // Send acknowledgement to the board even if there was no data! + pB->i2eOutMailWaiting |= MB_IN_STRIPPED; + return; +} + +//****************************************************************************** +// Function: i2Write2Fifo(pB,address,count) +// Parameters: Pointer to a board structure, source address, byte count +// Returns: bytes written +// +// Description: +// Writes count bytes to board io address(implied) from source +// Adjusts count, leaves reserve for next time around bypass cmds +//****************************************************************************** +static int +i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve) +{ + int rc = 0; + unsigned long flags; + write_lock_irqsave(&pB->write_fifo_spinlock, flags); + if (!pB->i2eWaitingForEmptyFifo) { + if (pB->i2eFifoRemains > (count+reserve)) { + pB->i2eFifoRemains -= count; + iiWriteBuf(pB, source, count); + pB->i2eOutMailWaiting |= MB_OUT_STUFFED; + rc = count; + } + } + write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); + return rc; +} +//****************************************************************************** +// Function: i2StuffFifoBypass(pB) +// Parameters: Pointer to a board structure +// Returns: Nothing +// +// Description: +// Stuffs as many bypass commands into the fifo as possible. This is simpler +// than stuffing data or inline commands to fifo, since we do not have +// flow-control to deal with. +//****************************************************************************** +static inline void +i2StuffFifoBypass(i2eBordStrPtr pB) +{ + i2ChanStrPtr pCh; + unsigned char *pRemove; + unsigned short stripIndex; + unsigned short packetSize; + unsigned short paddedSize; + unsigned short notClogged = 1; + unsigned long flags; + + int bailout = 1000; + + // Continue processing so long as there are entries, or there is room in the + // fifo. Each entry represents a channel with something to do. + while ( --bailout && notClogged && + (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS)))) + { + write_lock_irqsave(&pCh->Cbuf_spinlock, flags); + stripIndex = pCh->Cbuf_strip; + + // as long as there are packets for this channel... + + while (stripIndex != pCh->Cbuf_stuff) { + pRemove = &(pCh->Cbuf[stripIndex]); + packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader); + paddedSize = roundup(packetSize, 2); + + if (paddedSize > 0) { + if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) { + notClogged = 0; /* fifo full */ + i2QueueNeeds(pB, pCh, NEED_BYPASS); // Put back on queue + break; // Break from the channel + } + } +#ifdef DEBUG_FIFO +WriteDBGBuf("BYPS", pRemove, paddedSize); +#endif /* DEBUG_FIFO */ + pB->debugBypassCount++; + + pRemove += packetSize; + stripIndex += packetSize; + if (stripIndex >= CBUF_SIZE) { + stripIndex = 0; + pRemove = pCh->Cbuf; + } + } + // Done with this channel. Move to next, removing this one from + // the queue of channels if we cleaned it out (i.e., didn't get clogged. + pCh->Cbuf_strip = stripIndex; + write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); + } // Either clogged or finished all the work + +#ifdef IP2DEBUG_TRACE + if ( !bailout ) { + ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 ); + } +#endif +} + +//****************************************************************************** +// Function: i2StuffFifoFlow(pB) +// Parameters: Pointer to a board structure +// Returns: Nothing +// +// Description: +// Stuffs as many flow control packets into the fifo as possible. This is easier +// even than doing normal bypass commands, because there is always at most one +// packet, already assembled, for each channel. +//****************************************************************************** +static inline void +i2StuffFifoFlow(i2eBordStrPtr pB) +{ + i2ChanStrPtr pCh; + unsigned short paddedSize = roundup(sizeof(flowIn), 2); + + ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2, + pB->i2eFifoRemains, paddedSize ); + + // Continue processing so long as there are entries, or there is room in the + // fifo. Each entry represents a channel with something to do. + while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) { + pB->debugFlowCount++; + + // NO Chan LOCK needed ??? + if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) { + break; + } +#ifdef DEBUG_FIFO + WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize); +#endif /* DEBUG_FIFO */ + + } // Either clogged or finished all the work + + ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 ); +} + +//****************************************************************************** +// Function: i2StuffFifoInline(pB) +// Parameters: Pointer to a board structure +// Returns: Nothing +// +// Description: +// Stuffs as much data and inline commands into the fifo as possible. This is +// the most complex fifo-stuffing operation, since there if now the channel +// flow-control issue to deal with. +//****************************************************************************** +static inline void +i2StuffFifoInline(i2eBordStrPtr pB) +{ + i2ChanStrPtr pCh; + unsigned char *pRemove; + unsigned short stripIndex; + unsigned short packetSize; + unsigned short paddedSize; + unsigned short notClogged = 1; + unsigned short flowsize; + unsigned long flags; + + int bailout = 1000; + int bailout2; + + ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, + pB->i2Dbuf_strip, pB->i2Dbuf_stuff ); + + // Continue processing so long as there are entries, or there is room in the + // fifo. Each entry represents a channel with something to do. + while ( --bailout && notClogged && + (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) ) + { + write_lock_irqsave(&pCh->Obuf_spinlock, flags); + stripIndex = pCh->Obuf_strip; + + ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff ); + + // as long as there are packets for this channel... + bailout2 = 1000; + while ( --bailout2 && stripIndex != pCh->Obuf_stuff) { + pRemove = &(pCh->Obuf[stripIndex]); + + // Must determine whether this be a data or command packet to + // calculate correctly the header size and the amount of + // flow-control credit this type of packet will use. + if (PTYPE_OF(pRemove) == PTYPE_DATA) { + flowsize = DATA_COUNT_OF(pRemove); + packetSize = flowsize + sizeof(i2DataHeader); + } else { + flowsize = CMD_COUNT_OF(pRemove); + packetSize = flowsize + sizeof(i2CmdHeader); + } + flowsize = CREDIT_USAGE(flowsize); + paddedSize = roundup(packetSize, 2); + + ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize ); + + // If we don't have enough credits from the board to send the data, + // flag the channel that we are waiting for flow control credit, and + // break out. This will clean up this channel and remove us from the + // queue of hot things to do. + + ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize ); + + if (pCh->outfl.room <= flowsize) { + // Do Not have the credits to send this packet. + i2QueueNeeds(pB, pCh, NEED_CREDIT); + notClogged = 0; + break; // So to do next channel + } + if ( (paddedSize > 0) + && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) { + // Do Not have room in fifo to send this packet. + notClogged = 0; + i2QueueNeeds(pB, pCh, NEED_INLINE); + break; // Break from the channel + } +#ifdef DEBUG_FIFO +WriteDBGBuf("DATA", pRemove, paddedSize); +#endif /* DEBUG_FIFO */ + pB->debugInlineCount++; + + pCh->icount.tx += flowsize; + // Update current credits + pCh->outfl.room -= flowsize; + pCh->outfl.asof += flowsize; + if (PTYPE_OF(pRemove) == PTYPE_DATA) { + pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove); + } + pRemove += packetSize; + stripIndex += packetSize; + + ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip); + + if (stripIndex >= OBUF_SIZE) { + stripIndex = 0; + pRemove = pCh->Obuf; + + ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex ); + + } + } /* while */ + if ( !bailout2 ) { + ip2trace (CHANN, ITRC_ERROR, 3, 0 ); + } + // Done with this channel. Move to next, removing this one from the + // queue of channels if we cleaned it out (i.e., didn't get clogged. + pCh->Obuf_strip = stripIndex; + write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); + if ( notClogged ) + { + + ip2trace (CHANN, ITRC_SICMD, 8, 0 ); + + if ( pCh->pTTY ) { + ip2_owake(pCh->pTTY); + } + } + } // Either clogged or finished all the work + + if ( !bailout ) { + ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 ); + } + + ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip); +} + +//****************************************************************************** +// Function: serviceOutgoingFifo(pB) +// Parameters: Pointer to a board structure +// Returns: Nothing +// +// Description: +// Helper routine to put data in the outgoing fifo, if we aren't already waiting +// for something to be there. If the fifo has only room for a very little data, +// go head and hit the board with a mailbox hit immediately. Otherwise, it will +// have to happen later in the interrupt processing. Since this routine may be +// called both at interrupt and foreground time, we must turn off interrupts +// during the entire process. +//****************************************************************************** +static void +serviceOutgoingFifo(i2eBordStrPtr pB) +{ + // If we aren't currently waiting for the board to empty our fifo, service + // everything that is pending, in priority order (especially, Bypass before + // Inline). + if ( ! pB->i2eWaitingForEmptyFifo ) + { + i2StuffFifoFlow(pB); + i2StuffFifoBypass(pB); + i2StuffFifoInline(pB); + + iiSendPendingMail(pB); + } +} + +//****************************************************************************** +// Function: i2ServiceBoard(pB) +// Parameters: Pointer to a board structure +// Returns: Nothing +// +// Description: +// Normally this is called from interrupt level, but there is deliberately +// nothing in here specific to being called from interrupt level. All the +// hardware-specific, interrupt-specific things happen at the outer levels. +// +// For example, a timer interrupt could drive this routine for some sort of +// polled operation. The only requirement is that the programmer deal with any +// atomiticity/concurrency issues that result. +// +// This routine responds to the board's having sent mailbox information to the +// host (which would normally cause an interrupt). This routine reads the +// incoming mailbox. If there is no data in it, this board did not create the +// interrupt and/or has nothing to be done to it. (Except, if we have been +// waiting to write mailbox data to it, we may do so. +// +// Based on the value in the mailbox, we may take various actions. +// +// No checking here of pB validity: after all, it shouldn't have been called by +// the handler unless pB were on the list. +//****************************************************************************** +static inline int +i2ServiceBoard ( i2eBordStrPtr pB ) +{ + unsigned inmail; + unsigned long flags; + + + /* This should be atomic because of the way we are called... */ + if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) { + inmail = iiGetMail(pB); + } + pB->i2eStartMail = NO_MAIL_HERE; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail ); + + if (inmail != NO_MAIL_HERE) { + // If the board has gone fatal, nothing to do but hit a bit that will + // alert foreground tasks to protest! + if ( inmail & MB_FATAL_ERROR ) { + pB->i2eFatal = 1; + goto exit_i2ServiceBoard; + } + + /* Assuming no fatal condition, we proceed to do work */ + if ( inmail & MB_IN_STUFFED ) { + pB->i2eFifoInInts++; + i2StripFifo(pB); /* There might be incoming packets */ + } + + if (inmail & MB_OUT_STRIPPED) { + pB->i2eFifoOutInts++; + write_lock_irqsave(&pB->write_fifo_spinlock, flags); + pB->i2eFifoRemains = pB->i2eFifoSize; + pB->i2eWaitingForEmptyFifo = 0; + write_unlock_irqrestore(&pB->write_fifo_spinlock, + flags); + + ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains ); + + } + serviceOutgoingFifo(pB); + } + + ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 ); + +exit_i2ServiceBoard: + + return 0; +} diff --git a/drivers/staging/tty/ip2/i2lib.h b/drivers/staging/tty/ip2/i2lib.h new file mode 100644 index 000000000000..e559e9bac06d --- /dev/null +++ b/drivers/staging/tty/ip2/i2lib.h @@ -0,0 +1,351 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Header file for high level library functions +* +*******************************************************************************/ +#ifndef I2LIB_H +#define I2LIB_H 1 +//------------------------------------------------------------------------------ +// I2LIB.H +// +// IntelliPort-II and IntelliPort-IIEX +// +// Defines, structure definitions, and external declarations for i2lib.c +//------------------------------------------------------------------------------ +//-------------------------------------- +// Mandatory Includes: +//-------------------------------------- +#include "ip2types.h" +#include "i2ellis.h" +#include "i2pack.h" +#include "i2cmd.h" +#include + +//------------------------------------------------------------------------------ +// i2ChanStr -- Channel Structure: +// Used to track per-channel information for the library routines using standard +// loadware. Note also, a pointer to an array of these structures is patched +// into the i2eBordStr (see i2ellis.h) +//------------------------------------------------------------------------------ +// +// If we make some limits on the maximum block sizes, we can avoid dealing with +// buffer wrap. The wrapping of the buffer is based on where the start of the +// packet is. Then there is always room for the packet contiguously. +// +// Maximum total length of an outgoing data or in-line command block. The limit +// of 36 on data is quite arbitrary and based more on DOS memory limitations +// than the board interface. However, for commands, the maximum packet length is +// MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits +// (see I2PACK.H) in such packets. For data packets, the count field size is not +// the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE, +// but be careful if wanting to modify either. +// +#define MAX_OBUF_BLOCK 36 + +// Another note on maximum block sizes: we are buffering packets here. Data is +// put into the buffer (if there is room) regardless of the credits from the +// board. The board sends new credits whenever it has removed from his buffers a +// number of characters equal to 80% of total buffer size. (Of course, the total +// buffer size is what is reported when the very first set of flow control +// status packets are received from the board. Therefore, to be robust, you must +// always fill the board to at least 80% of the current credit limit, else you +// might not give it enough to trigger a new report. These conditions are +// obtained here so long as the maximum output block size is less than 20% the +// size of the board's output buffers. This is true at present by "coincidence" +// or "infernal knowledge": the board's output buffers are at least 700 bytes +// long (20% = 140 bytes, at least). The 80% figure is "official", so the safest +// strategy might be to trap the first flow control report and guarantee that +// the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first +// reported buffer credit. +// +#define MAX_CBUF_BLOCK 6 // Maximum total length of a bypass command block + +#define IBUF_SIZE 512 // character capacity of input buffer per channel +#define OBUF_SIZE 1024// character capacity of output buffer per channel +#define CBUF_SIZE 10 // character capacity of output bypass buffer + +typedef struct _i2ChanStr +{ + // First, back-pointers so that given a pointer to this structure, you can + // determine the correct board and channel number to reference, (say, when + // issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.) + + int port_index; // Index of port in channel structure array attached + // to board structure. + PTTY pTTY; // Pointer to tty structure for port (OS specific) + USHORT validity; // Indicates whether the given channel has been + // initialized, really exists (or is a missing + // channel, e.g. channel 9 on an 8-port box.) + + i2eBordStrPtr pMyBord; // Back-pointer to this channel's board structure + + int wopen; // waiting fer carrier + + int throttled; // Set if upper layer can take no data + + int flags; // Defined in tty.h + + PWAITQ open_wait; // Pointer for OS sleep function. + PWAITQ close_wait; // Pointer for OS sleep function. + PWAITQ delta_msr_wait;// Pointer for OS sleep function. + PWAITQ dss_now_wait; // Pointer for OS sleep function. + + struct timer_list BookmarkTimer; // Used by i2DrainOutput + wait_queue_head_t pBookmarkWait; // Used by i2DrainOutput + + int BaudBase; + int BaudDivisor; + + USHORT ClosingDelay; + USHORT ClosingWaitTime; + + volatile + flowIn infl; // This structure is initialized as a completely + // formed flow-control command packet, and as such + // has the channel number, also the capacity and + // "as-of" data needed continuously. + + USHORT sinceLastFlow; // Counts the number of characters read from input + // buffers, since the last time flow control info + // was sent. + + USHORT whenSendFlow; // Determines when new flow control is to be sent to + // the board. Note unlike earlier manifestations of + // the driver, these packets can be sent from + // in-place. + + USHORT channelNeeds; // Bit map of important things which must be done + // for this channel. (See bits below ) + + volatile + flowStat outfl; // Same type of structure is used to hold current + // flow control information used to control our + // output. "asof" is kept updated as data is sent, + // and "room" never goes to zero. + + // The incoming ring buffer + // Unlike the outgoing buffers, this holds raw data, not packets. The two + // extra bytes are used to hold the byte-padding when there is room for an + // odd number of bytes before we must wrap. + // + UCHAR Ibuf[IBUF_SIZE + 2]; + volatile + USHORT Ibuf_stuff; // Stuffing index + volatile + USHORT Ibuf_strip; // Stripping index + + // The outgoing ring-buffer: Holds Data and command packets. N.B., even + // though these are in the channel structure, the channel is also written + // here, the easier to send it to the fifo when ready. HOWEVER, individual + // packets here are NOT padded to even length: the routines for writing + // blocks to the fifo will pad to even byte counts. + // + UCHAR Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4]; + volatile + USHORT Obuf_stuff; // Stuffing index + volatile + USHORT Obuf_strip; // Stripping index + int Obuf_char_count; + + // The outgoing bypass-command buffer. Unlike earlier manifestations, the + // flow control packets are sent directly from the structures. As above, the + // channel number is included in the packet, but they are NOT padded to even + // size. + // + UCHAR Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2]; + volatile + USHORT Cbuf_stuff; // Stuffing index + volatile + USHORT Cbuf_strip; // Stripping index + + // The temporary buffer for the Linux tty driver PutChar entry. + // + UCHAR Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)]; + volatile + USHORT Pbuf_stuff; // Stuffing index + + // The state of incoming data-set signals + // + USHORT dataSetIn; // Bit-mapped according to below. Also indicates + // whether a break has been detected since last + // inquiry. + + // The state of outcoming data-set signals (as far as we can tell!) + // + USHORT dataSetOut; // Bit-mapped according to below. + + // Most recent hot-key identifier detected + // + USHORT hotKeyIn; // Hot key as sent by the board, HOT_CLEAR indicates + // no hot key detected since last examined. + + // Counter of outstanding requests for bookmarks + // + short bookMarks; // Number of outstanding bookmark requests, (+ive + // whenever a bookmark request if queued up, -ive + // whenever a bookmark is received). + + // Misc options + // + USHORT channelOptions; // See below + + // To store various incoming special packets + // + debugStat channelStatus; + cntStat channelRcount; + cntStat channelTcount; + failStat channelFail; + + // To store the last values for line characteristics we sent to the board. + // + int speed; + + int flush_flags; + + void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...); + + /* + * Kernel counters for the 4 input interrupts + */ + struct async_icount icount; + + /* + * Task queues for processing input packets from the board. + */ + struct work_struct tqueue_input; + struct work_struct tqueue_status; + struct work_struct tqueue_hangup; + + rwlock_t Ibuf_spinlock; + rwlock_t Obuf_spinlock; + rwlock_t Cbuf_spinlock; + rwlock_t Pbuf_spinlock; + +} i2ChanStr, *i2ChanStrPtr; + +//--------------------------------------------------- +// Manifests and bit-maps for elements in i2ChanStr +//--------------------------------------------------- +// +// flush flags +// +#define STARTFL_FLAG 1 +#define STOPFL_FLAG 2 + +// validity +// +#define CHANNEL_MAGIC_BITS 0xff00 +#define CHANNEL_MAGIC 0x5300 // (validity & CHANNEL_MAGIC_BITS) == + // CHANNEL_MAGIC --> structure good + +#define CHANNEL_SUPPORT 0x0001 // Indicates channel is supported, exists, + // and passed P.O.S.T. + +// channelNeeds +// +#define NEED_FLOW 1 // Indicates flow control has been queued +#define NEED_INLINE 2 // Indicates inline commands or data queued +#define NEED_BYPASS 4 // Indicates bypass commands queued +#define NEED_CREDIT 8 // Indicates would be sending except has not sufficient + // credit. The data is still in the channel structure, + // but the channel is not enqueued in the board + // structure again until there is a credit received from + // the board. + +// dataSetIn (Also the bits for i2GetStatus return value) +// +#define I2_DCD 1 +#define I2_CTS 2 +#define I2_DSR 4 +#define I2_RI 8 + +// dataSetOut (Also the bits for i2GetStatus return value) +// +#define I2_DTR 1 +#define I2_RTS 2 + +// i2GetStatus() can optionally clear these bits +// +#define I2_BRK 0x10 // A break was detected +#define I2_PAR 0x20 // A parity error was received +#define I2_FRA 0x40 // A framing error was received +#define I2_OVR 0x80 // An overrun error was received + +// i2GetStatus() automatically clears these bits */ +// +#define I2_DDCD 0x100 // DCD changed from its former value +#define I2_DCTS 0x200 // CTS changed from its former value +#define I2_DDSR 0x400 // DSR changed from its former value +#define I2_DRI 0x800 // RI changed from its former value + +// hotKeyIn +// +#define HOT_CLEAR 0x1322 // Indicates that no hot-key has been detected + +// channelOptions +// +#define CO_NBLOCK_WRITE 1 // Writes don't block waiting for buffer. (Default + // is, they do wait.) + +// fcmodes +// +#define I2_OUTFLOW_CTS 0x0001 +#define I2_INFLOW_RTS 0x0002 +#define I2_INFLOW_DSR 0x0004 +#define I2_INFLOW_DTR 0x0008 +#define I2_OUTFLOW_DSR 0x0010 +#define I2_OUTFLOW_DTR 0x0020 +#define I2_OUTFLOW_XON 0x0040 +#define I2_OUTFLOW_XANY 0x0080 +#define I2_INFLOW_XON 0x0100 + +#define I2_CRTSCTS (I2_OUTFLOW_CTS|I2_INFLOW_RTS) +#define I2_IXANY_MODE (I2_OUTFLOW_XON|I2_OUTFLOW_XANY) + +//------------------------------------------- +// Macros used from user level like functions +//------------------------------------------- + +// Macros to set and clear channel options +// +#define i2SetOption(pCh, option) pCh->channelOptions |= option +#define i2ClrOption(pCh, option) pCh->channelOptions &= ~option + +// Macro to set fatal-error trap +// +#define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine + +//-------------------------------------------- +// Declarations and prototypes for i2lib.c +//-------------------------------------------- +// +static int i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr); +static int i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...); +static int i2GetStatus(i2ChanStrPtr, int); +static int i2Input(i2ChanStrPtr); +static int i2InputFlush(i2ChanStrPtr); +static int i2Output(i2ChanStrPtr, const char *, int); +static int i2OutputFree(i2ChanStrPtr); +static int i2ServiceBoard(i2eBordStrPtr); +static void i2DrainOutput(i2ChanStrPtr, int); + +#ifdef IP2DEBUG_TRACE +void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...); +#else +#define ip2trace(a,b,c,d...) do {} while (0) +#endif + +// Argument to i2QueueCommands +// +#define C_IN_LINE 1 +#define C_BYPASS 0 + +#endif // I2LIB_H diff --git a/drivers/staging/tty/ip2/i2pack.h b/drivers/staging/tty/ip2/i2pack.h new file mode 100644 index 000000000000..00342a677c90 --- /dev/null +++ b/drivers/staging/tty/ip2/i2pack.h @@ -0,0 +1,364 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Definitions of the packets used to transfer data and commands +* Host <--> Board. Information provided here is only applicable +* when the standard loadware is active. +* +*******************************************************************************/ +#ifndef I2PACK_H +#define I2PACK_H 1 + +//----------------------------------------------- +// Revision History: +// +// 10 October 1991 MAG First draft +// 24 February 1992 MAG Additions for 1.4.x loadware +// 11 March 1992 MAG New status packets +// +//----------------------------------------------- + +//------------------------------------------------------------------------------ +// Packet Formats: +// +// Information passes between the host and board through the FIFO in packets. +// These have headers which indicate the type of packet. Because the fifo data +// path may be 16-bits wide, the protocol is constrained such that each packet +// is always padded to an even byte count. (The lower-level interface routines +// -- i2ellis.c -- are designed to do this). +// +// The sender (be it host or board) must place some number of complete packets +// in the fifo, then place a message in the mailbox that packets are available. +// Placing such a message interrupts the "receiver" (be it board or host), who +// reads the mailbox message and determines that there are incoming packets +// ready. Since there are no partial packets, and the length of a packet is +// given in the header, the remainder of the packet can be read without checking +// for FIFO empty condition. The process is repeated, packet by packet, until +// the incoming FIFO is empty. Then the receiver uses the outbound mailbox to +// signal the board that it has read the data. Only then can the sender place +// additional data in the fifo. +//------------------------------------------------------------------------------ +// +//------------------------------------------------ +// Definition of Packet Header Area +//------------------------------------------------ +// +// Caution: these only define header areas. In actual use the data runs off +// beyond the end of these structures. +// +// Since these structures are based on sequences of bytes which go to the board, +// there cannot be ANY padding between the elements. +#pragma pack(1) + +//---------------------------- +// DATA PACKETS +//---------------------------- + +typedef struct _i2DataHeader +{ + unsigned char i2sChannel; /* The channel number: 0-255 */ + + // -- Bitfields are allocated LSB first -- + + // For incoming data, indicates whether this is an ordinary packet or a + // special one (e.g., hot key hit). + unsigned i2sId : 2 __attribute__ ((__packed__)); + + // For tagging data packets. There are flush commands which flush only data + // packets bearing a particular tag. (used in implementing IntelliView and + // IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has + // meaning internally to the loadware). + unsigned i2sTag : 4; + + // These two bits determine the type of packet sent/received. + unsigned i2sType : 2; + + // The count of data to follow: does not include the possible additional + // padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0. + unsigned short i2sCount; + +} i2DataHeader, *i2DataHeaderPtr; + +// Structure is immediately followed by the data, proper. + +//---------------------------- +// NON-DATA PACKETS +//---------------------------- + +typedef struct _i2CmdHeader +{ + unsigned char i2sChannel; // The channel number: 0-255 (Except where noted + // - see below + + // Number of bytes of commands, status or whatever to follow + unsigned i2sCount : 6; + + // These two bits determine the type of packet sent/received. + unsigned i2sType : 2; + +} i2CmdHeader, *i2CmdHeaderPtr; + +// Structure is immediately followed by the applicable data. + +//--------------------------------------- +// Flow Control Packets (Outbound) +//--------------------------------------- + +// One type of outbound command packet is so important that the entire structure +// is explicitly defined here. That is the flow-control packet. This is never +// sent by user-level code (as would be the commands to raise/lower DTR, for +// example). These are only sent by the library routines in response to reading +// incoming data into the buffers. +// +// The parameters inside the command block are maintained in place, then the +// block is sent at the appropriate time. + +typedef struct _flowIn +{ + i2CmdHeader hd; // Channel #, count, type (see above) + unsigned char fcmd; // The flow control command (37) + unsigned short asof; // As of byte number "asof" (LSB first!) I have room + // for "room" bytes + unsigned short room; +} flowIn, *flowInPtr; + +//---------------------------------------- +// (Incoming) Status Packets +//---------------------------------------- + +// Incoming packets which are non-data packets are status packets. In this case, +// the channel number in the header is unimportant. What follows are one or more +// sub-packets, the first word of which consists of the channel (first or low +// byte) and the status indicator (second or high byte), followed by possibly +// more data. + +#define STAT_CTS_UP 0 /* CTS raised (no other bytes) */ +#define STAT_CTS_DN 1 /* CTS dropped (no other bytes) */ +#define STAT_DCD_UP 2 /* DCD raised (no other bytes) */ +#define STAT_DCD_DN 3 /* DCD dropped (no other bytes) */ +#define STAT_DSR_UP 4 /* DSR raised (no other bytes) */ +#define STAT_DSR_DN 5 /* DSR dropped (no other bytes) */ +#define STAT_RI_UP 6 /* RI raised (no other bytes) */ +#define STAT_RI_DN 7 /* RI dropped (no other bytes) */ +#define STAT_BRK_DET 8 /* BRK detect (no other bytes) */ +#define STAT_FLOW 9 /* Flow control(-- more: see below */ +#define STAT_BMARK 10 /* Bookmark (no other bytes) + * Bookmark is sent as a response to + * a command 60: request for bookmark + */ +#define STAT_STATUS 11 /* Special packet: see below */ +#define STAT_TXCNT 12 /* Special packet: see below */ +#define STAT_RXCNT 13 /* Special packet: see below */ +#define STAT_BOXIDS 14 /* Special packet: see below */ +#define STAT_HWFAIL 15 /* Special packet: see below */ + +#define STAT_MOD_ERROR 0xc0 +#define STAT_MODEM 0xc0/* If status & STAT_MOD_ERROR: + * == STAT_MODEM, then this is a modem + * status packet, given in response to a + * CMD_DSS_NOW command. + * The low nibble has each data signal: + */ +#define STAT_MOD_DCD 0x8 +#define STAT_MOD_RI 0x4 +#define STAT_MOD_DSR 0x2 +#define STAT_MOD_CTS 0x1 + +#define STAT_ERROR 0x80/* If status & STAT_MOD_ERROR + * == STAT_ERROR, then + * sort of error on the channel. + * The remaining seven bits indicate + * what sort of error it is. + */ +/* The low three bits indicate parity, framing, or overrun errors */ + +#define STAT_E_PARITY 4 /* Parity error */ +#define STAT_E_FRAMING 2 /* Framing error */ +#define STAT_E_OVERRUN 1 /* (uxart) overrun error */ + +//--------------------------------------- +// STAT_FLOW packets +//--------------------------------------- + +typedef struct _flowStat +{ + unsigned short asof; + unsigned short room; +}flowStat, *flowStatPtr; + +// flowStat packets are received from the board to regulate the flow of outgoing +// data. A local copy of this structure is also kept to track the amount of +// credits used and credits remaining. "room" is the amount of space in the +// board's buffers, "as of" having received a certain byte number. When sending +// data to the fifo, you must calculate how much buffer space your packet will +// use. Add this to the current "asof" and subtract it from the current "room". +// +// The calculation for the board's buffer is given by CREDIT_USAGE, where size +// is the un-rounded count of either data characters or command characters. +// (Which is to say, the count rounded up, plus two). + +#define CREDIT_USAGE(size) (((size) + 3) & ~1) + +//--------------------------------------- +// STAT_STATUS packets +//--------------------------------------- + +typedef struct _debugStat +{ + unsigned char d_ccsr; + unsigned char d_txinh; + unsigned char d_stat1; + unsigned char d_stat2; +} debugStat, *debugStatPtr; + +// debugStat packets are sent to the host in response to a CMD_GET_STATUS +// command. Each byte is bit-mapped as described below: + +#define D_CCSR_XON 2 /* Has received XON, ready to transmit */ +#define D_CCSR_XOFF 4 /* Has received XOFF, not transmitting */ +#define D_CCSR_TXENAB 8 /* Transmitter is enabled */ +#define D_CCSR_RXENAB 0x80 /* Receiver is enabled */ + +#define D_TXINH_BREAK 1 /* We are sending a break */ +#define D_TXINH_EMPTY 2 /* No data to send */ +#define D_TXINH_SUSP 4 /* Output suspended via command 57 */ +#define D_TXINH_CMD 8 /* We are processing an in-line command */ +#define D_TXINH_LCD 0x10 /* LCD diagnostics are running */ +#define D_TXINH_PAUSE 0x20 /* We are processing a PAUSE command */ +#define D_TXINH_DCD 0x40 /* DCD is low, preventing transmission */ +#define D_TXINH_DSR 0x80 /* DSR is low, preventing transmission */ + +#define D_STAT1_TXEN 1 /* Transmit INTERRUPTS enabled */ +#define D_STAT1_RXEN 2 /* Receiver INTERRUPTS enabled */ +#define D_STAT1_MDEN 4 /* Modem (data set sigs) interrupts enabled */ +#define D_STAT1_RLM 8 /* Remote loopback mode selected */ +#define D_STAT1_LLM 0x10 /* Local internal loopback mode selected */ +#define D_STAT1_CTS 0x20 /* CTS is low, preventing transmission */ +#define D_STAT1_DTR 0x40 /* DTR is low, to stop remote transmission */ +#define D_STAT1_RTS 0x80 /* RTS is low, to stop remote transmission */ + +#define D_STAT2_TXMT 1 /* Transmit buffers are all empty */ +#define D_STAT2_RXMT 2 /* Receive buffers are all empty */ +#define D_STAT2_RXINH 4 /* Loadware has tried to inhibit remote + * transmission: dropped DTR, sent XOFF, + * whatever... + */ +#define D_STAT2_RXFLO 8 /* Loadware can send no more data to host + * until it receives a flow-control packet + */ +//----------------------------------------- +// STAT_TXCNT and STAT_RXCNT packets +//---------------------------------------- + +typedef struct _cntStat +{ + unsigned short cs_time; // (Assumes host is little-endian!) + unsigned short cs_count; +} cntStat, *cntStatPtr; + +// These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT +// bypass command. cs_time is a running 1 Millisecond counter which acts as a +// time stamp. cs_count is a running counter of data sent or received from the +// uxarts. (Not including data added by the chip itself, as with CRLF +// processing). +//------------------------------------------ +// STAT_HWFAIL packets +//------------------------------------------ + +typedef struct _failStat +{ + unsigned char fs_written; + unsigned char fs_read; + unsigned short fs_address; +} failStat, *failStatPtr; + +// This packet is sent whenever the on-board diagnostic process detects an +// error. At startup, this process is dormant. The host can wake it up by +// issuing the bypass command CMD_HW_TEST. The process runs at low priority and +// performs continuous hardware verification; writing data to certain on-board +// registers, reading it back, and comparing. If it detects an error, this +// packet is sent to the host, and the process goes dormant again until the host +// sends another CMD_HW_TEST. It then continues with the next register to be +// tested. + +//------------------------------------------------------------------------------ +// Macros to deal with the headers more easily! Note that these are defined so +// they may be used as "left" as well as "right" expressions. +//------------------------------------------------------------------------------ + +// Given a pointer to the packet, reference the channel number +// +#define CHANNEL_OF(pP) ((i2DataHeaderPtr)(pP))->i2sChannel + +// Given a pointer to the packet, reference the Packet type +// +#define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType + +// The possible types of packets +// +#define PTYPE_DATA 0 /* Host <--> Board */ +#define PTYPE_BYPASS 1 /* Host ---> Board */ +#define PTYPE_INLINE 2 /* Host ---> Board */ +#define PTYPE_STATUS 2 /* Host <--- Board */ + +// Given a pointer to a Data packet, reference the Tag +// +#define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag + +// Given a pointer to a Data packet, reference the data i.d. +// +#define ID_OF(pP) ((i2DataHeaderPtr)(pP))->i2sId + +// The possible types of ID's +// +#define ID_ORDINARY_DATA 0 +#define ID_HOT_KEY 1 + +// Given a pointer to a Data packet, reference the count +// +#define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount + +// Given a pointer to a Data packet, reference the beginning of data +// +#define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header + +// Given a pointer to a Non-Data packet, reference the count +// +#define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount + +#define MAX_CMD_PACK_SIZE 62 // Maximum size of such a count + +// Given a pointer to a Non-Data packet, reference the beginning of data +// +#define CMD_OF(pP) &((unsigned char *)(pP))[2] // 2 = size of header + +//-------------------------------- +// MailBox Bits: +//-------------------------------- + +//-------------------------- +// Outgoing (host to board) +//-------------------------- +// +#define MB_OUT_STUFFED 0x80 // Host has placed output in fifo +#define MB_IN_STRIPPED 0x40 // Host has read in all input from fifo + +//-------------------------- +// Incoming (board to host) +//-------------------------- +// +#define MB_IN_STUFFED 0x80 // Board has placed input in fifo +#define MB_OUT_STRIPPED 0x40 // Board has read all output from fifo +#define MB_FATAL_ERROR 0x20 // Board has encountered a fatal error + +#pragma pack() // Reset padding to command-line default + +#endif // I2PACK_H + diff --git a/drivers/staging/tty/ip2/ip2.h b/drivers/staging/tty/ip2/ip2.h new file mode 100644 index 000000000000..936ccc533949 --- /dev/null +++ b/drivers/staging/tty/ip2/ip2.h @@ -0,0 +1,107 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Driver constants for configuration and tuning +* +* NOTES: +* +*******************************************************************************/ +#ifndef IP2_H +#define IP2_H + +#include "ip2types.h" +#include "i2cmd.h" + +/*************/ +/* Constants */ +/*************/ + +/* Device major numbers - since version 2.0.26. */ +#define IP2_TTY_MAJOR 71 +#define IP2_CALLOUT_MAJOR 72 +#define IP2_IPL_MAJOR 73 + +/* Board configuration array. + * This array defines the hardware irq and address for up to IP2_MAX_BOARDS + * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified, + * PCI and EISA boards are probed for and automagicly configed + * iff the addresses are set to 1 and 2 respectivily. + * 0x0100 - 0x03f0 == ISA + * 1 == PCI + * 2 == EISA + * 0 == (skip this board) + * This array defines the hardware addresses for them. Special + * addresses are EISA and PCI which go sniffing for boards. + + * In a multiboard system the position in the array determines which port + * devices are assigned to each board: + * board 0 is assigned ttyF0.. to ttyF63, + * board 1 is assigned ttyF64 to ttyF127, + * board 2 is assigned ttyF128 to ttyF191, + * board 3 is assigned ttyF192 to ttyF255. + * + * In PCI and EISA bus systems each range is mapped to card in + * monotonically increasing slot number order, ISA position is as specified + * here. + + * If the irqs are ALL set to 0,0,0,0 all boards operate in + * polled mode. For interrupt operation ISA boards require that the IRQ be + * specified, while PCI and EISA boards any nonzero entry + * will enable interrupts using the BIOS configured irq for the board. + * An invalid irq entry will default to polled mode for that card and print + * console warning. + + * When the driver is loaded as a module these setting can be overridden on the + * modprobe command line or on an option line in /etc/modprobe.conf. + * If the driver is built-in the configuration must be + * set here for ISA cards and address set to 1 and 2 for PCI and EISA. + * + * Here is an example that shows most if not all possibe combinations: + + *static ip2config_t ip2config = + *{ + * {11,1,0,0}, // irqs + * { // Addresses + * 0x0308, // Board 0, ttyF0 - ttyF63// ISA card at io=0x308, irq=11 + * 0x0001, // Board 1, ttyF64 - ttyF127//PCI card configured by BIOS + * 0x0000, // Board 2, ttyF128 - ttyF191// Slot skipped + * 0x0002 // Board 3, ttyF192 - ttyF255//EISA card configured by BIOS + * // but polled not irq driven + * } + *}; + */ + + /* this structure is zeroed out because the suggested method is to configure + * the driver as a module, set up the parameters with an options line in + * /etc/modprobe.conf and load with modprobe or kmod, the kernel + * module loader + */ + + /* This structure is NOW always initialized when the driver is initialized. + * Compiled in defaults MUST be added to the io and irq arrays in + * ip2.c. Those values are configurable from insmod parameters in the + * case of modules or from command line parameters (ip2=io,irq) when + * compiled in. + */ + +static ip2config_t ip2config = +{ + {0,0,0,0}, // irqs + { // Addresses + /* Do NOT set compile time defaults HERE! Use the arrays in + ip2.c! These WILL be overwritten! =mhw= */ + 0x0000, // Board 0, ttyF0 - ttyF63 + 0x0000, // Board 1, ttyF64 - ttyF127 + 0x0000, // Board 2, ttyF128 - ttyF191 + 0x0000 // Board 3, ttyF192 - ttyF255 + } +}; + +#endif diff --git a/drivers/staging/tty/ip2/ip2ioctl.h b/drivers/staging/tty/ip2/ip2ioctl.h new file mode 100644 index 000000000000..aa0a9da85e05 --- /dev/null +++ b/drivers/staging/tty/ip2/ip2ioctl.h @@ -0,0 +1,35 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Driver constants for configuration and tuning +* +* NOTES: +* +*******************************************************************************/ + +#ifndef IP2IOCTL_H +#define IP2IOCTL_H + +//************* +//* Constants * +//************* + +// High baud rates (if not defined elsewhere. +#ifndef B153600 +# define B153600 0010005 +#endif +#ifndef B307200 +# define B307200 0010006 +#endif +#ifndef B921600 +# define B921600 0010007 +#endif + +#endif diff --git a/drivers/staging/tty/ip2/ip2main.c b/drivers/staging/tty/ip2/ip2main.c new file mode 100644 index 000000000000..ea7a8fb08283 --- /dev/null +++ b/drivers/staging/tty/ip2/ip2main.c @@ -0,0 +1,3234 @@ +/* +* +* (c) 1999 by Computone Corporation +* +******************************************************************************** +* +* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Mainline code for the device driver +* +*******************************************************************************/ +// ToDo: +// +// Fix the immediate DSS_NOW problem. +// Work over the channel stats return logic in ip2_ipl_ioctl so they +// make sense for all 256 possible channels and so the user space +// utilities will compile and work properly. +// +// Done: +// +// 1.2.14 /\/\|=mhw=|\/\/ +// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. +// Changed the definition of ip2trace to be more consistent with kernel style +// Thanks to Andreas Dilger for these updates +// +// 1.2.13 /\/\|=mhw=|\/\/ +// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform +// to agreed devfs serial device naming convention. +// +// 1.2.12 /\/\|=mhw=|\/\/ +// Cleaned up some remove queue cut and paste errors +// +// 1.2.11 /\/\|=mhw=|\/\/ +// Clean up potential NULL pointer dereferences +// Clean up devfs registration +// Add kernel command line parsing for io and irq +// Compile defaults for io and irq are now set in ip2.c not ip2.h! +// Reworked poll_only hack for explicit parameter setting +// You must now EXPLICITLY set poll_only = 1 or set all irqs to 0 +// Merged ip2_loadmain and old_ip2_init +// Converted all instances of interruptible_sleep_on into queue calls +// Most of these had no race conditions but better to clean up now +// +// 1.2.10 /\/\|=mhw=|\/\/ +// Fixed the bottom half interrupt handler and enabled USE_IQI +// to split the interrupt handler into a formal top-half / bottom-half +// Fixed timing window on high speed processors that queued messages to +// the outbound mail fifo faster than the board could handle. +// +// 1.2.9 +// Four box EX was barfing on >128k kmalloc, made structure smaller by +// reducing output buffer size +// +// 1.2.8 +// Device file system support (MHW) +// +// 1.2.7 +// Fixed +// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules +// +// 1.2.6 +//Fixes DCD problems +// DCD was not reported when CLOCAL was set on call to TIOCMGET +// +//Enhancements: +// TIOCMGET requests and waits for status return +// No DSS interrupts enabled except for DCD when needed +// +// For internal use only +// +//#define IP2DEBUG_INIT +//#define IP2DEBUG_OPEN +//#define IP2DEBUG_WRITE +//#define IP2DEBUG_READ +//#define IP2DEBUG_IOCTL +//#define IP2DEBUG_IPL + +//#define IP2DEBUG_TRACE +//#define DEBUG_FIFO + +/************/ +/* Includes */ +/************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "ip2types.h" +#include "ip2trace.h" +#include "ip2ioctl.h" +#include "ip2.h" +#include "i2ellis.h" +#include "i2lib.h" + +/***************** + * /proc/ip2mem * + *****************/ + +#include +#include + +static DEFINE_MUTEX(ip2_mutex); +static const struct file_operations ip2mem_proc_fops; +static const struct file_operations ip2_proc_fops; + +/********************/ +/* Type Definitions */ +/********************/ + +/*************/ +/* Constants */ +/*************/ + +/* String constants to identify ourselves */ +static const char pcName[] = "Computone IntelliPort Plus multiport driver"; +static const char pcVersion[] = "1.2.14"; + +/* String constants for port names */ +static const char pcDriver_name[] = "ip2"; +static const char pcIpl[] = "ip2ipl"; + +/***********************/ +/* Function Prototypes */ +/***********************/ + +/* Global module entry functions */ + +/* Private (static) functions */ +static int ip2_open(PTTY, struct file *); +static void ip2_close(PTTY, struct file *); +static int ip2_write(PTTY, const unsigned char *, int); +static int ip2_putchar(PTTY, unsigned char); +static void ip2_flush_chars(PTTY); +static int ip2_write_room(PTTY); +static int ip2_chars_in_buf(PTTY); +static void ip2_flush_buffer(PTTY); +static int ip2_ioctl(PTTY, UINT, ULONG); +static void ip2_set_termios(PTTY, struct ktermios *); +static void ip2_set_line_discipline(PTTY); +static void ip2_throttle(PTTY); +static void ip2_unthrottle(PTTY); +static void ip2_stop(PTTY); +static void ip2_start(PTTY); +static void ip2_hangup(PTTY); +static int ip2_tiocmget(struct tty_struct *tty); +static int ip2_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); +static int ip2_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount); + +static void set_irq(int, int); +static void ip2_interrupt_bh(struct work_struct *work); +static irqreturn_t ip2_interrupt(int irq, void *dev_id); +static void ip2_poll(unsigned long arg); +static inline void service_all_boards(void); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); + +static void ip2_wait_until_sent(PTTY,int); + +static void set_params (i2ChanStrPtr, struct ktermios *); +static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); +static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); + +static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); +static long ip2_ipl_ioctl(struct file *, UINT, ULONG); +static int ip2_ipl_open(struct inode *, struct file *); + +static int DumpTraceBuffer(char __user *, int); +static int DumpFifoBuffer( char __user *, int); + +static void ip2_init_board(int, const struct firmware *); +static unsigned short find_eisa_board(int); +static int ip2_setup(char *str); + +/***************/ +/* Static Data */ +/***************/ + +static struct tty_driver *ip2_tty_driver; + +/* Here, then is a table of board pointers which the interrupt routine should + * scan through to determine who it must service. + */ +static unsigned short i2nBoards; // Number of boards here + +static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS]; + +static i2ChanStrPtr DevTable[IP2_MAX_PORTS]; +//DevTableMem just used to save addresses for kfree +static void *DevTableMem[IP2_MAX_BOARDS]; + +/* This is the driver descriptor for the ip2ipl device, which is used to + * download the loadware to the boards. + */ +static const struct file_operations ip2_ipl = { + .owner = THIS_MODULE, + .read = ip2_ipl_read, + .write = ip2_ipl_write, + .unlocked_ioctl = ip2_ipl_ioctl, + .open = ip2_ipl_open, + .llseek = noop_llseek, +}; + +static unsigned long irq_counter; +static unsigned long bh_counter; + +// Use immediate queue to service interrupts +#define USE_IQI +//#define USE_IQ // PCI&2.2 needs work + +/* The timer_list entry for our poll routine. If interrupt operation is not + * selected, the board is serviced periodically to see if anything needs doing. + */ +#define POLL_TIMEOUT (jiffies + 1) +static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); + +#ifdef IP2DEBUG_TRACE +/* Trace (debug) buffer data */ +#define TRACEMAX 1000 +static unsigned long tracebuf[TRACEMAX]; +static int tracestuff; +static int tracestrip; +static int tracewrap; +#endif + +/**********/ +/* Macros */ +/**********/ + +#ifdef IP2DEBUG_OPEN +#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ + tty->name,(pCh->flags), \ + tty->count,/*GET_USE_COUNT(module)*/0,s) +#else +#define DBG_CNT(s) +#endif + +/********/ +/* Code */ +/********/ + +#include "i2ellis.c" /* Extremely low-level interface services */ +#include "i2cmd.c" /* Standard loadware command definitions */ +#include "i2lib.c" /* High level interface services */ + +/* Configuration area for modprobe */ + +MODULE_AUTHOR("Doug McNash"); +MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); +MODULE_LICENSE("GPL"); + +#define MAX_CMD_STR 50 + +static int poll_only; +static char cmd[MAX_CMD_STR]; + +static int Eisa_irq; +static int Eisa_slot; + +static int iindx; +static char rirqs[IP2_MAX_BOARDS]; +static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; + +/* Note: Add compiled in defaults to these arrays, not to the structure + in ip2.h any longer. That structure WILL get overridden + by these values, or command line values, or insmod values!!! =mhw= +*/ +static int io[IP2_MAX_BOARDS]; +static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; + +MODULE_AUTHOR("Doug McNash"); +MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); +module_param_array(irq, int, NULL, 0); +MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards"); +module_param_array(io, int, NULL, 0); +MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); +module_param(poll_only, bool, 0); +MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); +module_param_string(ip2, cmd, MAX_CMD_STR, 0); +MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); + +/* for sysfs class support */ +static struct class *ip2_class; + +/* Some functions to keep track of what irqs we have */ + +static int __init is_valid_irq(int irq) +{ + int *i = Valid_Irqs; + + while (*i != 0 && *i != irq) + i++; + + return *i; +} + +static void __init mark_requested_irq(char irq) +{ + rirqs[iindx++] = irq; +} + +static int __exit clear_requested_irq(char irq) +{ + int i; + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + if (rirqs[i] == irq) { + rirqs[i] = 0; + return 1; + } + } + return 0; +} + +static int have_requested_irq(char irq) +{ + /* array init to zeros so 0 irq will not be requested as a side + * effect */ + int i; + for (i = 0; i < IP2_MAX_BOARDS; ++i) + if (rirqs[i] == irq) + return 1; + return 0; +} + +/******************************************************************************/ +/* Function: cleanup_module() */ +/* Parameters: None */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This is a required entry point for an installable module. It has to return */ +/* the device and the driver to a passive state. It should not be necessary */ +/* to reset the board fully, especially as the loadware is downloaded */ +/* externally rather than in the driver. We just want to disable the board */ +/* and clear the loadware to a reset state. To allow this there has to be a */ +/* way to detect whether the board has the loadware running at init time to */ +/* handle subsequent installations of the driver. All memory allocated by the */ +/* driver should be returned since it may be unloaded from memory. */ +/******************************************************************************/ +static void __exit ip2_cleanup_module(void) +{ + int err; + int i; + + del_timer_sync(&PollTimer); + + /* Reset the boards we have. */ + for (i = 0; i < IP2_MAX_BOARDS; i++) + if (i2BoardPtrTable[i]) + iiReset(i2BoardPtrTable[i]); + + /* The following is done at most once, if any boards were installed. */ + for (i = 0; i < IP2_MAX_BOARDS; i++) { + if (i2BoardPtrTable[i]) { + iiResetDelay(i2BoardPtrTable[i]); + /* free io addresses and Tibet */ + release_region(ip2config.addr[i], 8); + device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); + device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, + 4 * i + 1)); + } + /* Disable and remove interrupt handler. */ + if (ip2config.irq[i] > 0 && + have_requested_irq(ip2config.irq[i])) { + free_irq(ip2config.irq[i], (void *)&pcName); + clear_requested_irq(ip2config.irq[i]); + } + } + class_destroy(ip2_class); + err = tty_unregister_driver(ip2_tty_driver); + if (err) + printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", + err); + put_tty_driver(ip2_tty_driver); + unregister_chrdev(IP2_IPL_MAJOR, pcIpl); + remove_proc_entry("ip2mem", NULL); + + /* free memory */ + for (i = 0; i < IP2_MAX_BOARDS; i++) { + void *pB; +#ifdef CONFIG_PCI + if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { + pci_disable_device(ip2config.pci_dev[i]); + pci_dev_put(ip2config.pci_dev[i]); + ip2config.pci_dev[i] = NULL; + } +#endif + pB = i2BoardPtrTable[i]; + if (pB != NULL) { + kfree(pB); + i2BoardPtrTable[i] = NULL; + } + if (DevTableMem[i] != NULL) { + kfree(DevTableMem[i]); + DevTableMem[i] = NULL; + } + } +} +module_exit(ip2_cleanup_module); + +static const struct tty_operations ip2_ops = { + .open = ip2_open, + .close = ip2_close, + .write = ip2_write, + .put_char = ip2_putchar, + .flush_chars = ip2_flush_chars, + .write_room = ip2_write_room, + .chars_in_buffer = ip2_chars_in_buf, + .flush_buffer = ip2_flush_buffer, + .ioctl = ip2_ioctl, + .throttle = ip2_throttle, + .unthrottle = ip2_unthrottle, + .set_termios = ip2_set_termios, + .set_ldisc = ip2_set_line_discipline, + .stop = ip2_stop, + .start = ip2_start, + .hangup = ip2_hangup, + .tiocmget = ip2_tiocmget, + .tiocmset = ip2_tiocmset, + .get_icount = ip2_get_icount, + .proc_fops = &ip2_proc_fops, +}; + +/******************************************************************************/ +/* Function: ip2_loadmain() */ +/* Parameters: irq, io from command line of insmod et. al. */ +/* pointer to fip firmware and firmware size for boards */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/* This was the required entry point for all drivers (now in ip2.c) */ +/* It performs all */ +/* initialisation of the devices and driver structures, and registers itself */ +/* with the relevant kernel modules. */ +/******************************************************************************/ +/* IRQF_DISABLED - if set blocks all interrupts else only this line */ +/* IRQF_SHARED - for shared irq PCI or maybe EISA only */ +/* SA_RANDOM - can be source for cert. random number generators */ +#define IP2_SA_FLAGS 0 + + +static const struct firmware *ip2_request_firmware(void) +{ + struct platform_device *pdev; + const struct firmware *fw; + + pdev = platform_device_register_simple("ip2", 0, NULL, 0); + if (IS_ERR(pdev)) { + printk(KERN_ERR "Failed to register platform device for ip2\n"); + return NULL; + } + if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) { + printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n"); + fw = NULL; + } + platform_device_unregister(pdev); + return fw; +} + +/****************************************************************************** + * ip2_setup: + * str: kernel command line string + * + * Can't autoprobe the boards so user must specify configuration on + * kernel command line. Sane people build it modular but the others + * come here. + * + * Alternating pairs of io,irq for up to 4 boards. + * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 + * + * io=0 => No board + * io=1 => PCI + * io=2 => EISA + * else => ISA I/O address + * + * irq=0 or invalid for ISA will revert to polling mode + * + * Any value = -1, do not overwrite compiled in value. + * + ******************************************************************************/ +static int __init ip2_setup(char *str) +{ + int j, ints[10]; /* 4 boards, 2 parameters + 2 */ + unsigned int i; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + for (i = 0, j = 1; i < 4; i++) { + if (j > ints[0]) + break; + if (ints[j] >= 0) + io[i] = ints[j]; + j++; + if (j > ints[0]) + break; + if (ints[j] >= 0) + irq[i] = ints[j]; + j++; + } + return 1; +} +__setup("ip2=", ip2_setup); + +static int __init ip2_loadmain(void) +{ + int i, j, box; + int err = 0; + i2eBordStrPtr pB = NULL; + int rc = -1; + const struct firmware *fw = NULL; + char *str; + + str = cmd; + + if (poll_only) { + /* Hard lock the interrupts to zero */ + irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; + } + + /* Check module parameter with 'ip2=' has been passed or not */ + if (!poll_only && (!strncmp(str, "ip2=", 4))) + ip2_setup(str); + + ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); + + /* process command line arguments to modprobe or + insmod i.e. iop & irqp */ + /* irqp and iop should ALWAYS be specified now... But we check + them individually just to be sure, anyways... */ + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + ip2config.addr[i] = io[i]; + if (irq[i] >= 0) + ip2config.irq[i] = irq[i]; + else + ip2config.irq[i] = 0; + /* This is a little bit of a hack. If poll_only=1 on command + line back in ip2.c OR all IRQs on all specified boards are + explicitly set to 0, then drop to poll only mode and override + PCI or EISA interrupts. This superceeds the old hack of + triggering if all interrupts were zero (like da default). + Still a hack but less prone to random acts of terrorism. + + What we really should do, now that the IRQ default is set + to -1, is to use 0 as a hard coded, do not probe. + + /\/\|=mhw=|\/\/ + */ + poll_only |= irq[i]; + } + poll_only = !poll_only; + + /* Announce our presence */ + printk(KERN_INFO "%s version %s\n", pcName, pcVersion); + + ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); + if (!ip2_tty_driver) + return -ENOMEM; + + /* Initialise all the boards we can find (up to the maximum). */ + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + switch (ip2config.addr[i]) { + case 0: /* skip this slot even if card is present */ + break; + default: /* ISA */ + /* ISA address must be specified */ + if (ip2config.addr[i] < 0x100 || + ip2config.addr[i] > 0x3f8) { + printk(KERN_ERR "IP2: Bad ISA board %d " + "address %x\n", i, + ip2config.addr[i]); + ip2config.addr[i] = 0; + break; + } + ip2config.type[i] = ISA; + + /* Check for valid irq argument, set for polling if + * invalid */ + if (ip2config.irq[i] && + !is_valid_irq(ip2config.irq[i])) { + printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n", + ip2config.irq[i]); + /* 0 is polling and is valid in that sense */ + ip2config.irq[i] = 0; + } + break; + case PCI: +#ifdef CONFIG_PCI + { + struct pci_dev *pdev = NULL; + u32 addr; + int status; + + pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE, + PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev); + if (pdev == NULL) { + ip2config.addr[i] = 0; + printk(KERN_ERR "IP2: PCI board %d not " + "found\n", i); + break; + } + + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, "can't enable device\n"); + goto out; + } + ip2config.type[i] = PCI; + ip2config.pci_dev[i] = pci_dev_get(pdev); + status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, + &addr); + if (addr & 1) + ip2config.addr[i] = (USHORT)(addr & 0xfffe); + else + dev_err(&pdev->dev, "I/O address error\n"); + + ip2config.irq[i] = pdev->irq; +out: + pci_dev_put(pdev); + } +#else + printk(KERN_ERR "IP2: PCI card specified but PCI " + "support not enabled.\n"); + printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI " + "defined!\n"); +#endif /* CONFIG_PCI */ + break; + case EISA: + ip2config.addr[i] = find_eisa_board(Eisa_slot + 1); + if (ip2config.addr[i] != 0) { + /* Eisa_irq set as side effect, boo */ + ip2config.type[i] = EISA; + } + ip2config.irq[i] = Eisa_irq; + break; + } /* switch */ + } /* for */ + + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + if (ip2config.addr[i]) { + pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); + if (pB) { + i2BoardPtrTable[i] = pB; + iiSetAddress(pB, ip2config.addr[i], + ii2DelayTimer); + iiReset(pB); + } else + printk(KERN_ERR "IP2: board memory allocation " + "error\n"); + } + } + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + pB = i2BoardPtrTable[i]; + if (pB != NULL) { + iiResetDelay(pB); + break; + } + } + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + /* We don't want to request the firmware unless we have at + least one board */ + if (i2BoardPtrTable[i] != NULL) { + if (!fw) + fw = ip2_request_firmware(); + if (!fw) + break; + ip2_init_board(i, fw); + } + } + if (fw) + release_firmware(fw); + + ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0); + + ip2_tty_driver->owner = THIS_MODULE; + ip2_tty_driver->name = "ttyF"; + ip2_tty_driver->driver_name = pcDriver_name; + ip2_tty_driver->major = IP2_TTY_MAJOR; + ip2_tty_driver->minor_start = 0; + ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; + ip2_tty_driver->init_termios = tty_std_termios; + ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(ip2_tty_driver, &ip2_ops); + + ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0); + + err = tty_register_driver(ip2_tty_driver); + if (err) { + printk(KERN_ERR "IP2: failed to register tty driver\n"); + put_tty_driver(ip2_tty_driver); + return err; /* leaking resources */ + } + + err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl); + if (err) { + printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", + err); + } else { + /* create the sysfs class */ + ip2_class = class_create(THIS_MODULE, "ip2"); + if (IS_ERR(ip2_class)) { + err = PTR_ERR(ip2_class); + goto out_chrdev; + } + } + /* Register the read_procmem thing */ + if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { + printk(KERN_ERR "IP2: failed to register read_procmem\n"); + return -EIO; /* leaking resources */ + } + + ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0); + /* Register the interrupt handler or poll handler, depending upon the + * specified interrupt. + */ + + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + if (ip2config.addr[i] == 0) + continue; + + pB = i2BoardPtrTable[i]; + if (pB != NULL) { + device_create(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i), + NULL, "ipl%d", i); + device_create(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i + 1), + NULL, "stat%d", i); + + for (box = 0; box < ABS_MAX_BOXES; box++) + for (j = 0; j < ABS_BIGGEST_BOX; j++) + if (pB->i2eChannelMap[box] & (1 << j)) + tty_register_device( + ip2_tty_driver, + j + ABS_BIGGEST_BOX * + (box+i*ABS_MAX_BOXES), + NULL); + } + + if (poll_only) { + /* Poll only forces driver to only use polling and + to ignore the probed PCI or EISA interrupts. */ + ip2config.irq[i] = CIR_POLL; + } + if (ip2config.irq[i] == CIR_POLL) { +retry: + if (!timer_pending(&PollTimer)) { + mod_timer(&PollTimer, POLL_TIMEOUT); + printk(KERN_INFO "IP2: polling\n"); + } + } else { + if (have_requested_irq(ip2config.irq[i])) + continue; + rc = request_irq(ip2config.irq[i], ip2_interrupt, + IP2_SA_FLAGS | + (ip2config.type[i] == PCI ? IRQF_SHARED : 0), + pcName, i2BoardPtrTable[i]); + if (rc) { + printk(KERN_ERR "IP2: request_irq failed: " + "error %d\n", rc); + ip2config.irq[i] = CIR_POLL; + printk(KERN_INFO "IP2: Polling %ld/sec.\n", + (POLL_TIMEOUT - jiffies)); + goto retry; + } + mark_requested_irq(ip2config.irq[i]); + /* Initialise the interrupt handler bottom half + * (aka slih). */ + } + } + + for (i = 0; i < IP2_MAX_BOARDS; ++i) { + if (i2BoardPtrTable[i]) { + /* set and enable board interrupt */ + set_irq(i, ip2config.irq[i]); + } + } + + ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0); + + return 0; + +out_chrdev: + unregister_chrdev(IP2_IPL_MAJOR, "ip2"); + /* unregister and put tty here */ + return err; +} +module_init(ip2_loadmain); + +/******************************************************************************/ +/* Function: ip2_init_board() */ +/* Parameters: Index of board in configuration structure */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/* This function initializes the specified board. The loadware is copied to */ +/* the board, the channel structures are initialized, and the board details */ +/* are reported on the console. */ +/******************************************************************************/ +static void +ip2_init_board(int boardnum, const struct firmware *fw) +{ + int i; + int nports = 0, nboxes = 0; + i2ChanStrPtr pCh; + i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; + + if ( !iiInitialize ( pB ) ) { + printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", + pB->i2eBase, pB->i2eError ); + goto err_initialize; + } + printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, + ip2config.addr[boardnum], ip2config.irq[boardnum] ); + + if (!request_region( ip2config.addr[boardnum], 8, pcName )) { + printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]); + goto err_initialize; + } + + if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size ) + != II_DOWN_GOOD ) { + printk ( KERN_ERR "IP2: failed to download loadware\n" ); + goto err_release_region; + } else { + printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", + pB->i2ePom.e.porVersion, + pB->i2ePom.e.porRevision, + pB->i2ePom.e.porSubRev, pB->i2eLVersion, + pB->i2eLRevision, pB->i2eLSub ); + } + + switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { + + default: + printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", + pB->i2ePom.e.porID ); + nports = 0; + goto err_release_region; + break; + + case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ + printk ( KERN_INFO "IP2: ISA-4\n" ); + nports = 4; + break; + + case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ + printk ( KERN_INFO "IP2: ISA-8 std\n" ); + nports = 8; + break; + + case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ + printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); + nports = 8; + break; + + case POR_ID_FIIEX: /* IntelliPort IIEX */ + { + int portnum = IP2_PORTS_PER_BOARD * boardnum; + int box; + + for( box = 0; box < ABS_MAX_BOXES; ++box ) { + if ( pB->i2eChannelMap[box] != 0 ) { + ++nboxes; + } + for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { + if ( pB->i2eChannelMap[box] & 1<< i ) { + ++nports; + } + } + } + DevTableMem[boardnum] = pCh = + kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); + if ( !pCh ) { + printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); + goto err_release_region; + } + if ( !i2InitChannels( pB, nports, pCh ) ) { + printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); + kfree ( pCh ); + goto err_release_region; + } + pB->i2eChannelPtr = &DevTable[portnum]; + pB->i2eChannelCnt = ABS_MOST_PORTS; + + for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { + for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { + if ( pB->i2eChannelMap[box] & (1 << i) ) { + DevTable[portnum + i] = pCh; + pCh->port_index = portnum + i; + pCh++; + } + } + } + printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", + nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); + } + goto ex_exit; + } + DevTableMem[boardnum] = pCh = + kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); + if ( !pCh ) { + printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); + goto err_release_region; + } + pB->i2eChannelPtr = pCh; + pB->i2eChannelCnt = nports; + if ( !i2InitChannels( pB, nports, pCh ) ) { + printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); + kfree ( pCh ); + goto err_release_region; + } + pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; + + for( i = 0; i < pB->i2eChannelCnt; ++i ) { + DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; + pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; + pCh++; + } +ex_exit: + INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); + return; + +err_release_region: + release_region(ip2config.addr[boardnum], 8); +err_initialize: + kfree ( pB ); + i2BoardPtrTable[boardnum] = NULL; + return; +} + +/******************************************************************************/ +/* Function: find_eisa_board ( int start_slot ) */ +/* Parameters: First slot to check */ +/* Returns: Address of EISA IntelliPort II controller */ +/* */ +/* Description: */ +/* This function searches for an EISA IntelliPort controller, starting */ +/* from the specified slot number. If the motherboard is not identified as an */ +/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ +/* it returns the base address of the controller. */ +/******************************************************************************/ +static unsigned short +find_eisa_board( int start_slot ) +{ + int i, j; + unsigned int idm = 0; + unsigned int idp = 0; + unsigned int base = 0; + unsigned int value; + int setup_address; + int setup_irq; + int ismine = 0; + + /* + * First a check for an EISA motherboard, which we do by comparing the + * EISA ID registers for the system board and the first couple of slots. + * No slot ID should match the system board ID, but on an ISA or PCI + * machine the odds are that an empty bus will return similar values for + * each slot. + */ + i = 0x0c80; + value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); + for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { + j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); + if ( value == j ) + return 0; + } + + /* + * OK, so we are inclined to believe that this is an EISA machine. Find + * an IntelliPort controller. + */ + for( i = start_slot; i < 16; i++ ) { + base = i << 12; + idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); + idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); + ismine = 0; + if ( idm == 0x0e8e ) { + if ( idp == 0x0281 || idp == 0x0218 ) { + ismine = 1; + } else if ( idp == 0x0282 || idp == 0x0283 ) { + ismine = 3; /* Can do edge-trigger */ + } + if ( ismine ) { + Eisa_slot = i; + break; + } + } + } + if ( !ismine ) + return 0; + + /* It's some sort of EISA card, but at what address is it configured? */ + + setup_address = base + 0xc88; + value = inb(base + 0xc86); + setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; + + if ( (ismine & 2) && !(value & 0x10) ) { + ismine = 1; /* Could be edging, but not */ + } + + if ( Eisa_irq == 0 ) { + Eisa_irq = setup_irq; + } else if ( Eisa_irq != setup_irq ) { + printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); + } + +#ifdef IP2DEBUG_INIT +printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", + base >> 12, idm, idp, setup_address); + if ( Eisa_irq ) { + printk(KERN_DEBUG ", Interrupt %d %s\n", + setup_irq, (ismine & 2) ? "(edge)" : "(level)"); + } else { + printk(KERN_DEBUG ", (polled)\n"); + } +#endif + return setup_address; +} + +/******************************************************************************/ +/* Function: set_irq() */ +/* Parameters: index to board in board table */ +/* IRQ to use */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/******************************************************************************/ +static void +set_irq( int boardnum, int boardIrq ) +{ + unsigned char tempCommand[16]; + i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; + unsigned long flags; + + /* + * Notify the boards they may generate interrupts. This is done by + * sending an in-line command to channel 0 on each board. This is why + * the channels have to be defined already. For each board, if the + * interrupt has never been defined, we must do so NOW, directly, since + * board will not send flow control or even give an interrupt until this + * is done. If polling we must send 0 as the interrupt parameter. + */ + + // We will get an interrupt here at the end of this function + + iiDisableMailIrq(pB); + + /* We build up the entire packet header. */ + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_INLINE; + CMD_COUNT_OF(tempCommand) = 2; + (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ; + (CMD_OF(tempCommand))[1] = boardIrq; + /* + * Write to FIFO; don't bother to adjust fifo capacity for this, since + * board will respond almost immediately after SendMail hit. + */ + write_lock_irqsave(&pB->write_fifo_spinlock, flags); + iiWriteBuf(pB, tempCommand, 4); + write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); + pB->i2eUsingIrq = boardIrq; + pB->i2eOutMailWaiting |= MB_OUT_STUFFED; + + /* Need to update number of boards before you enable mailbox int */ + ++i2nBoards; + + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_BYPASS; + CMD_COUNT_OF(tempCommand) = 6; + (CMD_OF(tempCommand))[0] = 88; // SILO + (CMD_OF(tempCommand))[1] = 64; // chars + (CMD_OF(tempCommand))[2] = 32; // ms + + (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK + (CMD_OF(tempCommand))[4] = 64; // chars + + (CMD_OF(tempCommand))[5] = 87; // HW_TEST + write_lock_irqsave(&pB->write_fifo_spinlock, flags); + iiWriteBuf(pB, tempCommand, 8); + write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); + + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_BYPASS; + CMD_COUNT_OF(tempCommand) = 1; + (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ + iiWriteBuf(pB, tempCommand, 3); + +#ifdef XXX + // enable heartbeat for test porpoises + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_BYPASS; + CMD_COUNT_OF(tempCommand) = 2; + (CMD_OF(tempCommand))[0] = 44; /* get ping */ + (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ + write_lock_irqsave(&pB->write_fifo_spinlock, flags); + iiWriteBuf(pB, tempCommand, 4); + write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); +#endif + + iiEnableMailIrq(pB); + iiSendPendingMail(pB); +} + +/******************************************************************************/ +/* Interrupt Handler Section */ +/******************************************************************************/ + +static inline void +service_all_boards(void) +{ + int i; + i2eBordStrPtr pB; + + /* Service every board on the list */ + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + pB = i2BoardPtrTable[i]; + if ( pB ) { + i2ServiceBoard( pB ); + } + } +} + + +/******************************************************************************/ +/* Function: ip2_interrupt_bh(work) */ +/* Parameters: work - pointer to the board structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* Service the board in a bottom half interrupt handler and then */ +/* reenable the board's interrupts if it has an IRQ number */ +/* */ +/******************************************************************************/ +static void +ip2_interrupt_bh(struct work_struct *work) +{ + i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); +// pB better well be set or we have a problem! We can only get +// here from the IMMEDIATE queue. Here, we process the boards. +// Checking pB doesn't cost much and it saves us from the sanity checkers. + + bh_counter++; + + if ( pB ) { + i2ServiceBoard( pB ); + if( pB->i2eUsingIrq ) { +// Re-enable his interrupts + iiEnableMailIrq(pB); + } + } +} + + +/******************************************************************************/ +/* Function: ip2_interrupt(int irq, void *dev_id) */ +/* Parameters: irq - interrupt number */ +/* pointer to optional device ID structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* Our task here is simply to identify each board which needs servicing. */ +/* If we are queuing then, queue it to be serviced, and disable its irq */ +/* mask otherwise process the board directly. */ +/* */ +/* We could queue by IRQ but that just complicates things on both ends */ +/* with very little gain in performance (how many instructions does */ +/* it take to iterate on the immediate queue). */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_irq_work(i2eBordStrPtr pB) +{ +#ifdef USE_IQI + if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { +// Disable his interrupt (will be enabled when serviced) +// This is mostly to protect from reentrancy. + iiDisableMailIrq(pB); + +// Park the board on the immediate queue for processing. + schedule_work(&pB->tqueue_interrupt); + +// Make sure the immediate queue is flagged to fire. + } +#else + +// We are using immediate servicing here. This sucks and can +// cause all sorts of havoc with ppp and others. The failsafe +// check on iiSendPendingMail could also throw a hairball. + + i2ServiceBoard( pB ); + +#endif /* USE_IQI */ +} + +static void +ip2_polled_interrupt(void) +{ + int i; + i2eBordStrPtr pB; + + ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0); + + /* Service just the boards on the list using this irq */ + for( i = 0; i < i2nBoards; ++i ) { + pB = i2BoardPtrTable[i]; + +// Only process those boards which match our IRQ. +// IRQ = 0 for polled boards, we won't poll "IRQ" boards + + if (pB && pB->i2eUsingIrq == 0) + ip2_irq_work(pB); + } + + ++irq_counter; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); +} + +static irqreturn_t +ip2_interrupt(int irq, void *dev_id) +{ + i2eBordStrPtr pB = dev_id; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq ); + + ip2_irq_work(pB); + + ++irq_counter; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); + return IRQ_HANDLED; +} + +/******************************************************************************/ +/* Function: ip2_poll(unsigned long arg) */ +/* Parameters: ? */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This function calls the library routine i2ServiceBoard for each board in */ +/* the board table. This is used instead of the interrupt routine when polled */ +/* mode is specified. */ +/******************************************************************************/ +static void +ip2_poll(unsigned long arg) +{ + ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); + + // Just polled boards, IRQ = 0 will hit all non-interrupt boards. + // It will NOT poll boards handled by hard interrupts. + // The issue of queued BH interrupts is handled in ip2_interrupt(). + ip2_polled_interrupt(); + + mod_timer(&PollTimer, POLL_TIMEOUT); + + ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); +} + +static void do_input(struct work_struct *work) +{ + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); + unsigned long flags; + + ip2trace(CHANN, ITRC_INPUT, 21, 0 ); + + // Data input + if ( pCh->pTTY != NULL ) { + read_lock_irqsave(&pCh->Ibuf_spinlock, flags); + if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { + read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + i2Input( pCh ); + } else + read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); + } else { + ip2trace(CHANN, ITRC_INPUT, 22, 0 ); + + i2InputFlush( pCh ); + } +} + +// code duplicated from n_tty (ldisc) +static inline void isig(int sig, struct tty_struct *tty, int flush) +{ + /* FIXME: This is completely bogus */ + if (tty->pgrp) + kill_pgrp(tty->pgrp, sig, 1); + if (flush || !L_NOFLSH(tty)) { + if ( tty->ldisc->ops->flush_buffer ) + tty->ldisc->ops->flush_buffer(tty); + i2InputFlush( tty->driver_data ); + } +} + +static void do_status(struct work_struct *work) +{ + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); + int status; + + status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); + + ip2trace (CHANN, ITRC_STATUS, 21, 1, status ); + + if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { + if ( (status & I2_BRK) ) { + // code duplicated from n_tty (ldisc) + if (I_IGNBRK(pCh->pTTY)) + goto skip_this; + if (I_BRKINT(pCh->pTTY)) { + isig(SIGINT, pCh->pTTY, 1); + goto skip_this; + } + wake_up_interruptible(&pCh->pTTY->read_wait); + } +#ifdef NEVER_HAPPENS_AS_SETUP_XXX + // and can't work because we don't know the_char + // as the_char is reported on a separate path + // The intelligent board does this stuff as setup + { + char brkf = TTY_NORMAL; + unsigned char brkc = '\0'; + unsigned char tmp; + if ( (status & I2_BRK) ) { + brkf = TTY_BREAK; + brkc = '\0'; + } + else if (status & I2_PAR) { + brkf = TTY_PARITY; + brkc = the_char; + } else if (status & I2_FRA) { + brkf = TTY_FRAME; + brkc = the_char; + } else if (status & I2_OVR) { + brkf = TTY_OVERRUN; + brkc = the_char; + } + tmp = pCh->pTTY->real_raw; + pCh->pTTY->real_raw = 0; + pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); + pCh->pTTY->real_raw = tmp; + } +#endif /* NEVER_HAPPENS_AS_SETUP_XXX */ + } +skip_this: + + if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { + wake_up_interruptible(&pCh->delta_msr_wait); + + if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { + if ( status & I2_DCD ) { + if ( pCh->wopen ) { + wake_up_interruptible ( &pCh->open_wait ); + } + } else { + if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { + tty_hangup( pCh->pTTY ); + } + } + } + } + + ip2trace (CHANN, ITRC_STATUS, 26, 0 ); +} + +/******************************************************************************/ +/* Device Open/Close/Ioctl Entry Point Section */ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: open_sanity_check() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* Verifies the structure magic numbers and cross links. */ +/******************************************************************************/ +#ifdef IP2DEBUG_OPEN +static void +open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ) +{ + if ( pBrd->i2eValid != I2E_MAGIC ) { + printk(KERN_ERR "IP2: invalid board structure\n" ); + } else if ( pBrd != pCh->pMyBord ) { + printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", + pCh->pMyBord ); + } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { + printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); + } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { + } else { + printk(KERN_INFO "IP2: all pointers check out!\n" ); + } +} +#endif + + +/******************************************************************************/ +/* Function: ip2_open() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Returns: Success or failure */ +/* */ +/* Description: (MANDATORY) */ +/* A successful device open has to run a gauntlet of checks before it */ +/* completes. After some sanity checking and pointer setup, the function */ +/* blocks until all conditions are satisfied. It then initialises the port to */ +/* the default characteristics and returns. */ +/******************************************************************************/ +static int +ip2_open( PTTY tty, struct file *pFile ) +{ + wait_queue_t wait; + int rc = 0; + int do_clocal = 0; + i2ChanStrPtr pCh = DevTable[tty->index]; + + ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 ); + + if ( pCh == NULL ) { + return -ENODEV; + } + /* Setup pointer links in device and tty structures */ + pCh->pTTY = tty; + tty->driver_data = pCh; + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG \ + "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n", + tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index); + open_sanity_check ( pCh, pCh->pMyBord ); +#endif + + i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); + pCh->dataSetOut |= (I2_DTR | I2_RTS); + serviceOutgoingFifo( pCh->pMyBord ); + + /* Block here until the port is ready (per serial and istallion) */ + /* + * 1. If the port is in the middle of closing wait for the completion + * and then return the appropriate error. + */ + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->close_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { + if ( pCh->flags & ASYNC_CLOSING ) { + tty_unlock(); + schedule(); + tty_lock(); + } + if ( tty_hung_up_p(pFile) ) { + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->close_wait, &wait); + return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; + } + } + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->close_wait, &wait); + + /* + * 3. Handle a non-blocking open of a normal port. + */ + if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<flags |= ASYNC_NORMAL_ACTIVE; + goto noblock; + } + /* + * 4. Now loop waiting for the port to be free and carrier present + * (if required). + */ + if ( tty->termios->c_cflag & CLOCAL ) + do_clocal = 1; + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal); +#endif + + ++pCh->wopen; + + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->open_wait, &wait); + + for(;;) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); + pCh->dataSetOut |= (I2_DTR | I2_RTS); + set_current_state( TASK_INTERRUPTIBLE ); + serviceOutgoingFifo( pCh->pMyBord ); + if ( tty_hung_up_p(pFile) ) { + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->open_wait, &wait); + return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; + } + if (!(pCh->flags & ASYNC_CLOSING) && + (do_clocal || (pCh->dataSetIn & I2_DCD) )) { + rc = 0; + break; + } + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", + (pCh->flags & ASYNC_CLOSING)?"True":"False"); + printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n"); +#endif + ip2trace (CHANN, ITRC_OPEN, 3, 2, 0, + (pCh->flags & ASYNC_CLOSING) ); + /* check for signal */ + if (signal_pending(current)) { + rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); + break; + } + tty_unlock(); + schedule(); + tty_lock(); + } + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->open_wait, &wait); + + --pCh->wopen; //why count? + + ip2trace (CHANN, ITRC_OPEN, 4, 0 ); + + if (rc != 0 ) { + return rc; + } + pCh->flags |= ASYNC_NORMAL_ACTIVE; + +noblock: + + /* first open - Assign termios structure to port */ + if ( tty->count == 1 ) { + i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); + /* Now we must send the termios settings to the loadware */ + set_params( pCh, NULL ); + } + + /* + * Now set any i2lib options. These may go away if the i2lib code ends + * up rolled into the mainline. + */ + pCh->channelOptions |= CO_NBLOCK_WRITE; + +#ifdef IP2DEBUG_OPEN + printk (KERN_DEBUG "IP2: open completed\n" ); +#endif + serviceOutgoingFifo( pCh->pMyBord ); + + ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); + + return 0; +} + +/******************************************************************************/ +/* Function: ip2_close() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_close( PTTY tty, struct file *pFile ) +{ + i2ChanStrPtr pCh = tty->driver_data; + + if ( !pCh ) { + return; + } + + ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 ); + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG "IP2:close %s:\n",tty->name); +#endif + + if ( tty_hung_up_p ( pFile ) ) { + + ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); + + return; + } + if ( tty->count > 1 ) { /* not the last close */ + + ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); + + return; + } + pCh->flags |= ASYNC_CLOSING; // last close actually + + tty->closing = 1; + + if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { + /* + * Before we drop DTR, make sure the transmitter has completely drained. + * This uses an timeout, after which the close + * completes. + */ + ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); + } + /* + * At this point we stop accepting input. Here we flush the channel + * input buffer which will allow the board to send up more data. Any + * additional input is tossed at interrupt/poll time. + */ + i2InputFlush( pCh ); + + /* disable DSS reporting */ + i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, + CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); + if (tty->termios->c_cflag & HUPCL) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); + pCh->dataSetOut &= ~(I2_DTR | I2_RTS); + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); + } + + serviceOutgoingFifo ( pCh->pMyBord ); + + tty_ldisc_flush(tty); + tty_driver_flush_buffer(tty); + tty->closing = 0; + + pCh->pTTY = NULL; + + if (pCh->wopen) { + if (pCh->ClosingDelay) { + msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); + } + wake_up_interruptible(&pCh->open_wait); + } + + pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&pCh->close_wait); + +#ifdef IP2DEBUG_OPEN + DBG_CNT("ip2_close: after wakeups--"); +#endif + + + ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); + + return; +} + +/******************************************************************************/ +/* Function: ip2_hangup() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_hangup ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + + if( !pCh ) { + return; + } + + ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); + + ip2_flush_buffer(tty); + + /* disable DSS reporting */ + + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); + i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); + if ( (tty->termios->c_cflag & HUPCL) ) { + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); + pCh->dataSetOut &= ~(I2_DTR | I2_RTS); + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); + } + i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, + CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); + serviceOutgoingFifo ( pCh->pMyBord ); + + wake_up_interruptible ( &pCh->delta_msr_wait ); + + pCh->flags &= ~ASYNC_NORMAL_ACTIVE; + pCh->pTTY = NULL; + wake_up_interruptible ( &pCh->open_wait ); + + ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 ); +} + +/******************************************************************************/ +/******************************************************************************/ +/* Device Output Section */ +/******************************************************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: ip2_write() */ +/* Parameters: Pointer to tty structure */ +/* Flag denoting data is in user (1) or kernel (0) space */ +/* Pointer to data */ +/* Number of bytes to write */ +/* Returns: Number of bytes actually written */ +/* */ +/* Description: (MANDATORY) */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_write( PTTY tty, const unsigned char *pData, int count) +{ + i2ChanStrPtr pCh = tty->driver_data; + int bytesSent = 0; + unsigned long flags; + + ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); + + /* Flush out any buffered data left over from ip2_putchar() calls. */ + ip2_flush_chars( tty ); + + /* This is the actual move bit. Make sure it does what we need!!!!! */ + write_lock_irqsave(&pCh->Pbuf_spinlock, flags); + bytesSent = i2Output( pCh, pData, count); + write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); + + ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); + + return bytesSent > 0 ? bytesSent : 0; +} + +/******************************************************************************/ +/* Function: ip2_putchar() */ +/* Parameters: Pointer to tty structure */ +/* Character to write */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_putchar( PTTY tty, unsigned char ch ) +{ + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + +// ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); + + write_lock_irqsave(&pCh->Pbuf_spinlock, flags); + pCh->Pbuf[pCh->Pbuf_stuff++] = ch; + if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { + write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); + ip2_flush_chars( tty ); + } else + write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); + return 1; + +// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); +} + +/******************************************************************************/ +/* Function: ip2_flush_chars() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/******************************************************************************/ +static void +ip2_flush_chars( PTTY tty ) +{ + int strip; + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + + write_lock_irqsave(&pCh->Pbuf_spinlock, flags); + if ( pCh->Pbuf_stuff ) { + +// ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); + + // + // We may need to restart i2Output if it does not fullfill this request + // + strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff); + if ( strip != pCh->Pbuf_stuff ) { + memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); + } + pCh->Pbuf_stuff -= strip; + } + write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); +} + +/******************************************************************************/ +/* Function: ip2_write_room() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Number of bytes that the driver can accept */ +/* */ +/* Description: */ +/* */ +/******************************************************************************/ +static int +ip2_write_room ( PTTY tty ) +{ + int bytesFree; + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + + read_lock_irqsave(&pCh->Pbuf_spinlock, flags); + bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; + read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); + + ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); + + return ((bytesFree > 0) ? bytesFree : 0); +} + +/******************************************************************************/ +/* Function: ip2_chars_in_buf() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Number of bytes queued for transmission */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_chars_in_buf ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + int rc; + unsigned long flags; + + ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff ); + +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", + pCh->Obuf_char_count + pCh->Pbuf_stuff, + pCh->Obuf_char_count, pCh->Pbuf_stuff ); +#endif + read_lock_irqsave(&pCh->Obuf_spinlock, flags); + rc = pCh->Obuf_char_count; + read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); + read_lock_irqsave(&pCh->Pbuf_spinlock, flags); + rc += pCh->Pbuf_stuff; + read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); + return rc; +} + +/******************************************************************************/ +/* Function: ip2_flush_buffer() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_flush_buffer( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + + ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 ); + +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: flush buffer\n" ); +#endif + write_lock_irqsave(&pCh->Pbuf_spinlock, flags); + pCh->Pbuf_stuff = 0; + write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); + i2FlushOutput( pCh ); + ip2_owake(tty); + + ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 ); + +} + +/******************************************************************************/ +/* Function: ip2_wait_until_sent() */ +/* Parameters: Pointer to tty structure */ +/* Timeout for wait. */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This function is used in place of the normal tty_wait_until_sent, which */ +/* only waits for the driver buffers to be empty (or rather, those buffers */ +/* reported by chars_in_buffer) which doesn't work for IP2 due to the */ +/* indeterminate number of bytes buffered on the board. */ +/******************************************************************************/ +static void +ip2_wait_until_sent ( PTTY tty, int timeout ) +{ + int i = jiffies; + i2ChanStrPtr pCh = tty->driver_data; + + tty_wait_until_sent(tty, timeout ); + if ( (i = timeout - (jiffies -i)) > 0) + i2DrainOutput( pCh, i ); +} + +/******************************************************************************/ +/******************************************************************************/ +/* Device Input Section */ +/******************************************************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: ip2_throttle() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_throttle ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + +#ifdef IP2DEBUG_READ + printk (KERN_DEBUG "IP2: throttle\n" ); +#endif + /* + * Signal the poll/interrupt handlers not to forward incoming data to + * the line discipline. This will cause the buffers to fill up in the + * library and thus cause the library routines to send the flow control + * stuff. + */ + pCh->throttled = 1; +} + +/******************************************************************************/ +/* Function: ip2_unthrottle() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_unthrottle ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + +#ifdef IP2DEBUG_READ + printk (KERN_DEBUG "IP2: unthrottle\n" ); +#endif + + /* Pass incoming data up to the line discipline again. */ + pCh->throttled = 0; + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); + serviceOutgoingFifo( pCh->pMyBord ); + read_lock_irqsave(&pCh->Ibuf_spinlock, flags); + if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) { + read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); +#ifdef IP2DEBUG_READ + printk (KERN_DEBUG "i2Input called from unthrottle\n" ); +#endif + i2Input( pCh ); + } else + read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); +} + +static void +ip2_start ( PTTY tty ) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND); + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME); +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: start tx\n" ); +#endif +} + +static void +ip2_stop ( PTTY tty ) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND); +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: stop tx\n" ); +#endif +} + +/******************************************************************************/ +/* Device Ioctl Section */ +/******************************************************************************/ + +static int ip2_tiocmget(struct tty_struct *tty) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; +#ifdef ENABLE_DSSNOW + wait_queue_t wait; +#endif + + if (pCh == NULL) + return -ENODEV; + +/* + FIXME - the following code is causing a NULL pointer dereference in + 2.3.51 in an interrupt handler. It's suppose to prompt the board + to return the DSS signal status immediately. Why doesn't it do + the same thing in 2.2.14? +*/ + +/* This thing is still busted in the 1.2.12 driver on 2.4.x + and even hoses the serial console so the oops can be trapped. + /\/\|=mhw=|\/\/ */ + +#ifdef ENABLE_DSSNOW + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); + + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->dss_now_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + serviceOutgoingFifo( pCh->pMyBord ); + + schedule(); + + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->dss_now_wait, &wait); + + if (signal_pending(current)) { + return -EINTR; + } +#endif + return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) + | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) + | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) + | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) + | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) + | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); +} + +static int ip2_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + if (pCh == NULL) + return -ENODEV; + + if (set & TIOCM_RTS) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); + pCh->dataSetOut |= I2_RTS; + } + if (set & TIOCM_DTR) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); + pCh->dataSetOut |= I2_DTR; + } + + if (clear & TIOCM_RTS) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); + pCh->dataSetOut &= ~I2_RTS; + } + if (clear & TIOCM_DTR) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); + pCh->dataSetOut &= ~I2_DTR; + } + serviceOutgoingFifo( pCh->pMyBord ); + return 0; +} + +/******************************************************************************/ +/* Function: ip2_ioctl() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Command */ +/* Argument */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg ) +{ + wait_queue_t wait; + i2ChanStrPtr pCh = DevTable[tty->index]; + i2eBordStrPtr pB; + struct async_icount cprev, cnow; /* kernel counter temps */ + int rc = 0; + unsigned long flags; + void __user *argp = (void __user *)arg; + + if ( pCh == NULL ) + return -ENODEV; + + pB = pCh->pMyBord; + + ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg ); + +#ifdef IP2DEBUG_IOCTL + printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg ); +#endif + + switch(cmd) { + case TIOCGSERIAL: + + ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc ); + + rc = get_serial_info(pCh, argp); + if (rc) + return rc; + break; + + case TIOCSSERIAL: + + ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc ); + + rc = set_serial_info(pCh, argp); + if (rc) + return rc; + break; + + case TCXONC: + rc = tty_check_change(tty); + if (rc) + return rc; + switch (arg) { + case TCOOFF: + //return -ENOIOCTLCMD; + break; + case TCOON: + //return -ENOIOCTLCMD; + break; + case TCIOFF: + if (STOP_CHAR(tty) != __DISABLED_CHAR) { + i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, + CMD_XMIT_NOW(STOP_CHAR(tty))); + } + break; + case TCION: + if (START_CHAR(tty) != __DISABLED_CHAR) { + i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, + CMD_XMIT_NOW(START_CHAR(tty))); + } + break; + default: + return -EINVAL; + } + return 0; + + case TCSBRK: /* SVID version: non-zero arg --> no break */ + rc = tty_check_change(tty); + + ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc ); + + if (!rc) { + ip2_wait_until_sent(tty,0); + if (!arg) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250)); + serviceOutgoingFifo( pCh->pMyBord ); + } + } + break; + + case TCSBRKP: /* support for POSIX tcsendbreak() */ + rc = tty_check_change(tty); + + ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc ); + + if (!rc) { + ip2_wait_until_sent(tty,0); + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, + CMD_SEND_BRK(arg ? arg*100 : 250)); + serviceOutgoingFifo ( pCh->pMyBord ); + } + break; + + case TIOCGSOFTCAR: + + ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); + + rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); + if (rc) + return rc; + break; + + case TIOCSSOFTCAR: + + ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); + + rc = get_user(arg,(unsigned long __user *) argp); + if (rc) + return rc; + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) + | (arg ? CLOCAL : 0)); + + break; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask + * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS + * for masking). Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + write_lock_irqsave(&pB->read_fifo_spinlock, flags); + cprev = pCh->icount; /* note the counters on entry */ + write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, + CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP); + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->delta_msr_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + serviceOutgoingFifo( pCh->pMyBord ); + for(;;) { + ip2trace (CHANN, ITRC_IOCTL, 10, 0 ); + + schedule(); + + ip2trace (CHANN, ITRC_IOCTL, 11, 0 ); + + /* see if a signal did it */ + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + write_lock_irqsave(&pB->read_fifo_spinlock, flags); + cnow = pCh->icount; /* atomic copy */ + write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + rc = -EIO; /* no change => rc */ + break; + } + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + rc = 0; + break; + } + cprev = cnow; + } + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->delta_msr_wait, &wait); + + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, + CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); + if ( ! (pCh->flags & ASYNC_CHECK_CD)) { + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP); + } + serviceOutgoingFifo( pCh->pMyBord ); + return rc; + break; + + /* + * The rest are not supported by this driver. By returning -ENOIOCTLCMD they + * will be passed to the line discipline for it to handle. + */ + case TIOCSERCONFIG: + case TIOCSERGWILD: + case TIOCSERGETLSR: + case TIOCSERSWILD: + case TIOCSERGSTRUCT: + case TIOCSERGETMULTI: + case TIOCSERSETMULTI: + + default: + ip2trace (CHANN, ITRC_IOCTL, 12, 0 ); + + rc = -ENOIOCTLCMD; + break; + } + + ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 ); + + return rc; +} + +static int ip2_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + i2eBordStrPtr pB; + struct async_icount cnow; /* kernel counter temp */ + unsigned long flags; + + if ( pCh == NULL ) + return -ENODEV; + + pB = pCh->pMyBord; + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for RI where + * only 0->1 is counted. The controller is quite capable of counting + * both, but this done to preserve compatibility with the standard + * serial driver. + */ + + write_lock_irqsave(&pB->read_fifo_spinlock, flags); + cnow = pCh->icount; + write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->frame = cnow.frame; + icount->overrun = cnow.overrun; + icount->parity = cnow.parity; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + return 0; +} + +/******************************************************************************/ +/* Function: GetSerialInfo() */ +/* Parameters: Pointer to channel structure */ +/* Pointer to old termios structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This is to support the setserial command, and requires processing of the */ +/* standard Linux serial structure. */ +/******************************************************************************/ +static int +get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo ) +{ + struct serial_struct tmp; + + memset ( &tmp, 0, sizeof(tmp) ); + tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16]; + if (BID_HAS_654(tmp.type)) { + tmp.type = PORT_16650; + } else { + tmp.type = PORT_CIRRUS; + } + tmp.line = pCh->port_index; + tmp.port = pCh->pMyBord->i2eBase; + tmp.irq = ip2config.irq[pCh->port_index/64]; + tmp.flags = pCh->flags; + tmp.baud_base = pCh->BaudBase; + tmp.close_delay = pCh->ClosingDelay; + tmp.closing_wait = pCh->ClosingWaitTime; + tmp.custom_divisor = pCh->BaudDivisor; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); +} + +/******************************************************************************/ +/* Function: SetSerialInfo() */ +/* Parameters: Pointer to channel structure */ +/* Pointer to old termios structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This function provides support for setserial, which uses the TIOCSSERIAL */ +/* ioctl. Not all setserial parameters are relevant. If the user attempts to */ +/* change the IRQ, address or type of the port the ioctl fails. */ +/******************************************************************************/ +static int +set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) +{ + struct serial_struct ns; + int old_flags, old_baud_divisor; + + if (copy_from_user(&ns, new_info, sizeof (ns))) + return -EFAULT; + + /* + * We don't allow setserial to change IRQ, board address, type or baud + * base. Also line nunber as such is meaningless but we use it for our + * array index so it is fixed also. + */ + if ( (ns.irq != ip2config.irq[pCh->port_index]) + || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) + || (ns.baud_base != pCh->BaudBase) + || (ns.line != pCh->port_index) ) { + return -EINVAL; + } + + old_flags = pCh->flags; + old_baud_divisor = pCh->BaudDivisor; + + if ( !capable(CAP_SYS_ADMIN) ) { + if ( ( ns.close_delay != pCh->ClosingDelay ) || + ( (ns.flags & ~ASYNC_USR_MASK) != + (pCh->flags & ~ASYNC_USR_MASK) ) ) { + return -EPERM; + } + + pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) | + (ns.flags & ASYNC_USR_MASK); + pCh->BaudDivisor = ns.custom_divisor; + } else { + pCh->flags = (pCh->flags & ~ASYNC_FLAGS) | + (ns.flags & ASYNC_FLAGS); + pCh->BaudDivisor = ns.custom_divisor; + pCh->ClosingDelay = ns.close_delay * HZ/100; + pCh->ClosingWaitTime = ns.closing_wait * HZ/100; + } + + if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) ) + || (old_baud_divisor != pCh->BaudDivisor) ) { + // Invalidate speed and reset parameters + set_params( pCh, NULL ); + } + + return 0; +} + +/******************************************************************************/ +/* Function: ip2_set_termios() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to old termios structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_set_termios( PTTY tty, struct ktermios *old_termios ) +{ + i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; + +#ifdef IP2DEBUG_IOCTL + printk (KERN_DEBUG "IP2: set termios %p\n", old_termios ); +#endif + + set_params( pCh, old_termios ); +} + +/******************************************************************************/ +/* Function: ip2_set_line_discipline() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: Does nothing */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_set_line_discipline ( PTTY tty ) +{ +#ifdef IP2DEBUG_IOCTL + printk (KERN_DEBUG "IP2: set line discipline\n" ); +#endif + + ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 ); + +} + +/******************************************************************************/ +/* Function: SetLine Characteristics() */ +/* Parameters: Pointer to channel structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This routine is called to update the channel structure with the new line */ +/* characteristics, and send the appropriate commands to the board when they */ +/* change. */ +/******************************************************************************/ +static void +set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) +{ + tcflag_t cflag, iflag, lflag; + char stop_char, start_char; + struct ktermios dummy; + + lflag = pCh->pTTY->termios->c_lflag; + cflag = pCh->pTTY->termios->c_cflag; + iflag = pCh->pTTY->termios->c_iflag; + + if (o_tios == NULL) { + dummy.c_lflag = ~lflag; + dummy.c_cflag = ~cflag; + dummy.c_iflag = ~iflag; + o_tios = &dummy; + } + + { + switch ( cflag & CBAUD ) { + case B0: + i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); + pCh->dataSetOut &= ~(I2_DTR | I2_RTS); + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); + pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag); + goto service_it; + break; + case B38400: + /* + * This is the speed that is overloaded with all the other high + * speeds, depending upon the flag settings. + */ + if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) { + pCh->speed = CBR_57600; + } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) { + pCh->speed = CBR_115200; + } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) { + pCh->speed = CBR_C1; + } else { + pCh->speed = CBR_38400; + } + break; + case B50: pCh->speed = CBR_50; break; + case B75: pCh->speed = CBR_75; break; + case B110: pCh->speed = CBR_110; break; + case B134: pCh->speed = CBR_134; break; + case B150: pCh->speed = CBR_150; break; + case B200: pCh->speed = CBR_200; break; + case B300: pCh->speed = CBR_300; break; + case B600: pCh->speed = CBR_600; break; + case B1200: pCh->speed = CBR_1200; break; + case B1800: pCh->speed = CBR_1800; break; + case B2400: pCh->speed = CBR_2400; break; + case B4800: pCh->speed = CBR_4800; break; + case B9600: pCh->speed = CBR_9600; break; + case B19200: pCh->speed = CBR_19200; break; + case B57600: pCh->speed = CBR_57600; break; + case B115200: pCh->speed = CBR_115200; break; + case B153600: pCh->speed = CBR_153600; break; + case B230400: pCh->speed = CBR_230400; break; + case B307200: pCh->speed = CBR_307200; break; + case B460800: pCh->speed = CBR_460800; break; + case B921600: pCh->speed = CBR_921600; break; + default: pCh->speed = CBR_9600; break; + } + if ( pCh->speed == CBR_C1 ) { + // Process the custom speed parameters. + int bps = pCh->BaudBase / pCh->BaudDivisor; + if ( bps == 921600 ) { + pCh->speed = CBR_921600; + } else { + bps = bps/10; + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) ); + } + } + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed)); + + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); + pCh->dataSetOut |= (I2_DTR | I2_RTS); + } + if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) + { + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, + CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1)); + } + if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) + { + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, + CMD_SETPAR( + (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP) + ) + ); + } + /* byte size and parity */ + if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) + { + int datasize; + switch ( cflag & CSIZE ) { + case CS5: datasize = CSZ_5; break; + case CS6: datasize = CSZ_6; break; + case CS7: datasize = CSZ_7; break; + case CS8: datasize = CSZ_8; break; + default: datasize = CSZ_5; break; /* as per serial.c */ + } + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) ); + } + /* Process CTS flow control flag setting */ + if ( (cflag & CRTSCTS) ) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, + 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB); + } else { + i2QueueCommands(PTYPE_INLINE, pCh, 100, + 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); + } + // + // Process XON/XOFF flow control flags settings + // + stop_char = STOP_CHAR(pCh->pTTY); + start_char = START_CHAR(pCh->pTTY); + + //////////// can't be \000 + if (stop_char == __DISABLED_CHAR ) + { + stop_char = ~__DISABLED_CHAR; + } + if (start_char == __DISABLED_CHAR ) + { + start_char = ~__DISABLED_CHAR; + } + ///////////////////////////////// + + if ( o_tios->c_cc[VSTART] != start_char ) + { + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char)); + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char)); + } + if ( o_tios->c_cc[VSTOP] != stop_char ) + { + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char)); + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char)); + } + if (stop_char == __DISABLED_CHAR ) + { + stop_char = ~__DISABLED_CHAR; //TEST123 + goto no_xoff; + } + if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) + { + if ( iflag & IXOFF ) { // Enable XOFF output flow control + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON)); + } else { // Disable XOFF output flow control +no_xoff: + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE)); + } + } + if (start_char == __DISABLED_CHAR ) + { + goto no_xon; + } + if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) + { + if ( iflag & IXON ) { + if ( iflag & IXANY ) { // Enable XON/XANY output flow control + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY)); + } else { // Enable XON output flow control + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON)); + } + } else { // Disable XON output flow control +no_xon: + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE)); + } + } + if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) + { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, + CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0))); + } + if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) + { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, + CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB)); + } + + if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) + ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) + { + char brkrpt = 0; + char parrpt = 0; + + if ( iflag & IGNBRK ) { /* Ignore breaks altogether */ + /* Ignore breaks altogether */ + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP); + } else { + if ( iflag & BRKINT ) { + if ( iflag & PARMRK ) { + brkrpt = 0x0a; // exception an inline triple + } else { + brkrpt = 0x1a; // exception and NULL + } + brkrpt |= 0x04; // flush input + } else { + if ( iflag & PARMRK ) { + brkrpt = 0x0b; //POSIX triple \0377 \0 \0 + } else { + brkrpt = 0x01; // Null only + } + } + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt)); + } + + if (iflag & IGNPAR) { + parrpt = 0x20; + /* would be 2 for not cirrus bug */ + /* would be 0x20 cept for cirrus bug */ + } else { + if ( iflag & PARMRK ) { + /* + * Replace error characters with 3-byte sequence (\0377,\0,char) + */ + parrpt = 0x04 ; + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0)); + } else { + parrpt = 0x03; + } + } + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt)); + } + if (cflag & CLOCAL) { + // Status reporting fails for DCD if this is off + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP); + pCh->flags &= ~ASYNC_CHECK_CD; + } else { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP); + pCh->flags |= ASYNC_CHECK_CD; + } + +service_it: + i2DrainOutput( pCh, 100 ); +} + +/******************************************************************************/ +/* IPL Device Section */ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: ip2_ipl_read() */ +/* Parameters: Pointer to device inode */ +/* Pointer to file structure */ +/* Pointer to data */ +/* Number of bytes to read */ +/* Returns: Success or failure */ +/* */ +/* Description: Ugly */ +/* */ +/* */ +/******************************************************************************/ + +static +ssize_t +ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) +{ + unsigned int minor = iminor(pFile->f_path.dentry->d_inode); + int rc = 0; + +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count ); +#endif + + switch( minor ) { + case 0: // IPL device + rc = -EINVAL; + break; + case 1: // Status dump + rc = -EINVAL; + break; + case 2: // Ping device + rc = -EINVAL; + break; + case 3: // Trace device + rc = DumpTraceBuffer ( pData, count ); + break; + case 4: // Trace device + rc = DumpFifoBuffer ( pData, count ); + break; + default: + rc = -ENODEV; + break; + } + return rc; +} + +static int +DumpFifoBuffer ( char __user *pData, int count ) +{ +#ifdef DEBUG_FIFO + int rc; + rc = copy_to_user(pData, DBGBuf, count); + + printk(KERN_DEBUG "Last index %d\n", I ); + + return count; +#endif /* DEBUG_FIFO */ + return 0; +} + +static int +DumpTraceBuffer ( char __user *pData, int count ) +{ +#ifdef IP2DEBUG_TRACE + int rc; + int dumpcount; + int chunk; + int *pIndex = (int __user *)pData; + + if ( count < (sizeof(int) * 6) ) { + return -EIO; + } + rc = put_user(tracewrap, pIndex ); + rc = put_user(TRACEMAX, ++pIndex ); + rc = put_user(tracestrip, ++pIndex ); + rc = put_user(tracestuff, ++pIndex ); + pData += sizeof(int) * 6; + count -= sizeof(int) * 6; + + dumpcount = tracestuff - tracestrip; + if ( dumpcount < 0 ) { + dumpcount += TRACEMAX; + } + if ( dumpcount > count ) { + dumpcount = count; + } + chunk = TRACEMAX - tracestrip; + if ( dumpcount > chunk ) { + rc = copy_to_user(pData, &tracebuf[tracestrip], + chunk * sizeof(tracebuf[0]) ); + pData += chunk * sizeof(tracebuf[0]); + tracestrip = 0; + chunk = dumpcount - chunk; + } else { + chunk = dumpcount; + } + rc = copy_to_user(pData, &tracebuf[tracestrip], + chunk * sizeof(tracebuf[0]) ); + tracestrip += chunk; + tracewrap = 0; + + rc = put_user(tracestrip, ++pIndex ); + rc = put_user(tracestuff, ++pIndex ); + + return dumpcount; +#else + return 0; +#endif +} + +/******************************************************************************/ +/* Function: ip2_ipl_write() */ +/* Parameters: */ +/* Pointer to file structure */ +/* Pointer to data */ +/* Number of bytes to write */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static ssize_t +ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off) +{ +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count ); +#endif + return 0; +} + +/******************************************************************************/ +/* Function: ip2_ipl_ioctl() */ +/* Parameters: Pointer to device inode */ +/* Pointer to file structure */ +/* Command */ +/* Argument */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static long +ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) +{ + unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); + int rc = 0; + void __user *argp = (void __user *)arg; + ULONG __user *pIndex = argp; + i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4]; + i2ChanStrPtr pCh; + +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); +#endif + + mutex_lock(&ip2_mutex); + + switch ( iplminor ) { + case 0: // IPL device + rc = -EINVAL; + break; + case 1: // Status dump + case 5: + case 9: + case 13: + switch ( cmd ) { + case 64: /* Driver - ip2stat */ + rc = put_user(-1, pIndex++ ); + rc = put_user(irq_counter, pIndex++ ); + rc = put_user(bh_counter, pIndex++ ); + break; + + case 65: /* Board - ip2stat */ + if ( pB ) { + rc = copy_to_user(argp, pB, sizeof(i2eBordStr)); + rc = put_user(inb(pB->i2eStatus), + (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); + } else { + rc = -ENODEV; + } + break; + + default: + if (cmd < IP2_MAX_PORTS) { + pCh = DevTable[cmd]; + if ( pCh ) + { + rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); + if (rc) + rc = -EFAULT; + } else { + rc = -ENODEV; + } + } else { + rc = -EINVAL; + } + } + break; + + case 2: // Ping device + rc = -EINVAL; + break; + case 3: // Trace device + /* + * akpm: This used to write a whole bunch of function addresses + * to userspace, which generated lots of put_user() warnings. + * I killed it all. Just return "success" and don't do + * anything. + */ + if (cmd == 1) + rc = 0; + else + rc = -EINVAL; + break; + + default: + rc = -ENODEV; + break; + } + mutex_unlock(&ip2_mutex); + return rc; +} + +/******************************************************************************/ +/* Function: ip2_ipl_open() */ +/* Parameters: Pointer to device inode */ +/* Pointer to file structure */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_ipl_open( struct inode *pInode, struct file *pFile ) +{ + +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: open\n" ); +#endif + return 0; +} + +static int +proc_ip2mem_show(struct seq_file *m, void *v) +{ + i2eBordStrPtr pB; + i2ChanStrPtr pCh; + PTTY tty; + int i; + +#define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n" +#define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n" +#define FMTLIN3 " 0x%04x 0x%04x rc flow\n" + + seq_printf(m,"\n"); + + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + pB = i2BoardPtrTable[i]; + if ( pB ) { + seq_printf(m,"board %d:\n",i); + seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n", + pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting); + } + } + + seq_printf(m,"#: tty flags, port flags, cflags, iflags\n"); + for (i=0; i < IP2_MAX_PORTS; i++) { + pCh = DevTable[i]; + if (pCh) { + tty = pCh->pTTY; + if (tty && tty->count) { + seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags, + tty->termios->c_cflag,tty->termios->c_iflag); + + seq_printf(m,FMTLIN2, + pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds); + seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room); + } + } + } + return 0; +} + +static int proc_ip2mem_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_ip2mem_show, NULL); +} + +static const struct file_operations ip2mem_proc_fops = { + .owner = THIS_MODULE, + .open = proc_ip2mem_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * This is the handler for /proc/tty/driver/ip2 + * + * This stretch of code has been largely plagerized from at least three + * different sources including ip2mkdev.c and a couple of other drivers. + * The bugs are all mine. :-) =mhw= + */ +static int ip2_proc_show(struct seq_file *m, void *v) +{ + int i, j, box; + int boxes = 0; + int ports = 0; + int tports = 0; + i2eBordStrPtr pB; + char *sep; + + seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); + seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", + IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, + IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); + + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + /* This need to be reset for a board by board count... */ + boxes = 0; + pB = i2BoardPtrTable[i]; + if( pB ) { + switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) + { + case POR_ID_FIIEX: + seq_printf(m, "Board %d: EX ports=", i); + sep = ""; + for( box = 0; box < ABS_MAX_BOXES; ++box ) + { + ports = 0; + + if( pB->i2eChannelMap[box] != 0 ) ++boxes; + for( j = 0; j < ABS_BIGGEST_BOX; ++j ) + { + if( pB->i2eChannelMap[box] & 1<< j ) { + ++ports; + } + } + seq_printf(m, "%s%d", sep, ports); + sep = ","; + tports += ports; + } + seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); + break; + + case POR_ID_II_4: + seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); + tports = ports = 4; + break; + + case POR_ID_II_8: + seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); + tports = ports = 8; + break; + + case POR_ID_II_8R: + seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); + tports = ports = 8; + break; + + default: + seq_printf(m, "Board %d: unknown", i); + /* Don't try and probe for minor numbers */ + tports = ports = 0; + } + + } else { + /* Don't try and probe for minor numbers */ + seq_printf(m, "Board %d: vacant", i); + tports = ports = 0; + } + + if( tports ) { + seq_puts(m, " minors="); + sep = ""; + for ( box = 0; box < ABS_MAX_BOXES; ++box ) + { + for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) + { + if ( pB->i2eChannelMap[box] & (1 << j) ) + { + seq_printf(m, "%s%d", sep, + j + ABS_BIGGEST_BOX * + (box+i*ABS_MAX_BOXES)); + sep = ","; + } + } + } + } + seq_putc(m, '\n'); + } + return 0; + } + +static int ip2_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ip2_proc_show, NULL); +} + +static const struct file_operations ip2_proc_fops = { + .owner = THIS_MODULE, + .open = ip2_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/******************************************************************************/ +/* Function: ip2trace() */ +/* Parameters: Value to add to trace buffer */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +#ifdef IP2DEBUG_TRACE +void +ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...) +{ + long flags; + unsigned long *pCode = &codes; + union ip2breadcrumb bc; + i2ChanStrPtr pCh; + + + tracebuf[tracestuff++] = jiffies; + if ( tracestuff == TRACEMAX ) { + tracestuff = 0; + } + if ( tracestuff == tracestrip ) { + if ( ++tracestrip == TRACEMAX ) { + tracestrip = 0; + } + ++tracewrap; + } + + bc.hdr.port = 0xff & pn; + bc.hdr.cat = cat; + bc.hdr.codes = (unsigned char)( codes & 0xff ); + bc.hdr.label = label; + tracebuf[tracestuff++] = bc.value; + + for (;;) { + if ( tracestuff == TRACEMAX ) { + tracestuff = 0; + } + if ( tracestuff == tracestrip ) { + if ( ++tracestrip == TRACEMAX ) { + tracestrip = 0; + } + ++tracewrap; + } + + if ( !codes-- ) + break; + + tracebuf[tracestuff++] = *++pCode; + } +} +#endif + + +MODULE_LICENSE("GPL"); + +static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = { + { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) }, + { } +}; + +MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); + +MODULE_FIRMWARE("intelliport2.bin"); diff --git a/drivers/staging/tty/ip2/ip2trace.h b/drivers/staging/tty/ip2/ip2trace.h new file mode 100644 index 000000000000..da20435dc8a6 --- /dev/null +++ b/drivers/staging/tty/ip2/ip2trace.h @@ -0,0 +1,42 @@ + +// +union ip2breadcrumb +{ + struct { + unsigned char port, cat, codes, label; + } __attribute__ ((packed)) hdr; + unsigned long value; +}; + +#define ITRC_NO_PORT 0xFF +#define CHANN (pCh->port_index) + +#define ITRC_ERROR '!' +#define ITRC_INIT 'A' +#define ITRC_OPEN 'B' +#define ITRC_CLOSE 'C' +#define ITRC_DRAIN 'D' +#define ITRC_IOCTL 'E' +#define ITRC_FLUSH 'F' +#define ITRC_STATUS 'G' +#define ITRC_HANGUP 'H' +#define ITRC_INTR 'I' +#define ITRC_SFLOW 'J' +#define ITRC_SBCMD 'K' +#define ITRC_SICMD 'L' +#define ITRC_MODEM 'M' +#define ITRC_INPUT 'N' +#define ITRC_OUTPUT 'O' +#define ITRC_PUTC 'P' +#define ITRC_QUEUE 'Q' +#define ITRC_STFLW 'R' +#define ITRC_SFIFO 'S' +#define ITRC_VERIFY 'V' +#define ITRC_WRITE 'W' + +#define ITRC_ENTER 0x00 +#define ITRC_RETURN 0xFF + +#define ITRC_QUEUE_ROOM 2 +#define ITRC_QUEUE_CMD 6 + diff --git a/drivers/staging/tty/ip2/ip2types.h b/drivers/staging/tty/ip2/ip2types.h new file mode 100644 index 000000000000..9d67b260b2f6 --- /dev/null +++ b/drivers/staging/tty/ip2/ip2types.h @@ -0,0 +1,57 @@ +/******************************************************************************* +* +* (c) 1998 by Computone Corporation +* +******************************************************************************** +* +* +* PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Driver constants and type definitions. +* +* NOTES: +* +*******************************************************************************/ +#ifndef IP2TYPES_H +#define IP2TYPES_H + +//************* +//* Constants * +//************* + +// Define some limits for this driver. Ports per board is a hardware limitation +// that will not change. Current hardware limits this to 64 ports per board. +// Boards per driver is a self-imposed limit. +// +#define IP2_MAX_BOARDS 4 +#define IP2_PORTS_PER_BOARD ABS_MOST_PORTS +#define IP2_MAX_PORTS (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD) + +#define ISA 0 +#define PCI 1 +#define EISA 2 + +//******************** +//* Type Definitions * +//******************** + +typedef struct tty_struct * PTTY; +typedef wait_queue_head_t PWAITQ; + +typedef unsigned char UCHAR; +typedef unsigned int UINT; +typedef unsigned short USHORT; +typedef unsigned long ULONG; + +typedef struct +{ + short irq[IP2_MAX_BOARDS]; + unsigned short addr[IP2_MAX_BOARDS]; + int type[IP2_MAX_BOARDS]; +#ifdef CONFIG_PCI + struct pci_dev *pci_dev[IP2_MAX_BOARDS]; +#endif +} ip2config_t; + +#endif diff --git a/drivers/staging/tty/istallion.c b/drivers/staging/tty/istallion.c new file mode 100644 index 000000000000..0b266272cccd --- /dev/null +++ b/drivers/staging/tty/istallion.c @@ -0,0 +1,4507 @@ +/*****************************************************************************/ + +/* + * istallion.c -- stallion intelligent multiport serial driver. + * + * Copyright (C) 1996-1999 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This code is loosely based on the Linux serial driver, written by + * Linus Torvalds, Theodore T'so and others. + * + * 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. + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/*****************************************************************************/ + +/* + * Define different board types. Not all of the following board types + * are supported by this driver. But I will use the standard "assigned" + * board numbers. Currently supported boards are abbreviated as: + * ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and + * STAL = Stallion. + */ +#define BRD_UNKNOWN 0 +#define BRD_STALLION 1 +#define BRD_BRUMBY4 2 +#define BRD_ONBOARD2 3 +#define BRD_ONBOARD 4 +#define BRD_ONBOARDE 7 +#define BRD_ECP 23 +#define BRD_ECPE 24 +#define BRD_ECPMC 25 +#define BRD_ECPPCI 29 + +#define BRD_BRUMBY BRD_BRUMBY4 + +/* + * Define a configuration structure to hold the board configuration. + * Need to set this up in the code (for now) with the boards that are + * to be configured into the system. This is what needs to be modified + * when adding/removing/modifying boards. Each line entry in the + * stli_brdconf[] array is a board. Each line contains io/irq/memory + * ranges for that board (as well as what type of board it is). + * Some examples: + * { BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 }, + * This line will configure an EasyConnection 8/64 at io address 2a0, + * and shared memory address of cc000. Multiple EasyConnection 8/64 + * boards can share the same shared memory address space. No interrupt + * is required for this board type. + * Another example: + * { BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 }, + * This line will configure an EasyConnection 8/64 EISA in slot 5 and + * shared memory address of 0x80000000 (2 GByte). Multiple + * EasyConnection 8/64 EISA boards can share the same shared memory + * address space. No interrupt is required for this board type. + * Another example: + * { BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 }, + * This line will configure an ONboard (ISA type) at io address 240, + * and shared memory address of d0000. Multiple ONboards can share + * the same shared memory address space. No interrupt required. + * Another example: + * { BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 }, + * This line will configure a Brumby board (any number of ports!) at + * io address 360 and shared memory address of c8000. All Brumby boards + * configured into a system must have their own separate io and memory + * addresses. No interrupt is required. + * Another example: + * { BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 }, + * This line will configure an original Stallion board at io address 330 + * and shared memory address d0000 (this would only be valid for a "V4.0" + * or Rev.O Stallion board). All Stallion boards configured into the + * system must have their own separate io and memory addresses. No + * interrupt is required. + */ + +struct stlconf { + int brdtype; + int ioaddr1; + int ioaddr2; + unsigned long memaddr; + int irq; + int irqtype; +}; + +static unsigned int stli_nrbrds; + +/* stli_lock must NOT be taken holding brd_lock */ +static spinlock_t stli_lock; /* TTY logic lock */ +static spinlock_t brd_lock; /* Board logic lock */ + +/* + * There is some experimental EISA board detection code in this driver. + * By default it is disabled, but for those that want to try it out, + * then set the define below to be 1. + */ +#define STLI_EISAPROBE 0 + +/*****************************************************************************/ + +/* + * Define some important driver characteristics. Device major numbers + * allocated as per Linux Device Registry. + */ +#ifndef STL_SIOMEMMAJOR +#define STL_SIOMEMMAJOR 28 +#endif +#ifndef STL_SERIALMAJOR +#define STL_SERIALMAJOR 24 +#endif +#ifndef STL_CALLOUTMAJOR +#define STL_CALLOUTMAJOR 25 +#endif + +/*****************************************************************************/ + +/* + * Define our local driver identity first. Set up stuff to deal with + * all the local structures required by a serial tty driver. + */ +static char *stli_drvtitle = "Stallion Intelligent Multiport Serial Driver"; +static char *stli_drvname = "istallion"; +static char *stli_drvversion = "5.6.0"; +static char *stli_serialname = "ttyE"; + +static struct tty_driver *stli_serial; +static const struct tty_port_operations stli_port_ops; + +#define STLI_TXBUFSIZE 4096 + +/* + * Use a fast local buffer for cooked characters. Typically a whole + * bunch of cooked characters come in for a port, 1 at a time. So we + * save those up into a local buffer, then write out the whole lot + * with a large memcpy. Just use 1 buffer for all ports, since its + * use it is only need for short periods of time by each port. + */ +static char *stli_txcookbuf; +static int stli_txcooksize; +static int stli_txcookrealsize; +static struct tty_struct *stli_txcooktty; + +/* + * Define a local default termios struct. All ports will be created + * with this termios initially. Basically all it defines is a raw port + * at 9600 baud, 8 data bits, no parity, 1 stop bit. + */ +static struct ktermios stli_deftermios = { + .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), + .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, +}; + +/* + * Define global stats structures. Not used often, and can be + * re-used for each stats call. + */ +static comstats_t stli_comstats; +static combrd_t stli_brdstats; +static struct asystats stli_cdkstats; + +/*****************************************************************************/ + +static DEFINE_MUTEX(stli_brdslock); +static struct stlibrd *stli_brds[STL_MAXBRDS]; + +static int stli_shared; + +/* + * Per board state flags. Used with the state field of the board struct. + * Not really much here... All we need to do is keep track of whether + * the board has been detected, and whether it is actually running a slave + * or not. + */ +#define BST_FOUND 0 +#define BST_STARTED 1 +#define BST_PROBED 2 + +/* + * Define the set of port state flags. These are marked for internal + * state purposes only, usually to do with the state of communications + * with the slave. Most of them need to be updated atomically, so always + * use the bit setting operations (unless protected by cli/sti). + */ +#define ST_OPENING 2 +#define ST_CLOSING 3 +#define ST_CMDING 4 +#define ST_TXBUSY 5 +#define ST_RXING 6 +#define ST_DOFLUSHRX 7 +#define ST_DOFLUSHTX 8 +#define ST_DOSIGS 9 +#define ST_RXSTOP 10 +#define ST_GETSIGS 11 + +/* + * Define an array of board names as printable strings. Handy for + * referencing boards when printing trace and stuff. + */ +static char *stli_brdnames[] = { + "Unknown", + "Stallion", + "Brumby", + "ONboard-MC", + "ONboard", + "Brumby", + "Brumby", + "ONboard-EI", + NULL, + "ONboard", + "ONboard-MC", + "ONboard-MC", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "EasyIO", + "EC8/32-AT", + "EC8/32-MC", + "EC8/64-AT", + "EC8/64-EI", + "EC8/64-MC", + "EC8/32-PCI", + "EC8/64-PCI", + "EasyIO-PCI", + "EC/RA-PCI", +}; + +/*****************************************************************************/ + +/* + * Define some string labels for arguments passed from the module + * load line. These allow for easy board definitions, and easy + * modification of the io, memory and irq resoucres. + */ + +static char *board0[8]; +static char *board1[8]; +static char *board2[8]; +static char *board3[8]; + +static char **stli_brdsp[] = { + (char **) &board0, + (char **) &board1, + (char **) &board2, + (char **) &board3 +}; + +/* + * Define a set of common board names, and types. This is used to + * parse any module arguments. + */ + +static struct stlibrdtype { + char *name; + int type; +} stli_brdstr[] = { + { "stallion", BRD_STALLION }, + { "1", BRD_STALLION }, + { "brumby", BRD_BRUMBY }, + { "brumby4", BRD_BRUMBY }, + { "brumby/4", BRD_BRUMBY }, + { "brumby-4", BRD_BRUMBY }, + { "brumby8", BRD_BRUMBY }, + { "brumby/8", BRD_BRUMBY }, + { "brumby-8", BRD_BRUMBY }, + { "brumby16", BRD_BRUMBY }, + { "brumby/16", BRD_BRUMBY }, + { "brumby-16", BRD_BRUMBY }, + { "2", BRD_BRUMBY }, + { "onboard2", BRD_ONBOARD2 }, + { "onboard-2", BRD_ONBOARD2 }, + { "onboard/2", BRD_ONBOARD2 }, + { "onboard-mc", BRD_ONBOARD2 }, + { "onboard/mc", BRD_ONBOARD2 }, + { "onboard-mca", BRD_ONBOARD2 }, + { "onboard/mca", BRD_ONBOARD2 }, + { "3", BRD_ONBOARD2 }, + { "onboard", BRD_ONBOARD }, + { "onboardat", BRD_ONBOARD }, + { "4", BRD_ONBOARD }, + { "onboarde", BRD_ONBOARDE }, + { "onboard-e", BRD_ONBOARDE }, + { "onboard/e", BRD_ONBOARDE }, + { "onboard-ei", BRD_ONBOARDE }, + { "onboard/ei", BRD_ONBOARDE }, + { "7", BRD_ONBOARDE }, + { "ecp", BRD_ECP }, + { "ecpat", BRD_ECP }, + { "ec8/64", BRD_ECP }, + { "ec8/64-at", BRD_ECP }, + { "ec8/64-isa", BRD_ECP }, + { "23", BRD_ECP }, + { "ecpe", BRD_ECPE }, + { "ecpei", BRD_ECPE }, + { "ec8/64-e", BRD_ECPE }, + { "ec8/64-ei", BRD_ECPE }, + { "24", BRD_ECPE }, + { "ecpmc", BRD_ECPMC }, + { "ec8/64-mc", BRD_ECPMC }, + { "ec8/64-mca", BRD_ECPMC }, + { "25", BRD_ECPMC }, + { "ecppci", BRD_ECPPCI }, + { "ec/ra", BRD_ECPPCI }, + { "ec/ra-pc", BRD_ECPPCI }, + { "ec/ra-pci", BRD_ECPPCI }, + { "29", BRD_ECPPCI }, +}; + +/* + * Define the module agruments. + */ +MODULE_AUTHOR("Greg Ungerer"); +MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver"); +MODULE_LICENSE("GPL"); + + +module_param_array(board0, charp, NULL, 0); +MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]"); +module_param_array(board1, charp, NULL, 0); +MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]"); +module_param_array(board2, charp, NULL, 0); +MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); +module_param_array(board3, charp, NULL, 0); +MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); + +#if STLI_EISAPROBE != 0 +/* + * Set up a default memory address table for EISA board probing. + * The default addresses are all bellow 1Mbyte, which has to be the + * case anyway. They should be safe, since we only read values from + * them, and interrupts are disabled while we do it. If the higher + * memory support is compiled in then we also try probing around + * the 1Gb, 2Gb and 3Gb areas as well... + */ +static unsigned long stli_eisamemprobeaddrs[] = { + 0xc0000, 0xd0000, 0xe0000, 0xf0000, + 0x80000000, 0x80010000, 0x80020000, 0x80030000, + 0x40000000, 0x40010000, 0x40020000, 0x40030000, + 0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000, + 0xff000000, 0xff010000, 0xff020000, 0xff030000, +}; + +static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs); +#endif + +/* + * Define the Stallion PCI vendor and device IDs. + */ +#ifndef PCI_DEVICE_ID_ECRA +#define PCI_DEVICE_ID_ECRA 0x0004 +#endif + +static struct pci_device_id istallion_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); + +static struct pci_driver stli_pcidriver; + +/*****************************************************************************/ + +/* + * Hardware configuration info for ECP boards. These defines apply + * to the directly accessible io ports of the ECP. There is a set of + * defines for each ECP board type, ISA, EISA, MCA and PCI. + */ +#define ECP_IOSIZE 4 + +#define ECP_MEMSIZE (128 * 1024) +#define ECP_PCIMEMSIZE (256 * 1024) + +#define ECP_ATPAGESIZE (4 * 1024) +#define ECP_MCPAGESIZE (4 * 1024) +#define ECP_EIPAGESIZE (64 * 1024) +#define ECP_PCIPAGESIZE (64 * 1024) + +#define STL_EISAID 0x8c4e + +/* + * Important defines for the ISA class of ECP board. + */ +#define ECP_ATIREG 0 +#define ECP_ATCONFR 1 +#define ECP_ATMEMAR 2 +#define ECP_ATMEMPR 3 +#define ECP_ATSTOP 0x1 +#define ECP_ATINTENAB 0x10 +#define ECP_ATENABLE 0x20 +#define ECP_ATDISABLE 0x00 +#define ECP_ATADDRMASK 0x3f000 +#define ECP_ATADDRSHFT 12 + +/* + * Important defines for the EISA class of ECP board. + */ +#define ECP_EIIREG 0 +#define ECP_EIMEMARL 1 +#define ECP_EICONFR 2 +#define ECP_EIMEMARH 3 +#define ECP_EIENABLE 0x1 +#define ECP_EIDISABLE 0x0 +#define ECP_EISTOP 0x4 +#define ECP_EIEDGE 0x00 +#define ECP_EILEVEL 0x80 +#define ECP_EIADDRMASKL 0x00ff0000 +#define ECP_EIADDRSHFTL 16 +#define ECP_EIADDRMASKH 0xff000000 +#define ECP_EIADDRSHFTH 24 +#define ECP_EIBRDENAB 0xc84 + +#define ECP_EISAID 0x4 + +/* + * Important defines for the Micro-channel class of ECP board. + * (It has a lot in common with the ISA boards.) + */ +#define ECP_MCIREG 0 +#define ECP_MCCONFR 1 +#define ECP_MCSTOP 0x20 +#define ECP_MCENABLE 0x80 +#define ECP_MCDISABLE 0x00 + +/* + * Important defines for the PCI class of ECP board. + * (It has a lot in common with the other ECP boards.) + */ +#define ECP_PCIIREG 0 +#define ECP_PCICONFR 1 +#define ECP_PCISTOP 0x01 + +/* + * Hardware configuration info for ONboard and Brumby boards. These + * defines apply to the directly accessible io ports of these boards. + */ +#define ONB_IOSIZE 16 +#define ONB_MEMSIZE (64 * 1024) +#define ONB_ATPAGESIZE (64 * 1024) +#define ONB_MCPAGESIZE (64 * 1024) +#define ONB_EIMEMSIZE (128 * 1024) +#define ONB_EIPAGESIZE (64 * 1024) + +/* + * Important defines for the ISA class of ONboard board. + */ +#define ONB_ATIREG 0 +#define ONB_ATMEMAR 1 +#define ONB_ATCONFR 2 +#define ONB_ATSTOP 0x4 +#define ONB_ATENABLE 0x01 +#define ONB_ATDISABLE 0x00 +#define ONB_ATADDRMASK 0xff0000 +#define ONB_ATADDRSHFT 16 + +#define ONB_MEMENABLO 0 +#define ONB_MEMENABHI 0x02 + +/* + * Important defines for the EISA class of ONboard board. + */ +#define ONB_EIIREG 0 +#define ONB_EIMEMARL 1 +#define ONB_EICONFR 2 +#define ONB_EIMEMARH 3 +#define ONB_EIENABLE 0x1 +#define ONB_EIDISABLE 0x0 +#define ONB_EISTOP 0x4 +#define ONB_EIEDGE 0x00 +#define ONB_EILEVEL 0x80 +#define ONB_EIADDRMASKL 0x00ff0000 +#define ONB_EIADDRSHFTL 16 +#define ONB_EIADDRMASKH 0xff000000 +#define ONB_EIADDRSHFTH 24 +#define ONB_EIBRDENAB 0xc84 + +#define ONB_EISAID 0x1 + +/* + * Important defines for the Brumby boards. They are pretty simple, + * there is not much that is programmably configurable. + */ +#define BBY_IOSIZE 16 +#define BBY_MEMSIZE (64 * 1024) +#define BBY_PAGESIZE (16 * 1024) + +#define BBY_ATIREG 0 +#define BBY_ATCONFR 1 +#define BBY_ATSTOP 0x4 + +/* + * Important defines for the Stallion boards. They are pretty simple, + * there is not much that is programmably configurable. + */ +#define STAL_IOSIZE 16 +#define STAL_MEMSIZE (64 * 1024) +#define STAL_PAGESIZE (64 * 1024) + +/* + * Define the set of status register values for EasyConnection panels. + * The signature will return with the status value for each panel. From + * this we can determine what is attached to the board - before we have + * actually down loaded any code to it. + */ +#define ECH_PNLSTATUS 2 +#define ECH_PNL16PORT 0x20 +#define ECH_PNLIDMASK 0x07 +#define ECH_PNLXPID 0x40 +#define ECH_PNLINTRPEND 0x80 + +/* + * Define some macros to do things to the board. Even those these boards + * are somewhat related there is often significantly different ways of + * doing some operation on it (like enable, paging, reset, etc). So each + * board class has a set of functions which do the commonly required + * operations. The macros below basically just call these functions, + * generally checking for a NULL function - which means that the board + * needs nothing done to it to achieve this operation! + */ +#define EBRDINIT(brdp) \ + if (brdp->init != NULL) \ + (* brdp->init)(brdp) + +#define EBRDENABLE(brdp) \ + if (brdp->enable != NULL) \ + (* brdp->enable)(brdp); + +#define EBRDDISABLE(brdp) \ + if (brdp->disable != NULL) \ + (* brdp->disable)(brdp); + +#define EBRDINTR(brdp) \ + if (brdp->intr != NULL) \ + (* brdp->intr)(brdp); + +#define EBRDRESET(brdp) \ + if (brdp->reset != NULL) \ + (* brdp->reset)(brdp); + +#define EBRDGETMEMPTR(brdp,offset) \ + (* brdp->getmemptr)(brdp, offset, __LINE__) + +/* + * Define the maximal baud rate, and the default baud base for ports. + */ +#define STL_MAXBAUD 460800 +#define STL_BAUDBASE 115200 +#define STL_CLOSEDELAY (5 * HZ / 10) + +/*****************************************************************************/ + +/* + * Define macros to extract a brd or port number from a minor number. + */ +#define MINOR2BRD(min) (((min) & 0xc0) >> 6) +#define MINOR2PORT(min) ((min) & 0x3f) + +/*****************************************************************************/ + +/* + * Prototype all functions in this driver! + */ + +static int stli_parsebrd(struct stlconf *confp, char **argp); +static int stli_open(struct tty_struct *tty, struct file *filp); +static void stli_close(struct tty_struct *tty, struct file *filp); +static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); +static int stli_putchar(struct tty_struct *tty, unsigned char ch); +static void stli_flushchars(struct tty_struct *tty); +static int stli_writeroom(struct tty_struct *tty); +static int stli_charsinbuffer(struct tty_struct *tty); +static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); +static void stli_settermios(struct tty_struct *tty, struct ktermios *old); +static void stli_throttle(struct tty_struct *tty); +static void stli_unthrottle(struct tty_struct *tty); +static void stli_stop(struct tty_struct *tty); +static void stli_start(struct tty_struct *tty); +static void stli_flushbuffer(struct tty_struct *tty); +static int stli_breakctl(struct tty_struct *tty, int state); +static void stli_waituntilsent(struct tty_struct *tty, int timeout); +static void stli_sendxchar(struct tty_struct *tty, char ch); +static void stli_hangup(struct tty_struct *tty); + +static int stli_brdinit(struct stlibrd *brdp); +static int stli_startbrd(struct stlibrd *brdp); +static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); +static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); +static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); +static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); +static void stli_poll(unsigned long arg); +static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); +static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); +static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); +static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); +static int stli_setport(struct tty_struct *tty); +static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); +static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); +static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); +static long stli_mktiocm(unsigned long sigvalue); +static void stli_read(struct stlibrd *brdp, struct stliport *portp); +static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); +static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp); +static int stli_getbrdstats(combrd_t __user *bp); +static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp); +static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp); +static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); +static int stli_getportstruct(struct stliport __user *arg); +static int stli_getbrdstruct(struct stlibrd __user *arg); +static struct stlibrd *stli_allocbrd(void); + +static void stli_ecpinit(struct stlibrd *brdp); +static void stli_ecpenable(struct stlibrd *brdp); +static void stli_ecpdisable(struct stlibrd *brdp); +static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpreset(struct stlibrd *brdp); +static void stli_ecpintr(struct stlibrd *brdp); +static void stli_ecpeiinit(struct stlibrd *brdp); +static void stli_ecpeienable(struct stlibrd *brdp); +static void stli_ecpeidisable(struct stlibrd *brdp); +static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpeireset(struct stlibrd *brdp); +static void stli_ecpmcenable(struct stlibrd *brdp); +static void stli_ecpmcdisable(struct stlibrd *brdp); +static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpmcreset(struct stlibrd *brdp); +static void stli_ecppciinit(struct stlibrd *brdp); +static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecppcireset(struct stlibrd *brdp); + +static void stli_onbinit(struct stlibrd *brdp); +static void stli_onbenable(struct stlibrd *brdp); +static void stli_onbdisable(struct stlibrd *brdp); +static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_onbreset(struct stlibrd *brdp); +static void stli_onbeinit(struct stlibrd *brdp); +static void stli_onbeenable(struct stlibrd *brdp); +static void stli_onbedisable(struct stlibrd *brdp); +static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_onbereset(struct stlibrd *brdp); +static void stli_bbyinit(struct stlibrd *brdp); +static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_bbyreset(struct stlibrd *brdp); +static void stli_stalinit(struct stlibrd *brdp); +static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_stalreset(struct stlibrd *brdp); + +static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr); + +static int stli_initecp(struct stlibrd *brdp); +static int stli_initonb(struct stlibrd *brdp); +#if STLI_EISAPROBE != 0 +static int stli_eisamemprobe(struct stlibrd *brdp); +#endif +static int stli_initports(struct stlibrd *brdp); + +/*****************************************************************************/ + +/* + * Define the driver info for a user level shared memory device. This + * device will work sort of like the /dev/kmem device - except that it + * will give access to the shared memory on the Stallion intelligent + * board. This is also a very useful debugging tool. + */ +static const struct file_operations stli_fsiomem = { + .owner = THIS_MODULE, + .read = stli_memread, + .write = stli_memwrite, + .unlocked_ioctl = stli_memioctl, + .llseek = default_llseek, +}; + +/*****************************************************************************/ + +/* + * Define a timer_list entry for our poll routine. The slave board + * is polled every so often to see if anything needs doing. This is + * much cheaper on host cpu than using interrupts. It turns out to + * not increase character latency by much either... + */ +static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0); + +static int stli_timeron; + +/* + * Define the calculation for the timeout routine. + */ +#define STLI_TIMEOUT (jiffies + 1) + +/*****************************************************************************/ + +static struct class *istallion_class; + +static void stli_cleanup_ports(struct stlibrd *brdp) +{ + struct stliport *portp; + unsigned int j; + struct tty_struct *tty; + + for (j = 0; j < STL_MAXPORTS; j++) { + portp = brdp->ports[j]; + if (portp != NULL) { + tty = tty_port_tty_get(&portp->port); + if (tty != NULL) { + tty_hangup(tty); + tty_kref_put(tty); + } + kfree(portp); + } + } +} + +/*****************************************************************************/ + +/* + * Parse the supplied argument string, into the board conf struct. + */ + +static int stli_parsebrd(struct stlconf *confp, char **argp) +{ + unsigned int i; + char *sp; + + if (argp[0] == NULL || *argp[0] == 0) + return 0; + + for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) + *sp = tolower(*sp); + + for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) { + if (strcmp(stli_brdstr[i].name, argp[0]) == 0) + break; + } + if (i == ARRAY_SIZE(stli_brdstr)) { + printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]); + return 0; + } + + confp->brdtype = stli_brdstr[i].type; + if (argp[1] != NULL && *argp[1] != 0) + confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0); + if (argp[2] != NULL && *argp[2] != 0) + confp->memaddr = simple_strtoul(argp[2], NULL, 0); + return(1); +} + +/*****************************************************************************/ + +/* + * On the first open of the device setup the port hardware, and + * initialize the per port data structure. Since initializing the port + * requires several commands to the board we will need to wait for any + * other open that is already initializing the port. + * + * Locking: protected by the port mutex. + */ + +static int stli_activate(struct tty_port *port, struct tty_struct *tty) +{ + struct stliport *portp = container_of(port, struct stliport, port); + struct stlibrd *brdp = stli_brds[portp->brdnr]; + int rc; + + if ((rc = stli_initopen(tty, brdp, portp)) >= 0) + clear_bit(TTY_IO_ERROR, &tty->flags); + wake_up_interruptible(&portp->raw_wait); + return rc; +} + +static int stli_open(struct tty_struct *tty, struct file *filp) +{ + struct stlibrd *brdp; + struct stliport *portp; + unsigned int minordev, brdnr, portnr; + + minordev = tty->index; + brdnr = MINOR2BRD(minordev); + if (brdnr >= stli_nrbrds) + return -ENODEV; + brdp = stli_brds[brdnr]; + if (brdp == NULL) + return -ENODEV; + if (!test_bit(BST_STARTED, &brdp->state)) + return -ENODEV; + portnr = MINOR2PORT(minordev); + if (portnr > brdp->nrports) + return -ENODEV; + + portp = brdp->ports[portnr]; + if (portp == NULL) + return -ENODEV; + if (portp->devnr < 1) + return -ENODEV; + + tty->driver_data = portp; + return tty_port_open(&portp->port, tty, filp); +} + + +/*****************************************************************************/ + +static void stli_shutdown(struct tty_port *port) +{ + struct stlibrd *brdp; + unsigned long ftype; + unsigned long flags; + struct stliport *portp = container_of(port, struct stliport, port); + + if (portp->brdnr >= stli_nrbrds) + return; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return; + + /* + * May want to wait for data to drain before closing. The BUSY + * flag keeps track of whether we are still transmitting or not. + * It is updated by messages from the slave - indicating when all + * chars really have drained. + */ + + if (!test_bit(ST_CLOSING, &portp->state)) + stli_rawclose(brdp, portp, 0, 0); + + spin_lock_irqsave(&stli_lock, flags); + clear_bit(ST_TXBUSY, &portp->state); + clear_bit(ST_RXSTOP, &portp->state); + spin_unlock_irqrestore(&stli_lock, flags); + + ftype = FLUSHTX | FLUSHRX; + stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); +} + +static void stli_close(struct tty_struct *tty, struct file *filp) +{ + struct stliport *portp = tty->driver_data; + unsigned long flags; + if (portp == NULL) + return; + spin_lock_irqsave(&stli_lock, flags); + /* Flush any internal buffering out first */ + if (tty == stli_txcooktty) + stli_flushchars(tty); + spin_unlock_irqrestore(&stli_lock, flags); + tty_port_close(&portp->port, tty, filp); +} + +/*****************************************************************************/ + +/* + * Carry out first open operations on a port. This involves a number of + * commands to be sent to the slave. We need to open the port, set the + * notification events, set the initial port settings, get and set the + * initial signal values. We sleep and wait in between each one. But + * this still all happens pretty quickly. + */ + +static int stli_initopen(struct tty_struct *tty, + struct stlibrd *brdp, struct stliport *portp) +{ + asynotify_t nt; + asyport_t aport; + int rc; + + if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0) + return rc; + + memset(&nt, 0, sizeof(asynotify_t)); + nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK); + nt.signal = SG_DCD; + if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt, + sizeof(asynotify_t), 0)) < 0) + return rc; + + stli_mkasyport(tty, portp, &aport, tty->termios); + if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, + sizeof(asyport_t), 0)) < 0) + return rc; + + set_bit(ST_GETSIGS, &portp->state); + if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig, + sizeof(asysigs_t), 1)) < 0) + return rc; + if (test_and_clear_bit(ST_GETSIGS, &portp->state)) + portp->sigs = stli_mktiocm(portp->asig.sigvalue); + stli_mkasysigs(&portp->asig, 1, 1); + if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, + sizeof(asysigs_t), 0)) < 0) + return rc; + + return 0; +} + +/*****************************************************************************/ + +/* + * Send an open message to the slave. This will sleep waiting for the + * acknowledgement, so must have user context. We need to co-ordinate + * with close events here, since we don't want open and close events + * to overlap. + */ + +static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) +{ + cdkhdr_t __iomem *hdrp; + cdkctrl_t __iomem *cp; + unsigned char __iomem *bits; + unsigned long flags; + int rc; + +/* + * Send a message to the slave to open this port. + */ + +/* + * Slave is already closing this port. This can happen if a hangup + * occurs on this port. So we must wait until it is complete. The + * order of opens and closes may not be preserved across shared + * memory, so we must wait until it is complete. + */ + wait_event_interruptible_tty(portp->raw_wait, + !test_bit(ST_CLOSING, &portp->state)); + if (signal_pending(current)) { + return -ERESTARTSYS; + } + +/* + * Everything is ready now, so write the open message into shared + * memory. Once the message is in set the service bits to say that + * this port wants service. + */ + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; + writel(arg, &cp->openarg); + writeb(1, &cp->open); + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + + portp->portidx; + writeb(readb(bits) | portp->portbit, bits); + EBRDDISABLE(brdp); + + if (wait == 0) { + spin_unlock_irqrestore(&brd_lock, flags); + return 0; + } + +/* + * Slave is in action, so now we must wait for the open acknowledgment + * to come back. + */ + rc = 0; + set_bit(ST_OPENING, &portp->state); + spin_unlock_irqrestore(&brd_lock, flags); + + wait_event_interruptible_tty(portp->raw_wait, + !test_bit(ST_OPENING, &portp->state)); + if (signal_pending(current)) + rc = -ERESTARTSYS; + + if ((rc == 0) && (portp->rc != 0)) + rc = -EIO; + return rc; +} + +/*****************************************************************************/ + +/* + * Send a close message to the slave. Normally this will sleep waiting + * for the acknowledgement, but if wait parameter is 0 it will not. If + * wait is true then must have user context (to sleep). + */ + +static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) +{ + cdkhdr_t __iomem *hdrp; + cdkctrl_t __iomem *cp; + unsigned char __iomem *bits; + unsigned long flags; + int rc; + +/* + * Slave is already closing this port. This can happen if a hangup + * occurs on this port. + */ + if (wait) { + wait_event_interruptible_tty(portp->raw_wait, + !test_bit(ST_CLOSING, &portp->state)); + if (signal_pending(current)) { + return -ERESTARTSYS; + } + } + +/* + * Write the close command into shared memory. + */ + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; + writel(arg, &cp->closearg); + writeb(1, &cp->close); + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + + portp->portidx; + writeb(readb(bits) |portp->portbit, bits); + EBRDDISABLE(brdp); + + set_bit(ST_CLOSING, &portp->state); + spin_unlock_irqrestore(&brd_lock, flags); + + if (wait == 0) + return 0; + +/* + * Slave is in action, so now we must wait for the open acknowledgment + * to come back. + */ + rc = 0; + wait_event_interruptible_tty(portp->raw_wait, + !test_bit(ST_CLOSING, &portp->state)); + if (signal_pending(current)) + rc = -ERESTARTSYS; + + if ((rc == 0) && (portp->rc != 0)) + rc = -EIO; + return rc; +} + +/*****************************************************************************/ + +/* + * Send a command to the slave and wait for the response. This must + * have user context (it sleeps). This routine is generic in that it + * can send any type of command. Its purpose is to wait for that command + * to complete (as opposed to initiating the command then returning). + */ + +static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) +{ + /* + * no need for wait_event_tty because clearing ST_CMDING cannot block + * on BTM + */ + wait_event_interruptible(portp->raw_wait, + !test_bit(ST_CMDING, &portp->state)); + if (signal_pending(current)) + return -ERESTARTSYS; + + stli_sendcmd(brdp, portp, cmd, arg, size, copyback); + + wait_event_interruptible(portp->raw_wait, + !test_bit(ST_CMDING, &portp->state)); + if (signal_pending(current)) + return -ERESTARTSYS; + + if (portp->rc != 0) + return -EIO; + return 0; +} + +/*****************************************************************************/ + +/* + * Send the termios settings for this port to the slave. This sleeps + * waiting for the command to complete - so must have user context. + */ + +static int stli_setport(struct tty_struct *tty) +{ + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; + asyport_t aport; + + if (portp == NULL) + return -ENODEV; + if (portp->brdnr >= stli_nrbrds) + return -ENODEV; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return -ENODEV; + + stli_mkasyport(tty, portp, &aport, tty->termios); + return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0)); +} + +/*****************************************************************************/ + +static int stli_carrier_raised(struct tty_port *port) +{ + struct stliport *portp = container_of(port, struct stliport, port); + return (portp->sigs & TIOCM_CD) ? 1 : 0; +} + +static void stli_dtr_rts(struct tty_port *port, int on) +{ + struct stliport *portp = container_of(port, struct stliport, port); + struct stlibrd *brdp = stli_brds[portp->brdnr]; + stli_mkasysigs(&portp->asig, on, on); + if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, + sizeof(asysigs_t), 0) < 0) + printk(KERN_WARNING "istallion: dtr set failed.\n"); +} + + +/*****************************************************************************/ + +/* + * Write routine. Take the data and put it in the shared memory ring + * queue. If port is not already sending chars then need to mark the + * service bits for this port. + */ + +static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + cdkasy_t __iomem *ap; + cdkhdr_t __iomem *hdrp; + unsigned char __iomem *bits; + unsigned char __iomem *shbuf; + unsigned char *chbuf; + struct stliport *portp; + struct stlibrd *brdp; + unsigned int len, stlen, head, tail, size; + unsigned long flags; + + if (tty == stli_txcooktty) + stli_flushchars(tty); + portp = tty->driver_data; + if (portp == NULL) + return 0; + if (portp->brdnr >= stli_nrbrds) + return 0; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return 0; + chbuf = (unsigned char *) buf; + +/* + * All data is now local, shove as much as possible into shared memory. + */ + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); + head = (unsigned int) readw(&ap->txq.head); + tail = (unsigned int) readw(&ap->txq.tail); + if (tail != ((unsigned int) readw(&ap->txq.tail))) + tail = (unsigned int) readw(&ap->txq.tail); + size = portp->txsize; + if (head >= tail) { + len = size - (head - tail) - 1; + stlen = size - head; + } else { + len = tail - head - 1; + stlen = len; + } + + len = min(len, (unsigned int)count); + count = 0; + shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset); + + while (len > 0) { + stlen = min(len, stlen); + memcpy_toio(shbuf + head, chbuf, stlen); + chbuf += stlen; + len -= stlen; + count += stlen; + head += stlen; + if (head >= size) { + head = 0; + stlen = tail; + } + } + + ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); + writew(head, &ap->txq.head); + if (test_bit(ST_TXBUSY, &portp->state)) { + if (readl(&ap->changed.data) & DT_TXEMPTY) + writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data); + } + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + + portp->portidx; + writeb(readb(bits) | portp->portbit, bits); + set_bit(ST_TXBUSY, &portp->state); + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); + + return(count); +} + +/*****************************************************************************/ + +/* + * Output a single character. We put it into a temporary local buffer + * (for speed) then write out that buffer when the flushchars routine + * is called. There is a safety catch here so that if some other port + * writes chars before the current buffer has been, then we write them + * first them do the new ports. + */ + +static int stli_putchar(struct tty_struct *tty, unsigned char ch) +{ + if (tty != stli_txcooktty) { + if (stli_txcooktty != NULL) + stli_flushchars(stli_txcooktty); + stli_txcooktty = tty; + } + + stli_txcookbuf[stli_txcooksize++] = ch; + return 0; +} + +/*****************************************************************************/ + +/* + * Transfer characters from the local TX cooking buffer to the board. + * We sort of ignore the tty that gets passed in here. We rely on the + * info stored with the TX cook buffer to tell us which port to flush + * the data on. In any case we clean out the TX cook buffer, for re-use + * by someone else. + */ + +static void stli_flushchars(struct tty_struct *tty) +{ + cdkhdr_t __iomem *hdrp; + unsigned char __iomem *bits; + cdkasy_t __iomem *ap; + struct tty_struct *cooktty; + struct stliport *portp; + struct stlibrd *brdp; + unsigned int len, stlen, head, tail, size, count, cooksize; + unsigned char *buf; + unsigned char __iomem *shbuf; + unsigned long flags; + + cooksize = stli_txcooksize; + cooktty = stli_txcooktty; + stli_txcooksize = 0; + stli_txcookrealsize = 0; + stli_txcooktty = NULL; + + if (cooktty == NULL) + return; + if (tty != cooktty) + tty = cooktty; + if (cooksize == 0) + return; + + portp = tty->driver_data; + if (portp == NULL) + return; + if (portp->brdnr >= stli_nrbrds) + return; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + + ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); + head = (unsigned int) readw(&ap->txq.head); + tail = (unsigned int) readw(&ap->txq.tail); + if (tail != ((unsigned int) readw(&ap->txq.tail))) + tail = (unsigned int) readw(&ap->txq.tail); + size = portp->txsize; + if (head >= tail) { + len = size - (head - tail) - 1; + stlen = size - head; + } else { + len = tail - head - 1; + stlen = len; + } + + len = min(len, cooksize); + count = 0; + shbuf = EBRDGETMEMPTR(brdp, portp->txoffset); + buf = stli_txcookbuf; + + while (len > 0) { + stlen = min(len, stlen); + memcpy_toio(shbuf + head, buf, stlen); + buf += stlen; + len -= stlen; + count += stlen; + head += stlen; + if (head >= size) { + head = 0; + stlen = tail; + } + } + + ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); + writew(head, &ap->txq.head); + + if (test_bit(ST_TXBUSY, &portp->state)) { + if (readl(&ap->changed.data) & DT_TXEMPTY) + writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data); + } + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + + portp->portidx; + writeb(readb(bits) | portp->portbit, bits); + set_bit(ST_TXBUSY, &portp->state); + + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +static int stli_writeroom(struct tty_struct *tty) +{ + cdkasyrq_t __iomem *rp; + struct stliport *portp; + struct stlibrd *brdp; + unsigned int head, tail, len; + unsigned long flags; + + if (tty == stli_txcooktty) { + if (stli_txcookrealsize != 0) { + len = stli_txcookrealsize - stli_txcooksize; + return len; + } + } + + portp = tty->driver_data; + if (portp == NULL) + return 0; + if (portp->brdnr >= stli_nrbrds) + return 0; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return 0; + + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq; + head = (unsigned int) readw(&rp->head); + tail = (unsigned int) readw(&rp->tail); + if (tail != ((unsigned int) readw(&rp->tail))) + tail = (unsigned int) readw(&rp->tail); + len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head); + len--; + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); + + if (tty == stli_txcooktty) { + stli_txcookrealsize = len; + len -= stli_txcooksize; + } + return len; +} + +/*****************************************************************************/ + +/* + * Return the number of characters in the transmit buffer. Normally we + * will return the number of chars in the shared memory ring queue. + * We need to kludge around the case where the shared memory buffer is + * empty but not all characters have drained yet, for this case just + * return that there is 1 character in the buffer! + */ + +static int stli_charsinbuffer(struct tty_struct *tty) +{ + cdkasyrq_t __iomem *rp; + struct stliport *portp; + struct stlibrd *brdp; + unsigned int head, tail, len; + unsigned long flags; + + if (tty == stli_txcooktty) + stli_flushchars(tty); + portp = tty->driver_data; + if (portp == NULL) + return 0; + if (portp->brdnr >= stli_nrbrds) + return 0; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return 0; + + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq; + head = (unsigned int) readw(&rp->head); + tail = (unsigned int) readw(&rp->tail); + if (tail != ((unsigned int) readw(&rp->tail))) + tail = (unsigned int) readw(&rp->tail); + len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head)); + if ((len == 0) && test_bit(ST_TXBUSY, &portp->state)) + len = 1; + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); + + return len; +} + +/*****************************************************************************/ + +/* + * Generate the serial struct info. + */ + +static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp) +{ + struct serial_struct sio; + struct stlibrd *brdp; + + memset(&sio, 0, sizeof(struct serial_struct)); + sio.type = PORT_UNKNOWN; + sio.line = portp->portnr; + sio.irq = 0; + sio.flags = portp->port.flags; + sio.baud_base = portp->baud_base; + sio.close_delay = portp->port.close_delay; + sio.closing_wait = portp->closing_wait; + sio.custom_divisor = portp->custom_divisor; + sio.xmit_fifo_size = 0; + sio.hub6 = 0; + + brdp = stli_brds[portp->brdnr]; + if (brdp != NULL) + sio.port = brdp->iobase; + + return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? + -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Set port according to the serial struct info. + * At this point we do not do any auto-configure stuff, so we will + * just quietly ignore any requests to change irq, etc. + */ + +static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp) +{ + struct serial_struct sio; + int rc; + struct stliport *portp = tty->driver_data; + + if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) + return -EFAULT; + if (!capable(CAP_SYS_ADMIN)) { + if ((sio.baud_base != portp->baud_base) || + (sio.close_delay != portp->port.close_delay) || + ((sio.flags & ~ASYNC_USR_MASK) != + (portp->port.flags & ~ASYNC_USR_MASK))) + return -EPERM; + } + + portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | + (sio.flags & ASYNC_USR_MASK); + portp->baud_base = sio.baud_base; + portp->port.close_delay = sio.close_delay; + portp->closing_wait = sio.closing_wait; + portp->custom_divisor = sio.custom_divisor; + + if ((rc = stli_setport(tty)) < 0) + return rc; + return 0; +} + +/*****************************************************************************/ + +static int stli_tiocmget(struct tty_struct *tty) +{ + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; + int rc; + + if (portp == NULL) + return -ENODEV; + if (portp->brdnr >= stli_nrbrds) + return 0; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return 0; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, + &portp->asig, sizeof(asysigs_t), 1)) < 0) + return rc; + + return stli_mktiocm(portp->asig.sigvalue); +} + +static int stli_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; + int rts = -1, dtr = -1; + + if (portp == NULL) + return -ENODEV; + if (portp->brdnr >= stli_nrbrds) + return 0; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return 0; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + stli_mkasysigs(&portp->asig, dtr, rts); + + return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, + sizeof(asysigs_t), 0); +} + +static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) +{ + struct stliport *portp; + struct stlibrd *brdp; + int rc; + void __user *argp = (void __user *)arg; + + portp = tty->driver_data; + if (portp == NULL) + return -ENODEV; + if (portp->brdnr >= stli_nrbrds) + return 0; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return 0; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + rc = 0; + + switch (cmd) { + case TIOCGSERIAL: + rc = stli_getserial(portp, argp); + break; + case TIOCSSERIAL: + rc = stli_setserial(tty, argp); + break; + case STL_GETPFLAG: + rc = put_user(portp->pflag, (unsigned __user *)argp); + break; + case STL_SETPFLAG: + if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0) + stli_setport(tty); + break; + case COM_GETPORTSTATS: + rc = stli_getportstats(tty, portp, argp); + break; + case COM_CLRPORTSTATS: + rc = stli_clrportstats(portp, argp); + break; + case TIOCSERCONFIG: + case TIOCSERGWILD: + case TIOCSERSWILD: + case TIOCSERGETLSR: + case TIOCSERGSTRUCT: + case TIOCSERGETMULTI: + case TIOCSERSETMULTI: + default: + rc = -ENOIOCTLCMD; + break; + } + + return rc; +} + +/*****************************************************************************/ + +/* + * This routine assumes that we have user context and can sleep. + * Looks like it is true for the current ttys implementation..!! + */ + +static void stli_settermios(struct tty_struct *tty, struct ktermios *old) +{ + struct stliport *portp; + struct stlibrd *brdp; + struct ktermios *tiosp; + asyport_t aport; + + portp = tty->driver_data; + if (portp == NULL) + return; + if (portp->brdnr >= stli_nrbrds) + return; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return; + + tiosp = tty->termios; + + stli_mkasyport(tty, portp, &aport, tiosp); + stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); + stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1); + stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, + sizeof(asysigs_t), 0); + if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) + tty->hw_stopped = 0; + if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) + wake_up_interruptible(&portp->port.open_wait); +} + +/*****************************************************************************/ + +/* + * Attempt to flow control who ever is sending us data. We won't really + * do any flow control action here. We can't directly, and even if we + * wanted to we would have to send a command to the slave. The slave + * knows how to flow control, and will do so when its buffers reach its + * internal high water marks. So what we will do is set a local state + * bit that will stop us sending any RX data up from the poll routine + * (which is the place where RX data from the slave is handled). + */ + +static void stli_throttle(struct tty_struct *tty) +{ + struct stliport *portp = tty->driver_data; + if (portp == NULL) + return; + set_bit(ST_RXSTOP, &portp->state); +} + +/*****************************************************************************/ + +/* + * Unflow control the device sending us data... That means that all + * we have to do is clear the RXSTOP state bit. The next poll call + * will then be able to pass the RX data back up. + */ + +static void stli_unthrottle(struct tty_struct *tty) +{ + struct stliport *portp = tty->driver_data; + if (portp == NULL) + return; + clear_bit(ST_RXSTOP, &portp->state); +} + +/*****************************************************************************/ + +/* + * Stop the transmitter. + */ + +static void stli_stop(struct tty_struct *tty) +{ +} + +/*****************************************************************************/ + +/* + * Start the transmitter again. + */ + +static void stli_start(struct tty_struct *tty) +{ +} + +/*****************************************************************************/ + + +/* + * Hangup this port. This is pretty much like closing the port, only + * a little more brutal. No waiting for data to drain. Shutdown the + * port and maybe drop signals. This is rather tricky really. We want + * to close the port as well. + */ + +static void stli_hangup(struct tty_struct *tty) +{ + struct stliport *portp = tty->driver_data; + tty_port_hangup(&portp->port); +} + +/*****************************************************************************/ + +/* + * Flush characters from the lower buffer. We may not have user context + * so we cannot sleep waiting for it to complete. Also we need to check + * if there is chars for this port in the TX cook buffer, and flush them + * as well. + */ + +static void stli_flushbuffer(struct tty_struct *tty) +{ + struct stliport *portp; + struct stlibrd *brdp; + unsigned long ftype, flags; + + portp = tty->driver_data; + if (portp == NULL) + return; + if (portp->brdnr >= stli_nrbrds) + return; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + if (tty == stli_txcooktty) { + stli_txcooktty = NULL; + stli_txcooksize = 0; + stli_txcookrealsize = 0; + } + if (test_bit(ST_CMDING, &portp->state)) { + set_bit(ST_DOFLUSHTX, &portp->state); + } else { + ftype = FLUSHTX; + if (test_bit(ST_DOFLUSHRX, &portp->state)) { + ftype |= FLUSHRX; + clear_bit(ST_DOFLUSHRX, &portp->state); + } + __stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); + } + spin_unlock_irqrestore(&brd_lock, flags); + tty_wakeup(tty); +} + +/*****************************************************************************/ + +static int stli_breakctl(struct tty_struct *tty, int state) +{ + struct stlibrd *brdp; + struct stliport *portp; + long arg; + + portp = tty->driver_data; + if (portp == NULL) + return -EINVAL; + if (portp->brdnr >= stli_nrbrds) + return -EINVAL; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return -EINVAL; + + arg = (state == -1) ? BREAKON : BREAKOFF; + stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); + return 0; +} + +/*****************************************************************************/ + +static void stli_waituntilsent(struct tty_struct *tty, int timeout) +{ + struct stliport *portp; + unsigned long tend; + + portp = tty->driver_data; + if (portp == NULL) + return; + + if (timeout == 0) + timeout = HZ; + tend = jiffies + timeout; + + while (test_bit(ST_TXBUSY, &portp->state)) { + if (signal_pending(current)) + break; + msleep_interruptible(20); + if (time_after_eq(jiffies, tend)) + break; + } +} + +/*****************************************************************************/ + +static void stli_sendxchar(struct tty_struct *tty, char ch) +{ + struct stlibrd *brdp; + struct stliport *portp; + asyctrl_t actrl; + + portp = tty->driver_data; + if (portp == NULL) + return; + if (portp->brdnr >= stli_nrbrds) + return; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return; + + memset(&actrl, 0, sizeof(asyctrl_t)); + if (ch == STOP_CHAR(tty)) { + actrl.rxctrl = CT_STOPFLOW; + } else if (ch == START_CHAR(tty)) { + actrl.rxctrl = CT_STARTFLOW; + } else { + actrl.txctrl = CT_SENDCHR; + actrl.tximdch = ch; + } + stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); +} + +static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr) +{ + char *uart; + int rc; + + rc = stli_portcmdstats(NULL, portp); + + uart = "UNKNOWN"; + if (test_bit(BST_STARTED, &brdp->state)) { + switch (stli_comstats.hwid) { + case 0: uart = "2681"; break; + case 1: uart = "SC26198"; break; + default:uart = "CD1400"; break; + } + } + seq_printf(m, "%d: uart:%s ", portnr, uart); + + if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) { + char sep; + + seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, + (int) stli_comstats.rxtotal); + + if (stli_comstats.rxframing) + seq_printf(m, " fe:%d", + (int) stli_comstats.rxframing); + if (stli_comstats.rxparity) + seq_printf(m, " pe:%d", + (int) stli_comstats.rxparity); + if (stli_comstats.rxbreaks) + seq_printf(m, " brk:%d", + (int) stli_comstats.rxbreaks); + if (stli_comstats.rxoverrun) + seq_printf(m, " oe:%d", + (int) stli_comstats.rxoverrun); + + sep = ' '; + if (stli_comstats.signals & TIOCM_RTS) { + seq_printf(m, "%c%s", sep, "RTS"); + sep = '|'; + } + if (stli_comstats.signals & TIOCM_CTS) { + seq_printf(m, "%c%s", sep, "CTS"); + sep = '|'; + } + if (stli_comstats.signals & TIOCM_DTR) { + seq_printf(m, "%c%s", sep, "DTR"); + sep = '|'; + } + if (stli_comstats.signals & TIOCM_CD) { + seq_printf(m, "%c%s", sep, "DCD"); + sep = '|'; + } + if (stli_comstats.signals & TIOCM_DSR) { + seq_printf(m, "%c%s", sep, "DSR"); + sep = '|'; + } + } + seq_putc(m, '\n'); +} + +/*****************************************************************************/ + +/* + * Port info, read from the /proc file system. + */ + +static int stli_proc_show(struct seq_file *m, void *v) +{ + struct stlibrd *brdp; + struct stliport *portp; + unsigned int brdnr, portnr, totalport; + + totalport = 0; + + seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion); + +/* + * We scan through for each board, panel and port. The offset is + * calculated on the fly, and irrelevant ports are skipped. + */ + for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) { + brdp = stli_brds[brdnr]; + if (brdp == NULL) + continue; + if (brdp->state == 0) + continue; + + totalport = brdnr * STL_MAXPORTS; + for (portnr = 0; (portnr < brdp->nrports); portnr++, + totalport++) { + portp = brdp->ports[portnr]; + if (portp == NULL) + continue; + stli_portinfo(m, brdp, portp, totalport); + } + } + return 0; +} + +static int stli_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, stli_proc_show, NULL); +} + +static const struct file_operations stli_proc_fops = { + .owner = THIS_MODULE, + .open = stli_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/*****************************************************************************/ + +/* + * Generic send command routine. This will send a message to the slave, + * of the specified type with the specified argument. Must be very + * careful of data that will be copied out from shared memory - + * containing command results. The command completion is all done from + * a poll routine that does not have user context. Therefore you cannot + * copy back directly into user space, or to the kernel stack of a + * process. This routine does not sleep, so can be called from anywhere. + * + * The caller must hold the brd_lock (see also stli_sendcmd the usual + * entry point) + */ + +static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) +{ + cdkhdr_t __iomem *hdrp; + cdkctrl_t __iomem *cp; + unsigned char __iomem *bits; + + if (test_bit(ST_CMDING, &portp->state)) { + printk(KERN_ERR "istallion: command already busy, cmd=%x!\n", + (int) cmd); + return; + } + + EBRDENABLE(brdp); + cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl; + if (size > 0) { + memcpy_toio((void __iomem *) &(cp->args[0]), arg, size); + if (copyback) { + portp->argp = arg; + portp->argsize = size; + } + } + writel(0, &cp->status); + writel(cmd, &cp->cmd); + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset + + portp->portidx; + writeb(readb(bits) | portp->portbit, bits); + set_bit(ST_CMDING, &portp->state); + EBRDDISABLE(brdp); +} + +static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) +{ + unsigned long flags; + + spin_lock_irqsave(&brd_lock, flags); + __stli_sendcmd(brdp, portp, cmd, arg, size, copyback); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Read data from shared memory. This assumes that the shared memory + * is enabled and that interrupts are off. Basically we just empty out + * the shared memory buffer into the tty buffer. Must be careful to + * handle the case where we fill up the tty buffer, but still have + * more chars to unload. + */ + +static void stli_read(struct stlibrd *brdp, struct stliport *portp) +{ + cdkasyrq_t __iomem *rp; + char __iomem *shbuf; + struct tty_struct *tty; + unsigned int head, tail, size; + unsigned int len, stlen; + + if (test_bit(ST_RXSTOP, &portp->state)) + return; + tty = tty_port_tty_get(&portp->port); + if (tty == NULL) + return; + + rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq; + head = (unsigned int) readw(&rp->head); + if (head != ((unsigned int) readw(&rp->head))) + head = (unsigned int) readw(&rp->head); + tail = (unsigned int) readw(&rp->tail); + size = portp->rxsize; + if (head >= tail) { + len = head - tail; + stlen = len; + } else { + len = size - (tail - head); + stlen = size - tail; + } + + len = tty_buffer_request_room(tty, len); + + shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset); + + while (len > 0) { + unsigned char *cptr; + + stlen = min(len, stlen); + tty_prepare_flip_string(tty, &cptr, stlen); + memcpy_fromio(cptr, shbuf + tail, stlen); + len -= stlen; + tail += stlen; + if (tail >= size) { + tail = 0; + stlen = head; + } + } + rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq; + writew(tail, &rp->tail); + + if (head != tail) + set_bit(ST_RXING, &portp->state); + + tty_schedule_flip(tty); + tty_kref_put(tty); +} + +/*****************************************************************************/ + +/* + * Set up and carry out any delayed commands. There is only a small set + * of slave commands that can be done "off-level". So it is not too + * difficult to deal with them here. + */ + +static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp) +{ + int cmd; + + if (test_bit(ST_DOSIGS, &portp->state)) { + if (test_bit(ST_DOFLUSHTX, &portp->state) && + test_bit(ST_DOFLUSHRX, &portp->state)) + cmd = A_SETSIGNALSF; + else if (test_bit(ST_DOFLUSHTX, &portp->state)) + cmd = A_SETSIGNALSFTX; + else if (test_bit(ST_DOFLUSHRX, &portp->state)) + cmd = A_SETSIGNALSFRX; + else + cmd = A_SETSIGNALS; + clear_bit(ST_DOFLUSHTX, &portp->state); + clear_bit(ST_DOFLUSHRX, &portp->state); + clear_bit(ST_DOSIGS, &portp->state); + memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig, + sizeof(asysigs_t)); + writel(0, &cp->status); + writel(cmd, &cp->cmd); + set_bit(ST_CMDING, &portp->state); + } else if (test_bit(ST_DOFLUSHTX, &portp->state) || + test_bit(ST_DOFLUSHRX, &portp->state)) { + cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0); + cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0); + clear_bit(ST_DOFLUSHTX, &portp->state); + clear_bit(ST_DOFLUSHRX, &portp->state); + memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int)); + writel(0, &cp->status); + writel(A_FLUSH, &cp->cmd); + set_bit(ST_CMDING, &portp->state); + } +} + +/*****************************************************************************/ + +/* + * Host command service checking. This handles commands or messages + * coming from the slave to the host. Must have board shared memory + * enabled and interrupts off when called. Notice that by servicing the + * read data last we don't need to change the shared memory pointer + * during processing (which is a slow IO operation). + * Return value indicates if this port is still awaiting actions from + * the slave (like open, command, or even TX data being sent). If 0 + * then port is still busy, otherwise no longer busy. + */ + +static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) +{ + cdkasy_t __iomem *ap; + cdkctrl_t __iomem *cp; + struct tty_struct *tty; + asynotify_t nt; + unsigned long oldsigs; + int rc, donerx; + + ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); + cp = &ap->ctrl; + +/* + * Check if we are waiting for an open completion message. + */ + if (test_bit(ST_OPENING, &portp->state)) { + rc = readl(&cp->openarg); + if (readb(&cp->open) == 0 && rc != 0) { + if (rc > 0) + rc--; + writel(0, &cp->openarg); + portp->rc = rc; + clear_bit(ST_OPENING, &portp->state); + wake_up_interruptible(&portp->raw_wait); + } + } + +/* + * Check if we are waiting for a close completion message. + */ + if (test_bit(ST_CLOSING, &portp->state)) { + rc = (int) readl(&cp->closearg); + if (readb(&cp->close) == 0 && rc != 0) { + if (rc > 0) + rc--; + writel(0, &cp->closearg); + portp->rc = rc; + clear_bit(ST_CLOSING, &portp->state); + wake_up_interruptible(&portp->raw_wait); + } + } + +/* + * Check if we are waiting for a command completion message. We may + * need to copy out the command results associated with this command. + */ + if (test_bit(ST_CMDING, &portp->state)) { + rc = readl(&cp->status); + if (readl(&cp->cmd) == 0 && rc != 0) { + if (rc > 0) + rc--; + if (portp->argp != NULL) { + memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]), + portp->argsize); + portp->argp = NULL; + } + writel(0, &cp->status); + portp->rc = rc; + clear_bit(ST_CMDING, &portp->state); + stli_dodelaycmd(portp, cp); + wake_up_interruptible(&portp->raw_wait); + } + } + +/* + * Check for any notification messages ready. This includes lots of + * different types of events - RX chars ready, RX break received, + * TX data low or empty in the slave, modem signals changed state. + */ + donerx = 0; + + if (ap->notify) { + nt = ap->changed; + ap->notify = 0; + tty = tty_port_tty_get(&portp->port); + + if (nt.signal & SG_DCD) { + oldsigs = portp->sigs; + portp->sigs = stli_mktiocm(nt.sigvalue); + clear_bit(ST_GETSIGS, &portp->state); + if ((portp->sigs & TIOCM_CD) && + ((oldsigs & TIOCM_CD) == 0)) + wake_up_interruptible(&portp->port.open_wait); + if ((oldsigs & TIOCM_CD) && + ((portp->sigs & TIOCM_CD) == 0)) { + if (portp->port.flags & ASYNC_CHECK_CD) { + if (tty) + tty_hangup(tty); + } + } + } + + if (nt.data & DT_TXEMPTY) + clear_bit(ST_TXBUSY, &portp->state); + if (nt.data & (DT_TXEMPTY | DT_TXLOW)) { + if (tty != NULL) { + tty_wakeup(tty); + EBRDENABLE(brdp); + } + } + + if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) { + if (tty != NULL) { + tty_insert_flip_char(tty, 0, TTY_BREAK); + if (portp->port.flags & ASYNC_SAK) { + do_SAK(tty); + EBRDENABLE(brdp); + } + tty_schedule_flip(tty); + } + } + tty_kref_put(tty); + + if (nt.data & DT_RXBUSY) { + donerx++; + stli_read(brdp, portp); + } + } + +/* + * It might seem odd that we are checking for more RX chars here. + * But, we need to handle the case where the tty buffer was previously + * filled, but we had more characters to pass up. The slave will not + * send any more RX notify messages until the RX buffer has been emptied. + * But it will leave the service bits on (since the buffer is not empty). + * So from here we can try to process more RX chars. + */ + if ((!donerx) && test_bit(ST_RXING, &portp->state)) { + clear_bit(ST_RXING, &portp->state); + stli_read(brdp, portp); + } + + return((test_bit(ST_OPENING, &portp->state) || + test_bit(ST_CLOSING, &portp->state) || + test_bit(ST_CMDING, &portp->state) || + test_bit(ST_TXBUSY, &portp->state) || + test_bit(ST_RXING, &portp->state)) ? 0 : 1); +} + +/*****************************************************************************/ + +/* + * Service all ports on a particular board. Assumes that the boards + * shared memory is enabled, and that the page pointer is pointed + * at the cdk header structure. + */ + +static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp) +{ + struct stliport *portp; + unsigned char hostbits[(STL_MAXCHANS / 8) + 1]; + unsigned char slavebits[(STL_MAXCHANS / 8) + 1]; + unsigned char __iomem *slavep; + int bitpos, bitat, bitsize; + int channr, nrdevs, slavebitchange; + + bitsize = brdp->bitsize; + nrdevs = brdp->nrdevs; + +/* + * Check if slave wants any service. Basically we try to do as + * little work as possible here. There are 2 levels of service + * bits. So if there is nothing to do we bail early. We check + * 8 service bits at a time in the inner loop, so we can bypass + * the lot if none of them want service. + */ + memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset), + bitsize); + + memset(&slavebits[0], 0, bitsize); + slavebitchange = 0; + + for (bitpos = 0; (bitpos < bitsize); bitpos++) { + if (hostbits[bitpos] == 0) + continue; + channr = bitpos * 8; + for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) { + if (hostbits[bitpos] & bitat) { + portp = brdp->ports[(channr - 1)]; + if (stli_hostcmd(brdp, portp)) { + slavebitchange++; + slavebits[bitpos] |= bitat; + } + } + } + } + +/* + * If any of the ports are no longer busy then update them in the + * slave request bits. We need to do this after, since a host port + * service may initiate more slave requests. + */ + if (slavebitchange) { + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset; + for (bitpos = 0; (bitpos < bitsize); bitpos++) { + if (readb(slavebits + bitpos)) + writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos); + } + } +} + +/*****************************************************************************/ + +/* + * Driver poll routine. This routine polls the boards in use and passes + * messages back up to host when necessary. This is actually very + * CPU efficient, since we will always have the kernel poll clock, it + * adds only a few cycles when idle (since board service can be + * determined very easily), but when loaded generates no interrupts + * (with their expensive associated context change). + */ + +static void stli_poll(unsigned long arg) +{ + cdkhdr_t __iomem *hdrp; + struct stlibrd *brdp; + unsigned int brdnr; + + mod_timer(&stli_timerlist, STLI_TIMEOUT); + +/* + * Check each board and do any servicing required. + */ + for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) { + brdp = stli_brds[brdnr]; + if (brdp == NULL) + continue; + if (!test_bit(BST_STARTED, &brdp->state)) + continue; + + spin_lock(&brd_lock); + EBRDENABLE(brdp); + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + if (readb(&hdrp->hostreq)) + stli_brdpoll(brdp, hdrp); + EBRDDISABLE(brdp); + spin_unlock(&brd_lock); + } +} + +/*****************************************************************************/ + +/* + * Translate the termios settings into the port setting structure of + * the slave. + */ + +static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, + asyport_t *pp, struct ktermios *tiosp) +{ + memset(pp, 0, sizeof(asyport_t)); + +/* + * Start of by setting the baud, char size, parity and stop bit info. + */ + pp->baudout = tty_get_baud_rate(tty); + if ((tiosp->c_cflag & CBAUD) == B38400) { + if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + pp->baudout = 57600; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + pp->baudout = 115200; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + pp->baudout = 230400; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + pp->baudout = 460800; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) + pp->baudout = (portp->baud_base / portp->custom_divisor); + } + if (pp->baudout > STL_MAXBAUD) + pp->baudout = STL_MAXBAUD; + pp->baudin = pp->baudout; + + switch (tiosp->c_cflag & CSIZE) { + case CS5: + pp->csize = 5; + break; + case CS6: + pp->csize = 6; + break; + case CS7: + pp->csize = 7; + break; + default: + pp->csize = 8; + break; + } + + if (tiosp->c_cflag & CSTOPB) + pp->stopbs = PT_STOP2; + else + pp->stopbs = PT_STOP1; + + if (tiosp->c_cflag & PARENB) { + if (tiosp->c_cflag & PARODD) + pp->parity = PT_ODDPARITY; + else + pp->parity = PT_EVENPARITY; + } else { + pp->parity = PT_NOPARITY; + } + +/* + * Set up any flow control options enabled. + */ + if (tiosp->c_iflag & IXON) { + pp->flow |= F_IXON; + if (tiosp->c_iflag & IXANY) + pp->flow |= F_IXANY; + } + if (tiosp->c_cflag & CRTSCTS) + pp->flow |= (F_RTSFLOW | F_CTSFLOW); + + pp->startin = tiosp->c_cc[VSTART]; + pp->stopin = tiosp->c_cc[VSTOP]; + pp->startout = tiosp->c_cc[VSTART]; + pp->stopout = tiosp->c_cc[VSTOP]; + +/* + * Set up the RX char marking mask with those RX error types we must + * catch. We can get the slave to help us out a little here, it will + * ignore parity errors and breaks for us, and mark parity errors in + * the data stream. + */ + if (tiosp->c_iflag & IGNPAR) + pp->iflag |= FI_IGNRXERRS; + if (tiosp->c_iflag & IGNBRK) + pp->iflag |= FI_IGNBREAK; + + portp->rxmarkmsk = 0; + if (tiosp->c_iflag & (INPCK | PARMRK)) + pp->iflag |= FI_1MARKRXERRS; + if (tiosp->c_iflag & BRKINT) + portp->rxmarkmsk |= BRKINT; + +/* + * Set up clocal processing as required. + */ + if (tiosp->c_cflag & CLOCAL) + portp->port.flags &= ~ASYNC_CHECK_CD; + else + portp->port.flags |= ASYNC_CHECK_CD; + +/* + * Transfer any persistent flags into the asyport structure. + */ + pp->pflag = (portp->pflag & 0xffff); + pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0; + pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0; + pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0; +} + +/*****************************************************************************/ + +/* + * Construct a slave signals structure for setting the DTR and RTS + * signals as specified. + */ + +static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts) +{ + memset(sp, 0, sizeof(asysigs_t)); + if (dtr >= 0) { + sp->signal |= SG_DTR; + sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0); + } + if (rts >= 0) { + sp->signal |= SG_RTS; + sp->sigvalue |= ((rts > 0) ? SG_RTS : 0); + } +} + +/*****************************************************************************/ + +/* + * Convert the signals returned from the slave into a local TIOCM type + * signals value. We keep them locally in TIOCM format. + */ + +static long stli_mktiocm(unsigned long sigvalue) +{ + long tiocm = 0; + tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0); + tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0); + tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0); + tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0); + tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0); + tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0); + return(tiocm); +} + +/*****************************************************************************/ + +/* + * All panels and ports actually attached have been worked out. All + * we need to do here is set up the appropriate per port data structures. + */ + +static int stli_initports(struct stlibrd *brdp) +{ + struct stliport *portp; + unsigned int i, panelnr, panelport; + + for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { + portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); + if (!portp) { + printk(KERN_WARNING "istallion: failed to allocate port structure\n"); + continue; + } + tty_port_init(&portp->port); + portp->port.ops = &stli_port_ops; + portp->magic = STLI_PORTMAGIC; + portp->portnr = i; + portp->brdnr = brdp->brdnr; + portp->panelnr = panelnr; + portp->baud_base = STL_BAUDBASE; + portp->port.close_delay = STL_CLOSEDELAY; + portp->closing_wait = 30 * HZ; + init_waitqueue_head(&portp->port.open_wait); + init_waitqueue_head(&portp->port.close_wait); + init_waitqueue_head(&portp->raw_wait); + panelport++; + if (panelport >= brdp->panels[panelnr]) { + panelport = 0; + panelnr++; + } + brdp->ports[i] = portp; + } + + return 0; +} + +/*****************************************************************************/ + +/* + * All the following routines are board specific hardware operations. + */ + +static void stli_ecpinit(struct stlibrd *brdp) +{ + unsigned long memconf; + + outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); + udelay(10); + outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); + udelay(100); + + memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT; + outb(memconf, (brdp->iobase + ECP_ATMEMAR)); +} + +/*****************************************************************************/ + +static void stli_ecpenable(struct stlibrd *brdp) +{ + outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR)); +} + +/*****************************************************************************/ + +static void stli_ecpdisable(struct stlibrd *brdp) +{ + outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); +} + +/*****************************************************************************/ + +static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + unsigned char val; + + if (offset > brdp->memsize) { + printk(KERN_ERR "istallion: shared memory pointer=%x out of " + "range at line=%d(%d), brd=%d\n", + (int) offset, line, __LINE__, brdp->brdnr); + ptr = NULL; + val = 0; + } else { + ptr = brdp->membase + (offset % ECP_ATPAGESIZE); + val = (unsigned char) (offset / ECP_ATPAGESIZE); + } + outb(val, (brdp->iobase + ECP_ATMEMPR)); + return(ptr); +} + +/*****************************************************************************/ + +static void stli_ecpreset(struct stlibrd *brdp) +{ + outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); + udelay(10); + outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); + udelay(500); +} + +/*****************************************************************************/ + +static void stli_ecpintr(struct stlibrd *brdp) +{ + outb(0x1, brdp->iobase); +} + +/*****************************************************************************/ + +/* + * The following set of functions act on ECP EISA boards. + */ + +static void stli_ecpeiinit(struct stlibrd *brdp) +{ + unsigned long memconf; + + outb(0x1, (brdp->iobase + ECP_EIBRDENAB)); + outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); + udelay(10); + outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); + udelay(500); + + memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL; + outb(memconf, (brdp->iobase + ECP_EIMEMARL)); + memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH; + outb(memconf, (brdp->iobase + ECP_EIMEMARH)); +} + +/*****************************************************************************/ + +static void stli_ecpeienable(struct stlibrd *brdp) +{ + outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR)); +} + +/*****************************************************************************/ + +static void stli_ecpeidisable(struct stlibrd *brdp) +{ + outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); +} + +/*****************************************************************************/ + +static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + unsigned char val; + + if (offset > brdp->memsize) { + printk(KERN_ERR "istallion: shared memory pointer=%x out of " + "range at line=%d(%d), brd=%d\n", + (int) offset, line, __LINE__, brdp->brdnr); + ptr = NULL; + val = 0; + } else { + ptr = brdp->membase + (offset % ECP_EIPAGESIZE); + if (offset < ECP_EIPAGESIZE) + val = ECP_EIENABLE; + else + val = ECP_EIENABLE | 0x40; + } + outb(val, (brdp->iobase + ECP_EICONFR)); + return(ptr); +} + +/*****************************************************************************/ + +static void stli_ecpeireset(struct stlibrd *brdp) +{ + outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); + udelay(10); + outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); + udelay(500); +} + +/*****************************************************************************/ + +/* + * The following set of functions act on ECP MCA boards. + */ + +static void stli_ecpmcenable(struct stlibrd *brdp) +{ + outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR)); +} + +/*****************************************************************************/ + +static void stli_ecpmcdisable(struct stlibrd *brdp) +{ + outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); +} + +/*****************************************************************************/ + +static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + unsigned char val; + + if (offset > brdp->memsize) { + printk(KERN_ERR "istallion: shared memory pointer=%x out of " + "range at line=%d(%d), brd=%d\n", + (int) offset, line, __LINE__, brdp->brdnr); + ptr = NULL; + val = 0; + } else { + ptr = brdp->membase + (offset % ECP_MCPAGESIZE); + val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE; + } + outb(val, (brdp->iobase + ECP_MCCONFR)); + return(ptr); +} + +/*****************************************************************************/ + +static void stli_ecpmcreset(struct stlibrd *brdp) +{ + outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR)); + udelay(10); + outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); + udelay(500); +} + +/*****************************************************************************/ + +/* + * The following set of functions act on ECP PCI boards. + */ + +static void stli_ecppciinit(struct stlibrd *brdp) +{ + outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); + udelay(10); + outb(0, (brdp->iobase + ECP_PCICONFR)); + udelay(500); +} + +/*****************************************************************************/ + +static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + unsigned char val; + + if (offset > brdp->memsize) { + printk(KERN_ERR "istallion: shared memory pointer=%x out of " + "range at line=%d(%d), board=%d\n", + (int) offset, line, __LINE__, brdp->brdnr); + ptr = NULL; + val = 0; + } else { + ptr = brdp->membase + (offset % ECP_PCIPAGESIZE); + val = (offset / ECP_PCIPAGESIZE) << 1; + } + outb(val, (brdp->iobase + ECP_PCICONFR)); + return(ptr); +} + +/*****************************************************************************/ + +static void stli_ecppcireset(struct stlibrd *brdp) +{ + outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); + udelay(10); + outb(0, (brdp->iobase + ECP_PCICONFR)); + udelay(500); +} + +/*****************************************************************************/ + +/* + * The following routines act on ONboards. + */ + +static void stli_onbinit(struct stlibrd *brdp) +{ + unsigned long memconf; + + outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); + udelay(10); + outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR)); + mdelay(1000); + + memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT; + outb(memconf, (brdp->iobase + ONB_ATMEMAR)); + outb(0x1, brdp->iobase); + mdelay(1); +} + +/*****************************************************************************/ + +static void stli_onbenable(struct stlibrd *brdp) +{ + outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR)); +} + +/*****************************************************************************/ + +static void stli_onbdisable(struct stlibrd *brdp) +{ + outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR)); +} + +/*****************************************************************************/ + +static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + + if (offset > brdp->memsize) { + printk(KERN_ERR "istallion: shared memory pointer=%x out of " + "range at line=%d(%d), brd=%d\n", + (int) offset, line, __LINE__, brdp->brdnr); + ptr = NULL; + } else { + ptr = brdp->membase + (offset % ONB_ATPAGESIZE); + } + return(ptr); +} + +/*****************************************************************************/ + +static void stli_onbreset(struct stlibrd *brdp) +{ + outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); + udelay(10); + outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR)); + mdelay(1000); +} + +/*****************************************************************************/ + +/* + * The following routines act on ONboard EISA. + */ + +static void stli_onbeinit(struct stlibrd *brdp) +{ + unsigned long memconf; + + outb(0x1, (brdp->iobase + ONB_EIBRDENAB)); + outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); + udelay(10); + outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); + mdelay(1000); + + memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL; + outb(memconf, (brdp->iobase + ONB_EIMEMARL)); + memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH; + outb(memconf, (brdp->iobase + ONB_EIMEMARH)); + outb(0x1, brdp->iobase); + mdelay(1); +} + +/*****************************************************************************/ + +static void stli_onbeenable(struct stlibrd *brdp) +{ + outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR)); +} + +/*****************************************************************************/ + +static void stli_onbedisable(struct stlibrd *brdp) +{ + outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); +} + +/*****************************************************************************/ + +static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + unsigned char val; + + if (offset > brdp->memsize) { + printk(KERN_ERR "istallion: shared memory pointer=%x out of " + "range at line=%d(%d), brd=%d\n", + (int) offset, line, __LINE__, brdp->brdnr); + ptr = NULL; + val = 0; + } else { + ptr = brdp->membase + (offset % ONB_EIPAGESIZE); + if (offset < ONB_EIPAGESIZE) + val = ONB_EIENABLE; + else + val = ONB_EIENABLE | 0x40; + } + outb(val, (brdp->iobase + ONB_EICONFR)); + return(ptr); +} + +/*****************************************************************************/ + +static void stli_onbereset(struct stlibrd *brdp) +{ + outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); + udelay(10); + outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); + mdelay(1000); +} + +/*****************************************************************************/ + +/* + * The following routines act on Brumby boards. + */ + +static void stli_bbyinit(struct stlibrd *brdp) +{ + outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); + udelay(10); + outb(0, (brdp->iobase + BBY_ATCONFR)); + mdelay(1000); + outb(0x1, brdp->iobase); + mdelay(1); +} + +/*****************************************************************************/ + +static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + void __iomem *ptr; + unsigned char val; + + BUG_ON(offset > brdp->memsize); + + ptr = brdp->membase + (offset % BBY_PAGESIZE); + val = (unsigned char) (offset / BBY_PAGESIZE); + outb(val, (brdp->iobase + BBY_ATCONFR)); + return(ptr); +} + +/*****************************************************************************/ + +static void stli_bbyreset(struct stlibrd *brdp) +{ + outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); + udelay(10); + outb(0, (brdp->iobase + BBY_ATCONFR)); + mdelay(1000); +} + +/*****************************************************************************/ + +/* + * The following routines act on original old Stallion boards. + */ + +static void stli_stalinit(struct stlibrd *brdp) +{ + outb(0x1, brdp->iobase); + mdelay(1000); +} + +/*****************************************************************************/ + +static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) +{ + BUG_ON(offset > brdp->memsize); + return brdp->membase + (offset % STAL_PAGESIZE); +} + +/*****************************************************************************/ + +static void stli_stalreset(struct stlibrd *brdp) +{ + u32 __iomem *vecp; + + vecp = (u32 __iomem *) (brdp->membase + 0x30); + writel(0xffff0000, vecp); + outb(0, brdp->iobase); + mdelay(1000); +} + +/*****************************************************************************/ + +/* + * Try to find an ECP board and initialize it. This handles only ECP + * board types. + */ + +static int stli_initecp(struct stlibrd *brdp) +{ + cdkecpsig_t sig; + cdkecpsig_t __iomem *sigsp; + unsigned int status, nxtid; + char *name; + int retval, panelnr, nrports; + + if ((brdp->iobase == 0) || (brdp->memaddr == 0)) { + retval = -ENODEV; + goto err; + } + + brdp->iosize = ECP_IOSIZE; + + if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { + retval = -EIO; + goto err; + } + +/* + * Based on the specific board type setup the common vars to access + * and enable shared memory. Set all board specific information now + * as well. + */ + switch (brdp->brdtype) { + case BRD_ECP: + brdp->memsize = ECP_MEMSIZE; + brdp->pagesize = ECP_ATPAGESIZE; + brdp->init = stli_ecpinit; + brdp->enable = stli_ecpenable; + brdp->reenable = stli_ecpenable; + brdp->disable = stli_ecpdisable; + brdp->getmemptr = stli_ecpgetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_ecpreset; + name = "serial(EC8/64)"; + break; + + case BRD_ECPE: + brdp->memsize = ECP_MEMSIZE; + brdp->pagesize = ECP_EIPAGESIZE; + brdp->init = stli_ecpeiinit; + brdp->enable = stli_ecpeienable; + brdp->reenable = stli_ecpeienable; + brdp->disable = stli_ecpeidisable; + brdp->getmemptr = stli_ecpeigetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_ecpeireset; + name = "serial(EC8/64-EI)"; + break; + + case BRD_ECPMC: + brdp->memsize = ECP_MEMSIZE; + brdp->pagesize = ECP_MCPAGESIZE; + brdp->init = NULL; + brdp->enable = stli_ecpmcenable; + brdp->reenable = stli_ecpmcenable; + brdp->disable = stli_ecpmcdisable; + brdp->getmemptr = stli_ecpmcgetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_ecpmcreset; + name = "serial(EC8/64-MCA)"; + break; + + case BRD_ECPPCI: + brdp->memsize = ECP_PCIMEMSIZE; + brdp->pagesize = ECP_PCIPAGESIZE; + brdp->init = stli_ecppciinit; + brdp->enable = NULL; + brdp->reenable = NULL; + brdp->disable = NULL; + brdp->getmemptr = stli_ecppcigetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_ecppcireset; + name = "serial(EC/RA-PCI)"; + break; + + default: + retval = -EINVAL; + goto err_reg; + } + +/* + * The per-board operations structure is all set up, so now let's go + * and get the board operational. Firstly initialize board configuration + * registers. Set the memory mapping info so we can get at the boards + * shared memory. + */ + EBRDINIT(brdp); + + brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); + if (brdp->membase == NULL) { + retval = -ENOMEM; + goto err_reg; + } + +/* + * Now that all specific code is set up, enable the shared memory and + * look for the a signature area that will tell us exactly what board + * this is, and what it is connected to it. + */ + EBRDENABLE(brdp); + sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); + memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t)); + EBRDDISABLE(brdp); + + if (sig.magic != cpu_to_le32(ECP_MAGIC)) { + retval = -ENODEV; + goto err_unmap; + } + +/* + * Scan through the signature looking at the panels connected to the + * board. Calculate the total number of ports as we go. + */ + for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) { + status = sig.panelid[nxtid]; + if ((status & ECH_PNLIDMASK) != nxtid) + break; + + brdp->panelids[panelnr] = status; + nrports = (status & ECH_PNL16PORT) ? 16 : 8; + if ((nrports == 16) && ((status & ECH_PNLXPID) == 0)) + nxtid++; + brdp->panels[panelnr] = nrports; + brdp->nrports += nrports; + nxtid++; + brdp->nrpanels++; + } + + + set_bit(BST_FOUND, &brdp->state); + return 0; +err_unmap: + iounmap(brdp->membase); + brdp->membase = NULL; +err_reg: + release_region(brdp->iobase, brdp->iosize); +err: + return retval; +} + +/*****************************************************************************/ + +/* + * Try to find an ONboard, Brumby or Stallion board and initialize it. + * This handles only these board types. + */ + +static int stli_initonb(struct stlibrd *brdp) +{ + cdkonbsig_t sig; + cdkonbsig_t __iomem *sigsp; + char *name; + int i, retval; + +/* + * Do a basic sanity check on the IO and memory addresses. + */ + if (brdp->iobase == 0 || brdp->memaddr == 0) { + retval = -ENODEV; + goto err; + } + + brdp->iosize = ONB_IOSIZE; + + if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { + retval = -EIO; + goto err; + } + +/* + * Based on the specific board type setup the common vars to access + * and enable shared memory. Set all board specific information now + * as well. + */ + switch (brdp->brdtype) { + case BRD_ONBOARD: + case BRD_ONBOARD2: + brdp->memsize = ONB_MEMSIZE; + brdp->pagesize = ONB_ATPAGESIZE; + brdp->init = stli_onbinit; + brdp->enable = stli_onbenable; + brdp->reenable = stli_onbenable; + brdp->disable = stli_onbdisable; + brdp->getmemptr = stli_onbgetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_onbreset; + if (brdp->memaddr > 0x100000) + brdp->enabval = ONB_MEMENABHI; + else + brdp->enabval = ONB_MEMENABLO; + name = "serial(ONBoard)"; + break; + + case BRD_ONBOARDE: + brdp->memsize = ONB_EIMEMSIZE; + brdp->pagesize = ONB_EIPAGESIZE; + brdp->init = stli_onbeinit; + brdp->enable = stli_onbeenable; + brdp->reenable = stli_onbeenable; + brdp->disable = stli_onbedisable; + brdp->getmemptr = stli_onbegetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_onbereset; + name = "serial(ONBoard/E)"; + break; + + case BRD_BRUMBY4: + brdp->memsize = BBY_MEMSIZE; + brdp->pagesize = BBY_PAGESIZE; + brdp->init = stli_bbyinit; + brdp->enable = NULL; + brdp->reenable = NULL; + brdp->disable = NULL; + brdp->getmemptr = stli_bbygetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_bbyreset; + name = "serial(Brumby)"; + break; + + case BRD_STALLION: + brdp->memsize = STAL_MEMSIZE; + brdp->pagesize = STAL_PAGESIZE; + brdp->init = stli_stalinit; + brdp->enable = NULL; + brdp->reenable = NULL; + brdp->disable = NULL; + brdp->getmemptr = stli_stalgetmemptr; + brdp->intr = stli_ecpintr; + brdp->reset = stli_stalreset; + name = "serial(Stallion)"; + break; + + default: + retval = -EINVAL; + goto err_reg; + } + +/* + * The per-board operations structure is all set up, so now let's go + * and get the board operational. Firstly initialize board configuration + * registers. Set the memory mapping info so we can get at the boards + * shared memory. + */ + EBRDINIT(brdp); + + brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); + if (brdp->membase == NULL) { + retval = -ENOMEM; + goto err_reg; + } + +/* + * Now that all specific code is set up, enable the shared memory and + * look for the a signature area that will tell us exactly what board + * this is, and how many ports. + */ + EBRDENABLE(brdp); + sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); + memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t)); + EBRDDISABLE(brdp); + + if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) || + sig.magic1 != cpu_to_le16(ONB_MAGIC1) || + sig.magic2 != cpu_to_le16(ONB_MAGIC2) || + sig.magic3 != cpu_to_le16(ONB_MAGIC3)) { + retval = -ENODEV; + goto err_unmap; + } + +/* + * Scan through the signature alive mask and calculate how many ports + * there are on this board. + */ + brdp->nrpanels = 1; + if (sig.amask1) { + brdp->nrports = 32; + } else { + for (i = 0; (i < 16); i++) { + if (((sig.amask0 << i) & 0x8000) == 0) + break; + } + brdp->nrports = i; + } + brdp->panels[0] = brdp->nrports; + + + set_bit(BST_FOUND, &brdp->state); + return 0; +err_unmap: + iounmap(brdp->membase); + brdp->membase = NULL; +err_reg: + release_region(brdp->iobase, brdp->iosize); +err: + return retval; +} + +/*****************************************************************************/ + +/* + * Start up a running board. This routine is only called after the + * code has been down loaded to the board and is operational. It will + * read in the memory map, and get the show on the road... + */ + +static int stli_startbrd(struct stlibrd *brdp) +{ + cdkhdr_t __iomem *hdrp; + cdkmem_t __iomem *memp; + cdkasy_t __iomem *ap; + unsigned long flags; + unsigned int portnr, nrdevs, i; + struct stliport *portp; + int rc = 0; + u32 memoff; + + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR); + nrdevs = hdrp->nrdevs; + +#if 0 + printk("%s(%d): CDK version %d.%d.%d --> " + "nrdevs=%d memp=%x hostp=%x slavep=%x\n", + __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification), + readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp), + readl(&hdrp->slavep)); +#endif + + if (nrdevs < (brdp->nrports + 1)) { + printk(KERN_ERR "istallion: slave failed to allocate memory for " + "all devices, devices=%d\n", nrdevs); + brdp->nrports = nrdevs - 1; + } + brdp->nrdevs = nrdevs; + brdp->hostoffset = hdrp->hostp - CDK_CDKADDR; + brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR; + brdp->bitsize = (nrdevs + 7) / 8; + memoff = readl(&hdrp->memp); + if (memoff > brdp->memsize) { + printk(KERN_ERR "istallion: corrupted shared memory region?\n"); + rc = -EIO; + goto stli_donestartup; + } + memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); + if (readw(&memp->dtype) != TYP_ASYNCTRL) { + printk(KERN_ERR "istallion: no slave control device found\n"); + goto stli_donestartup; + } + memp++; + +/* + * Cycle through memory allocation of each port. We are guaranteed to + * have all ports inside the first page of slave window, so no need to + * change pages while reading memory map. + */ + for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) { + if (readw(&memp->dtype) != TYP_ASYNC) + break; + portp = brdp->ports[portnr]; + if (portp == NULL) + break; + portp->devnr = i; + portp->addr = readl(&memp->offset); + portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs)); + portp->portidx = (unsigned char) (i / 8); + portp->portbit = (unsigned char) (0x1 << (i % 8)); + } + + writeb(0xff, &hdrp->slavereq); + +/* + * For each port setup a local copy of the RX and TX buffer offsets + * and sizes. We do this separate from the above, because we need to + * move the shared memory page... + */ + for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) { + portp = brdp->ports[portnr]; + if (portp == NULL) + break; + if (portp->addr == 0) + break; + ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr); + if (ap != NULL) { + portp->rxsize = readw(&ap->rxq.size); + portp->txsize = readw(&ap->txq.size); + portp->rxoffset = readl(&ap->rxq.offset); + portp->txoffset = readl(&ap->txq.offset); + } + } + +stli_donestartup: + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); + + if (rc == 0) + set_bit(BST_STARTED, &brdp->state); + + if (! stli_timeron) { + stli_timeron++; + mod_timer(&stli_timerlist, STLI_TIMEOUT); + } + + return rc; +} + +/*****************************************************************************/ + +/* + * Probe and initialize the specified board. + */ + +static int __devinit stli_brdinit(struct stlibrd *brdp) +{ + int retval; + + switch (brdp->brdtype) { + case BRD_ECP: + case BRD_ECPE: + case BRD_ECPMC: + case BRD_ECPPCI: + retval = stli_initecp(brdp); + break; + case BRD_ONBOARD: + case BRD_ONBOARDE: + case BRD_ONBOARD2: + case BRD_BRUMBY4: + case BRD_STALLION: + retval = stli_initonb(brdp); + break; + default: + printk(KERN_ERR "istallion: board=%d is unknown board " + "type=%d\n", brdp->brdnr, brdp->brdtype); + retval = -ENODEV; + } + + if (retval) + return retval; + + stli_initports(brdp); + printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x " + "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], + brdp->brdnr, brdp->iobase, (int) brdp->memaddr, + brdp->nrpanels, brdp->nrports); + return 0; +} + +#if STLI_EISAPROBE != 0 +/*****************************************************************************/ + +/* + * Probe around trying to find where the EISA boards shared memory + * might be. This is a bit if hack, but it is the best we can do. + */ + +static int stli_eisamemprobe(struct stlibrd *brdp) +{ + cdkecpsig_t ecpsig, __iomem *ecpsigp; + cdkonbsig_t onbsig, __iomem *onbsigp; + int i, foundit; + +/* + * First up we reset the board, to get it into a known state. There + * is only 2 board types here we need to worry about. Don;t use the + * standard board init routine here, it programs up the shared + * memory address, and we don't know it yet... + */ + if (brdp->brdtype == BRD_ECPE) { + outb(0x1, (brdp->iobase + ECP_EIBRDENAB)); + outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); + udelay(10); + outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); + udelay(500); + stli_ecpeienable(brdp); + } else if (brdp->brdtype == BRD_ONBOARDE) { + outb(0x1, (brdp->iobase + ONB_EIBRDENAB)); + outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); + udelay(10); + outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); + mdelay(100); + outb(0x1, brdp->iobase); + mdelay(1); + stli_onbeenable(brdp); + } else { + return -ENODEV; + } + + foundit = 0; + brdp->memsize = ECP_MEMSIZE; + +/* + * Board shared memory is enabled, so now we have a poke around and + * see if we can find it. + */ + for (i = 0; (i < stli_eisamempsize); i++) { + brdp->memaddr = stli_eisamemprobeaddrs[i]; + brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize); + if (brdp->membase == NULL) + continue; + + if (brdp->brdtype == BRD_ECPE) { + ecpsigp = stli_ecpeigetmemptr(brdp, + CDK_SIGADDR, __LINE__); + memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t)); + if (ecpsig.magic == cpu_to_le32(ECP_MAGIC)) + foundit = 1; + } else { + onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp, + CDK_SIGADDR, __LINE__); + memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t)); + if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) && + (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) && + (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) && + (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3))) + foundit = 1; + } + + iounmap(brdp->membase); + if (foundit) + break; + } + +/* + * Regardless of whether we found the shared memory or not we must + * disable the region. After that return success or failure. + */ + if (brdp->brdtype == BRD_ECPE) + stli_ecpeidisable(brdp); + else + stli_onbedisable(brdp); + + if (! foundit) { + brdp->memaddr = 0; + brdp->membase = NULL; + printk(KERN_ERR "istallion: failed to probe shared memory " + "region for %s in EISA slot=%d\n", + stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); + return -ENODEV; + } + return 0; +} +#endif + +static int stli_getbrdnr(void) +{ + unsigned int i; + + for (i = 0; i < STL_MAXBRDS; i++) { + if (!stli_brds[i]) { + if (i >= stli_nrbrds) + stli_nrbrds = i + 1; + return i; + } + } + return -1; +} + +#if STLI_EISAPROBE != 0 +/*****************************************************************************/ + +/* + * Probe around and try to find any EISA boards in system. The biggest + * problem here is finding out what memory address is associated with + * an EISA board after it is found. The registers of the ECPE and + * ONboardE are not readable - so we can't read them from there. We + * don't have access to the EISA CMOS (or EISA BIOS) so we don't + * actually have any way to find out the real value. The best we can + * do is go probing around in the usual places hoping we can find it. + */ + +static int __init stli_findeisabrds(void) +{ + struct stlibrd *brdp; + unsigned int iobase, eid, i; + int brdnr, found = 0; + +/* + * Firstly check if this is an EISA system. If this is not an EISA system then + * don't bother going any further! + */ + if (EISA_bus) + return 0; + +/* + * Looks like an EISA system, so go searching for EISA boards. + */ + for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) { + outb(0xff, (iobase + 0xc80)); + eid = inb(iobase + 0xc80); + eid |= inb(iobase + 0xc81) << 8; + if (eid != STL_EISAID) + continue; + +/* + * We have found a board. Need to check if this board was + * statically configured already (just in case!). + */ + for (i = 0; (i < STL_MAXBRDS); i++) { + brdp = stli_brds[i]; + if (brdp == NULL) + continue; + if (brdp->iobase == iobase) + break; + } + if (i < STL_MAXBRDS) + continue; + +/* + * We have found a Stallion board and it is not configured already. + * Allocate a board structure and initialize it. + */ + if ((brdp = stli_allocbrd()) == NULL) + return found ? : -ENOMEM; + brdnr = stli_getbrdnr(); + if (brdnr < 0) + return found ? : -ENOMEM; + brdp->brdnr = (unsigned int)brdnr; + eid = inb(iobase + 0xc82); + if (eid == ECP_EISAID) + brdp->brdtype = BRD_ECPE; + else if (eid == ONB_EISAID) + brdp->brdtype = BRD_ONBOARDE; + else + brdp->brdtype = BRD_UNKNOWN; + brdp->iobase = iobase; + outb(0x1, (iobase + 0xc84)); + if (stli_eisamemprobe(brdp)) + outb(0, (iobase + 0xc84)); + if (stli_brdinit(brdp) < 0) { + kfree(brdp); + continue; + } + + stli_brds[brdp->brdnr] = brdp; + found++; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, + brdp->brdnr * STL_MAXPORTS + i, NULL); + } + + return found; +} +#else +static inline int stli_findeisabrds(void) { return 0; } +#endif + +/*****************************************************************************/ + +/* + * Find the next available board number that is free. + */ + +/*****************************************************************************/ + +/* + * We have a Stallion board. Allocate a board structure and + * initialize it. Read its IO and MEMORY resources from PCI + * configuration space. + */ + +static int __devinit stli_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct stlibrd *brdp; + unsigned int i; + int brdnr, retval = -EIO; + + retval = pci_enable_device(pdev); + if (retval) + goto err; + brdp = stli_allocbrd(); + if (brdp == NULL) { + retval = -ENOMEM; + goto err; + } + mutex_lock(&stli_brdslock); + brdnr = stli_getbrdnr(); + if (brdnr < 0) { + printk(KERN_INFO "istallion: too many boards found, " + "maximum supported %d\n", STL_MAXBRDS); + mutex_unlock(&stli_brdslock); + retval = -EIO; + goto err_fr; + } + brdp->brdnr = (unsigned int)brdnr; + stli_brds[brdp->brdnr] = brdp; + mutex_unlock(&stli_brdslock); + brdp->brdtype = BRD_ECPPCI; +/* + * We have all resources from the board, so lets setup the actual + * board structure now. + */ + brdp->iobase = pci_resource_start(pdev, 3); + brdp->memaddr = pci_resource_start(pdev, 2); + retval = stli_brdinit(brdp); + if (retval) + goto err_null; + + set_bit(BST_PROBED, &brdp->state); + pci_set_drvdata(pdev, brdp); + + EBRDENABLE(brdp); + brdp->enable = NULL; + brdp->disable = NULL; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i, + &pdev->dev); + + return 0; +err_null: + stli_brds[brdp->brdnr] = NULL; +err_fr: + kfree(brdp); +err: + return retval; +} + +static void __devexit stli_pciremove(struct pci_dev *pdev) +{ + struct stlibrd *brdp = pci_get_drvdata(pdev); + + stli_cleanup_ports(brdp); + + iounmap(brdp->membase); + if (brdp->iosize > 0) + release_region(brdp->iobase, brdp->iosize); + + stli_brds[brdp->brdnr] = NULL; + kfree(brdp); +} + +static struct pci_driver stli_pcidriver = { + .name = "istallion", + .id_table = istallion_pci_tbl, + .probe = stli_pciprobe, + .remove = __devexit_p(stli_pciremove) +}; +/*****************************************************************************/ + +/* + * Allocate a new board structure. Fill out the basic info in it. + */ + +static struct stlibrd *stli_allocbrd(void) +{ + struct stlibrd *brdp; + + brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); + if (!brdp) { + printk(KERN_ERR "istallion: failed to allocate memory " + "(size=%Zd)\n", sizeof(struct stlibrd)); + return NULL; + } + brdp->magic = STLI_BOARDMAGIC; + return brdp; +} + +/*****************************************************************************/ + +/* + * Scan through all the boards in the configuration and see what we + * can find. + */ + +static int __init stli_initbrds(void) +{ + struct stlibrd *brdp, *nxtbrdp; + struct stlconf conf; + unsigned int i, j, found = 0; + int retval; + + for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp); + stli_nrbrds++) { + memset(&conf, 0, sizeof(conf)); + if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0) + continue; + if ((brdp = stli_allocbrd()) == NULL) + continue; + brdp->brdnr = stli_nrbrds; + brdp->brdtype = conf.brdtype; + brdp->iobase = conf.ioaddr1; + brdp->memaddr = conf.memaddr; + if (stli_brdinit(brdp) < 0) { + kfree(brdp); + continue; + } + stli_brds[brdp->brdnr] = brdp; + found++; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, + brdp->brdnr * STL_MAXPORTS + i, NULL); + } + + retval = stli_findeisabrds(); + if (retval > 0) + found += retval; + +/* + * All found boards are initialized. Now for a little optimization, if + * no boards are sharing the "shared memory" regions then we can just + * leave them all enabled. This is in fact the usual case. + */ + stli_shared = 0; + if (stli_nrbrds > 1) { + for (i = 0; (i < stli_nrbrds); i++) { + brdp = stli_brds[i]; + if (brdp == NULL) + continue; + for (j = i + 1; (j < stli_nrbrds); j++) { + nxtbrdp = stli_brds[j]; + if (nxtbrdp == NULL) + continue; + if ((brdp->membase >= nxtbrdp->membase) && + (brdp->membase <= (nxtbrdp->membase + + nxtbrdp->memsize - 1))) { + stli_shared++; + break; + } + } + } + } + + if (stli_shared == 0) { + for (i = 0; (i < stli_nrbrds); i++) { + brdp = stli_brds[i]; + if (brdp == NULL) + continue; + if (test_bit(BST_FOUND, &brdp->state)) { + EBRDENABLE(brdp); + brdp->enable = NULL; + brdp->disable = NULL; + } + } + } + + retval = pci_register_driver(&stli_pcidriver); + if (retval && found == 0) { + printk(KERN_ERR "Neither isa nor eisa cards found nor pci " + "driver can be registered!\n"); + goto err; + } + + return 0; +err: + return retval; +} + +/*****************************************************************************/ + +/* + * Code to handle an "staliomem" read operation. This device is the + * contents of the board shared memory. It is used for down loading + * the slave image (and debugging :-) + */ + +static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp) +{ + unsigned long flags; + void __iomem *memptr; + struct stlibrd *brdp; + unsigned int brdnr; + int size, n; + void *p; + loff_t off = *offp; + + brdnr = iminor(fp->f_path.dentry->d_inode); + if (brdnr >= stli_nrbrds) + return -ENODEV; + brdp = stli_brds[brdnr]; + if (brdp == NULL) + return -ENODEV; + if (brdp->state == 0) + return -ENODEV; + if (off >= brdp->memsize || off + count < off) + return 0; + + size = min(count, (size_t)(brdp->memsize - off)); + + /* + * Copy the data a page at a time + */ + + p = (void *)__get_free_page(GFP_KERNEL); + if(p == NULL) + return -ENOMEM; + + while (size > 0) { + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + memptr = EBRDGETMEMPTR(brdp, off); + n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); + n = min(n, (int)PAGE_SIZE); + memcpy_fromio(p, memptr, n); + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); + if (copy_to_user(buf, p, n)) { + count = -EFAULT; + goto out; + } + off += n; + buf += n; + size -= n; + } +out: + *offp = off; + free_page((unsigned long)p); + return count; +} + +/*****************************************************************************/ + +/* + * Code to handle an "staliomem" write operation. This device is the + * contents of the board shared memory. It is used for down loading + * the slave image (and debugging :-) + * + * FIXME: copy under lock + */ + +static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp) +{ + unsigned long flags; + void __iomem *memptr; + struct stlibrd *brdp; + char __user *chbuf; + unsigned int brdnr; + int size, n; + void *p; + loff_t off = *offp; + + brdnr = iminor(fp->f_path.dentry->d_inode); + + if (brdnr >= stli_nrbrds) + return -ENODEV; + brdp = stli_brds[brdnr]; + if (brdp == NULL) + return -ENODEV; + if (brdp->state == 0) + return -ENODEV; + if (off >= brdp->memsize || off + count < off) + return 0; + + chbuf = (char __user *) buf; + size = min(count, (size_t)(brdp->memsize - off)); + + /* + * Copy the data a page at a time + */ + + p = (void *)__get_free_page(GFP_KERNEL); + if(p == NULL) + return -ENOMEM; + + while (size > 0) { + n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); + n = min(n, (int)PAGE_SIZE); + if (copy_from_user(p, chbuf, n)) { + if (count == 0) + count = -EFAULT; + goto out; + } + spin_lock_irqsave(&brd_lock, flags); + EBRDENABLE(brdp); + memptr = EBRDGETMEMPTR(brdp, off); + memcpy_toio(memptr, p, n); + EBRDDISABLE(brdp); + spin_unlock_irqrestore(&brd_lock, flags); + off += n; + chbuf += n; + size -= n; + } +out: + free_page((unsigned long) p); + *offp = off; + return count; +} + +/*****************************************************************************/ + +/* + * Return the board stats structure to user app. + */ + +static int stli_getbrdstats(combrd_t __user *bp) +{ + struct stlibrd *brdp; + unsigned int i; + + if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t))) + return -EFAULT; + if (stli_brdstats.brd >= STL_MAXBRDS) + return -ENODEV; + brdp = stli_brds[stli_brdstats.brd]; + if (brdp == NULL) + return -ENODEV; + + memset(&stli_brdstats, 0, sizeof(combrd_t)); + + stli_brdstats.brd = brdp->brdnr; + stli_brdstats.type = brdp->brdtype; + stli_brdstats.hwid = 0; + stli_brdstats.state = brdp->state; + stli_brdstats.ioaddr = brdp->iobase; + stli_brdstats.memaddr = brdp->memaddr; + stli_brdstats.nrpanels = brdp->nrpanels; + stli_brdstats.nrports = brdp->nrports; + for (i = 0; (i < brdp->nrpanels); i++) { + stli_brdstats.panels[i].panel = i; + stli_brdstats.panels[i].hwid = brdp->panelids[i]; + stli_brdstats.panels[i].nrports = brdp->panels[i]; + } + + if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t))) + return -EFAULT; + return 0; +} + +/*****************************************************************************/ + +/* + * Resolve the referenced port number into a port struct pointer. + */ + +static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, + unsigned int portnr) +{ + struct stlibrd *brdp; + unsigned int i; + + if (brdnr >= STL_MAXBRDS) + return NULL; + brdp = stli_brds[brdnr]; + if (brdp == NULL) + return NULL; + for (i = 0; (i < panelnr); i++) + portnr += brdp->panels[i]; + if (portnr >= brdp->nrports) + return NULL; + return brdp->ports[portnr]; +} + +/*****************************************************************************/ + +/* + * Return the port stats structure to user app. A NULL port struct + * pointer passed in means that we need to find out from the app + * what port to get stats for (used through board control device). + */ + +static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) +{ + unsigned long flags; + struct stlibrd *brdp; + int rc; + + memset(&stli_comstats, 0, sizeof(comstats_t)); + + if (portp == NULL) + return -ENODEV; + brdp = stli_brds[portp->brdnr]; + if (brdp == NULL) + return -ENODEV; + + mutex_lock(&portp->port.mutex); + if (test_bit(BST_STARTED, &brdp->state)) { + if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, + &stli_cdkstats, sizeof(asystats_t), 1)) < 0) { + mutex_unlock(&portp->port.mutex); + return rc; + } + } else { + memset(&stli_cdkstats, 0, sizeof(asystats_t)); + } + + stli_comstats.brd = portp->brdnr; + stli_comstats.panel = portp->panelnr; + stli_comstats.port = portp->portnr; + stli_comstats.state = portp->state; + stli_comstats.flags = portp->port.flags; + + spin_lock_irqsave(&brd_lock, flags); + if (tty != NULL) { + if (portp->port.tty == tty) { + stli_comstats.ttystate = tty->flags; + stli_comstats.rxbuffered = -1; + if (tty->termios != NULL) { + stli_comstats.cflags = tty->termios->c_cflag; + stli_comstats.iflags = tty->termios->c_iflag; + stli_comstats.oflags = tty->termios->c_oflag; + stli_comstats.lflags = tty->termios->c_lflag; + } + } + } + spin_unlock_irqrestore(&brd_lock, flags); + + stli_comstats.txtotal = stli_cdkstats.txchars; + stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover; + stli_comstats.txbuffered = stli_cdkstats.txringq; + stli_comstats.rxbuffered += stli_cdkstats.rxringq; + stli_comstats.rxoverrun = stli_cdkstats.overruns; + stli_comstats.rxparity = stli_cdkstats.parity; + stli_comstats.rxframing = stli_cdkstats.framing; + stli_comstats.rxlost = stli_cdkstats.ringover; + stli_comstats.rxbreaks = stli_cdkstats.rxbreaks; + stli_comstats.txbreaks = stli_cdkstats.txbreaks; + stli_comstats.txxon = stli_cdkstats.txstart; + stli_comstats.txxoff = stli_cdkstats.txstop; + stli_comstats.rxxon = stli_cdkstats.rxstart; + stli_comstats.rxxoff = stli_cdkstats.rxstop; + stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2; + stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff; + stli_comstats.modem = stli_cdkstats.dcdcnt; + stli_comstats.hwid = stli_cdkstats.hwid; + stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); + mutex_unlock(&portp->port.mutex); + + return 0; +} + +/*****************************************************************************/ + +/* + * Return the port stats structure to user app. A NULL port struct + * pointer passed in means that we need to find out from the app + * what port to get stats for (used through board control device). + */ + +static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, + comstats_t __user *cp) +{ + struct stlibrd *brdp; + int rc; + + if (!portp) { + if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t))) + return -EFAULT; + portp = stli_getport(stli_comstats.brd, stli_comstats.panel, + stli_comstats.port); + if (!portp) + return -ENODEV; + } + + brdp = stli_brds[portp->brdnr]; + if (!brdp) + return -ENODEV; + + if ((rc = stli_portcmdstats(tty, portp)) < 0) + return rc; + + return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ? + -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Clear the port stats structure. We also return it zeroed out... + */ + +static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) +{ + struct stlibrd *brdp; + int rc; + + if (!portp) { + if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t))) + return -EFAULT; + portp = stli_getport(stli_comstats.brd, stli_comstats.panel, + stli_comstats.port); + if (!portp) + return -ENODEV; + } + + brdp = stli_brds[portp->brdnr]; + if (!brdp) + return -ENODEV; + + mutex_lock(&portp->port.mutex); + + if (test_bit(BST_STARTED, &brdp->state)) { + if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) { + mutex_unlock(&portp->port.mutex); + return rc; + } + } + + memset(&stli_comstats, 0, sizeof(comstats_t)); + stli_comstats.brd = portp->brdnr; + stli_comstats.panel = portp->panelnr; + stli_comstats.port = portp->portnr; + mutex_unlock(&portp->port.mutex); + + if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) + return -EFAULT; + return 0; +} + +/*****************************************************************************/ + +/* + * Return the entire driver ports structure to a user app. + */ + +static int stli_getportstruct(struct stliport __user *arg) +{ + struct stliport stli_dummyport; + struct stliport *portp; + + if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport))) + return -EFAULT; + portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr, + stli_dummyport.portnr); + if (!portp) + return -ENODEV; + if (copy_to_user(arg, portp, sizeof(struct stliport))) + return -EFAULT; + return 0; +} + +/*****************************************************************************/ + +/* + * Return the entire driver board structure to a user app. + */ + +static int stli_getbrdstruct(struct stlibrd __user *arg) +{ + struct stlibrd stli_dummybrd; + struct stlibrd *brdp; + + if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd))) + return -EFAULT; + if (stli_dummybrd.brdnr >= STL_MAXBRDS) + return -ENODEV; + brdp = stli_brds[stli_dummybrd.brdnr]; + if (!brdp) + return -ENODEV; + if (copy_to_user(arg, brdp, sizeof(struct stlibrd))) + return -EFAULT; + return 0; +} + +/*****************************************************************************/ + +/* + * The "staliomem" device is also required to do some special operations on + * the board. We need to be able to send an interrupt to the board, + * reset it, and start/stop it. + */ + +static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + struct stlibrd *brdp; + int brdnr, rc, done; + void __user *argp = (void __user *)arg; + +/* + * First up handle the board independent ioctls. + */ + done = 0; + rc = 0; + + switch (cmd) { + case COM_GETPORTSTATS: + rc = stli_getportstats(NULL, NULL, argp); + done++; + break; + case COM_CLRPORTSTATS: + rc = stli_clrportstats(NULL, argp); + done++; + break; + case COM_GETBRDSTATS: + rc = stli_getbrdstats(argp); + done++; + break; + case COM_READPORT: + rc = stli_getportstruct(argp); + done++; + break; + case COM_READBOARD: + rc = stli_getbrdstruct(argp); + done++; + break; + } + if (done) + return rc; + +/* + * Now handle the board specific ioctls. These all depend on the + * minor number of the device they were called from. + */ + brdnr = iminor(fp->f_dentry->d_inode); + if (brdnr >= STL_MAXBRDS) + return -ENODEV; + brdp = stli_brds[brdnr]; + if (!brdp) + return -ENODEV; + if (brdp->state == 0) + return -ENODEV; + + switch (cmd) { + case STL_BINTR: + EBRDINTR(brdp); + break; + case STL_BSTART: + rc = stli_startbrd(brdp); + break; + case STL_BSTOP: + clear_bit(BST_STARTED, &brdp->state); + break; + case STL_BRESET: + clear_bit(BST_STARTED, &brdp->state); + EBRDRESET(brdp); + if (stli_shared == 0) { + if (brdp->reenable != NULL) + (* brdp->reenable)(brdp); + } + break; + default: + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + +static const struct tty_operations stli_ops = { + .open = stli_open, + .close = stli_close, + .write = stli_write, + .put_char = stli_putchar, + .flush_chars = stli_flushchars, + .write_room = stli_writeroom, + .chars_in_buffer = stli_charsinbuffer, + .ioctl = stli_ioctl, + .set_termios = stli_settermios, + .throttle = stli_throttle, + .unthrottle = stli_unthrottle, + .stop = stli_stop, + .start = stli_start, + .hangup = stli_hangup, + .flush_buffer = stli_flushbuffer, + .break_ctl = stli_breakctl, + .wait_until_sent = stli_waituntilsent, + .send_xchar = stli_sendxchar, + .tiocmget = stli_tiocmget, + .tiocmset = stli_tiocmset, + .proc_fops = &stli_proc_fops, +}; + +static const struct tty_port_operations stli_port_ops = { + .carrier_raised = stli_carrier_raised, + .dtr_rts = stli_dtr_rts, + .activate = stli_activate, + .shutdown = stli_shutdown, +}; + +/*****************************************************************************/ +/* + * Loadable module initialization stuff. + */ + +static void istallion_cleanup_isa(void) +{ + struct stlibrd *brdp; + unsigned int j; + + for (j = 0; (j < stli_nrbrds); j++) { + if ((brdp = stli_brds[j]) == NULL || + test_bit(BST_PROBED, &brdp->state)) + continue; + + stli_cleanup_ports(brdp); + + iounmap(brdp->membase); + if (brdp->iosize > 0) + release_region(brdp->iobase, brdp->iosize); + kfree(brdp); + stli_brds[j] = NULL; + } +} + +static int __init istallion_module_init(void) +{ + unsigned int i; + int retval; + + printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); + + spin_lock_init(&stli_lock); + spin_lock_init(&brd_lock); + + stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); + if (!stli_txcookbuf) { + printk(KERN_ERR "istallion: failed to allocate memory " + "(size=%d)\n", STLI_TXBUFSIZE); + retval = -ENOMEM; + goto err; + } + + stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); + if (!stli_serial) { + retval = -ENOMEM; + goto err_free; + } + + stli_serial->owner = THIS_MODULE; + stli_serial->driver_name = stli_drvname; + stli_serial->name = stli_serialname; + stli_serial->major = STL_SERIALMAJOR; + stli_serial->minor_start = 0; + stli_serial->type = TTY_DRIVER_TYPE_SERIAL; + stli_serial->subtype = SERIAL_TYPE_NORMAL; + stli_serial->init_termios = stli_deftermios; + stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(stli_serial, &stli_ops); + + retval = tty_register_driver(stli_serial); + if (retval) { + printk(KERN_ERR "istallion: failed to register serial driver\n"); + goto err_ttyput; + } + + retval = stli_initbrds(); + if (retval) + goto err_ttyunr; + +/* + * Set up a character driver for the shared memory region. We need this + * to down load the slave code image. Also it is a useful debugging tool. + */ + retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); + if (retval) { + printk(KERN_ERR "istallion: failed to register serial memory " + "device\n"); + goto err_deinit; + } + + istallion_class = class_create(THIS_MODULE, "staliomem"); + for (i = 0; i < 4; i++) + device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); + + return 0; +err_deinit: + pci_unregister_driver(&stli_pcidriver); + istallion_cleanup_isa(); +err_ttyunr: + tty_unregister_driver(stli_serial); +err_ttyput: + put_tty_driver(stli_serial); +err_free: + kfree(stli_txcookbuf); +err: + return retval; +} + +/*****************************************************************************/ + +static void __exit istallion_module_exit(void) +{ + unsigned int j; + + printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, + stli_drvversion); + + if (stli_timeron) { + stli_timeron = 0; + del_timer_sync(&stli_timerlist); + } + + unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); + + for (j = 0; j < 4; j++) + device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j)); + class_destroy(istallion_class); + + pci_unregister_driver(&stli_pcidriver); + istallion_cleanup_isa(); + + tty_unregister_driver(stli_serial); + put_tty_driver(stli_serial); + + kfree(stli_txcookbuf); +} + +module_init(istallion_module_init); +module_exit(istallion_module_exit); diff --git a/drivers/staging/tty/riscom8.c b/drivers/staging/tty/riscom8.c new file mode 100644 index 000000000000..602643a40b4b --- /dev/null +++ b/drivers/staging/tty/riscom8.c @@ -0,0 +1,1560 @@ +/* + * linux/drivers/char/riscom.c -- RISCom/8 multiport serial driver. + * + * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) + * + * This code is loosely based on the Linux serial driver, written by + * Linus Torvalds, Theodore T'so and others. The RISCom/8 card + * programming info was obtained from various drivers for other OSes + * (FreeBSD, ISC, etc), but no source code from those drivers were + * directly included in this driver. + * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Revision 1.1 + * + * ChangeLog: + * Arnaldo Carvalho de Melo - 27-Jun-2001 + * - get rid of check_region and several cleanups + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "riscom8.h" +#include "riscom8_reg.h" + +/* Am I paranoid or not ? ;-) */ +#define RISCOM_PARANOIA_CHECK + +/* + * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals. + * You can slightly speed up things by #undefing the following option, + * if you are REALLY sure that your board is correct one. + */ + +#define RISCOM_BRAIN_DAMAGED_CTS + +/* + * The following defines are mostly for testing purposes. But if you need + * some nice reporting in your syslog, you can define them also. + */ +#undef RC_REPORT_FIFO +#undef RC_REPORT_OVERRUN + + +#define RISCOM_LEGAL_FLAGS \ + (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ + ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ + ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) + +static struct tty_driver *riscom_driver; + +static DEFINE_SPINLOCK(riscom_lock); + +static struct riscom_board rc_board[RC_NBOARD] = { + { + .base = RC_IOBASE1, + }, + { + .base = RC_IOBASE2, + }, + { + .base = RC_IOBASE3, + }, + { + .base = RC_IOBASE4, + }, +}; + +static struct riscom_port rc_port[RC_NBOARD * RC_NPORT]; + +/* RISCom/8 I/O ports addresses (without address translation) */ +static unsigned short rc_ioport[] = { +#if 1 + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, +#else + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10, + 0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62, + 0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101 +#endif +}; +#define RC_NIOPORT ARRAY_SIZE(rc_ioport) + + +static int rc_paranoia_check(struct riscom_port const *port, + char *name, const char *routine) +{ +#ifdef RISCOM_PARANOIA_CHECK + static const char badmagic[] = KERN_INFO + "rc: Warning: bad riscom port magic number for device %s in %s\n"; + static const char badinfo[] = KERN_INFO + "rc: Warning: null riscom port for device %s in %s\n"; + + if (!port) { + printk(badinfo, name, routine); + return 1; + } + if (port->magic != RISCOM8_MAGIC) { + printk(badmagic, name, routine); + return 1; + } +#endif + return 0; +} + +/* + * + * Service functions for RISCom/8 driver. + * + */ + +/* Get board number from pointer */ +static inline int board_No(struct riscom_board const *bp) +{ + return bp - rc_board; +} + +/* Get port number from pointer */ +static inline int port_No(struct riscom_port const *port) +{ + return RC_PORT(port - rc_port); +} + +/* Get pointer to board from pointer to port */ +static inline struct riscom_board *port_Board(struct riscom_port const *port) +{ + return &rc_board[RC_BOARD(port - rc_port)]; +} + +/* Input Byte from CL CD180 register */ +static inline unsigned char rc_in(struct riscom_board const *bp, + unsigned short reg) +{ + return inb(bp->base + RC_TO_ISA(reg)); +} + +/* Output Byte to CL CD180 register */ +static inline void rc_out(struct riscom_board const *bp, unsigned short reg, + unsigned char val) +{ + outb(val, bp->base + RC_TO_ISA(reg)); +} + +/* Wait for Channel Command Register ready */ +static void rc_wait_CCR(struct riscom_board const *bp) +{ + unsigned long delay; + + /* FIXME: need something more descriptive then 100000 :) */ + for (delay = 100000; delay; delay--) + if (!rc_in(bp, CD180_CCR)) + return; + + printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp)); +} + +/* + * RISCom/8 probe functions. + */ + +static int rc_request_io_range(struct riscom_board * const bp) +{ + int i; + + for (i = 0; i < RC_NIOPORT; i++) + if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1, + "RISCom/8")) { + goto out_release; + } + return 0; +out_release: + printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n", + board_No(bp), bp->base); + while (--i >= 0) + release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1); + return 1; +} + +static void rc_release_io_range(struct riscom_board * const bp) +{ + int i; + + for (i = 0; i < RC_NIOPORT; i++) + release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1); +} + +/* Reset and setup CD180 chip */ +static void __init rc_init_CD180(struct riscom_board const *bp) +{ + unsigned long flags; + + spin_lock_irqsave(&riscom_lock, flags); + + rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ + rc_wait_CCR(bp); /* Wait for CCR ready */ + rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ + spin_unlock_irqrestore(&riscom_lock, flags); + msleep(50); /* Delay 0.05 sec */ + spin_lock_irqsave(&riscom_lock, flags); + rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ + rc_out(bp, CD180_GICR, 0); /* Clear all bits */ + rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ + rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for tx intr */ + rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for rx intr */ + + /* Setting up prescaler. We need 4 ticks per 1 ms */ + rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); + rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); + + spin_unlock_irqrestore(&riscom_lock, flags); +} + +/* Main probing routine, also sets irq. */ +static int __init rc_probe(struct riscom_board *bp) +{ + unsigned char val1, val2; + int irqs = 0; + int retries; + + bp->irq = 0; + + if (rc_request_io_range(bp)) + return 1; + + /* Are the I/O ports here ? */ + rc_out(bp, CD180_PPRL, 0x5a); + outb(0xff, 0x80); + val1 = rc_in(bp, CD180_PPRL); + rc_out(bp, CD180_PPRL, 0xa5); + outb(0x00, 0x80); + val2 = rc_in(bp, CD180_PPRL); + + if ((val1 != 0x5a) || (val2 != 0xa5)) { + printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n", + board_No(bp), bp->base); + goto out_release; + } + + /* It's time to find IRQ for this board */ + for (retries = 0; retries < 5 && irqs <= 0; retries++) { + irqs = probe_irq_on(); + rc_init_CD180(bp); /* Reset CD180 chip */ + rc_out(bp, CD180_CAR, 2); /* Select port 2 */ + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */ + rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr */ + msleep(50); + irqs = probe_irq_off(irqs); + val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */ + val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */ + rc_init_CD180(bp); /* Reset CD180 again */ + + if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX))) { + printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not " + "found.\n", board_No(bp), bp->base); + goto out_release; + } + } + + if (irqs <= 0) { + printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board " + "at 0x%03x.\n", board_No(bp), bp->base); + goto out_release; + } + bp->irq = irqs; + bp->flags |= RC_BOARD_PRESENT; + + printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at " + "0x%03x, IRQ %d.\n", + board_No(bp), + (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A', /* Board revision */ + bp->base, bp->irq); + + return 0; +out_release: + rc_release_io_range(bp); + return 1; +} + +/* + * + * Interrupt processing routines. + * + */ + +static struct riscom_port *rc_get_port(struct riscom_board const *bp, + unsigned char const *what) +{ + unsigned char channel; + struct riscom_port *port; + + channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF; + if (channel < CD180_NCH) { + port = &rc_port[board_No(bp) * RC_NPORT + channel]; + if (port->port.flags & ASYNC_INITIALIZED) + return port; + } + printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n", + board_No(bp), what, channel); + return NULL; +} + +static void rc_receive_exc(struct riscom_board const *bp) +{ + struct riscom_port *port; + struct tty_struct *tty; + unsigned char status; + unsigned char ch, flag; + + port = rc_get_port(bp, "Receive"); + if (port == NULL) + return; + + tty = tty_port_tty_get(&port->port); + +#ifdef RC_REPORT_OVERRUN + status = rc_in(bp, CD180_RCSR); + if (status & RCSR_OE) + port->overrun++; + status &= port->mark_mask; +#else + status = rc_in(bp, CD180_RCSR) & port->mark_mask; +#endif + ch = rc_in(bp, CD180_RDR); + if (!status) + goto out; + if (status & RCSR_TOUT) { + printk(KERN_WARNING "rc%d: port %d: Receiver timeout. " + "Hardware problems ?\n", + board_No(bp), port_No(port)); + goto out; + + } else if (status & RCSR_BREAK) { + printk(KERN_INFO "rc%d: port %d: Handling break...\n", + board_No(bp), port_No(port)); + flag = TTY_BREAK; + if (tty && (port->port.flags & ASYNC_SAK)) + do_SAK(tty); + + } else if (status & RCSR_PE) + flag = TTY_PARITY; + + else if (status & RCSR_FE) + flag = TTY_FRAME; + + else if (status & RCSR_OE) + flag = TTY_OVERRUN; + else + flag = TTY_NORMAL; + + if (tty) { + tty_insert_flip_char(tty, ch, flag); + tty_flip_buffer_push(tty); + } +out: + tty_kref_put(tty); +} + +static void rc_receive(struct riscom_board const *bp) +{ + struct riscom_port *port; + struct tty_struct *tty; + unsigned char count; + + port = rc_get_port(bp, "Receive"); + if (port == NULL) + return; + + tty = tty_port_tty_get(&port->port); + + count = rc_in(bp, CD180_RDCR); + +#ifdef RC_REPORT_FIFO + port->hits[count > 8 ? 9 : count]++; +#endif + + while (count--) { + u8 ch = rc_in(bp, CD180_RDR); + if (tty) + tty_insert_flip_char(tty, ch, TTY_NORMAL); + } + if (tty) { + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } +} + +static void rc_transmit(struct riscom_board const *bp) +{ + struct riscom_port *port; + struct tty_struct *tty; + unsigned char count; + + port = rc_get_port(bp, "Transmit"); + if (port == NULL) + return; + + tty = tty_port_tty_get(&port->port); + + if (port->IER & IER_TXEMPTY) { + /* FIFO drained */ + rc_out(bp, CD180_CAR, port_No(port)); + port->IER &= ~IER_TXEMPTY; + rc_out(bp, CD180_IER, port->IER); + goto out; + } + + if ((port->xmit_cnt <= 0 && !port->break_length) + || (tty && (tty->stopped || tty->hw_stopped))) { + rc_out(bp, CD180_CAR, port_No(port)); + port->IER &= ~IER_TXRDY; + rc_out(bp, CD180_IER, port->IER); + goto out; + } + + if (port->break_length) { + if (port->break_length > 0) { + if (port->COR2 & COR2_ETC) { + rc_out(bp, CD180_TDR, CD180_C_ESC); + rc_out(bp, CD180_TDR, CD180_C_SBRK); + port->COR2 &= ~COR2_ETC; + } + count = min_t(int, port->break_length, 0xff); + rc_out(bp, CD180_TDR, CD180_C_ESC); + rc_out(bp, CD180_TDR, CD180_C_DELAY); + rc_out(bp, CD180_TDR, count); + port->break_length -= count; + if (port->break_length == 0) + port->break_length--; + } else { + rc_out(bp, CD180_TDR, CD180_C_ESC); + rc_out(bp, CD180_TDR, CD180_C_EBRK); + rc_out(bp, CD180_COR2, port->COR2); + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_CORCHG2); + port->break_length = 0; + } + goto out; + } + + count = CD180_NFIFO; + do { + rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]); + port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); + if (--port->xmit_cnt <= 0) + break; + } while (--count > 0); + + if (port->xmit_cnt <= 0) { + rc_out(bp, CD180_CAR, port_No(port)); + port->IER &= ~IER_TXRDY; + rc_out(bp, CD180_IER, port->IER); + } + if (tty && port->xmit_cnt <= port->wakeup_chars) + tty_wakeup(tty); +out: + tty_kref_put(tty); +} + +static void rc_check_modem(struct riscom_board const *bp) +{ + struct riscom_port *port; + struct tty_struct *tty; + unsigned char mcr; + + port = rc_get_port(bp, "Modem"); + if (port == NULL) + return; + + tty = tty_port_tty_get(&port->port); + + mcr = rc_in(bp, CD180_MCR); + if (mcr & MCR_CDCHG) { + if (rc_in(bp, CD180_MSVR) & MSVR_CD) + wake_up_interruptible(&port->port.open_wait); + else if (tty) + tty_hangup(tty); + } + +#ifdef RISCOM_BRAIN_DAMAGED_CTS + if (mcr & MCR_CTSCHG) { + if (rc_in(bp, CD180_MSVR) & MSVR_CTS) { + port->IER |= IER_TXRDY; + if (tty) { + tty->hw_stopped = 0; + if (port->xmit_cnt <= port->wakeup_chars) + tty_wakeup(tty); + } + } else { + if (tty) + tty->hw_stopped = 1; + port->IER &= ~IER_TXRDY; + } + rc_out(bp, CD180_IER, port->IER); + } + if (mcr & MCR_DSRCHG) { + if (rc_in(bp, CD180_MSVR) & MSVR_DSR) { + port->IER |= IER_TXRDY; + if (tty) { + tty->hw_stopped = 0; + if (port->xmit_cnt <= port->wakeup_chars) + tty_wakeup(tty); + } + } else { + if (tty) + tty->hw_stopped = 1; + port->IER &= ~IER_TXRDY; + } + rc_out(bp, CD180_IER, port->IER); + } +#endif /* RISCOM_BRAIN_DAMAGED_CTS */ + + /* Clear change bits */ + rc_out(bp, CD180_MCR, 0); + tty_kref_put(tty); +} + +/* The main interrupt processing routine */ +static irqreturn_t rc_interrupt(int dummy, void *dev_id) +{ + unsigned char status; + unsigned char ack; + struct riscom_board *bp = dev_id; + unsigned long loop = 0; + int handled = 0; + + if (!(bp->flags & RC_BOARD_ACTIVE)) + return IRQ_NONE; + + while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) & + (RC_BSR_TOUT | RC_BSR_TINT | + RC_BSR_MINT | RC_BSR_RINT))) { + handled = 1; + if (status & RC_BSR_TOUT) + printk(KERN_WARNING "rc%d: Got timeout. Hardware " + "error?\n", board_No(bp)); + else if (status & RC_BSR_RINT) { + ack = rc_in(bp, RC_ACK_RINT); + if (ack == (RC_ID | GIVR_IT_RCV)) + rc_receive(bp); + else if (ack == (RC_ID | GIVR_IT_REXC)) + rc_receive_exc(bp); + else + printk(KERN_WARNING "rc%d: Bad receive ack " + "0x%02x.\n", + board_No(bp), ack); + } else if (status & RC_BSR_TINT) { + ack = rc_in(bp, RC_ACK_TINT); + if (ack == (RC_ID | GIVR_IT_TX)) + rc_transmit(bp); + else + printk(KERN_WARNING "rc%d: Bad transmit ack " + "0x%02x.\n", + board_No(bp), ack); + } else /* if (status & RC_BSR_MINT) */ { + ack = rc_in(bp, RC_ACK_MINT); + if (ack == (RC_ID | GIVR_IT_MODEM)) + rc_check_modem(bp); + else + printk(KERN_WARNING "rc%d: Bad modem ack " + "0x%02x.\n", + board_No(bp), ack); + } + rc_out(bp, CD180_EOIR, 0); /* Mark end of interrupt */ + rc_out(bp, RC_CTOUT, 0); /* Clear timeout flag */ + } + return IRQ_RETVAL(handled); +} + +/* + * Routines for open & close processing. + */ + +/* Called with disabled interrupts */ +static int rc_setup_board(struct riscom_board *bp) +{ + int error; + + if (bp->flags & RC_BOARD_ACTIVE) + return 0; + + error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED, + "RISCom/8", bp); + if (error) + return error; + + rc_out(bp, RC_CTOUT, 0); /* Just in case */ + bp->DTR = ~0; + rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ + + bp->flags |= RC_BOARD_ACTIVE; + + return 0; +} + +/* Called with disabled interrupts */ +static void rc_shutdown_board(struct riscom_board *bp) +{ + if (!(bp->flags & RC_BOARD_ACTIVE)) + return; + + bp->flags &= ~RC_BOARD_ACTIVE; + + free_irq(bp->irq, NULL); + + bp->DTR = ~0; + rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ + +} + +/* + * Setting up port characteristics. + * Must be called with disabled interrupts + */ +static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp, + struct riscom_port *port) +{ + unsigned long baud; + long tmp; + unsigned char cor1 = 0, cor3 = 0; + unsigned char mcor1 = 0, mcor2 = 0; + + port->IER = 0; + port->COR2 = 0; + port->MSVR = MSVR_RTS; + + baud = tty_get_baud_rate(tty); + + /* Select port on the board */ + rc_out(bp, CD180_CAR, port_No(port)); + + if (!baud) { + /* Drop DTR & exit */ + bp->DTR |= (1u << port_No(port)); + rc_out(bp, RC_DTR, bp->DTR); + return; + } else { + /* Set DTR on */ + bp->DTR &= ~(1u << port_No(port)); + rc_out(bp, RC_DTR, bp->DTR); + } + + /* + * Now we must calculate some speed depended things + */ + + /* Set baud rate for port */ + tmp = (((RC_OSCFREQ + baud/2) / baud + + CD180_TPC/2) / CD180_TPC); + + rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); + rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff); + rc_out(bp, CD180_RBPRL, tmp & 0xff); + rc_out(bp, CD180_TBPRL, tmp & 0xff); + + baud = (baud + 5) / 10; /* Estimated CPS */ + + /* Two timer ticks seems enough to wakeup something like SLIP driver */ + tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO; + port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? + SERIAL_XMIT_SIZE - 1 : tmp); + + /* Receiver timeout will be transmission time for 1.5 chars */ + tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud; + tmp = (tmp > 0xff) ? 0xff : tmp; + rc_out(bp, CD180_RTPR, tmp); + + switch (C_CSIZE(tty)) { + case CS5: + cor1 |= COR1_5BITS; + break; + case CS6: + cor1 |= COR1_6BITS; + break; + case CS7: + cor1 |= COR1_7BITS; + break; + case CS8: + cor1 |= COR1_8BITS; + break; + } + if (C_CSTOPB(tty)) + cor1 |= COR1_2SB; + + cor1 |= COR1_IGNORE; + if (C_PARENB(tty)) { + cor1 |= COR1_NORMPAR; + if (C_PARODD(tty)) + cor1 |= COR1_ODDP; + if (I_INPCK(tty)) + cor1 &= ~COR1_IGNORE; + } + /* Set marking of some errors */ + port->mark_mask = RCSR_OE | RCSR_TOUT; + if (I_INPCK(tty)) + port->mark_mask |= RCSR_FE | RCSR_PE; + if (I_BRKINT(tty) || I_PARMRK(tty)) + port->mark_mask |= RCSR_BREAK; + if (I_IGNPAR(tty)) + port->mark_mask &= ~(RCSR_FE | RCSR_PE); + if (I_IGNBRK(tty)) { + port->mark_mask &= ~RCSR_BREAK; + if (I_IGNPAR(tty)) + /* Real raw mode. Ignore all */ + port->mark_mask &= ~RCSR_OE; + } + /* Enable Hardware Flow Control */ + if (C_CRTSCTS(tty)) { +#ifdef RISCOM_BRAIN_DAMAGED_CTS + port->IER |= IER_DSR | IER_CTS; + mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; + mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; + tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & + (MSVR_CTS|MSVR_DSR)); +#else + port->COR2 |= COR2_CTSAE; +#endif + } + /* Enable Software Flow Control. FIXME: I'm not sure about this */ + /* Some people reported that it works, but I still doubt */ + if (I_IXON(tty)) { + port->COR2 |= COR2_TXIBE; + cor3 |= (COR3_FCT | COR3_SCDE); + if (I_IXANY(tty)) + port->COR2 |= COR2_IXM; + rc_out(bp, CD180_SCHR1, START_CHAR(tty)); + rc_out(bp, CD180_SCHR2, STOP_CHAR(tty)); + rc_out(bp, CD180_SCHR3, START_CHAR(tty)); + rc_out(bp, CD180_SCHR4, STOP_CHAR(tty)); + } + if (!C_CLOCAL(tty)) { + /* Enable CD check */ + port->IER |= IER_CD; + mcor1 |= MCOR1_CDZD; + mcor2 |= MCOR2_CDOD; + } + + if (C_CREAD(tty)) + /* Enable receiver */ + port->IER |= IER_RXD; + + /* Set input FIFO size (1-8 bytes) */ + cor3 |= RISCOM_RXFIFO; + /* Setting up CD180 channel registers */ + rc_out(bp, CD180_COR1, cor1); + rc_out(bp, CD180_COR2, port->COR2); + rc_out(bp, CD180_COR3, cor3); + /* Make CD180 know about registers change */ + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); + /* Setting up modem option registers */ + rc_out(bp, CD180_MCOR1, mcor1); + rc_out(bp, CD180_MCOR2, mcor2); + /* Enable CD180 transmitter & receiver */ + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN); + /* Enable interrupts */ + rc_out(bp, CD180_IER, port->IER); + /* And finally set RTS on */ + rc_out(bp, CD180_MSVR, port->MSVR); +} + +/* Must be called with interrupts enabled */ +static int rc_activate_port(struct tty_port *port, struct tty_struct *tty) +{ + struct riscom_port *rp = container_of(port, struct riscom_port, port); + struct riscom_board *bp = port_Board(rp); + unsigned long flags; + + if (tty_port_alloc_xmit_buf(port) < 0) + return -ENOMEM; + + spin_lock_irqsave(&riscom_lock, flags); + + clear_bit(TTY_IO_ERROR, &tty->flags); + bp->count++; + rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0; + rc_change_speed(tty, bp, rp); + spin_unlock_irqrestore(&riscom_lock, flags); + return 0; +} + +/* Must be called with interrupts disabled */ +static void rc_shutdown_port(struct tty_struct *tty, + struct riscom_board *bp, struct riscom_port *port) +{ +#ifdef RC_REPORT_OVERRUN + printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", + board_No(bp), port_No(port), port->overrun); +#endif +#ifdef RC_REPORT_FIFO + { + int i; + + printk(KERN_INFO "rc%d: port %d: FIFO hits [ ", + board_No(bp), port_No(port)); + for (i = 0; i < 10; i++) + printk("%ld ", port->hits[i]); + printk("].\n"); + } +#endif + tty_port_free_xmit_buf(&port->port); + + /* Select port */ + rc_out(bp, CD180_CAR, port_No(port)); + /* Reset port */ + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_SOFTRESET); + /* Disable all interrupts from this port */ + port->IER = 0; + rc_out(bp, CD180_IER, port->IER); + + set_bit(TTY_IO_ERROR, &tty->flags); + + if (--bp->count < 0) { + printk(KERN_INFO "rc%d: rc_shutdown_port: " + "bad board count: %d\n", + board_No(bp), bp->count); + bp->count = 0; + } + /* + * If this is the last opened port on the board + * shutdown whole board + */ + if (!bp->count) + rc_shutdown_board(bp); +} + +static int carrier_raised(struct tty_port *port) +{ + struct riscom_port *p = container_of(port, struct riscom_port, port); + struct riscom_board *bp = port_Board(p); + unsigned long flags; + int CD; + + spin_lock_irqsave(&riscom_lock, flags); + rc_out(bp, CD180_CAR, port_No(p)); + CD = rc_in(bp, CD180_MSVR) & MSVR_CD; + rc_out(bp, CD180_MSVR, MSVR_RTS); + bp->DTR &= ~(1u << port_No(p)); + rc_out(bp, RC_DTR, bp->DTR); + spin_unlock_irqrestore(&riscom_lock, flags); + return CD; +} + +static void dtr_rts(struct tty_port *port, int onoff) +{ + struct riscom_port *p = container_of(port, struct riscom_port, port); + struct riscom_board *bp = port_Board(p); + unsigned long flags; + + spin_lock_irqsave(&riscom_lock, flags); + bp->DTR &= ~(1u << port_No(p)); + if (onoff == 0) + bp->DTR |= (1u << port_No(p)); + rc_out(bp, RC_DTR, bp->DTR); + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static int rc_open(struct tty_struct *tty, struct file *filp) +{ + int board; + int error; + struct riscom_port *port; + struct riscom_board *bp; + + board = RC_BOARD(tty->index); + if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT)) + return -ENODEV; + + bp = &rc_board[board]; + port = rc_port + board * RC_NPORT + RC_PORT(tty->index); + if (rc_paranoia_check(port, tty->name, "rc_open")) + return -ENODEV; + + error = rc_setup_board(bp); + if (error) + return error; + + tty->driver_data = port; + return tty_port_open(&port->port, tty, filp); +} + +static void rc_flush_buffer(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) + return; + + spin_lock_irqsave(&riscom_lock, flags); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + spin_unlock_irqrestore(&riscom_lock, flags); + + tty_wakeup(tty); +} + +static void rc_close_port(struct tty_port *port) +{ + unsigned long flags; + struct riscom_port *rp = container_of(port, struct riscom_port, port); + struct riscom_board *bp = port_Board(rp); + unsigned long timeout; + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + + spin_lock_irqsave(&riscom_lock, flags); + rp->IER &= ~IER_RXD; + + rp->IER &= ~IER_TXRDY; + rp->IER |= IER_TXEMPTY; + rc_out(bp, CD180_CAR, port_No(rp)); + rc_out(bp, CD180_IER, rp->IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + timeout = jiffies + HZ; + while (rp->IER & IER_TXEMPTY) { + spin_unlock_irqrestore(&riscom_lock, flags); + msleep_interruptible(jiffies_to_msecs(rp->timeout)); + spin_lock_irqsave(&riscom_lock, flags); + if (time_after(jiffies, timeout)) + break; + } + rc_shutdown_port(port->tty, bp, rp); + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static void rc_close(struct tty_struct *tty, struct file *filp) +{ + struct riscom_port *port = tty->driver_data; + + if (!port || rc_paranoia_check(port, tty->name, "close")) + return; + tty_port_close(&port->port, tty, filp); +} + +static int rc_write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp; + int c, total = 0; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_write")) + return 0; + + bp = port_Board(port); + + while (1) { + spin_lock_irqsave(&riscom_lock, flags); + + c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) + break; /* lock continues to be held */ + + memcpy(port->port.xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + + spin_unlock_irqrestore(&riscom_lock, flags); + + buf += c; + count -= c; + total += c; + } + + if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && + !(port->IER & IER_TXRDY)) { + port->IER |= IER_TXRDY; + rc_out(bp, CD180_CAR, port_No(port)); + rc_out(bp, CD180_IER, port->IER); + } + + spin_unlock_irqrestore(&riscom_lock, flags); + + return total; +} + +static int rc_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct riscom_port *port = tty->driver_data; + unsigned long flags; + int ret = 0; + + if (rc_paranoia_check(port, tty->name, "rc_put_char")) + return 0; + + spin_lock_irqsave(&riscom_lock, flags); + + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) + goto out; + + port->port.xmit_buf[port->xmit_head++] = ch; + port->xmit_head &= SERIAL_XMIT_SIZE - 1; + port->xmit_cnt++; + ret = 1; + +out: + spin_unlock_irqrestore(&riscom_lock, flags); + return ret; +} + +static void rc_flush_chars(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_flush_chars")) + return; + + if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped) + return; + + spin_lock_irqsave(&riscom_lock, flags); + + port->IER |= IER_TXRDY; + rc_out(port_Board(port), CD180_CAR, port_No(port)); + rc_out(port_Board(port), CD180_IER, port->IER); + + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static int rc_write_room(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + int ret; + + if (rc_paranoia_check(port, tty->name, "rc_write_room")) + return 0; + + ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rc_chars_in_buffer(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + + if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer")) + return 0; + + return port->xmit_cnt; +} + +static int rc_tiocmget(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp; + unsigned char status; + unsigned int result; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, __func__)) + return -ENODEV; + + bp = port_Board(port); + + spin_lock_irqsave(&riscom_lock, flags); + + rc_out(bp, CD180_CAR, port_No(port)); + status = rc_in(bp, CD180_MSVR); + result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; + + spin_unlock_irqrestore(&riscom_lock, flags); + + result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) + | ((status & MSVR_DTR) ? TIOCM_DTR : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_DSR) ? TIOCM_DSR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + return result; +} + +static int rc_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct riscom_port *port = tty->driver_data; + unsigned long flags; + struct riscom_board *bp; + + if (rc_paranoia_check(port, tty->name, __func__)) + return -ENODEV; + + bp = port_Board(port); + + spin_lock_irqsave(&riscom_lock, flags); + + if (set & TIOCM_RTS) + port->MSVR |= MSVR_RTS; + if (set & TIOCM_DTR) + bp->DTR &= ~(1u << port_No(port)); + + if (clear & TIOCM_RTS) + port->MSVR &= ~MSVR_RTS; + if (clear & TIOCM_DTR) + bp->DTR |= (1u << port_No(port)); + + rc_out(bp, CD180_CAR, port_No(port)); + rc_out(bp, CD180_MSVR, port->MSVR); + rc_out(bp, RC_DTR, bp->DTR); + + spin_unlock_irqrestore(&riscom_lock, flags); + + return 0; +} + +static int rc_send_break(struct tty_struct *tty, int length) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp = port_Board(port); + unsigned long flags; + + if (length == 0 || length == -1) + return -EOPNOTSUPP; + + spin_lock_irqsave(&riscom_lock, flags); + + port->break_length = RISCOM_TPS / HZ * length; + port->COR2 |= COR2_ETC; + port->IER |= IER_TXRDY; + rc_out(bp, CD180_CAR, port_No(port)); + rc_out(bp, CD180_COR2, port->COR2); + rc_out(bp, CD180_IER, port->IER); + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_CORCHG2); + rc_wait_CCR(bp); + + spin_unlock_irqrestore(&riscom_lock, flags); + return 0; +} + +static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, + struct serial_struct __user *newinfo) +{ + struct serial_struct tmp; + struct riscom_board *bp = port_Board(port); + int change_speed; + + if (copy_from_user(&tmp, newinfo, sizeof(tmp))) + return -EFAULT; + + mutex_lock(&port->port.mutex); + change_speed = ((port->port.flags & ASYNC_SPD_MASK) != + (tmp.flags & ASYNC_SPD_MASK)); + + if (!capable(CAP_SYS_ADMIN)) { + if ((tmp.close_delay != port->port.close_delay) || + (tmp.closing_wait != port->port.closing_wait) || + ((tmp.flags & ~ASYNC_USR_MASK) != + (port->port.flags & ~ASYNC_USR_MASK))) { + mutex_unlock(&port->port.mutex); + return -EPERM; + } + port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | + (tmp.flags & ASYNC_USR_MASK)); + } else { + port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | + (tmp.flags & ASYNC_FLAGS)); + port->port.close_delay = tmp.close_delay; + port->port.closing_wait = tmp.closing_wait; + } + if (change_speed) { + unsigned long flags; + + spin_lock_irqsave(&riscom_lock, flags); + rc_change_speed(tty, bp, port); + spin_unlock_irqrestore(&riscom_lock, flags); + } + mutex_unlock(&port->port.mutex); + return 0; +} + +static int rc_get_serial_info(struct riscom_port *port, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + struct riscom_board *bp = port_Board(port); + + memset(&tmp, 0, sizeof(tmp)); + tmp.type = PORT_CIRRUS; + tmp.line = port - rc_port; + + mutex_lock(&port->port.mutex); + tmp.port = bp->base; + tmp.irq = bp->irq; + tmp.flags = port->port.flags; + tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; + tmp.close_delay = port->port.close_delay * HZ/100; + tmp.closing_wait = port->port.closing_wait * HZ/100; + mutex_unlock(&port->port.mutex); + tmp.xmit_fifo_size = CD180_NFIFO; + return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + +static int rc_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct riscom_port *port = tty->driver_data; + void __user *argp = (void __user *)arg; + int retval; + + if (rc_paranoia_check(port, tty->name, "rc_ioctl")) + return -ENODEV; + + switch (cmd) { + case TIOCGSERIAL: + retval = rc_get_serial_info(port, argp); + break; + case TIOCSSERIAL: + retval = rc_set_serial_info(tty, port, argp); + break; + default: + retval = -ENOIOCTLCMD; + } + return retval; +} + +static void rc_throttle(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_throttle")) + return; + bp = port_Board(port); + + spin_lock_irqsave(&riscom_lock, flags); + port->MSVR &= ~MSVR_RTS; + rc_out(bp, CD180_CAR, port_No(port)); + if (I_IXOFF(tty)) { + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_SSCH2); + rc_wait_CCR(bp); + } + rc_out(bp, CD180_MSVR, port->MSVR); + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static void rc_unthrottle(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_unthrottle")) + return; + bp = port_Board(port); + + spin_lock_irqsave(&riscom_lock, flags); + port->MSVR |= MSVR_RTS; + rc_out(bp, CD180_CAR, port_No(port)); + if (I_IXOFF(tty)) { + rc_wait_CCR(bp); + rc_out(bp, CD180_CCR, CCR_SSCH1); + rc_wait_CCR(bp); + } + rc_out(bp, CD180_MSVR, port->MSVR); + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static void rc_stop(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_stop")) + return; + + bp = port_Board(port); + + spin_lock_irqsave(&riscom_lock, flags); + port->IER &= ~IER_TXRDY; + rc_out(bp, CD180_CAR, port_No(port)); + rc_out(bp, CD180_IER, port->IER); + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static void rc_start(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + struct riscom_board *bp; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_start")) + return; + + bp = port_Board(port); + + spin_lock_irqsave(&riscom_lock, flags); + + if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) { + port->IER |= IER_TXRDY; + rc_out(bp, CD180_CAR, port_No(port)); + rc_out(bp, CD180_IER, port->IER); + } + spin_unlock_irqrestore(&riscom_lock, flags); +} + +static void rc_hangup(struct tty_struct *tty) +{ + struct riscom_port *port = tty->driver_data; + + if (rc_paranoia_check(port, tty->name, "rc_hangup")) + return; + + tty_port_hangup(&port->port); +} + +static void rc_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) +{ + struct riscom_port *port = tty->driver_data; + unsigned long flags; + + if (rc_paranoia_check(port, tty->name, "rc_set_termios")) + return; + + spin_lock_irqsave(&riscom_lock, flags); + rc_change_speed(tty, port_Board(port), port); + spin_unlock_irqrestore(&riscom_lock, flags); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rc_start(tty); + } +} + +static const struct tty_operations riscom_ops = { + .open = rc_open, + .close = rc_close, + .write = rc_write, + .put_char = rc_put_char, + .flush_chars = rc_flush_chars, + .write_room = rc_write_room, + .chars_in_buffer = rc_chars_in_buffer, + .flush_buffer = rc_flush_buffer, + .ioctl = rc_ioctl, + .throttle = rc_throttle, + .unthrottle = rc_unthrottle, + .set_termios = rc_set_termios, + .stop = rc_stop, + .start = rc_start, + .hangup = rc_hangup, + .tiocmget = rc_tiocmget, + .tiocmset = rc_tiocmset, + .break_ctl = rc_send_break, +}; + +static const struct tty_port_operations riscom_port_ops = { + .carrier_raised = carrier_raised, + .dtr_rts = dtr_rts, + .shutdown = rc_close_port, + .activate = rc_activate_port, +}; + + +static int __init rc_init_drivers(void) +{ + int error; + int i; + + riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT); + if (!riscom_driver) + return -ENOMEM; + + riscom_driver->owner = THIS_MODULE; + riscom_driver->name = "ttyL"; + riscom_driver->major = RISCOM8_NORMAL_MAJOR; + riscom_driver->type = TTY_DRIVER_TYPE_SERIAL; + riscom_driver->subtype = SERIAL_TYPE_NORMAL; + riscom_driver->init_termios = tty_std_termios; + riscom_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + riscom_driver->init_termios.c_ispeed = 9600; + riscom_driver->init_termios.c_ospeed = 9600; + riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; + tty_set_operations(riscom_driver, &riscom_ops); + error = tty_register_driver(riscom_driver); + if (error != 0) { + put_tty_driver(riscom_driver); + printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, " + "error = %d\n", error); + return 1; + } + memset(rc_port, 0, sizeof(rc_port)); + for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { + tty_port_init(&rc_port[i].port); + rc_port[i].port.ops = &riscom_port_ops; + rc_port[i].magic = RISCOM8_MAGIC; + } + return 0; +} + +static void rc_release_drivers(void) +{ + tty_unregister_driver(riscom_driver); + put_tty_driver(riscom_driver); +} + +#ifndef MODULE +/* + * Called at boot time. + * + * You can specify IO base for up to RC_NBOARD cards, + * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt. + * Note that there will be no probing at default + * addresses in this case. + * + */ +static int __init riscom8_setup(char *str) +{ + int ints[RC_NBOARD]; + int i; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + for (i = 0; i < RC_NBOARD; i++) { + if (i < ints[0]) + rc_board[i].base = ints[i+1]; + else + rc_board[i].base = 0; + } + return 1; +} + +__setup("riscom8=", riscom8_setup); +#endif + +static char banner[] __initdata = + KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin " + "1994-1996.\n"; +static char no_boards_msg[] __initdata = + KERN_INFO "rc: No RISCom/8 boards detected.\n"; + +/* + * This routine must be called by kernel at boot time + */ +static int __init riscom8_init(void) +{ + int i; + int found = 0; + + printk(banner); + + if (rc_init_drivers()) + return -EIO; + + for (i = 0; i < RC_NBOARD; i++) + if (rc_board[i].base && !rc_probe(&rc_board[i])) + found++; + if (!found) { + rc_release_drivers(); + printk(no_boards_msg); + return -EIO; + } + return 0; +} + +#ifdef MODULE +static int iobase; +static int iobase1; +static int iobase2; +static int iobase3; +module_param(iobase, int, 0); +module_param(iobase1, int, 0); +module_param(iobase2, int, 0); +module_param(iobase3, int, 0); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR); +#endif /* MODULE */ + +/* + * You can setup up to 4 boards (current value of RC_NBOARD) + * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter. + * + */ +static int __init riscom8_init_module(void) +{ +#ifdef MODULE + int i; + + if (iobase || iobase1 || iobase2 || iobase3) { + for (i = 0; i < RC_NBOARD; i++) + rc_board[i].base = 0; + } + + if (iobase) + rc_board[0].base = iobase; + if (iobase1) + rc_board[1].base = iobase1; + if (iobase2) + rc_board[2].base = iobase2; + if (iobase3) + rc_board[3].base = iobase3; +#endif /* MODULE */ + + return riscom8_init(); +} + +static void __exit riscom8_exit_module(void) +{ + int i; + + rc_release_drivers(); + for (i = 0; i < RC_NBOARD; i++) + if (rc_board[i].flags & RC_BOARD_PRESENT) + rc_release_io_range(&rc_board[i]); + +} + +module_init(riscom8_init_module); +module_exit(riscom8_exit_module); diff --git a/drivers/staging/tty/riscom8.h b/drivers/staging/tty/riscom8.h new file mode 100644 index 000000000000..c9876b3f9714 --- /dev/null +++ b/drivers/staging/tty/riscom8.h @@ -0,0 +1,91 @@ +/* + * linux/drivers/char/riscom8.h -- RISCom/8 multiport serial driver. + * + * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) + * + * This code is loosely based on the Linux serial driver, written by + * Linus Torvalds, Theodore T'so and others. The RISCom/8 card + * programming info was obtained from various drivers for other OSes + * (FreeBSD, ISC, etc), but no source code from those drivers were + * directly included in this driver. + * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_RISCOM8_H +#define __LINUX_RISCOM8_H + +#include + +#ifdef __KERNEL__ + +#define RC_NBOARD 4 +/* NOTE: RISCom decoder recognizes 16 addresses... */ +#define RC_NPORT 8 +#define RC_BOARD(line) (((line) >> 3) & 0x07) +#define RC_PORT(line) ((line) & (RC_NPORT - 1)) + +/* Ticks per sec. Used for setting receiver timeout and break length */ +#define RISCOM_TPS 4000 + +/* Yeah, after heavy testing I decided it must be 6. + * Sure, You can change it if needed. + */ +#define RISCOM_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ + +#define RISCOM8_MAGIC 0x0907 + +#define RC_IOBASE1 0x220 +#define RC_IOBASE2 0x240 +#define RC_IOBASE3 0x250 +#define RC_IOBASE4 0x260 + +struct riscom_board { + unsigned long flags; + unsigned short base; + unsigned char irq; + signed char count; + unsigned char DTR; +}; + +#define RC_BOARD_PRESENT 0x00000001 +#define RC_BOARD_ACTIVE 0x00000002 + +struct riscom_port { + int magic; + struct tty_port port; + int baud_base; + int timeout; + int custom_divisor; + int xmit_head; + int xmit_tail; + int xmit_cnt; + short wakeup_chars; + short break_length; + unsigned char mark_mask; + unsigned char IER; + unsigned char MSVR; + unsigned char COR2; +#ifdef RC_REPORT_OVERRUN + unsigned long overrun; +#endif +#ifdef RC_REPORT_FIFO + unsigned long hits[10]; +#endif +}; + +#endif /* __KERNEL__ */ +#endif /* __LINUX_RISCOM8_H */ diff --git a/drivers/staging/tty/riscom8_reg.h b/drivers/staging/tty/riscom8_reg.h new file mode 100644 index 000000000000..a32475ed0d18 --- /dev/null +++ b/drivers/staging/tty/riscom8_reg.h @@ -0,0 +1,254 @@ +/* + * linux/drivers/char/riscom8_reg.h -- RISCom/8 multiport serial driver. + */ + +/* + * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc. + */ + +/* + * Address mapping between Cirrus Logic CD180 chip internal registers + * and ISA port addresses: + * + * CL-CD180 A6 A5 A4 A3 A2 A1 A0 + * ISA A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 + */ +#define RC_TO_ISA(r) ((((r)&0x07)<<1) | (((r)&~0x07)<<7)) + + +/* RISCom/8 On-Board Registers (assuming address translation) */ + +#define RC_RI 0x100 /* Ring Indicator Register (R/O) */ +#define RC_DTR 0x100 /* DTR Register (W/O) */ +#define RC_BSR 0x101 /* Board Status Register (R/O) */ +#define RC_CTOUT 0x101 /* Clear Timeout (W/O) */ + + +/* Board Status Register */ + +#define RC_BSR_TOUT 0x08 /* Hardware Timeout */ +#define RC_BSR_RINT 0x04 /* Receiver Interrupt */ +#define RC_BSR_TINT 0x02 /* Transmitter Interrupt */ +#define RC_BSR_MINT 0x01 /* Modem Ctl Interrupt */ + + +/* On-board oscillator frequency (in Hz) */ +#define RC_OSCFREQ 9830400 + +/* Values of choice for Interrupt ACKs */ +#define RC_ACK_MINT 0x81 /* goes to PILR1 */ +#define RC_ACK_RINT 0x82 /* goes to PILR3 */ +#define RC_ACK_TINT 0x84 /* goes to PILR2 */ + +/* Chip ID (sorry, only one chip now) */ +#define RC_ID 0x10 + +/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */ + +#define CD180_NCH 8 /* Total number of channels */ +#define CD180_TPC 16 /* Ticks per character */ +#define CD180_NFIFO 8 /* TX FIFO size */ + + +/* Global registers */ + +#define CD180_GIVR 0x40 /* Global Interrupt Vector Register */ +#define CD180_GICR 0x41 /* Global Interrupting Channel Register */ +#define CD180_PILR1 0x61 /* Priority Interrupt Level Register 1 */ +#define CD180_PILR2 0x62 /* Priority Interrupt Level Register 2 */ +#define CD180_PILR3 0x63 /* Priority Interrupt Level Register 3 */ +#define CD180_CAR 0x64 /* Channel Access Register */ +#define CD180_GFRCR 0x6b /* Global Firmware Revision Code Register */ +#define CD180_PPRH 0x70 /* Prescaler Period Register High */ +#define CD180_PPRL 0x71 /* Prescaler Period Register Low */ +#define CD180_RDR 0x78 /* Receiver Data Register */ +#define CD180_RCSR 0x7a /* Receiver Character Status Register */ +#define CD180_TDR 0x7b /* Transmit Data Register */ +#define CD180_EOIR 0x7f /* End of Interrupt Register */ + + +/* Channel Registers */ + +#define CD180_CCR 0x01 /* Channel Command Register */ +#define CD180_IER 0x02 /* Interrupt Enable Register */ +#define CD180_COR1 0x03 /* Channel Option Register 1 */ +#define CD180_COR2 0x04 /* Channel Option Register 2 */ +#define CD180_COR3 0x05 /* Channel Option Register 3 */ +#define CD180_CCSR 0x06 /* Channel Control Status Register */ +#define CD180_RDCR 0x07 /* Receive Data Count Register */ +#define CD180_SCHR1 0x09 /* Special Character Register 1 */ +#define CD180_SCHR2 0x0a /* Special Character Register 2 */ +#define CD180_SCHR3 0x0b /* Special Character Register 3 */ +#define CD180_SCHR4 0x0c /* Special Character Register 4 */ +#define CD180_MCOR1 0x10 /* Modem Change Option 1 Register */ +#define CD180_MCOR2 0x11 /* Modem Change Option 2 Register */ +#define CD180_MCR 0x12 /* Modem Change Register */ +#define CD180_RTPR 0x18 /* Receive Timeout Period Register */ +#define CD180_MSVR 0x28 /* Modem Signal Value Register */ +#define CD180_RBPRH 0x31 /* Receive Baud Rate Period Register High */ +#define CD180_RBPRL 0x32 /* Receive Baud Rate Period Register Low */ +#define CD180_TBPRH 0x39 /* Transmit Baud Rate Period Register High */ +#define CD180_TBPRL 0x3a /* Transmit Baud Rate Period Register Low */ + + +/* Global Interrupt Vector Register (R/W) */ + +#define GIVR_ITMASK 0x07 /* Interrupt type mask */ +#define GIVR_IT_MODEM 0x01 /* Modem Signal Change Interrupt */ +#define GIVR_IT_TX 0x02 /* Transmit Data Interrupt */ +#define GIVR_IT_RCV 0x03 /* Receive Good Data Interrupt */ +#define GIVR_IT_REXC 0x07 /* Receive Exception Interrupt */ + + +/* Global Interrupt Channel Register (R/W) */ + +#define GICR_CHAN 0x1c /* Channel Number Mask */ +#define GICR_CHAN_OFF 2 /* Channel Number Offset */ + + +/* Channel Address Register (R/W) */ + +#define CAR_CHAN 0x07 /* Channel Number Mask */ +#define CAR_A7 0x08 /* A7 Address Extension (unused) */ + + +/* Receive Character Status Register (R/O) */ + +#define RCSR_TOUT 0x80 /* Rx Timeout */ +#define RCSR_SCDET 0x70 /* Special Character Detected Mask */ +#define RCSR_NO_SC 0x00 /* No Special Characters Detected */ +#define RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected */ +#define RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected */ +#define RCSR_SC_3 0x30 /* Special Char 3 Detected */ +#define RCSR_SC_4 0x40 /* Special Char 4 Detected */ +#define RCSR_BREAK 0x08 /* Break has been detected */ +#define RCSR_PE 0x04 /* Parity Error */ +#define RCSR_FE 0x02 /* Frame Error */ +#define RCSR_OE 0x01 /* Overrun Error */ + + +/* Channel Command Register (R/W) (commands in groups can be OR-ed) */ + +#define CCR_HARDRESET 0x81 /* Reset the chip */ + +#define CCR_SOFTRESET 0x80 /* Soft Channel Reset */ + +#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */ +#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */ +#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */ + +#define CCR_SSCH1 0x21 /* Send Special Character 1 */ + +#define CCR_SSCH2 0x22 /* Send Special Character 2 */ + +#define CCR_SSCH3 0x23 /* Send Special Character 3 */ + +#define CCR_SSCH4 0x24 /* Send Special Character 4 */ + +#define CCR_TXEN 0x18 /* Enable Transmitter */ +#define CCR_RXEN 0x12 /* Enable Receiver */ + +#define CCR_TXDIS 0x14 /* Disable Transmitter */ +#define CCR_RXDIS 0x11 /* Disable Receiver */ + + +/* Interrupt Enable Register (R/W) */ + +#define IER_DSR 0x80 /* Enable interrupt on DSR change */ +#define IER_CD 0x40 /* Enable interrupt on CD change */ +#define IER_CTS 0x20 /* Enable interrupt on CTS change */ +#define IER_RXD 0x10 /* Enable interrupt on Receive Data */ +#define IER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */ +#define IER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */ +#define IER_TXEMPTY 0x02 /* Enable interrupt on TX completely empty */ +#define IER_RET 0x01 /* Enable interrupt on RX Exc. Timeout */ + + +/* Channel Option Register 1 (R/W) */ + +#define COR1_ODDP 0x80 /* Odd Parity */ +#define COR1_PARMODE 0x60 /* Parity Mode mask */ +#define COR1_NOPAR 0x00 /* No Parity */ +#define COR1_FORCEPAR 0x20 /* Force Parity */ +#define COR1_NORMPAR 0x40 /* Normal Parity */ +#define COR1_IGNORE 0x10 /* Ignore Parity on RX */ +#define COR1_STOPBITS 0x0c /* Number of Stop Bits */ +#define COR1_1SB 0x00 /* 1 Stop Bit */ +#define COR1_15SB 0x04 /* 1.5 Stop Bits */ +#define COR1_2SB 0x08 /* 2 Stop Bits */ +#define COR1_CHARLEN 0x03 /* Character Length */ +#define COR1_5BITS 0x00 /* 5 bits */ +#define COR1_6BITS 0x01 /* 6 bits */ +#define COR1_7BITS 0x02 /* 7 bits */ +#define COR1_8BITS 0x03 /* 8 bits */ + + +/* Channel Option Register 2 (R/W) */ + +#define COR2_IXM 0x80 /* Implied XON mode */ +#define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */ +#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */ +#define COR2_LLM 0x10 /* Local Loopback Mode */ +#define COR2_RLM 0x08 /* Remote Loopback Mode */ +#define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */ +#define COR2_CTSAE 0x02 /* CTS Automatic Enable */ +#define COR2_DSRAE 0x01 /* DSR Automatic Enable */ + + +/* Channel Option Register 3 (R/W) */ + +#define COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3) */ +#define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4) */ +#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */ +#define COR3_SCDE 0x10 /* Special Character Detection Enable */ +#define COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8) */ + + +/* Channel Control Status Register (R/O) */ + +#define CCSR_RXEN 0x80 /* Receiver Enabled */ +#define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent) */ +#define CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent) */ +#define CCSR_TXEN 0x08 /* Transmitter Enabled */ +#define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */ +#define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */ + + +/* Modem Change Option Register 1 (R/W) */ + +#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */ +#define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */ +#define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */ +#define MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8) */ +#define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */ + + +/* Modem Change Option Register 2 (R/W) */ + +#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */ +#define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */ +#define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */ + + +/* Modem Change Register (R/W) */ + +#define MCR_DSRCHG 0x80 /* DSR Changed */ +#define MCR_CDCHG 0x40 /* CD Changed */ +#define MCR_CTSCHG 0x20 /* CTS Changed */ + + +/* Modem Signal Value Register (R/W) */ + +#define MSVR_DSR 0x80 /* Current state of DSR input */ +#define MSVR_CD 0x40 /* Current state of CD input */ +#define MSVR_CTS 0x20 /* Current state of CTS input */ +#define MSVR_DTR 0x02 /* Current state of DTR output */ +#define MSVR_RTS 0x01 /* Current state of RTS output */ + + +/* Escape characters */ + +#define CD180_C_ESC 0x00 /* Escape character */ +#define CD180_C_SBRK 0x81 /* Start sending BREAK */ +#define CD180_C_DELAY 0x82 /* Delay output */ +#define CD180_C_EBRK 0x83 /* Stop sending BREAK */ diff --git a/drivers/staging/tty/serial167.c b/drivers/staging/tty/serial167.c new file mode 100644 index 000000000000..674af6933978 --- /dev/null +++ b/drivers/staging/tty/serial167.c @@ -0,0 +1,2489 @@ +/* + * linux/drivers/char/serial167.c + * + * Driver for MVME166/7 board serial ports, which are via a CD2401. + * Based very much on cyclades.c. + * + * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk] + * + * ============================================================== + * + * static char rcsid[] = + * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $"; + * + * linux/kernel/cyclades.c + * + * Maintained by Marcio Saito (cyclades@netcom.com) and + * Randolph Bentson (bentson@grieg.seaslug.org) + * + * Much of the design and some of the code came from serial.c + * which was copyright (C) 1991, 1992 Linus Torvalds. It was + * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, + * and then fixed as suggested by Michael K. Johnson 12/12/92. + * + * This version does not support shared irq's. + * + * $Log: cyclades.c,v $ + * Revision 1.36.1.4 1995/03/29 06:14:14 bentson + * disambiguate between Cyclom-16Y and Cyclom-32Ye; + * + * Changes: + * + * 200 lines of changes record removed - RGH 11-10-95, starting work on + * converting this to drive serial ports on mvme166 (cd2401). + * + * Arnaldo Carvalho de Melo - 2000/08/25 + * - get rid of verify_area + * - use get_user to access memory from userspace in set_threshold, + * set_default_threshold and set_timeout + * - don't use the panic function in serial167_init + * - do resource release on failure on serial167_init + * - include missing restore_flags in mvme167_serial_console_setup + * + * Kars de Jong - 2004/09/06 + * - replace bottom half handler with task queue handler + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define SERIAL_PARANOIA_CHECK +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_THROTTLE +#undef SERIAL_DEBUG_OTHER +#undef SERIAL_DEBUG_IO +#undef SERIAL_DEBUG_COUNT +#undef SERIAL_DEBUG_DTR +#undef CYCLOM_16Y_HACK +#define CYCLOM_ENABLE_MONITORING + +#define WAKEUP_CHARS 256 + +#define STD_COM_FLAGS (0) + +static struct tty_driver *cy_serial_driver; +extern int serial_console; +static struct cyclades_port *serial_console_info = NULL; +static unsigned int serial_console_cflag = 0; +u_char initial_console_speed; + +/* Base address of cd2401 chip on mvme166/7 */ + +#define BASE_ADDR (0xfff45000) +#define pcc2chip ((volatile u_char *)0xfff42000) +#define PccSCCMICR 0x1d +#define PccSCCTICR 0x1e +#define PccSCCRICR 0x1f +#define PccTPIACKR 0x25 +#define PccRPIACKR 0x27 +#define PccIMLR 0x3f + +/* This is the per-port data structure */ +struct cyclades_port cy_port[] = { + /* CARD# */ + {-1}, /* ttyS0 */ + {-1}, /* ttyS1 */ + {-1}, /* ttyS2 */ + {-1}, /* ttyS3 */ +}; + +#define NR_PORTS ARRAY_SIZE(cy_port) + +/* + * This is used to look up the divisor speeds and the timeouts + * We're normally limited to 15 distinct baud rates. The extra + * are accessed via settings in info->flags. + * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + * 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 +}; + +#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_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 +}; + +/* 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 void shutdown(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 *); +#ifdef CYCLOM_SHOW_STATUS +static void show_status(int); +#endif + +/* + * I have my own version of udelay(), as it is needed when initialising + * the chip, before the delay loop has been calibrated. Should probably + * reference one of the vmechip2 or pccchip2 counter for an accurate + * delay, but this wild guess will do for now. + */ + +void my_udelay(long us) +{ + u_char x; + volatile u_char *p = &x; + int i; + + while (us--) + for (i = 100; i; i--) + x |= *p; +} + +static inline int serial_paranoia_check(struct cyclades_port *info, char *name, + const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + if (!info) { + printk("Warning: null cyclades_port for (%s) in %s\n", name, + routine); + return 1; + } + + if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) { + 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 */ + +#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); + printk(KERN_EMERG "%s", data); + local_irq_restore(flags); +} + +char scrn[2]; +void CP(char data) +{ + unsigned long flags; + local_irq_save(flags); + scrn[0] = data; + printk(KERN_EMERG "%c", 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 */ +#endif + +/* This routine waits up to 1000 micro-seconds for the previous + command to the Cirrus chip to complete and then issues the + 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) +{ + unsigned long flags; + volatile int i; + + 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); + } + /* if the CCR never cleared, the previous command + 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 */ + +/* 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) +{ + struct cyclades_port *info = 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); /* */ +#endif + + if (serial_paranoia_check(info, tty->name, "cy_stop")) + return; + + channel = info->line; + + 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) +{ + struct cyclades_port *info = 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); /* */ +#endif + + if (serial_paranoia_check(info, tty->name, "cy_start")) + return; + + channel = info->line; + + local_irq_save(flags); + base_addr[CyCAR] = (u_char) (channel); + base_addr[CyIER] |= CyTxMpty; + local_irq_restore(flags); +} /* cy_start */ + +/* 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) +{ + 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 */ + + 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 lose + 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) +{ + 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('!'); */ + wake_up_interruptible(&info->open_wait); + } else { +/* CP('@'); */ + tty_hangup(info->tty); + wake_up_interruptible(&info->open_wait); + info->flags &= ~ASYNC_NORMAL_ACTIVE; + } + } + 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; + tty_wakeup(info->tty); + } + } else { + if (!(mdm_status & CyCTS)) { + /* !!! cy_stop isn't used because... */ + info->tty->stopped = 1; + base_addr[CyIER] &= + ~(CyTxMpty | CyTxRdy); + } + } + } + if (mdm_status & CyDSR) { + } + } + base_addr[CyMEOIR] = 0; + return IRQ_HANDLED; +} /* cy_modem_interrupt */ + +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; + + /* determine the channel and change to that context */ + channel = (u_short) (base_addr[CyLICR] >> 2); + + /* 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 = &cy_port[channel]; + info->last_active = jiffies; + if (info->tty == 0) { + base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); + 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); + base_addr[CyTDR] = outch; + base_addr[CyTDR] = 0; + char_count--; + char_count--; + } else { + break; + } + } + } + + if (info->xmit_cnt < WAKEUP_CHARS) + tty_wakeup(info->tty); + + 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) +{ + 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; + + /* 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]; + + /* 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 + while (char_count--) { + data = base_addr[CyRDR]; + tty_insert_flip_char(tty, data, TTY_NORMAL); +#ifdef CYCLOM_16Y_HACK + udelay(10L); +#endif + } + tty_schedule_flip(tty); + } + /* end of service */ + base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; + return IRQ_HANDLED; +} /* cy_rx_interrupt */ + +/* This is called whenever a port becomes active; + interrupts are enabled and DTR & RTS are turned on. + */ +static int startup(struct cyclades_port *info) +{ + unsigned long flags; + volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; + int channel; + + if (info->flags & ASYNC_INITIALIZED) { + return 0; + } + + if (!info->type) { + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + return 0; + } + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); + if (!info->xmit_buf) { + return -ENOMEM; + } + } + + config_setup(info); + + channel = info->line; + +#ifdef SERIAL_DEBUG_OPEN + 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); + + 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]); +#endif + + base_addr[CyIER] |= CyRxData; + info->flags |= ASYNC_INITIALIZED; + + 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); + +#ifdef SERIAL_DEBUG_OPEN + printk(" done\n"); +#endif + return 0; +} /* startup */ + +void start_xmit(struct cyclades_port *info) +{ + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + + channel = info->line; + local_irq_save(flags); + base_addr[CyCAR] = channel; + base_addr[CyIER] |= CyTxMpty; + 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) +{ + unsigned long flags; + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int channel; + + if (!(info->flags & ASYNC_INITIALIZED)) { +/* CP('$'); */ + return; + } + + channel = info->line; + +#ifdef SERIAL_DEBUG_OPEN + 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; + } + + base_addr[CyCAR] = (u_char) channel; + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + base_addr[CyMSVR1] = 0; +/* CP('C');CP('1'); */ + 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]); +#endif + } + 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); + } + info->flags &= ~ASYNC_INITIALIZED; + local_irq_restore(flags); + +#ifdef SERIAL_DEBUG_OPEN + printk(" done\n"); +#endif +} /* shutdown */ + +/* + * This routine finds or computes the various line characteristics. + */ +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; +#ifdef CBAUDEX +/* Starting with kernel 1.1.65, there is direct support for + higher baud rates. The following code supports those + changes. The conditional aspect allows this driver to be + used for earlier as well as later kernel versions. (The + mapping is slightly different from serial.c because there + 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; +#ifdef B78600 + 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->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 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; + + /*********************************************** + The hardware option, CyRtsAO, presents RTS when + the chip has characters to send. Since most modems + use RTS as reverse (inbound) flow control, this + option is not used. If inbound flow control is + necessary, DTR can be programmed to provide the + appropriate signals for use with a non-standard + cable. Contact Marcio Saito for details. + ***********************************************/ + + channel = info->line; + + 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; + if (base_addr[CyLIVR] != 0x5c) + base_addr[CyLIVR] = 0x5c; + + /* tx and rx baud rate */ + + if (base_addr[CyCOR1] != info->cor1) + need_init_chan = 1; + if (base_addr[CyTCOR] != info->tco) + base_addr[CyTCOR] = info->tco; + if (base_addr[CyTBPR] != info->tbpr) + base_addr[CyTBPR] = info->tbpr; + if (base_addr[CyRCOR] != info->rco) + base_addr[CyRCOR] = info->rco; + if (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); + if (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); + if (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; + if (base_addr[CyCOR2] != info->cor2) + base_addr[CyCOR2] = info->cor2; + if (base_addr[CyCOR3] != info->cor3) + base_addr[CyCOR3] = info->cor3; + if (base_addr[CyCOR4] != info->cor4) + base_addr[CyCOR4] = info->cor4; + if (base_addr[CyCOR5] != info->cor5) + base_addr[CyCOR5] = info->cor5; + if (base_addr[CyCOR6] != info->cor6) + base_addr[CyCOR6] = info->cor6; + if (base_addr[CyCOR7] != info->cor7) + base_addr[CyCOR7] = info->cor7; + + if (need_init_chan) + write_cy_cmd(base_addr, CyINIT_CHAN); + + 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; + if (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; +#ifdef SERIAL_DEBUG_DTR + 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; +#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 + } + + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + + local_irq_restore(flags); + +} /* config_setup */ + +static int cy_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct cyclades_port *info = tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_IO + printk("cy_put_char %s(0x%02x)\n", tty->name, ch); +#endif + + if (serial_paranoia_check(info, tty->name, "cy_put_char")) + return 0; + + if (!info->xmit_buf) + return 0; + + local_irq_save(flags); + if (info->xmit_cnt >= PAGE_SIZE - 1) { + local_irq_restore(flags); + return 0; + } + + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= PAGE_SIZE - 1; + info->xmit_cnt++; + local_irq_restore(flags); + return 1; +} /* cy_put_char */ + +static void cy_flush_chars(struct tty_struct *tty) +{ + struct cyclades_port *info = 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); /* */ +#endif + + 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; + + channel = info->line; + + local_irq_save(flags); + base_addr[CyCAR] = channel; + base_addr[CyIER] |= CyTxMpty; + 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, + start it off by enabling interrupts. The interrupt service + 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) +{ + struct cyclades_port *info = tty->driver_data; + unsigned long flags; + int c, total = 0; + +#ifdef SERIAL_DEBUG_IO + 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 */ + +static int cy_write_room(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + int ret; + +#ifdef SERIAL_DEBUG_IO + 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 */ + +static int cy_chars_in_buffer(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + +#ifdef SERIAL_DEBUG_IO + 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 */ + +static void cy_flush_buffer(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_IO + printk("cy_flush_buffer %s\n", tty->name); /* */ +#endif + + 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 */ + +/* 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) +{ + struct cyclades_port *info = 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); +#endif + + 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!!! */ + } + + channel = info->line; + + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + base_addr[CyMSVR1] = 0; + local_irq_restore(flags); +} /* cy_throttle */ + +static void cy_unthrottle(struct tty_struct *tty) +{ + struct cyclades_port *info = 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); +#endif + + 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!!! */ + } + + channel = info->line; + + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + base_addr[CyMSVR1] = CyRTS; + local_irq_restore(flags); +} /* cy_unthrottle */ + +static int +get_serial_info(struct cyclades_port *info, + struct serial_struct __user * retinfo) +{ + 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 */ + +static int +set_serial_info(struct cyclades_port *info, + struct serial_struct __user * new_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 (!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; + +check_and_exit: + if (info->flags & ASYNC_INITIALIZED) { + config_setup(info); + return 0; + } + return startup(info); +} /* set_serial_info */ + +static int cy_tiocmget(struct tty_struct *tty) +{ + struct cyclades_port *info = 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 */ + +static int +cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) +{ + struct cyclades_port *info = 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); + } + if (set & TIOCM_DTR) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; +/* CP('S');CP('2'); */ + 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); + } + + if (clear & TIOCM_RTS) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + base_addr[CyMSVR1] = 0; + local_irq_restore(flags); + } + if (clear & TIOCM_DTR) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; +/* CP('C');CP('2'); */ + 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]); +#endif + 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 */ + +static int +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; +} + +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; +} + +static int +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); +} + +static int +set_default_threshold(struct cyclades_port *info, unsigned long __user * arg) +{ + unsigned long value; + + if (get_user(value, arg)) + return -EFAULT; + + info->default_threshold = value & 0x0f; + return 0; +} + +static int +get_default_threshold(struct cyclades_port *info, unsigned long __user * value) +{ + return put_user(info->default_threshold, value); +} + +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; +} + +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); +} + +static int set_default_timeout(struct cyclades_port *info, unsigned long value) +{ + info->default_timeout = value & 0xff; + return 0; +} + +static int +get_default_timeout(struct cyclades_port *info, unsigned long __user * value) +{ + return put_user(info->default_timeout, value); +} + +static int +cy_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct cyclades_port *info = 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 + + tty_lock(); + + 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; + +/* The following commands are incompletely implemented!!! */ + case TIOCGSERIAL: + ret_val = get_serial_info(info, argp); + break; + case TIOCSSERIAL: + ret_val = set_serial_info(info, argp); + break; + default: + ret_val = -ENOIOCTLCMD; + } + tty_unlock(); + +#ifdef SERIAL_DEBUG_OTHER + printk("cy_ioctl done\n"); +#endif + + return ret_val; +} /* cy_ioctl */ + +static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct cyclades_port *info = tty->driver_data; + +#ifdef SERIAL_DEBUG_OTHER + printk("cy_set_termios %s\n", tty->name); +#endif + + 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); + } +#ifdef tytso_patch_94Nov25_1726 + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); +#endif +} /* cy_set_termios */ + +static void cy_close(struct tty_struct *tty, struct file *filp) +{ + struct cyclades_port *info = tty->driver_data; + +/* CP('C'); */ +#ifdef SERIAL_DEBUG_OTHER + printk("cy_close %s\n", tty->name); +#endif + + 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; + } +#ifdef SERIAL_DEBUG_COUNT + 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); +#ifdef SERIAL_DEBUG_COUNT + 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); + cy_flush_buffer(tty); + tty_ldisc_flush(tty); + 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"); +#endif +} /* cy_close */ + +/* + * cy_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void cy_hangup(struct tty_struct *tty) +{ + struct cyclades_port *info = tty->driver_data; + +#ifdef SERIAL_DEBUG_OTHER + printk("cy_hangup %s\n", tty->name); /* */ +#endif + + if (serial_paranoia_check(info, tty->name, "cy_hangup")) + return; + + shutdown(info); +#if 0 + info->event = 0; + info->count = 0; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc: %d: setting count to 0\n", __LINE__); +#endif + info->tty = 0; +#endif + info->flags &= ~ASYNC_NORMAL_ACTIVE; + wake_up_interruptible(&info->open_wait); +} /* cy_hangup */ + +/* + * ------------------------------------------------------------ + * cy_open() and friends + * ------------------------------------------------------------ + */ + +static int +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); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: %s, count = %d\n", + tty->name, info->count); + /**/ +#endif + info->count--; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); +#endif + info->blocked_open++; + + channel = info->line; + + while (1) { + local_irq_save(flags); + base_addr[CyCAR] = (u_char) channel; + base_addr[CyMSVR1] = CyRTS; +/* CP('S');CP('4'); */ + 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; +/* 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; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: %s, count = %d\n", + tty->name, info->count); + /**/ +#endif + tty_unlock(); + schedule(); + tty_lock(); + } + __set_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); +#endif + } + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + 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 */ + +/* + * 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) +{ + 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; + } +#ifdef SERIAL_DEBUG_OTHER + printk("cy_open %s\n", tty->name); /* */ +#endif + 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); + /**/ +#endif + info->count++; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); +#endif + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + return 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); +#endif + return retval; + } +#ifdef SERIAL_DEBUG_OPEN + printk("cy_open done\n"); + /**/ +#endif + return 0; +} /* cy_open */ + +/* + * --------------------------------------------------------------------- + * serial167_init() and friends + * + * serial167_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static void show_version(void) +{ + printk("MVME166/167 cd2401 driver\n"); +} /* show_version */ + +/* initialize chips on card -- return number of valid + chips (which is number of ports/4) */ + +/* + * This initialises the hardware to a reasonable state. It should + * probe the chip first so as to copy 166-Bug setup as a default for + * port 0. It initialises CMR to CyASYNC; that is never done again, so + * as to limit the number of CyINIT_CHAN commands in normal running. + * + * ... I wonder what I should do if this fails ... + */ + +void mvme167_serial_console_setup(int cflag) +{ + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + int ch; + u_char spd; + u_char rcor, rbpr, badspeed = 0; + unsigned long flags; + + local_irq_save(flags); + + /* + * First probe channel zero of the chip, to see what speed has + * been selected. + */ + + base_addr[CyCAR] = 0; + + rcor = base_addr[CyRCOR] << 5; + rbpr = base_addr[CyRBPR]; + + for (spd = 0; spd < sizeof(baud_bpr); spd++) + if (rbpr == baud_bpr[spd] && rcor == baud_co[spd]) + break; + if (spd >= sizeof(baud_bpr)) { + spd = 14; /* 19200 */ + badspeed = 1; /* Failed to identify speed */ + } + initial_console_speed = spd; + + /* 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; + } + + 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; + } + + /* + * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms + * tick + */ + + 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 */ + + /* + * Attempt to set up all channels to something reasonable, and + * bang out a INIT_CHAN command. We should then be able to limit + * the amount of fiddling we have to do in normal running. + */ + + 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[CyLIVR] = 0x5c; + base_addr[CyTCOR] = baud_co[spd]; + base_addr[CyTBPR] = baud_bpr[spd]; + base_addr[CyRCOR] = baud_co[spd] >> 5; + base_addr[CyRBPR] = baud_bpr[spd]; + base_addr[CySCHR1] = 'Q' & 0x1f; + base_addr[CySCHR2] = 'X' & 0x1f; + 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[spd]; + base_addr[CyCOR5] = 0; + base_addr[CyCOR6] = 0; + 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); + } + + /* + * Now do specials for channel zero.... + */ + + base_addr[CyMSVR1] = CyRTS; + base_addr[CyMSVR2] = CyDTR; + base_addr[CyIER] = CyRxData; + 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]); + if (badspeed) + 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, + .close = cy_close, + .write = cy_write, + .put_char = cy_put_char, + .flush_chars = cy_flush_chars, + .write_room = cy_write_room, + .chars_in_buffer = cy_chars_in_buffer, + .flush_buffer = cy_flush_buffer, + .ioctl = cy_ioctl, + .throttle = cy_throttle, + .unthrottle = cy_unthrottle, + .set_termios = cy_set_termios, + .stop = cy_stop, + .start = cy_start, + .hangup = cy_hangup, + .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 + for Cyclom cards in the system. As each is found, it is probed + to discover how many chips (and thus how many ports) are present. + These ports are mapped to the tty ports 64 and upward in monotonic + fashion. If an 8-port card is replaced with a 16-port card, the + port mapping on a following card will shift. + + This approach is different from what is used in the other serial + device driver because the Cyclom is more properly a multiplexer, + not just an aggregation of serial ports on one card. + + 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) +{ + struct cyclades_port *info; + int ret = 0; + int good_ports = 0; + int port_num = 0; + int index; + int DefSpeed; +#ifdef notyet + struct sigaction sa; +#endif + + if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401)) + return 0; + + cy_serial_driver = alloc_tty_driver(NR_PORTS); + if (!cy_serial_driver) + return -ENOMEM; + +#if 0 + scrn[1] = '\0'; +#endif + + 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; +#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); + + 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; + } + + port_num = 0; + info = cy_port; + for (index = 0; index < 1; index++) { + + 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->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_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 "); + } + } + } + printk("\n"); + } + while (port_num < NR_PORTS) { + info->line = -1; + port_num++; + info++; + } + + 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); +cleanup_irq_cd2401_modem: + free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); +cleanup_irq_cd2401_errors: + 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 */ + +module_init(serial167_init); + +#ifdef CYCLOM_SHOW_STATUS +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); + +/* Global Registers */ + + printk(" CyGFRCR %x\n", base_addr[CyGFRCR]); + printk(" CyCAR %x\n", base_addr[CyCAR]); + printk(" CyRISR %x\n", base_addr[CyRISR]); + printk(" CyTISR %x\n", base_addr[CyTISR]); + printk(" CyMISR %x\n", base_addr[CyMISR]); + printk(" CyRIR %x\n", base_addr[CyRIR]); + printk(" CyTIR %x\n", base_addr[CyTIR]); + printk(" CyMIR %x\n", base_addr[CyMIR]); + printk(" CyTPR %x\n", base_addr[CyTPR]); + + base_addr[CyCAR] = (u_char) channel; + +/* Virtual Registers */ + +#if 0 + printk(" CyRIVR %x\n", base_addr[CyRIVR]); + printk(" CyTIVR %x\n", base_addr[CyTIVR]); + printk(" CyMIVR %x\n", base_addr[CyMIVR]); + printk(" CyMISR %x\n", base_addr[CyMISR]); +#endif + +/* Channel Registers */ + + printk(" CyCCR %x\n", base_addr[CyCCR]); + printk(" CyIER %x\n", base_addr[CyIER]); + printk(" CyCOR1 %x\n", base_addr[CyCOR1]); + printk(" CyCOR2 %x\n", base_addr[CyCOR2]); + printk(" CyCOR3 %x\n", base_addr[CyCOR3]); + printk(" CyCOR4 %x\n", base_addr[CyCOR4]); + printk(" CyCOR5 %x\n", base_addr[CyCOR5]); +#if 0 + printk(" CyCCSR %x\n", base_addr[CyCCSR]); + printk(" CyRDCR %x\n", base_addr[CyRDCR]); +#endif + printk(" CySCHR1 %x\n", base_addr[CySCHR1]); + printk(" CySCHR2 %x\n", base_addr[CySCHR2]); +#if 0 + printk(" CySCHR3 %x\n", base_addr[CySCHR3]); + printk(" CySCHR4 %x\n", base_addr[CySCHR4]); + printk(" CySCRL %x\n", base_addr[CySCRL]); + printk(" CySCRH %x\n", base_addr[CySCRH]); + printk(" CyLNC %x\n", base_addr[CyLNC]); + printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]); + printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]); +#endif + printk(" CyRTPRL %x\n", base_addr[CyRTPRL]); + printk(" CyRTPRH %x\n", base_addr[CyRTPRH]); + printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]); + printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]); + printk(" CyRBPR %x\n", base_addr[CyRBPR]); + printk(" CyRCOR %x\n", base_addr[CyRCOR]); + printk(" CyTBPR %x\n", base_addr[CyTBPR]); + printk(" CyTCOR %x\n", base_addr[CyTCOR]); + + local_irq_restore(flags); +} /* show_status */ +#endif + +#if 0 +/* Dummy routine in mvme16x/config.c for now */ + +/* Serial console setup. Called from linux/init/main.c */ + +void console_setup(char *str, int *ints) +{ + char *s; + int baud, bits, parity; + int cflag = 0; + + /* Sanity check. */ + 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 ((s = strchr(str, ','))) { + do { + s++; + } 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 (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; + } + + serial_console_info = &cy_port[ints[1]]; + serial_console_cflag = cflag; + serial_console = ints[1] + 64; /*callout_driver.minor_start */ +} +#endif + +/* + * The following is probably out of date for 2.1.x serial console stuff. + * + * The console is registered early on from arch/m68k/kernel/setup.c, and + * it therefore relies on the chip being setup correctly by 166-Bug. This + * seems reasonable, as the serial port has been used to invoke the system + * boot. It also means that this function must not rely on any data + * initialisation performed by serial167_init() etc. + * + * Of course, once the console has been registered, we had better ensure + * that serial167_init() doesn't leave the chip non-functional. + * + * The console must be locked when we get here. + */ + +void serial167_console_write(struct console *co, const char *str, + unsigned count) +{ + volatile unsigned char *base_addr = (u_char *) BASE_ADDR; + unsigned long flags; + volatile u_char sink; + u_char ier; + int port; + u_char do_lf = 0; + int i = 0; + + local_irq_save(flags); + + /* Ensure transmitter is enabled! */ + + port = 0; + base_addr[CyCAR] = (u_char) port; + while (base_addr[CyCCR]) + ; + base_addr[CyCCR] = CyENB_XMTR; + + ier = base_addr[CyIER]; + base_addr[CyIER] = CyTxMpty; + + while (1) { + if (pcc2chip[PccSCCTICR] & 0x20) { + /* We have a Tx int. Acknowledge it */ + sink = pcc2chip[PccTPIACKR]; + if ((base_addr[CyLICR] >> 2) == port) { + if (i == count) { + /* Last char of string is now output */ + base_addr[CyTEOIR] = CyNOTRANS; + break; + } + if (do_lf) { + base_addr[CyTDR] = '\n'; + str++; + i++; + do_lf = 0; + } else if (*str == '\n') { + base_addr[CyTDR] = '\r'; + do_lf = 1; + } else { + base_addr[CyTDR] = *str++; + i++; + } + base_addr[CyTEOIR] = 0; + } else + base_addr[CyTEOIR] = CyNOTRANS; + } + } + + base_addr[CyIER] = ier; + + local_irq_restore(flags); +} + +static struct tty_driver *serial167_console_device(struct console *c, + int *index) +{ + *index = c->index; + return cy_serial_driver; +} + +static struct console sercons = { + .name = "ttyS", + .write = serial167_console_write, + .device = serial167_console_device, + .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) { + mvme167_serial_console_setup(0); + register_console(&sercons); + } + return 0; +} + +console_initcall(serial167_console_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/tty/specialix.c b/drivers/staging/tty/specialix.c new file mode 100644 index 000000000000..47e5753f732a --- /dev/null +++ b/drivers/staging/tty/specialix.c @@ -0,0 +1,2368 @@ +/* + * specialix.c -- specialix IO8+ multiport serial driver. + * + * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) + * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) + * + * Specialix pays for the development and support of this driver. + * Please DO contact io8-linux@specialix.co.uk if you require + * support. But please read the documentation (specialix.txt) + * first. + * + * This driver was developped in the BitWizard linux device + * driver service. If you require a linux device driver for your + * product, please contact devices@BitWizard.nl for a quote. + * + * This code is firmly based on the riscom/8 serial driver, + * written by Dmitry Gorodchanin. The specialix IO8+ card + * programming information was obtained from the CL-CD1865 Data + * Book, and Specialix document number 6200059: IO8+ Hardware + * Functional Specification. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * Revision history: + * + * Revision 1.0: April 1st 1997. + * Initial release for alpha testing. + * Revision 1.1: April 14th 1997. + * Incorporated Richard Hudsons suggestions, + * removed some debugging printk's. + * Revision 1.2: April 15th 1997. + * Ported to 2.1.x kernels. + * Revision 1.3: April 17th 1997 + * Backported to 2.0. (Compatibility macros). + * Revision 1.4: April 18th 1997 + * Fixed DTR/RTS bug that caused the card to indicate + * "don't send data" to a modem after the password prompt. + * Fixed bug for premature (fake) interrupts. + * Revision 1.5: April 19th 1997 + * fixed a minor typo in the header file, cleanup a little. + * performance warnings are now MAXed at once per minute. + * Revision 1.6: May 23 1997 + * Changed the specialix=... format to include interrupt. + * Revision 1.7: May 27 1997 + * Made many more debug printk's a compile time option. + * Revision 1.8: Jul 1 1997 + * port to linux-2.1.43 kernel. + * Revision 1.9: Oct 9 1998 + * Added stuff for the IO8+/PCI version. + * Revision 1.10: Oct 22 1999 / Jan 21 2000. + * Added stuff for setserial. + * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr) + * + */ + +#define VERSION "1.11" + + +/* + * There is a bunch of documentation about the card, jumpers, config + * settings, restrictions, cables, device names and numbers in + * Documentation/serial/specialix.txt + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "specialix_io8.h" +#include "cd1865.h" + + +/* + This driver can spew a whole lot of debugging output at you. If you + need maximum performance, you should disable the DEBUG define. To + aid in debugging in the field, I'm leaving the compile-time debug + features enabled, and disable them "runtime". That allows me to + instruct people with problems to enable debugging without requiring + them to recompile... +*/ +#define DEBUG + +static int sx_debug; +static int sx_rxfifo = SPECIALIX_RXFIFO; +static int sx_rtscts; + +#ifdef DEBUG +#define dprintk(f, str...) if (sx_debug & f) printk(str) +#else +#define dprintk(f, str...) /* nothing */ +#endif + +#define SX_DEBUG_FLOW 0x0001 +#define SX_DEBUG_DATA 0x0002 +#define SX_DEBUG_PROBE 0x0004 +#define SX_DEBUG_CHAN 0x0008 +#define SX_DEBUG_INIT 0x0010 +#define SX_DEBUG_RX 0x0020 +#define SX_DEBUG_TX 0x0040 +#define SX_DEBUG_IRQ 0x0080 +#define SX_DEBUG_OPEN 0x0100 +#define SX_DEBUG_TERMIOS 0x0200 +#define SX_DEBUG_SIGNALS 0x0400 +#define SX_DEBUG_FIFO 0x0800 + + +#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) +#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) + + +/* Configurable options: */ + +/* Am I paranoid or not ? ;-) */ +#define SPECIALIX_PARANOIA_CHECK + +/* + * The following defines are mostly for testing purposes. But if you need + * some nice reporting in your syslog, you can define them also. + */ +#undef SX_REPORT_FIFO +#undef SX_REPORT_OVERRUN + + + + +#define SPECIALIX_LEGAL_FLAGS \ + (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ + ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ + ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) + +static struct tty_driver *specialix_driver; + +static struct specialix_board sx_board[SX_NBOARD] = { + { 0, SX_IOBASE1, 9, }, + { 0, SX_IOBASE2, 11, }, + { 0, SX_IOBASE3, 12, }, + { 0, SX_IOBASE4, 15, }, +}; + +static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; + + +static int sx_paranoia_check(struct specialix_port const *port, + char *name, const char *routine) +{ +#ifdef SPECIALIX_PARANOIA_CHECK + static const char *badmagic = KERN_ERR + "sx: Warning: bad specialix port magic number for device %s in %s\n"; + static const char *badinfo = KERN_ERR + "sx: Warning: null specialix port for device %s in %s\n"; + + if (!port) { + printk(badinfo, name, routine); + return 1; + } + if (port->magic != SPECIALIX_MAGIC) { + printk(badmagic, name, routine); + return 1; + } +#endif + return 0; +} + + +/* + * + * Service functions for specialix IO8+ driver. + * + */ + +/* Get board number from pointer */ +static inline int board_No(struct specialix_board *bp) +{ + return bp - sx_board; +} + + +/* Get port number from pointer */ +static inline int port_No(struct specialix_port const *port) +{ + return SX_PORT(port - sx_port); +} + + +/* Get pointer to board from pointer to port */ +static inline struct specialix_board *port_Board( + struct specialix_port const *port) +{ + return &sx_board[SX_BOARD(port - sx_port)]; +} + + +/* Input Byte from CL CD186x register */ +static inline unsigned char sx_in(struct specialix_board *bp, + unsigned short reg) +{ + bp->reg = reg | 0x80; + outb(reg | 0x80, bp->base + SX_ADDR_REG); + return inb(bp->base + SX_DATA_REG); +} + + +/* Output Byte to CL CD186x register */ +static inline void sx_out(struct specialix_board *bp, unsigned short reg, + unsigned char val) +{ + bp->reg = reg | 0x80; + outb(reg | 0x80, bp->base + SX_ADDR_REG); + outb(val, bp->base + SX_DATA_REG); +} + + +/* Input Byte from CL CD186x register */ +static inline unsigned char sx_in_off(struct specialix_board *bp, + unsigned short reg) +{ + bp->reg = reg; + outb(reg, bp->base + SX_ADDR_REG); + return inb(bp->base + SX_DATA_REG); +} + + +/* Output Byte to CL CD186x register */ +static inline void sx_out_off(struct specialix_board *bp, + unsigned short reg, unsigned char val) +{ + bp->reg = reg; + outb(reg, bp->base + SX_ADDR_REG); + outb(val, bp->base + SX_DATA_REG); +} + + +/* Wait for Channel Command Register ready */ +static void sx_wait_CCR(struct specialix_board *bp) +{ + unsigned long delay, flags; + unsigned char ccr; + + for (delay = SX_CCR_TIMEOUT; delay; delay--) { + spin_lock_irqsave(&bp->lock, flags); + ccr = sx_in(bp, CD186x_CCR); + spin_unlock_irqrestore(&bp->lock, flags); + if (!ccr) + return; + udelay(1); + } + + printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); +} + + +/* Wait for Channel Command Register ready */ +static void sx_wait_CCR_off(struct specialix_board *bp) +{ + unsigned long delay; + unsigned char crr; + unsigned long flags; + + for (delay = SX_CCR_TIMEOUT; delay; delay--) { + spin_lock_irqsave(&bp->lock, flags); + crr = sx_in_off(bp, CD186x_CCR); + spin_unlock_irqrestore(&bp->lock, flags); + if (!crr) + return; + udelay(1); + } + + printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); +} + + +/* + * specialix IO8+ IO range functions. + */ + +static int sx_request_io_range(struct specialix_board *bp) +{ + return request_region(bp->base, + bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, + "specialix IO8+") == NULL; +} + + +static void sx_release_io_range(struct specialix_board *bp) +{ + release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? + SX_PCI_IO_SPACE : SX_IO_SPACE); +} + + +/* Set the IRQ using the RTS lines that run to the PAL on the board.... */ +static int sx_set_irq(struct specialix_board *bp) +{ + int virq; + int i; + unsigned long flags; + + if (bp->flags & SX_BOARD_IS_PCI) + return 1; + switch (bp->irq) { + /* In the same order as in the docs... */ + case 15: + virq = 0; + break; + case 12: + virq = 1; + break; + case 11: + virq = 2; + break; + case 9: + virq = 3; + break; + default:printk(KERN_ERR + "Speclialix: cannot set irq to %d.\n", bp->irq); + return 0; + } + spin_lock_irqsave(&bp->lock, flags); + for (i = 0; i < 2; i++) { + sx_out(bp, CD186x_CAR, i); + sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); + } + spin_unlock_irqrestore(&bp->lock, flags); + return 1; +} + + +/* Reset and setup CD186x chip */ +static int sx_init_CD186x(struct specialix_board *bp) +{ + unsigned long flags; + int scaler; + int rv = 1; + + func_enter(); + sx_wait_CCR_off(bp); /* Wait for CCR ready */ + spin_lock_irqsave(&bp->lock, flags); + sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */ + spin_unlock_irqrestore(&bp->lock, flags); + msleep(50); /* Delay 0.05 sec */ + spin_lock_irqsave(&bp->lock, flags); + sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */ + sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */ + sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */ + sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ + sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ + /* Set RegAckEn */ + sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); + + /* Setting up prescaler. We need 4 ticks per 1 ms */ + scaler = SX_OSCFREQ/SPECIALIX_TPS; + + sx_out_off(bp, CD186x_PPRH, scaler >> 8); + sx_out_off(bp, CD186x_PPRL, scaler & 0xff); + spin_unlock_irqrestore(&bp->lock, flags); + + if (!sx_set_irq(bp)) { + /* Figure out how to pass this along... */ + printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); + rv = 0; + } + + func_exit(); + return rv; +} + + +static int read_cross_byte(struct specialix_board *bp, int reg, int bit) +{ + int i; + int t; + unsigned long flags; + + spin_lock_irqsave(&bp->lock, flags); + for (i = 0, t = 0; i < 8; i++) { + sx_out_off(bp, CD186x_CAR, i); + if (sx_in_off(bp, reg) & bit) + t |= 1 << i; + } + spin_unlock_irqrestore(&bp->lock, flags); + + return t; +} + + +/* Main probing routine, also sets irq. */ +static int sx_probe(struct specialix_board *bp) +{ + unsigned char val1, val2; + int rev; + int chip; + + func_enter(); + + if (sx_request_io_range(bp)) { + func_exit(); + return 1; + } + + /* Are the I/O ports here ? */ + sx_out_off(bp, CD186x_PPRL, 0x5a); + udelay(1); + val1 = sx_in_off(bp, CD186x_PPRL); + + sx_out_off(bp, CD186x_PPRL, 0xa5); + udelay(1); + val2 = sx_in_off(bp, CD186x_PPRL); + + + if (val1 != 0x5a || val2 != 0xa5) { + printk(KERN_INFO + "sx%d: specialix IO8+ Board at 0x%03x not found.\n", + board_No(bp), bp->base); + sx_release_io_range(bp); + func_exit(); + return 1; + } + + /* Check the DSR lines that Specialix uses as board + identification */ + val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); + val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); + dprintk(SX_DEBUG_INIT, + "sx%d: DSR lines are: %02x, rts lines are: %02x\n", + board_No(bp), val1, val2); + + /* They managed to switch the bit order between the docs and + the IO8+ card. The new PCI card now conforms to old docs. + They changed the PCI docs to reflect the situation on the + old card. */ + val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; + if (val1 != val2) { + printk(KERN_INFO + "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", + board_No(bp), val2, bp->base, val1); + sx_release_io_range(bp); + func_exit(); + return 1; + } + + + /* Reset CD186x again */ + if (!sx_init_CD186x(bp)) { + sx_release_io_range(bp); + func_exit(); + return 1; + } + + sx_request_io_range(bp); + bp->flags |= SX_BOARD_PRESENT; + + /* Chip revcode pkgtype + GFRCR SRCR bit 7 + CD180 rev B 0x81 0 + CD180 rev C 0x82 0 + CD1864 rev A 0x82 1 + CD1865 rev A 0x83 1 -- Do not use!!! Does not work. + CD1865 rev B 0x84 1 + -- Thanks to Gwen Wang, Cirrus Logic. + */ + + switch (sx_in_off(bp, CD186x_GFRCR)) { + case 0x82: + chip = 1864; + rev = 'A'; + break; + case 0x83: + chip = 1865; + rev = 'A'; + break; + case 0x84: + chip = 1865; + rev = 'B'; + break; + case 0x85: + chip = 1865; + rev = 'C'; + break; /* Does not exist at this time */ + default: + chip = -1; + rev = 'x'; + } + + dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); + + printk(KERN_INFO + "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", + board_No(bp), bp->base, bp->irq, chip, rev); + + func_exit(); + return 0; +} + +/* + * + * Interrupt processing routines. + * */ + +static struct specialix_port *sx_get_port(struct specialix_board *bp, + unsigned char const *what) +{ + unsigned char channel; + struct specialix_port *port = NULL; + + channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; + dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); + if (channel < CD186x_NCH) { + port = &sx_port[board_No(bp) * SX_NPORT + channel]; + dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", + board_No(bp) * SX_NPORT + channel, port, + port->port.flags & ASYNC_INITIALIZED); + + if (port->port.flags & ASYNC_INITIALIZED) { + dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); + func_exit(); + return port; + } + } + printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", + board_No(bp), what, channel); + return NULL; +} + + +static void sx_receive_exc(struct specialix_board *bp) +{ + struct specialix_port *port; + struct tty_struct *tty; + unsigned char status; + unsigned char ch, flag; + + func_enter(); + + port = sx_get_port(bp, "Receive"); + if (!port) { + dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); + func_exit(); + return; + } + tty = port->port.tty; + + status = sx_in(bp, CD186x_RCSR); + + dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); + if (status & RCSR_OE) { + port->overrun++; + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: Overrun. Total %ld overruns.\n", + board_No(bp), port_No(port), port->overrun); + } + status &= port->mark_mask; + + /* This flip buffer check needs to be below the reading of the + status register to reset the chip's IRQ.... */ + if (tty_buffer_request_room(tty, 1) == 0) { + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: Working around flip buffer overflow.\n", + board_No(bp), port_No(port)); + func_exit(); + return; + } + + ch = sx_in(bp, CD186x_RDR); + if (!status) { + func_exit(); + return; + } + if (status & RCSR_TOUT) { + printk(KERN_INFO + "sx%d: port %d: Receiver timeout. Hardware problems ?\n", + board_No(bp), port_No(port)); + func_exit(); + return; + + } else if (status & RCSR_BREAK) { + dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", + board_No(bp), port_No(port)); + flag = TTY_BREAK; + if (port->port.flags & ASYNC_SAK) + do_SAK(tty); + + } else if (status & RCSR_PE) + flag = TTY_PARITY; + + else if (status & RCSR_FE) + flag = TTY_FRAME; + + else if (status & RCSR_OE) + flag = TTY_OVERRUN; + + else + flag = TTY_NORMAL; + + if (tty_insert_flip_char(tty, ch, flag)) + tty_flip_buffer_push(tty); + func_exit(); +} + + +static void sx_receive(struct specialix_board *bp) +{ + struct specialix_port *port; + struct tty_struct *tty; + unsigned char count; + + func_enter(); + + port = sx_get_port(bp, "Receive"); + if (port == NULL) { + dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); + func_exit(); + return; + } + tty = port->port.tty; + + count = sx_in(bp, CD186x_RDCR); + dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); + port->hits[count > 8 ? 9 : count]++; + + while (count--) + tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); + tty_flip_buffer_push(tty); + func_exit(); +} + + +static void sx_transmit(struct specialix_board *bp) +{ + struct specialix_port *port; + struct tty_struct *tty; + unsigned char count; + + func_enter(); + port = sx_get_port(bp, "Transmit"); + if (port == NULL) { + func_exit(); + return; + } + dprintk(SX_DEBUG_TX, "port: %p\n", port); + tty = port->port.tty; + + if (port->IER & IER_TXEMPTY) { + /* FIFO drained */ + sx_out(bp, CD186x_CAR, port_No(port)); + port->IER &= ~IER_TXEMPTY; + sx_out(bp, CD186x_IER, port->IER); + func_exit(); + return; + } + + if ((port->xmit_cnt <= 0 && !port->break_length) + || tty->stopped || tty->hw_stopped) { + sx_out(bp, CD186x_CAR, port_No(port)); + port->IER &= ~IER_TXRDY; + sx_out(bp, CD186x_IER, port->IER); + func_exit(); + return; + } + + if (port->break_length) { + if (port->break_length > 0) { + if (port->COR2 & COR2_ETC) { + sx_out(bp, CD186x_TDR, CD186x_C_ESC); + sx_out(bp, CD186x_TDR, CD186x_C_SBRK); + port->COR2 &= ~COR2_ETC; + } + count = min_t(int, port->break_length, 0xff); + sx_out(bp, CD186x_TDR, CD186x_C_ESC); + sx_out(bp, CD186x_TDR, CD186x_C_DELAY); + sx_out(bp, CD186x_TDR, count); + port->break_length -= count; + if (port->break_length == 0) + port->break_length--; + } else { + sx_out(bp, CD186x_TDR, CD186x_C_ESC); + sx_out(bp, CD186x_TDR, CD186x_C_EBRK); + sx_out(bp, CD186x_COR2, port->COR2); + sx_wait_CCR(bp); + sx_out(bp, CD186x_CCR, CCR_CORCHG2); + port->break_length = 0; + } + + func_exit(); + return; + } + + count = CD186x_NFIFO; + do { + sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]); + port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); + if (--port->xmit_cnt <= 0) + break; + } while (--count > 0); + + if (port->xmit_cnt <= 0) { + sx_out(bp, CD186x_CAR, port_No(port)); + port->IER &= ~IER_TXRDY; + sx_out(bp, CD186x_IER, port->IER); + } + if (port->xmit_cnt <= port->wakeup_chars) + tty_wakeup(tty); + + func_exit(); +} + + +static void sx_check_modem(struct specialix_board *bp) +{ + struct specialix_port *port; + struct tty_struct *tty; + unsigned char mcr; + int msvr_cd; + + dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); + port = sx_get_port(bp, "Modem"); + if (port == NULL) + return; + + tty = port->port.tty; + + mcr = sx_in(bp, CD186x_MCR); + + if ((mcr & MCR_CDCHG)) { + dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); + msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; + if (msvr_cd) { + dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); + wake_up_interruptible(&port->port.open_wait); + } else { + dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); + tty_hangup(tty); + } + } + +#ifdef SPECIALIX_BRAIN_DAMAGED_CTS + if (mcr & MCR_CTSCHG) { + if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) { + tty->hw_stopped = 0; + port->IER |= IER_TXRDY; + if (port->xmit_cnt <= port->wakeup_chars) + tty_wakeup(tty); + } else { + tty->hw_stopped = 1; + port->IER &= ~IER_TXRDY; + } + sx_out(bp, CD186x_IER, port->IER); + } + if (mcr & MCR_DSSXHG) { + if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) { + tty->hw_stopped = 0; + port->IER |= IER_TXRDY; + if (port->xmit_cnt <= port->wakeup_chars) + tty_wakeup(tty); + } else { + tty->hw_stopped = 1; + port->IER &= ~IER_TXRDY; + } + sx_out(bp, CD186x_IER, port->IER); + } +#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */ + + /* Clear change bits */ + sx_out(bp, CD186x_MCR, 0); +} + + +/* The main interrupt processing routine */ +static irqreturn_t sx_interrupt(int dummy, void *dev_id) +{ + unsigned char status; + unsigned char ack; + struct specialix_board *bp = dev_id; + unsigned long loop = 0; + int saved_reg; + unsigned long flags; + + func_enter(); + + spin_lock_irqsave(&bp->lock, flags); + + dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, + port_No(sx_get_port(bp, "INT")), + SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); + if (!(bp->flags & SX_BOARD_ACTIVE)) { + dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", + bp->irq); + spin_unlock_irqrestore(&bp->lock, flags); + func_exit(); + return IRQ_NONE; + } + + saved_reg = bp->reg; + + while (++loop < 16) { + status = sx_in(bp, CD186x_SRSR) & + (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); + if (status == 0) + break; + if (status & SRSR_RREQint) { + ack = sx_in(bp, CD186x_RRAR); + + if (ack == (SX_ID | GIVR_IT_RCV)) + sx_receive(bp); + else if (ack == (SX_ID | GIVR_IT_REXC)) + sx_receive_exc(bp); + else + printk(KERN_ERR + "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", + board_No(bp), status, ack); + + } else if (status & SRSR_TREQint) { + ack = sx_in(bp, CD186x_TRAR); + + if (ack == (SX_ID | GIVR_IT_TX)) + sx_transmit(bp); + else + printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", + board_No(bp), status, ack, + port_No(sx_get_port(bp, "Int"))); + } else if (status & SRSR_MREQint) { + ack = sx_in(bp, CD186x_MRAR); + + if (ack == (SX_ID | GIVR_IT_MODEM)) + sx_check_modem(bp); + else + printk(KERN_ERR + "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", + board_No(bp), status, ack); + + } + + sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ + } + bp->reg = saved_reg; + outb(bp->reg, bp->base + SX_ADDR_REG); + spin_unlock_irqrestore(&bp->lock, flags); + func_exit(); + return IRQ_HANDLED; +} + + +/* + * Routines for open & close processing. + */ + +static void turn_ints_off(struct specialix_board *bp) +{ + unsigned long flags; + + func_enter(); + spin_lock_irqsave(&bp->lock, flags); + (void) sx_in_off(bp, 0); /* Turn off interrupts. */ + spin_unlock_irqrestore(&bp->lock, flags); + + func_exit(); +} + +static void turn_ints_on(struct specialix_board *bp) +{ + unsigned long flags; + + func_enter(); + + spin_lock_irqsave(&bp->lock, flags); + (void) sx_in(bp, 0); /* Turn ON interrupts. */ + spin_unlock_irqrestore(&bp->lock, flags); + + func_exit(); +} + + +/* Called with disabled interrupts */ +static int sx_setup_board(struct specialix_board *bp) +{ + int error; + + if (bp->flags & SX_BOARD_ACTIVE) + return 0; + + if (bp->flags & SX_BOARD_IS_PCI) + error = request_irq(bp->irq, sx_interrupt, + IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); + else + error = request_irq(bp->irq, sx_interrupt, + IRQF_DISABLED, "specialix IO8+", bp); + + if (error) + return error; + + turn_ints_on(bp); + bp->flags |= SX_BOARD_ACTIVE; + + return 0; +} + + +/* Called with disabled interrupts */ +static void sx_shutdown_board(struct specialix_board *bp) +{ + func_enter(); + + if (!(bp->flags & SX_BOARD_ACTIVE)) { + func_exit(); + return; + } + + bp->flags &= ~SX_BOARD_ACTIVE; + + dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", + bp->irq, board_No(bp)); + free_irq(bp->irq, bp); + turn_ints_off(bp); + func_exit(); +} + +static unsigned int sx_crtscts(struct tty_struct *tty) +{ + if (sx_rtscts) + return C_CRTSCTS(tty); + return 1; +} + +/* + * Setting up port characteristics. + * Must be called with disabled interrupts + */ +static void sx_change_speed(struct specialix_board *bp, + struct specialix_port *port) +{ + struct tty_struct *tty; + unsigned long baud; + long tmp; + unsigned char cor1 = 0, cor3 = 0; + unsigned char mcor1 = 0, mcor2 = 0; + static unsigned long again; + unsigned long flags; + + func_enter(); + + tty = port->port.tty; + if (!tty || !tty->termios) { + func_exit(); + return; + } + + port->IER = 0; + port->COR2 = 0; + /* Select port on the board */ + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CAR, port_No(port)); + + /* The Specialix board doens't implement the RTS lines. + They are used to set the IRQ level. Don't touch them. */ + if (sx_crtscts(tty)) + port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); + else + port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); + spin_unlock_irqrestore(&bp->lock, flags); + dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); + baud = tty_get_baud_rate(tty); + + if (baud == 38400) { + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baud = 57600; + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baud = 115200; + } + + if (!baud) { + /* Drop DTR & exit */ + dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); + if (!sx_crtscts(tty)) { + port->MSVR &= ~MSVR_DTR; + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_MSVR, port->MSVR); + spin_unlock_irqrestore(&bp->lock, flags); + } else + dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); + return; + } else { + /* Set DTR on */ + if (!sx_crtscts(tty)) + port->MSVR |= MSVR_DTR; + } + + /* + * Now we must calculate some speed depended things + */ + + /* Set baud rate for port */ + tmp = port->custom_divisor ; + if (tmp) + printk(KERN_INFO + "sx%d: Using custom baud rate divisor %ld. \n" + "This is an untested option, please be careful.\n", + port_No(port), tmp); + else + tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / + CD186x_TPC); + + if (tmp < 0x10 && time_before(again, jiffies)) { + again = jiffies + HZ * 60; + /* Page 48 of version 2.0 of the CL-CD1865 databook */ + if (tmp >= 12) { + printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" + "Performance degradation is possible.\n" + "Read specialix.txt for more info.\n", + port_No(port), tmp); + } else { + printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" + "Warning: overstressing Cirrus chip. This might not work.\n" + "Read specialix.txt for more info.\n", port_No(port), tmp); + } + } + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); + sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); + sx_out(bp, CD186x_RBPRL, tmp & 0xff); + sx_out(bp, CD186x_TBPRL, tmp & 0xff); + spin_unlock_irqrestore(&bp->lock, flags); + if (port->custom_divisor) + baud = (SX_OSCFREQ + port->custom_divisor/2) / + port->custom_divisor; + baud = (baud + 5) / 10; /* Estimated CPS */ + + /* Two timer ticks seems enough to wakeup something like SLIP driver */ + tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; + port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? + SERIAL_XMIT_SIZE - 1 : tmp); + + /* Receiver timeout will be transmission time for 1.5 chars */ + tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud; + tmp = (tmp > 0xff) ? 0xff : tmp; + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_RTPR, tmp); + spin_unlock_irqrestore(&bp->lock, flags); + switch (C_CSIZE(tty)) { + case CS5: + cor1 |= COR1_5BITS; + break; + case CS6: + cor1 |= COR1_6BITS; + break; + case CS7: + cor1 |= COR1_7BITS; + break; + case CS8: + cor1 |= COR1_8BITS; + break; + } + + if (C_CSTOPB(tty)) + cor1 |= COR1_2SB; + + cor1 |= COR1_IGNORE; + if (C_PARENB(tty)) { + cor1 |= COR1_NORMPAR; + if (C_PARODD(tty)) + cor1 |= COR1_ODDP; + if (I_INPCK(tty)) + cor1 &= ~COR1_IGNORE; + } + /* Set marking of some errors */ + port->mark_mask = RCSR_OE | RCSR_TOUT; + if (I_INPCK(tty)) + port->mark_mask |= RCSR_FE | RCSR_PE; + if (I_BRKINT(tty) || I_PARMRK(tty)) + port->mark_mask |= RCSR_BREAK; + if (I_IGNPAR(tty)) + port->mark_mask &= ~(RCSR_FE | RCSR_PE); + if (I_IGNBRK(tty)) { + port->mark_mask &= ~RCSR_BREAK; + if (I_IGNPAR(tty)) + /* Real raw mode. Ignore all */ + port->mark_mask &= ~RCSR_OE; + } + /* Enable Hardware Flow Control */ + if (C_CRTSCTS(tty)) { +#ifdef SPECIALIX_BRAIN_DAMAGED_CTS + port->IER |= IER_DSR | IER_CTS; + mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; + mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; + spin_lock_irqsave(&bp->lock, flags); + tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & + (MSVR_CTS|MSVR_DSR)); + spin_unlock_irqrestore(&bp->lock, flags); +#else + port->COR2 |= COR2_CTSAE; +#endif + } + /* Enable Software Flow Control. FIXME: I'm not sure about this */ + /* Some people reported that it works, but I still doubt it */ + if (I_IXON(tty)) { + port->COR2 |= COR2_TXIBE; + cor3 |= (COR3_FCT | COR3_SCDE); + if (I_IXANY(tty)) + port->COR2 |= COR2_IXM; + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_SCHR1, START_CHAR(tty)); + sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty)); + sx_out(bp, CD186x_SCHR3, START_CHAR(tty)); + sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty)); + spin_unlock_irqrestore(&bp->lock, flags); + } + if (!C_CLOCAL(tty)) { + /* Enable CD check */ + port->IER |= IER_CD; + mcor1 |= MCOR1_CDZD; + mcor2 |= MCOR2_CDOD; + } + + if (C_CREAD(tty)) + /* Enable receiver */ + port->IER |= IER_RXD; + + /* Set input FIFO size (1-8 bytes) */ + cor3 |= sx_rxfifo; + /* Setting up CD186x channel registers */ + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_COR1, cor1); + sx_out(bp, CD186x_COR2, port->COR2); + sx_out(bp, CD186x_COR3, cor3); + spin_unlock_irqrestore(&bp->lock, flags); + /* Make CD186x know about registers change */ + sx_wait_CCR(bp); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); + /* Setting up modem option registers */ + dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", + mcor1, mcor2); + sx_out(bp, CD186x_MCOR1, mcor1); + sx_out(bp, CD186x_MCOR2, mcor2); + spin_unlock_irqrestore(&bp->lock, flags); + /* Enable CD186x transmitter & receiver */ + sx_wait_CCR(bp); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN); + /* Enable interrupts */ + sx_out(bp, CD186x_IER, port->IER); + /* And finally set the modem lines... */ + sx_out(bp, CD186x_MSVR, port->MSVR); + spin_unlock_irqrestore(&bp->lock, flags); + + func_exit(); +} + + +/* Must be called with interrupts enabled */ +static int sx_setup_port(struct specialix_board *bp, + struct specialix_port *port) +{ + unsigned long flags; + + func_enter(); + + if (port->port.flags & ASYNC_INITIALIZED) { + func_exit(); + return 0; + } + + if (!port->xmit_buf) { + /* We may sleep in get_zeroed_page() */ + unsigned long tmp; + + tmp = get_zeroed_page(GFP_KERNEL); + if (tmp == 0L) { + func_exit(); + return -ENOMEM; + } + + if (port->xmit_buf) { + free_page(tmp); + func_exit(); + return -ERESTARTSYS; + } + port->xmit_buf = (unsigned char *) tmp; + } + + spin_lock_irqsave(&port->lock, flags); + + if (port->port.tty) + clear_bit(TTY_IO_ERROR, &port->port.tty->flags); + + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + sx_change_speed(bp, port); + port->port.flags |= ASYNC_INITIALIZED; + + spin_unlock_irqrestore(&port->lock, flags); + + + func_exit(); + return 0; +} + + +/* Must be called with interrupts disabled */ +static void sx_shutdown_port(struct specialix_board *bp, + struct specialix_port *port) +{ + struct tty_struct *tty; + int i; + unsigned long flags; + + func_enter(); + + if (!(port->port.flags & ASYNC_INITIALIZED)) { + func_exit(); + return; + } + + if (sx_debug & SX_DEBUG_FIFO) { + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: %ld overruns, FIFO hits [ ", + board_No(bp), port_No(port), port->overrun); + for (i = 0; i < 10; i++) + dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); + dprintk(SX_DEBUG_FIFO, "].\n"); + } + + if (port->xmit_buf) { + free_page((unsigned long) port->xmit_buf); + port->xmit_buf = NULL; + } + + /* Select port */ + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CAR, port_No(port)); + + tty = port->port.tty; + if (tty == NULL || C_HUPCL(tty)) { + /* Drop DTR */ + sx_out(bp, CD186x_MSVDTR, 0); + } + spin_unlock_irqrestore(&bp->lock, flags); + /* Reset port */ + sx_wait_CCR(bp); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CCR, CCR_SOFTRESET); + /* Disable all interrupts from this port */ + port->IER = 0; + sx_out(bp, CD186x_IER, port->IER); + spin_unlock_irqrestore(&bp->lock, flags); + if (tty) + set_bit(TTY_IO_ERROR, &tty->flags); + port->port.flags &= ~ASYNC_INITIALIZED; + + if (!bp->count) + sx_shutdown_board(bp); + func_exit(); +} + + +static int block_til_ready(struct tty_struct *tty, struct file *filp, + struct specialix_port *port) +{ + DECLARE_WAITQUEUE(wait, current); + struct specialix_board *bp = port_Board(port); + int retval; + int do_clocal = 0; + int CD; + unsigned long flags; + + func_enter(); + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { + interruptible_sleep_on(&port->port.close_wait); + if (port->port.flags & ASYNC_HUP_NOTIFY) { + func_exit(); + return -EAGAIN; + } else { + func_exit(); + return -ERESTARTSYS; + } + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + port->port.flags |= ASYNC_NORMAL_ACTIVE; + func_exit(); + return 0; + } + + if (C_CLOCAL(tty)) + do_clocal = 1; + + /* + * 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 + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&port->port.open_wait, &wait); + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) + port->port.count--; + spin_unlock_irqrestore(&port->lock, flags); + port->port.blocked_open++; + while (1) { + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CAR, port_No(port)); + CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; + if (sx_crtscts(tty)) { + /* Activate RTS */ + port->MSVR |= MSVR_DTR; /* WTF? */ + sx_out(bp, CD186x_MSVR, port->MSVR); + } else { + /* Activate DTR */ + port->MSVR |= MSVR_DTR; + sx_out(bp, CD186x_MSVR, port->MSVR); + } + spin_unlock_irqrestore(&bp->lock, flags); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(port->port.flags & ASYNC_INITIALIZED)) { + if (port->port.flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + break; + } + if (!(port->port.flags & ASYNC_CLOSING) && + (do_clocal || CD)) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + tty_unlock(); + schedule(); + tty_lock(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->port.open_wait, &wait); + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) + port->port.count++; + port->port.blocked_open--; + spin_unlock_irqrestore(&port->lock, flags); + if (retval) { + func_exit(); + return retval; + } + + port->port.flags |= ASYNC_NORMAL_ACTIVE; + func_exit(); + return 0; +} + + +static int sx_open(struct tty_struct *tty, struct file *filp) +{ + int board; + int error; + struct specialix_port *port; + struct specialix_board *bp; + int i; + unsigned long flags; + + func_enter(); + + board = SX_BOARD(tty->index); + + if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) { + func_exit(); + return -ENODEV; + } + + bp = &sx_board[board]; + port = sx_port + board * SX_NPORT + SX_PORT(tty->index); + port->overrun = 0; + for (i = 0; i < 10; i++) + port->hits[i] = 0; + + dprintk(SX_DEBUG_OPEN, + "Board = %d, bp = %p, port = %p, portno = %d.\n", + board, bp, port, SX_PORT(tty->index)); + + if (sx_paranoia_check(port, tty->name, "sx_open")) { + func_enter(); + return -ENODEV; + } + + error = sx_setup_board(bp); + if (error) { + func_exit(); + return error; + } + + spin_lock_irqsave(&bp->lock, flags); + port->port.count++; + bp->count++; + tty->driver_data = port; + port->port.tty = tty; + spin_unlock_irqrestore(&bp->lock, flags); + + error = sx_setup_port(bp, port); + if (error) { + func_enter(); + return error; + } + + error = block_til_ready(tty, filp, port); + if (error) { + func_enter(); + return error; + } + + func_exit(); + return 0; +} + +static void sx_flush_buffer(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + unsigned long flags; + struct specialix_board *bp; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) { + func_exit(); + return; + } + + bp = port_Board(port); + spin_lock_irqsave(&port->lock, flags); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + spin_unlock_irqrestore(&port->lock, flags); + tty_wakeup(tty); + + func_exit(); +} + +static void sx_close(struct tty_struct *tty, struct file *filp) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned long flags; + unsigned long timeout; + + func_enter(); + if (!port || sx_paranoia_check(port, tty->name, "close")) { + func_exit(); + return; + } + spin_lock_irqsave(&port->lock, flags); + + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&port->lock, flags); + func_exit(); + return; + } + + bp = port_Board(port); + if (tty->count == 1 && port->port.count != 1) { + printk(KERN_ERR "sx%d: sx_close: bad port count;" + " tty->count is 1, port count is %d\n", + board_No(bp), port->port.count); + port->port.count = 1; + } + + if (port->port.count > 1) { + port->port.count--; + bp->count--; + + spin_unlock_irqrestore(&port->lock, flags); + + func_exit(); + return; + } + port->port.flags |= ASYNC_CLOSING; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + spin_unlock_irqrestore(&port->lock, flags); + dprintk(SX_DEBUG_OPEN, "Closing\n"); + if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, port->port.closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + dprintk(SX_DEBUG_OPEN, "Closed\n"); + port->IER &= ~IER_RXD; + if (port->port.flags & ASYNC_INITIALIZED) { + port->IER &= ~IER_TXRDY; + port->IER |= IER_TXEMPTY; + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CAR, port_No(port)); + sx_out(bp, CD186x_IER, port->IER); + spin_unlock_irqrestore(&bp->lock, flags); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + timeout = jiffies+HZ; + while (port->IER & IER_TXEMPTY) { + set_current_state(TASK_INTERRUPTIBLE); + msleep_interruptible(jiffies_to_msecs(port->timeout)); + if (time_after(jiffies, timeout)) { + printk(KERN_INFO "Timeout waiting for close\n"); + break; + } + } + + } + + if (--bp->count < 0) { + printk(KERN_ERR + "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", + board_No(bp), bp->count, tty->index); + bp->count = 0; + } + if (--port->port.count < 0) { + printk(KERN_ERR + "sx%d: sx_close: bad port count for tty%d: %d\n", + board_No(bp), port_No(port), port->port.count); + port->port.count = 0; + } + + sx_shutdown_port(bp, port); + sx_flush_buffer(tty); + tty_ldisc_flush(tty); + spin_lock_irqsave(&port->lock, flags); + tty->closing = 0; + port->port.tty = NULL; + spin_unlock_irqrestore(&port->lock, flags); + if (port->port.blocked_open) { + if (port->port.close_delay) + msleep_interruptible( + jiffies_to_msecs(port->port.close_delay)); + wake_up_interruptible(&port->port.open_wait); + } + port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&port->port.close_wait); + + func_exit(); +} + + +static int sx_write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + int c, total = 0; + unsigned long flags; + + func_enter(); + if (sx_paranoia_check(port, tty->name, "sx_write")) { + func_exit(); + return 0; + } + + bp = port_Board(port); + + if (!port->xmit_buf) { + func_exit(); + return 0; + } + + while (1) { + spin_lock_irqsave(&port->lock, flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { + spin_unlock_irqrestore(&port->lock, flags); + break; + } + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + spin_unlock_irqrestore(&port->lock, flags); + + buf += c; + count -= c; + total += c; + } + + spin_lock_irqsave(&bp->lock, flags); + if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && + !(port->IER & IER_TXRDY)) { + port->IER |= IER_TXRDY; + sx_out(bp, CD186x_CAR, port_No(port)); + sx_out(bp, CD186x_IER, port->IER); + } + spin_unlock_irqrestore(&bp->lock, flags); + func_exit(); + + return total; +} + + +static int sx_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct specialix_port *port = tty->driver_data; + unsigned long flags; + struct specialix_board *bp; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_put_char")) { + func_exit(); + return 0; + } + dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); + if (!port->xmit_buf) { + func_exit(); + return 0; + } + bp = port_Board(port); + spin_lock_irqsave(&port->lock, flags); + + dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", + port->xmit_cnt, port->xmit_buf); + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { + spin_unlock_irqrestore(&port->lock, flags); + dprintk(SX_DEBUG_TX, "Exit size\n"); + func_exit(); + return 0; + } + dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); + port->xmit_buf[port->xmit_head++] = ch; + port->xmit_head &= SERIAL_XMIT_SIZE - 1; + port->xmit_cnt++; + spin_unlock_irqrestore(&port->lock, flags); + + func_exit(); + return 1; +} + + +static void sx_flush_chars(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + unsigned long flags; + struct specialix_board *bp = port_Board(port); + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) { + func_exit(); + return; + } + if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !port->xmit_buf) { + func_exit(); + return; + } + spin_lock_irqsave(&bp->lock, flags); + port->IER |= IER_TXRDY; + sx_out(port_Board(port), CD186x_CAR, port_No(port)); + sx_out(port_Board(port), CD186x_IER, port->IER); + spin_unlock_irqrestore(&bp->lock, flags); + + func_exit(); +} + + +static int sx_write_room(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + int ret; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_write_room")) { + func_exit(); + return 0; + } + + ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; + if (ret < 0) + ret = 0; + + func_exit(); + return ret; +} + + +static int sx_chars_in_buffer(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) { + func_exit(); + return 0; + } + func_exit(); + return port->xmit_cnt; +} + +static int sx_tiocmget(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned char status; + unsigned int result; + unsigned long flags; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, __func__)) { + func_exit(); + return -ENODEV; + } + + bp = port_Board(port); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CAR, port_No(port)); + status = sx_in(bp, CD186x_MSVR); + spin_unlock_irqrestore(&bp->lock, flags); + dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", + port_No(port), status, sx_in(bp, CD186x_CAR)); + dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); + if (sx_crtscts(port->port.tty)) { + result = TIOCM_DTR | TIOCM_DSR + | ((status & MSVR_DTR) ? TIOCM_RTS : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + } else { + result = TIOCM_RTS | TIOCM_DSR + | ((status & MSVR_DTR) ? TIOCM_DTR : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + } + + func_exit(); + + return result; +} + + +static int sx_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct specialix_port *port = tty->driver_data; + unsigned long flags; + struct specialix_board *bp; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, __func__)) { + func_exit(); + return -ENODEV; + } + + bp = port_Board(port); + + spin_lock_irqsave(&port->lock, flags); + if (sx_crtscts(port->port.tty)) { + if (set & TIOCM_RTS) + port->MSVR |= MSVR_DTR; + } else { + if (set & TIOCM_DTR) + port->MSVR |= MSVR_DTR; + } + if (sx_crtscts(port->port.tty)) { + if (clear & TIOCM_RTS) + port->MSVR &= ~MSVR_DTR; + } else { + if (clear & TIOCM_DTR) + port->MSVR &= ~MSVR_DTR; + } + spin_lock(&bp->lock); + sx_out(bp, CD186x_CAR, port_No(port)); + sx_out(bp, CD186x_MSVR, port->MSVR); + spin_unlock(&bp->lock); + spin_unlock_irqrestore(&port->lock, flags); + func_exit(); + return 0; +} + + +static int sx_send_break(struct tty_struct *tty, int length) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp = port_Board(port); + unsigned long flags; + + func_enter(); + if (length == 0 || length == -1) + return -EOPNOTSUPP; + + spin_lock_irqsave(&port->lock, flags); + port->break_length = SPECIALIX_TPS / HZ * length; + port->COR2 |= COR2_ETC; + port->IER |= IER_TXRDY; + spin_lock(&bp->lock); + sx_out(bp, CD186x_CAR, port_No(port)); + sx_out(bp, CD186x_COR2, port->COR2); + sx_out(bp, CD186x_IER, port->IER); + spin_unlock(&bp->lock); + spin_unlock_irqrestore(&port->lock, flags); + sx_wait_CCR(bp); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CCR, CCR_CORCHG2); + spin_unlock_irqrestore(&bp->lock, flags); + sx_wait_CCR(bp); + + func_exit(); + return 0; +} + + +static int sx_set_serial_info(struct specialix_port *port, + struct serial_struct __user *newinfo) +{ + struct serial_struct tmp; + struct specialix_board *bp = port_Board(port); + int change_speed; + + func_enter(); + + if (copy_from_user(&tmp, newinfo, sizeof(tmp))) { + func_enter(); + return -EFAULT; + } + + mutex_lock(&port->port.mutex); + change_speed = ((port->port.flags & ASYNC_SPD_MASK) != + (tmp.flags & ASYNC_SPD_MASK)); + change_speed |= (tmp.custom_divisor != port->custom_divisor); + + if (!capable(CAP_SYS_ADMIN)) { + if ((tmp.close_delay != port->port.close_delay) || + (tmp.closing_wait != port->port.closing_wait) || + ((tmp.flags & ~ASYNC_USR_MASK) != + (port->port.flags & ~ASYNC_USR_MASK))) { + func_exit(); + mutex_unlock(&port->port.mutex); + return -EPERM; + } + port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | + (tmp.flags & ASYNC_USR_MASK)); + port->custom_divisor = tmp.custom_divisor; + } else { + port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | + (tmp.flags & ASYNC_FLAGS)); + port->port.close_delay = tmp.close_delay; + port->port.closing_wait = tmp.closing_wait; + port->custom_divisor = tmp.custom_divisor; + } + if (change_speed) + sx_change_speed(bp, port); + + func_exit(); + mutex_unlock(&port->port.mutex); + return 0; +} + + +static int sx_get_serial_info(struct specialix_port *port, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + struct specialix_board *bp = port_Board(port); + + func_enter(); + + memset(&tmp, 0, sizeof(tmp)); + mutex_lock(&port->port.mutex); + tmp.type = PORT_CIRRUS; + tmp.line = port - sx_port; + tmp.port = bp->base; + tmp.irq = bp->irq; + tmp.flags = port->port.flags; + tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC; + tmp.close_delay = port->port.close_delay * HZ/100; + tmp.closing_wait = port->port.closing_wait * HZ/100; + tmp.custom_divisor = port->custom_divisor; + tmp.xmit_fifo_size = CD186x_NFIFO; + mutex_unlock(&port->port.mutex); + if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { + func_exit(); + return -EFAULT; + } + + func_exit(); + return 0; +} + + +static int sx_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct specialix_port *port = tty->driver_data; + void __user *argp = (void __user *)arg; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_ioctl")) { + func_exit(); + return -ENODEV; + } + + switch (cmd) { + case TIOCGSERIAL: + func_exit(); + return sx_get_serial_info(port, argp); + case TIOCSSERIAL: + func_exit(); + return sx_set_serial_info(port, argp); + default: + func_exit(); + return -ENOIOCTLCMD; + } + func_exit(); + return 0; +} + + +static void sx_throttle(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned long flags; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_throttle")) { + func_exit(); + return; + } + + bp = port_Board(port); + + /* Use DTR instead of RTS ! */ + if (sx_crtscts(tty)) + port->MSVR &= ~MSVR_DTR; + else { + /* Auch!!! I think the system shouldn't call this then. */ + /* Or maybe we're supposed (allowed?) to do our side of hw + handshake anyway, even when hardware handshake is off. + When you see this in your logs, please report.... */ + printk(KERN_ERR + "sx%d: Need to throttle, but can't (hardware hs is off)\n", + port_No(port)); + } + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CAR, port_No(port)); + spin_unlock_irqrestore(&bp->lock, flags); + if (I_IXOFF(tty)) { + sx_wait_CCR(bp); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CCR, CCR_SSCH2); + spin_unlock_irqrestore(&bp->lock, flags); + sx_wait_CCR(bp); + } + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_MSVR, port->MSVR); + spin_unlock_irqrestore(&bp->lock, flags); + + func_exit(); +} + + +static void sx_unthrottle(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned long flags; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) { + func_exit(); + return; + } + + bp = port_Board(port); + + spin_lock_irqsave(&port->lock, flags); + /* XXXX Use DTR INSTEAD???? */ + if (sx_crtscts(tty)) + port->MSVR |= MSVR_DTR; + /* Else clause: see remark in "sx_throttle"... */ + spin_lock(&bp->lock); + sx_out(bp, CD186x_CAR, port_No(port)); + spin_unlock(&bp->lock); + if (I_IXOFF(tty)) { + spin_unlock_irqrestore(&port->lock, flags); + sx_wait_CCR(bp); + spin_lock_irqsave(&bp->lock, flags); + sx_out(bp, CD186x_CCR, CCR_SSCH1); + spin_unlock_irqrestore(&bp->lock, flags); + sx_wait_CCR(bp); + spin_lock_irqsave(&port->lock, flags); + } + spin_lock(&bp->lock); + sx_out(bp, CD186x_MSVR, port->MSVR); + spin_unlock(&bp->lock); + spin_unlock_irqrestore(&port->lock, flags); + + func_exit(); +} + + +static void sx_stop(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned long flags; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_stop")) { + func_exit(); + return; + } + + bp = port_Board(port); + + spin_lock_irqsave(&port->lock, flags); + port->IER &= ~IER_TXRDY; + spin_lock(&bp->lock); + sx_out(bp, CD186x_CAR, port_No(port)); + sx_out(bp, CD186x_IER, port->IER); + spin_unlock(&bp->lock); + spin_unlock_irqrestore(&port->lock, flags); + + func_exit(); +} + + +static void sx_start(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned long flags; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_start")) { + func_exit(); + return; + } + + bp = port_Board(port); + + spin_lock_irqsave(&port->lock, flags); + if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { + port->IER |= IER_TXRDY; + spin_lock(&bp->lock); + sx_out(bp, CD186x_CAR, port_No(port)); + sx_out(bp, CD186x_IER, port->IER); + spin_unlock(&bp->lock); + } + spin_unlock_irqrestore(&port->lock, flags); + + func_exit(); +} + +static void sx_hangup(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; + unsigned long flags; + + func_enter(); + + if (sx_paranoia_check(port, tty->name, "sx_hangup")) { + func_exit(); + return; + } + + bp = port_Board(port); + + sx_shutdown_port(bp, port); + spin_lock_irqsave(&port->lock, flags); + bp->count -= port->port.count; + if (bp->count < 0) { + printk(KERN_ERR + "sx%d: sx_hangup: bad board count: %d port: %d\n", + board_No(bp), bp->count, tty->index); + bp->count = 0; + } + port->port.count = 0; + port->port.flags &= ~ASYNC_NORMAL_ACTIVE; + port->port.tty = NULL; + spin_unlock_irqrestore(&port->lock, flags); + wake_up_interruptible(&port->port.open_wait); + + func_exit(); +} + + +static void sx_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) +{ + struct specialix_port *port = tty->driver_data; + unsigned long flags; + struct specialix_board *bp; + + if (sx_paranoia_check(port, tty->name, "sx_set_termios")) + return; + + bp = port_Board(port); + spin_lock_irqsave(&port->lock, flags); + sx_change_speed(port_Board(port), port); + spin_unlock_irqrestore(&port->lock, flags); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + sx_start(tty); + } +} + +static const struct tty_operations sx_ops = { + .open = sx_open, + .close = sx_close, + .write = sx_write, + .put_char = sx_put_char, + .flush_chars = sx_flush_chars, + .write_room = sx_write_room, + .chars_in_buffer = sx_chars_in_buffer, + .flush_buffer = sx_flush_buffer, + .ioctl = sx_ioctl, + .throttle = sx_throttle, + .unthrottle = sx_unthrottle, + .set_termios = sx_set_termios, + .stop = sx_stop, + .start = sx_start, + .hangup = sx_hangup, + .tiocmget = sx_tiocmget, + .tiocmset = sx_tiocmset, + .break_ctl = sx_send_break, +}; + +static int sx_init_drivers(void) +{ + int error; + int i; + + func_enter(); + + specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT); + if (!specialix_driver) { + printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n"); + func_exit(); + return 1; + } + + specialix_driver->owner = THIS_MODULE; + specialix_driver->name = "ttyW"; + specialix_driver->major = SPECIALIX_NORMAL_MAJOR; + specialix_driver->type = TTY_DRIVER_TYPE_SERIAL; + specialix_driver->subtype = SERIAL_TYPE_NORMAL; + specialix_driver->init_termios = tty_std_termios; + specialix_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + specialix_driver->init_termios.c_ispeed = 9600; + specialix_driver->init_termios.c_ospeed = 9600; + specialix_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_HARDWARE_BREAK; + tty_set_operations(specialix_driver, &sx_ops); + + error = tty_register_driver(specialix_driver); + if (error) { + put_tty_driver(specialix_driver); + printk(KERN_ERR + "sx: Couldn't register specialix IO8+ driver, error = %d\n", + error); + func_exit(); + return 1; + } + memset(sx_port, 0, sizeof(sx_port)); + for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { + sx_port[i].magic = SPECIALIX_MAGIC; + tty_port_init(&sx_port[i].port); + spin_lock_init(&sx_port[i].lock); + } + + func_exit(); + return 0; +} + +static void sx_release_drivers(void) +{ + func_enter(); + + tty_unregister_driver(specialix_driver); + put_tty_driver(specialix_driver); + func_exit(); +} + +/* + * This routine must be called by kernel at boot time + */ +static int __init specialix_init(void) +{ + int i; + int found = 0; + + func_enter(); + + printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); + printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); + if (sx_rtscts) + printk(KERN_INFO + "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); + else + printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); + + for (i = 0; i < SX_NBOARD; i++) + spin_lock_init(&sx_board[i].lock); + + if (sx_init_drivers()) { + func_exit(); + return -EIO; + } + + for (i = 0; i < SX_NBOARD; i++) + if (sx_board[i].base && !sx_probe(&sx_board[i])) + found++; + +#ifdef CONFIG_PCI + { + struct pci_dev *pdev = NULL; + + i = 0; + while (i < SX_NBOARD) { + if (sx_board[i].flags & SX_BOARD_PRESENT) { + i++; + continue; + } + pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, + PCI_DEVICE_ID_SPECIALIX_IO8, pdev); + if (!pdev) + break; + + if (pci_enable_device(pdev)) + continue; + + sx_board[i].irq = pdev->irq; + + sx_board[i].base = pci_resource_start(pdev, 2); + + sx_board[i].flags |= SX_BOARD_IS_PCI; + if (!sx_probe(&sx_board[i])) + found++; + } + /* May exit pci_get sequence early with lots of boards */ + if (pdev != NULL) + pci_dev_put(pdev); + } +#endif + + if (!found) { + sx_release_drivers(); + printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n"); + func_exit(); + return -EIO; + } + + func_exit(); + return 0; +} + +static int iobase[SX_NBOARD] = {0,}; +static int irq[SX_NBOARD] = {0,}; + +module_param_array(iobase, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param(sx_debug, int, 0); +module_param(sx_rtscts, int, 0); +module_param(sx_rxfifo, int, 0); + +/* + * You can setup up to 4 boards. + * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter. + * You should specify the IRQs too in that case "irq=....,...". + * + * More than 4 boards in one computer is not possible, as the card can + * only use 4 different interrupts. + * + */ +static int __init specialix_init_module(void) +{ + int i; + + func_enter(); + + if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { + for (i = 0; i < SX_NBOARD; i++) { + sx_board[i].base = iobase[i]; + sx_board[i].irq = irq[i]; + sx_board[i].count = 0; + } + } + + func_exit(); + + return specialix_init(); +} + +static void __exit specialix_exit_module(void) +{ + int i; + + func_enter(); + + sx_release_drivers(); + for (i = 0; i < SX_NBOARD; i++) + if (sx_board[i].flags & SX_BOARD_PRESENT) + sx_release_io_range(&sx_board[i]); + func_exit(); +} + +static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = { + { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) }, + { } +}; +MODULE_DEVICE_TABLE(pci, specialx_pci_tbl); + +module_init(specialix_init_module); +module_exit(specialix_exit_module); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR); diff --git a/drivers/staging/tty/specialix_io8.h b/drivers/staging/tty/specialix_io8.h new file mode 100644 index 000000000000..c63005274d9b --- /dev/null +++ b/drivers/staging/tty/specialix_io8.h @@ -0,0 +1,140 @@ +/* + * linux/drivers/char/specialix_io8.h -- + * Specialix IO8+ multiport serial driver. + * + * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) + * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) + * + * + * Specialix pays for the development and support of this driver. + * Please DO contact io8-linux@specialix.co.uk if you require + * support. + * + * This driver was developped in the BitWizard linux device + * driver service. If you require a linux device driver for your + * product, please contact devices@BitWizard.nl for a quote. + * + * This code is firmly based on the riscom/8 serial driver, + * written by Dmitry Gorodchanin. The specialix IO8+ card + * programming information was obtained from the CL-CD1865 Data + * Book, and Specialix document number 6200059: IO8+ Hardware + * Functional Specification. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * */ + +#ifndef __LINUX_SPECIALIX_H +#define __LINUX_SPECIALIX_H + +#include + +#ifdef __KERNEL__ + +/* You can have max 4 ISA cards in one PC, and I recommend not much +more than a few PCI versions of the card. */ + +#define SX_NBOARD 8 + +/* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */ +#define SX_IO_SPACE 4 +/* The PCI version decodes 8 addresses, but still only 2 are used. */ +#define SX_PCI_IO_SPACE 8 + +/* eight ports per board. */ +#define SX_NPORT 8 +#define SX_BOARD(line) ((line) / SX_NPORT) +#define SX_PORT(line) ((line) & (SX_NPORT - 1)) + + +#define SX_DATA_REG 0 /* Base+0 : Data register */ +#define SX_ADDR_REG 1 /* base+1 : Address register. */ + +#define MHz *1000000 /* I'm ashamed of myself. */ + +/* On-board oscillator frequency */ +#define SX_OSCFREQ (25 MHz/2) +/* There is a 25MHz crystal on the board, but the chip is in /2 mode */ + + +/* Ticks per sec. Used for setting receiver timeout and break length */ +#define SPECIALIX_TPS 4000 + +/* Yeah, after heavy testing I decided it must be 6. + * Sure, You can change it if needed. + */ +#define SPECIALIX_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ + +#define SPECIALIX_MAGIC 0x0907 + +#define SX_CCR_TIMEOUT 10000 /* CCR timeout. You may need to wait upto + 10 milliseconds before the internal + processor is available again after + you give it a command */ + +#define SX_IOBASE1 0x100 +#define SX_IOBASE2 0x180 +#define SX_IOBASE3 0x250 +#define SX_IOBASE4 0x260 + +struct specialix_board { + unsigned long flags; + unsigned short base; + unsigned char irq; + //signed char count; + int count; + unsigned char DTR; + int reg; + spinlock_t lock; +}; + +#define SX_BOARD_PRESENT 0x00000001 +#define SX_BOARD_ACTIVE 0x00000002 +#define SX_BOARD_IS_PCI 0x00000004 + + +struct specialix_port { + int magic; + struct tty_port port; + int baud_base; + int flags; + int timeout; + unsigned char * xmit_buf; + int custom_divisor; + int xmit_head; + int xmit_tail; + int xmit_cnt; + short wakeup_chars; + short break_length; + unsigned char mark_mask; + unsigned char IER; + unsigned char MSVR; + unsigned char COR2; + unsigned long overrun; + unsigned long hits[10]; + spinlock_t lock; +}; + +#endif /* __KERNEL__ */ +#endif /* __LINUX_SPECIALIX_H */ + + + + + + + + + diff --git a/drivers/staging/tty/stallion.c b/drivers/staging/tty/stallion.c new file mode 100644 index 000000000000..4fff5cd3b163 --- /dev/null +++ b/drivers/staging/tty/stallion.c @@ -0,0 +1,4651 @@ +/*****************************************************************************/ + +/* + * stallion.c -- stallion multiport serial driver. + * + * Copyright (C) 1996-1999 Stallion Technologies + * Copyright (C) 1994-1996 Greg Ungerer. + * + * This code is loosely based on the Linux serial driver, written by + * Linus Torvalds, Theodore T'so and others. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/*****************************************************************************/ + +/* + * Define different board types. Use the standard Stallion "assigned" + * board numbers. Boards supported in this driver are abbreviated as + * EIO = EasyIO and ECH = EasyConnection 8/32. + */ +#define BRD_EASYIO 20 +#define BRD_ECH 21 +#define BRD_ECHMC 22 +#define BRD_ECHPCI 26 +#define BRD_ECH64PCI 27 +#define BRD_EASYIOPCI 28 + +struct stlconf { + unsigned int brdtype; + int ioaddr1; + int ioaddr2; + unsigned long memaddr; + int irq; + int irqtype; +}; + +static unsigned int stl_nrbrds; + +/*****************************************************************************/ + +/* + * Define some important driver characteristics. Device major numbers + * allocated as per Linux Device Registry. + */ +#ifndef STL_SIOMEMMAJOR +#define STL_SIOMEMMAJOR 28 +#endif +#ifndef STL_SERIALMAJOR +#define STL_SERIALMAJOR 24 +#endif +#ifndef STL_CALLOUTMAJOR +#define STL_CALLOUTMAJOR 25 +#endif + +/* + * Set the TX buffer size. Bigger is better, but we don't want + * to chew too much memory with buffers! + */ +#define STL_TXBUFLOW 512 +#define STL_TXBUFSIZE 4096 + +/*****************************************************************************/ + +/* + * Define our local driver identity first. Set up stuff to deal with + * all the local structures required by a serial tty driver. + */ +static char *stl_drvtitle = "Stallion Multiport Serial Driver"; +static char *stl_drvname = "stallion"; +static char *stl_drvversion = "5.6.0"; + +static struct tty_driver *stl_serial; + +/* + * Define a local default termios struct. All ports will be created + * with this termios initially. Basically all it defines is a raw port + * at 9600, 8 data bits, 1 stop bit. + */ +static struct ktermios stl_deftermios = { + .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), + .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, +}; + +/* + * Define global place to put buffer overflow characters. + */ +static char stl_unwanted[SC26198_RXFIFOSIZE]; + +/*****************************************************************************/ + +static DEFINE_MUTEX(stl_brdslock); +static struct stlbrd *stl_brds[STL_MAXBRDS]; + +static const struct tty_port_operations stl_port_ops; + +/* + * Per board state flags. Used with the state field of the board struct. + * Not really much here! + */ +#define BRD_FOUND 0x1 +#define STL_PROBED 0x2 + + +/* + * Define the port structure istate flags. These set of flags are + * modified at interrupt time - so setting and reseting them needs + * to be atomic. Use the bit clear/setting routines for this. + */ +#define ASYI_TXBUSY 1 +#define ASYI_TXLOW 2 +#define ASYI_TXFLOWED 3 + +/* + * Define an array of board names as printable strings. Handy for + * referencing boards when printing trace and stuff. + */ +static char *stl_brdnames[] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "EasyIO", + "EC8/32-AT", + "EC8/32-MC", + NULL, + NULL, + NULL, + "EC8/32-PCI", + "EC8/64-PCI", + "EasyIO-PCI", +}; + +/*****************************************************************************/ + +/* + * Define some string labels for arguments passed from the module + * load line. These allow for easy board definitions, and easy + * modification of the io, memory and irq resoucres. + */ +static unsigned int stl_nargs; +static char *board0[4]; +static char *board1[4]; +static char *board2[4]; +static char *board3[4]; + +static char **stl_brdsp[] = { + (char **) &board0, + (char **) &board1, + (char **) &board2, + (char **) &board3 +}; + +/* + * Define a set of common board names, and types. This is used to + * parse any module arguments. + */ + +static struct { + char *name; + int type; +} stl_brdstr[] = { + { "easyio", BRD_EASYIO }, + { "eio", BRD_EASYIO }, + { "20", BRD_EASYIO }, + { "ec8/32", BRD_ECH }, + { "ec8/32-at", BRD_ECH }, + { "ec8/32-isa", BRD_ECH }, + { "ech", BRD_ECH }, + { "echat", BRD_ECH }, + { "21", BRD_ECH }, + { "ec8/32-mc", BRD_ECHMC }, + { "ec8/32-mca", BRD_ECHMC }, + { "echmc", BRD_ECHMC }, + { "echmca", BRD_ECHMC }, + { "22", BRD_ECHMC }, + { "ec8/32-pc", BRD_ECHPCI }, + { "ec8/32-pci", BRD_ECHPCI }, + { "26", BRD_ECHPCI }, + { "ec8/64-pc", BRD_ECH64PCI }, + { "ec8/64-pci", BRD_ECH64PCI }, + { "ech-pci", BRD_ECH64PCI }, + { "echpci", BRD_ECH64PCI }, + { "echpc", BRD_ECH64PCI }, + { "27", BRD_ECH64PCI }, + { "easyio-pc", BRD_EASYIOPCI }, + { "easyio-pci", BRD_EASYIOPCI }, + { "eio-pci", BRD_EASYIOPCI }, + { "eiopci", BRD_EASYIOPCI }, + { "28", BRD_EASYIOPCI }, +}; + +/* + * Define the module agruments. + */ + +module_param_array(board0, charp, &stl_nargs, 0); +MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); +module_param_array(board1, charp, &stl_nargs, 0); +MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]"); +module_param_array(board2, charp, &stl_nargs, 0); +MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]"); +module_param_array(board3, charp, &stl_nargs, 0); +MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]"); + +/*****************************************************************************/ + +/* + * Hardware ID bits for the EasyIO and ECH boards. These defines apply + * to the directly accessible io ports of these boards (not the uarts - + * they are in cd1400.h and sc26198.h). + */ +#define EIO_8PORTRS 0x04 +#define EIO_4PORTRS 0x05 +#define EIO_8PORTDI 0x00 +#define EIO_8PORTM 0x06 +#define EIO_MK3 0x03 +#define EIO_IDBITMASK 0x07 + +#define EIO_BRDMASK 0xf0 +#define ID_BRD4 0x10 +#define ID_BRD8 0x20 +#define ID_BRD16 0x30 + +#define EIO_INTRPEND 0x08 +#define EIO_INTEDGE 0x00 +#define EIO_INTLEVEL 0x08 +#define EIO_0WS 0x10 + +#define ECH_ID 0xa0 +#define ECH_IDBITMASK 0xe0 +#define ECH_BRDENABLE 0x08 +#define ECH_BRDDISABLE 0x00 +#define ECH_INTENABLE 0x01 +#define ECH_INTDISABLE 0x00 +#define ECH_INTLEVEL 0x02 +#define ECH_INTEDGE 0x00 +#define ECH_INTRPEND 0x01 +#define ECH_BRDRESET 0x01 + +#define ECHMC_INTENABLE 0x01 +#define ECHMC_BRDRESET 0x02 + +#define ECH_PNLSTATUS 2 +#define ECH_PNL16PORT 0x20 +#define ECH_PNLIDMASK 0x07 +#define ECH_PNLXPID 0x40 +#define ECH_PNLINTRPEND 0x80 + +#define ECH_ADDR2MASK 0x1e0 + +/* + * Define the vector mapping bits for the programmable interrupt board + * hardware. These bits encode the interrupt for the board to use - it + * is software selectable (except the EIO-8M). + */ +static unsigned char stl_vecmap[] = { + 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07, + 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03 +}; + +/* + * Lock ordering is that you may not take stallion_lock holding + * brd_lock. + */ + +static spinlock_t brd_lock; /* Guard the board mapping */ +static spinlock_t stallion_lock; /* Guard the tty driver */ + +/* + * Set up enable and disable macros for the ECH boards. They require + * the secondary io address space to be activated and deactivated. + * This way all ECH boards can share their secondary io region. + * If this is an ECH-PCI board then also need to set the page pointer + * to point to the correct page. + */ +#define BRDENABLE(brdnr,pagenr) \ + if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ + outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \ + stl_brds[(brdnr)]->ioctrl); \ + else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \ + outb((pagenr), stl_brds[(brdnr)]->ioctrl); + +#define BRDDISABLE(brdnr) \ + if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ + outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \ + stl_brds[(brdnr)]->ioctrl); + +#define STL_CD1400MAXBAUD 230400 +#define STL_SC26198MAXBAUD 460800 + +#define STL_BAUDBASE 115200 +#define STL_CLOSEDELAY (5 * HZ / 10) + +/*****************************************************************************/ + +/* + * Define the Stallion PCI vendor and device IDs. + */ +#ifndef PCI_VENDOR_ID_STALLION +#define PCI_VENDOR_ID_STALLION 0x124d +#endif +#ifndef PCI_DEVICE_ID_ECHPCI832 +#define PCI_DEVICE_ID_ECHPCI832 0x0000 +#endif +#ifndef PCI_DEVICE_ID_ECHPCI864 +#define PCI_DEVICE_ID_ECHPCI864 0x0002 +#endif +#ifndef PCI_DEVICE_ID_EIOPCI +#define PCI_DEVICE_ID_EIOPCI 0x0003 +#endif + +/* + * Define structure to hold all Stallion PCI boards. + */ + +static struct pci_device_id stl_pcibrds[] = { + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864), + .driver_data = BRD_ECH64PCI }, + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI), + .driver_data = BRD_EASYIOPCI }, + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832), + .driver_data = BRD_ECHPCI }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), + .driver_data = BRD_ECHPCI }, + { } +}; +MODULE_DEVICE_TABLE(pci, stl_pcibrds); + +/*****************************************************************************/ + +/* + * Define macros to extract a brd/port number from a minor number. + */ +#define MINOR2BRD(min) (((min) & 0xc0) >> 6) +#define MINOR2PORT(min) ((min) & 0x3f) + +/* + * Define a baud rate table that converts termios baud rate selector + * into the actual baud rate value. All baud rate calculations are + * based on the actual baud rate required. + */ +static unsigned int stl_baudrates[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 +}; + +/*****************************************************************************/ + +/* + * Declare all those functions in this driver! + */ + +static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); +static int stl_brdinit(struct stlbrd *brdp); +static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); +static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); + +/* + * CD1400 uart specific handling functions. + */ +static void stl_cd1400setreg(struct stlport *portp, int regnr, int value); +static int stl_cd1400getreg(struct stlport *portp, int regnr); +static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value); +static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp); +static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp); +static int stl_cd1400getsignals(struct stlport *portp); +static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts); +static void stl_cd1400ccrwait(struct stlport *portp); +static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx); +static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx); +static void stl_cd1400disableintrs(struct stlport *portp); +static void stl_cd1400sendbreak(struct stlport *portp, int len); +static void stl_cd1400flowctrl(struct stlport *portp, int state); +static void stl_cd1400sendflow(struct stlport *portp, int state); +static void stl_cd1400flush(struct stlport *portp); +static int stl_cd1400datastate(struct stlport *portp); +static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase); +static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase); +static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr); +static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr); +static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr); + +static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr); + +/* + * SC26198 uart specific handling functions. + */ +static void stl_sc26198setreg(struct stlport *portp, int regnr, int value); +static int stl_sc26198getreg(struct stlport *portp, int regnr); +static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value); +static int stl_sc26198getglobreg(struct stlport *portp, int regnr); +static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp); +static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp); +static int stl_sc26198getsignals(struct stlport *portp); +static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts); +static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx); +static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx); +static void stl_sc26198disableintrs(struct stlport *portp); +static void stl_sc26198sendbreak(struct stlport *portp, int len); +static void stl_sc26198flowctrl(struct stlport *portp, int state); +static void stl_sc26198sendflow(struct stlport *portp, int state); +static void stl_sc26198flush(struct stlport *portp); +static int stl_sc26198datastate(struct stlport *portp); +static void stl_sc26198wait(struct stlport *portp); +static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty); +static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase); +static void stl_sc26198txisr(struct stlport *port); +static void stl_sc26198rxisr(struct stlport *port, unsigned int iack); +static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch); +static void stl_sc26198rxbadchars(struct stlport *portp); +static void stl_sc26198otherisr(struct stlport *port, unsigned int iack); + +/*****************************************************************************/ + +/* + * Generic UART support structure. + */ +typedef struct uart { + int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp); + void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); + void (*setport)(struct stlport *portp, struct ktermios *tiosp); + int (*getsignals)(struct stlport *portp); + void (*setsignals)(struct stlport *portp, int dtr, int rts); + void (*enablerxtx)(struct stlport *portp, int rx, int tx); + void (*startrxtx)(struct stlport *portp, int rx, int tx); + void (*disableintrs)(struct stlport *portp); + void (*sendbreak)(struct stlport *portp, int len); + void (*flowctrl)(struct stlport *portp, int state); + void (*sendflow)(struct stlport *portp, int state); + void (*flush)(struct stlport *portp); + int (*datastate)(struct stlport *portp); + void (*intr)(struct stlpanel *panelp, unsigned int iobase); +} uart_t; + +/* + * Define some macros to make calling these functions nice and clean. + */ +#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit) +#define stl_portinit (* ((uart_t *) portp->uartp)->portinit) +#define stl_setport (* ((uart_t *) portp->uartp)->setport) +#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals) +#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals) +#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx) +#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx) +#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs) +#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak) +#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl) +#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow) +#define stl_flush (* ((uart_t *) portp->uartp)->flush) +#define stl_datastate (* ((uart_t *) portp->uartp)->datastate) + +/*****************************************************************************/ + +/* + * CD1400 UART specific data initialization. + */ +static uart_t stl_cd1400uart = { + stl_cd1400panelinit, + stl_cd1400portinit, + stl_cd1400setport, + stl_cd1400getsignals, + stl_cd1400setsignals, + stl_cd1400enablerxtx, + stl_cd1400startrxtx, + stl_cd1400disableintrs, + stl_cd1400sendbreak, + stl_cd1400flowctrl, + stl_cd1400sendflow, + stl_cd1400flush, + stl_cd1400datastate, + stl_cd1400eiointr +}; + +/* + * Define the offsets within the register bank of a cd1400 based panel. + * These io address offsets are common to the EasyIO board as well. + */ +#define EREG_ADDR 0 +#define EREG_DATA 4 +#define EREG_RXACK 5 +#define EREG_TXACK 6 +#define EREG_MDACK 7 + +#define EREG_BANKSIZE 8 + +#define CD1400_CLK 25000000 +#define CD1400_CLK8M 20000000 + +/* + * Define the cd1400 baud rate clocks. These are used when calculating + * what clock and divisor to use for the required baud rate. Also + * define the maximum baud rate allowed, and the default base baud. + */ +static int stl_cd1400clkdivs[] = { + CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4 +}; + +/*****************************************************************************/ + +/* + * SC26198 UART specific data initization. + */ +static uart_t stl_sc26198uart = { + stl_sc26198panelinit, + stl_sc26198portinit, + stl_sc26198setport, + stl_sc26198getsignals, + stl_sc26198setsignals, + stl_sc26198enablerxtx, + stl_sc26198startrxtx, + stl_sc26198disableintrs, + stl_sc26198sendbreak, + stl_sc26198flowctrl, + stl_sc26198sendflow, + stl_sc26198flush, + stl_sc26198datastate, + stl_sc26198intr +}; + +/* + * Define the offsets within the register bank of a sc26198 based panel. + */ +#define XP_DATA 0 +#define XP_ADDR 1 +#define XP_MODID 2 +#define XP_STATUS 2 +#define XP_IACK 3 + +#define XP_BANKSIZE 4 + +/* + * Define the sc26198 baud rate table. Offsets within the table + * represent the actual baud rate selector of sc26198 registers. + */ +static unsigned int sc26198_baudtable[] = { + 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600, + 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, + 230400, 460800, 921600 +}; + +#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable) + +/*****************************************************************************/ + +/* + * Define the driver info for a user level control device. Used mainly + * to get at port stats - only not using the port device itself. + */ +static const struct file_operations stl_fsiomem = { + .owner = THIS_MODULE, + .unlocked_ioctl = stl_memioctl, + .llseek = noop_llseek, +}; + +static struct class *stallion_class; + +static void stl_cd_change(struct stlport *portp) +{ + unsigned int oldsigs = portp->sigs; + struct tty_struct *tty = tty_port_tty_get(&portp->port); + + if (!tty) + return; + + portp->sigs = stl_getsignals(portp); + + if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) + wake_up_interruptible(&portp->port.open_wait); + + if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) + if (portp->port.flags & ASYNC_CHECK_CD) + tty_hangup(tty); + tty_kref_put(tty); +} + +/* + * Check for any arguments passed in on the module load command line. + */ + +/*****************************************************************************/ + +/* + * Parse the supplied argument string, into the board conf struct. + */ + +static int __init stl_parsebrd(struct stlconf *confp, char **argp) +{ + char *sp; + unsigned int i; + + pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp); + + if ((argp[0] == NULL) || (*argp[0] == 0)) + return 0; + + for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++) + *sp = tolower(*sp); + + for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) + if (strcmp(stl_brdstr[i].name, argp[0]) == 0) + break; + + if (i == ARRAY_SIZE(stl_brdstr)) { + printk("STALLION: unknown board name, %s?\n", argp[0]); + return 0; + } + + confp->brdtype = stl_brdstr[i].type; + + i = 1; + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0); + i++; + if (confp->brdtype == BRD_ECH) { + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0); + i++; + } + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->irq = simple_strtoul(argp[i], NULL, 0); + return 1; +} + +/*****************************************************************************/ + +/* + * Allocate a new board structure. Fill out the basic info in it. + */ + +static struct stlbrd *stl_allocbrd(void) +{ + struct stlbrd *brdp; + + brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL); + if (!brdp) { + printk("STALLION: failed to allocate memory (size=%Zd)\n", + sizeof(struct stlbrd)); + return NULL; + } + + brdp->magic = STL_BOARDMAGIC; + return brdp; +} + +/*****************************************************************************/ + +static int stl_activate(struct tty_port *port, struct tty_struct *tty) +{ + struct stlport *portp = container_of(port, struct stlport, port); + if (!portp->tx.buf) { + portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); + if (!portp->tx.buf) + return -ENOMEM; + portp->tx.head = portp->tx.buf; + portp->tx.tail = portp->tx.buf; + } + stl_setport(portp, tty->termios); + portp->sigs = stl_getsignals(portp); + stl_setsignals(portp, 1, 1); + stl_enablerxtx(portp, 1, 1); + stl_startrxtx(portp, 1, 0); + return 0; +} + +static int stl_open(struct tty_struct *tty, struct file *filp) +{ + struct stlport *portp; + struct stlbrd *brdp; + unsigned int minordev, brdnr, panelnr; + int portnr; + + pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); + + minordev = tty->index; + brdnr = MINOR2BRD(minordev); + if (brdnr >= stl_nrbrds) + return -ENODEV; + brdp = stl_brds[brdnr]; + if (brdp == NULL) + return -ENODEV; + + minordev = MINOR2PORT(minordev); + for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { + if (brdp->panels[panelnr] == NULL) + break; + if (minordev < brdp->panels[panelnr]->nrports) { + portnr = minordev; + break; + } + minordev -= brdp->panels[panelnr]->nrports; + } + if (portnr < 0) + return -ENODEV; + + portp = brdp->panels[panelnr]->ports[portnr]; + if (portp == NULL) + return -ENODEV; + + tty->driver_data = portp; + return tty_port_open(&portp->port, tty, filp); + +} + +/*****************************************************************************/ + +static int stl_carrier_raised(struct tty_port *port) +{ + struct stlport *portp = container_of(port, struct stlport, port); + return (portp->sigs & TIOCM_CD) ? 1 : 0; +} + +static void stl_dtr_rts(struct tty_port *port, int on) +{ + struct stlport *portp = container_of(port, struct stlport, port); + /* Takes brd_lock internally */ + stl_setsignals(portp, on, on); +} + +/*****************************************************************************/ + +static void stl_flushbuffer(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_flushbuffer(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return; + + stl_flush(portp); + tty_wakeup(tty); +} + +/*****************************************************************************/ + +static void stl_waituntilsent(struct tty_struct *tty, int timeout) +{ + struct stlport *portp; + unsigned long tend; + + pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); + + portp = tty->driver_data; + if (portp == NULL) + return; + + if (timeout == 0) + timeout = HZ; + tend = jiffies + timeout; + + while (stl_datastate(portp)) { + if (signal_pending(current)) + break; + msleep_interruptible(20); + if (time_after_eq(jiffies, tend)) + break; + } +} + +/*****************************************************************************/ + +static void stl_shutdown(struct tty_port *port) +{ + struct stlport *portp = container_of(port, struct stlport, port); + stl_disableintrs(portp); + stl_enablerxtx(portp, 0, 0); + stl_flush(portp); + portp->istate = 0; + if (portp->tx.buf != NULL) { + kfree(portp->tx.buf); + portp->tx.buf = NULL; + portp->tx.head = NULL; + portp->tx.tail = NULL; + } +} + +static void stl_close(struct tty_struct *tty, struct file *filp) +{ + struct stlport*portp; + pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); + + portp = tty->driver_data; + if(portp == NULL) + return; + tty_port_close(&portp->port, tty, filp); +} + +/*****************************************************************************/ + +/* + * Write routine. Take data and stuff it in to the TX ring queue. + * If transmit interrupts are not running then start them. + */ + +static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + struct stlport *portp; + unsigned int len, stlen; + unsigned char *chbuf; + char *head, *tail; + + pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count); + + portp = tty->driver_data; + if (portp == NULL) + return 0; + if (portp->tx.buf == NULL) + return 0; + +/* + * If copying direct from user space we must cater for page faults, + * causing us to "sleep" here for a while. To handle this copy in all + * the data we need now, into a local buffer. Then when we got it all + * copy it into the TX buffer. + */ + chbuf = (unsigned char *) buf; + + head = portp->tx.head; + tail = portp->tx.tail; + if (head >= tail) { + len = STL_TXBUFSIZE - (head - tail) - 1; + stlen = STL_TXBUFSIZE - (head - portp->tx.buf); + } else { + len = tail - head - 1; + stlen = len; + } + + len = min(len, (unsigned int)count); + count = 0; + while (len > 0) { + stlen = min(len, stlen); + memcpy(head, chbuf, stlen); + len -= stlen; + chbuf += stlen; + count += stlen; + head += stlen; + if (head >= (portp->tx.buf + STL_TXBUFSIZE)) { + head = portp->tx.buf; + stlen = tail - head; + } + } + portp->tx.head = head; + + clear_bit(ASYI_TXLOW, &portp->istate); + stl_startrxtx(portp, -1, 1); + + return count; +} + +/*****************************************************************************/ + +static int stl_putchar(struct tty_struct *tty, unsigned char ch) +{ + struct stlport *portp; + unsigned int len; + char *head, *tail; + + pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); + + portp = tty->driver_data; + if (portp == NULL) + return -EINVAL; + if (portp->tx.buf == NULL) + return -EINVAL; + + head = portp->tx.head; + tail = portp->tx.tail; + + len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head); + len--; + + if (len > 0) { + *head++ = ch; + if (head >= (portp->tx.buf + STL_TXBUFSIZE)) + head = portp->tx.buf; + } + portp->tx.head = head; + return 0; +} + +/*****************************************************************************/ + +/* + * If there are any characters in the buffer then make sure that TX + * interrupts are on and get'em out. Normally used after the putchar + * routine has been called. + */ + +static void stl_flushchars(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_flushchars(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return; + if (portp->tx.buf == NULL) + return; + + stl_startrxtx(portp, -1, 1); +} + +/*****************************************************************************/ + +static int stl_writeroom(struct tty_struct *tty) +{ + struct stlport *portp; + char *head, *tail; + + pr_debug("stl_writeroom(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return 0; + if (portp->tx.buf == NULL) + return 0; + + head = portp->tx.head; + tail = portp->tx.tail; + return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1); +} + +/*****************************************************************************/ + +/* + * Return number of chars in the TX buffer. Normally we would just + * calculate the number of chars in the buffer and return that, but if + * the buffer is empty and TX interrupts are still on then we return + * that the buffer still has 1 char in it. This way whoever called us + * will not think that ALL chars have drained - since the UART still + * must have some chars in it (we are busy after all). + */ + +static int stl_charsinbuffer(struct tty_struct *tty) +{ + struct stlport *portp; + unsigned int size; + char *head, *tail; + + pr_debug("stl_charsinbuffer(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return 0; + if (portp->tx.buf == NULL) + return 0; + + head = portp->tx.head; + tail = portp->tx.tail; + size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); + if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate)) + size = 1; + return size; +} + +/*****************************************************************************/ + +/* + * Generate the serial struct info. + */ + +static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) +{ + struct serial_struct sio; + struct stlbrd *brdp; + + pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); + + memset(&sio, 0, sizeof(struct serial_struct)); + + mutex_lock(&portp->port.mutex); + sio.line = portp->portnr; + sio.port = portp->ioaddr; + sio.flags = portp->port.flags; + sio.baud_base = portp->baud_base; + sio.close_delay = portp->close_delay; + sio.closing_wait = portp->closing_wait; + sio.custom_divisor = portp->custom_divisor; + sio.hub6 = 0; + if (portp->uartp == &stl_cd1400uart) { + sio.type = PORT_CIRRUS; + sio.xmit_fifo_size = CD1400_TXFIFOSIZE; + } else { + sio.type = PORT_UNKNOWN; + sio.xmit_fifo_size = SC26198_TXFIFOSIZE; + } + + brdp = stl_brds[portp->brdnr]; + if (brdp != NULL) + sio.irq = brdp->irq; + mutex_unlock(&portp->port.mutex); + + return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Set port according to the serial struct info. + * At this point we do not do any auto-configure stuff, so we will + * just quietly ignore any requests to change irq, etc. + */ + +static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp) +{ + struct stlport * portp = tty->driver_data; + struct serial_struct sio; + + pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); + + if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) + return -EFAULT; + mutex_lock(&portp->port.mutex); + if (!capable(CAP_SYS_ADMIN)) { + if ((sio.baud_base != portp->baud_base) || + (sio.close_delay != portp->close_delay) || + ((sio.flags & ~ASYNC_USR_MASK) != + (portp->port.flags & ~ASYNC_USR_MASK))) { + mutex_unlock(&portp->port.mutex); + return -EPERM; + } + } + + portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | + (sio.flags & ASYNC_USR_MASK); + portp->baud_base = sio.baud_base; + portp->close_delay = sio.close_delay; + portp->closing_wait = sio.closing_wait; + portp->custom_divisor = sio.custom_divisor; + mutex_unlock(&portp->port.mutex); + stl_setport(portp, tty->termios); + return 0; +} + +/*****************************************************************************/ + +static int stl_tiocmget(struct tty_struct *tty) +{ + struct stlport *portp; + + portp = tty->driver_data; + if (portp == NULL) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + return stl_getsignals(portp); +} + +static int stl_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct stlport *portp; + int rts = -1, dtr = -1; + + portp = tty->driver_data; + if (portp == NULL) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + stl_setsignals(portp, dtr, rts); + return 0; +} + +static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) +{ + struct stlport *portp; + int rc; + void __user *argp = (void __user *)arg; + + pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg); + + portp = tty->driver_data; + if (portp == NULL) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + rc = 0; + + switch (cmd) { + case TIOCGSERIAL: + rc = stl_getserial(portp, argp); + break; + case TIOCSSERIAL: + rc = stl_setserial(tty, argp); + break; + case COM_GETPORTSTATS: + rc = stl_getportstats(tty, portp, argp); + break; + case COM_CLRPORTSTATS: + rc = stl_clrportstats(portp, argp); + break; + case TIOCSERCONFIG: + case TIOCSERGWILD: + case TIOCSERSWILD: + case TIOCSERGETLSR: + case TIOCSERGSTRUCT: + case TIOCSERGETMULTI: + case TIOCSERSETMULTI: + default: + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + +/*****************************************************************************/ + +/* + * Start the transmitter again. Just turn TX interrupts back on. + */ + +static void stl_start(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_start(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return; + stl_startrxtx(portp, -1, 1); +} + +/*****************************************************************************/ + +static void stl_settermios(struct tty_struct *tty, struct ktermios *old) +{ + struct stlport *portp; + struct ktermios *tiosp; + + pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); + + portp = tty->driver_data; + if (portp == NULL) + return; + + tiosp = tty->termios; + if ((tiosp->c_cflag == old->c_cflag) && + (tiosp->c_iflag == old->c_iflag)) + return; + + stl_setport(portp, tiosp); + stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0), + -1); + if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) { + tty->hw_stopped = 0; + stl_start(tty); + } + if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) + wake_up_interruptible(&portp->port.open_wait); +} + +/*****************************************************************************/ + +/* + * Attempt to flow control who ever is sending us data. Based on termios + * settings use software or/and hardware flow control. + */ + +static void stl_throttle(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_throttle(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return; + stl_flowctrl(portp, 0); +} + +/*****************************************************************************/ + +/* + * Unflow control the device sending us data... + */ + +static void stl_unthrottle(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_unthrottle(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return; + stl_flowctrl(portp, 1); +} + +/*****************************************************************************/ + +/* + * Stop the transmitter. Basically to do this we will just turn TX + * interrupts off. + */ + +static void stl_stop(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_stop(tty=%p)\n", tty); + + portp = tty->driver_data; + if (portp == NULL) + return; + stl_startrxtx(portp, -1, 0); +} + +/*****************************************************************************/ + +/* + * Hangup this port. This is pretty much like closing the port, only + * a little more brutal. No waiting for data to drain. Shutdown the + * port and maybe drop signals. + */ + +static void stl_hangup(struct tty_struct *tty) +{ + struct stlport *portp = tty->driver_data; + pr_debug("stl_hangup(tty=%p)\n", tty); + + if (portp == NULL) + return; + tty_port_hangup(&portp->port); +} + +/*****************************************************************************/ + +static int stl_breakctl(struct tty_struct *tty, int state) +{ + struct stlport *portp; + + pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); + + portp = tty->driver_data; + if (portp == NULL) + return -EINVAL; + + stl_sendbreak(portp, ((state == -1) ? 1 : 2)); + return 0; +} + +/*****************************************************************************/ + +static void stl_sendxchar(struct tty_struct *tty, char ch) +{ + struct stlport *portp; + + pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); + + portp = tty->driver_data; + if (portp == NULL) + return; + + if (ch == STOP_CHAR(tty)) + stl_sendflow(portp, 0); + else if (ch == START_CHAR(tty)) + stl_sendflow(portp, 1); + else + stl_putchar(tty, ch); +} + +static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr) +{ + int sigs; + char sep; + + seq_printf(m, "%d: uart:%s tx:%d rx:%d", + portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", + (int) portp->stats.txtotal, (int) portp->stats.rxtotal); + + if (portp->stats.rxframing) + seq_printf(m, " fe:%d", (int) portp->stats.rxframing); + if (portp->stats.rxparity) + seq_printf(m, " pe:%d", (int) portp->stats.rxparity); + if (portp->stats.rxbreaks) + seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks); + if (portp->stats.rxoverrun) + seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun); + + sigs = stl_getsignals(portp); + sep = ' '; + if (sigs & TIOCM_RTS) { + seq_printf(m, "%c%s", sep, "RTS"); + sep = '|'; + } + if (sigs & TIOCM_CTS) { + seq_printf(m, "%c%s", sep, "CTS"); + sep = '|'; + } + if (sigs & TIOCM_DTR) { + seq_printf(m, "%c%s", sep, "DTR"); + sep = '|'; + } + if (sigs & TIOCM_CD) { + seq_printf(m, "%c%s", sep, "DCD"); + sep = '|'; + } + if (sigs & TIOCM_DSR) { + seq_printf(m, "%c%s", sep, "DSR"); + sep = '|'; + } + seq_putc(m, '\n'); +} + +/*****************************************************************************/ + +/* + * Port info, read from the /proc file system. + */ + +static int stl_proc_show(struct seq_file *m, void *v) +{ + struct stlbrd *brdp; + struct stlpanel *panelp; + struct stlport *portp; + unsigned int brdnr, panelnr, portnr; + int totalport; + + totalport = 0; + + seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion); + +/* + * We scan through for each board, panel and port. The offset is + * calculated on the fly, and irrelevant ports are skipped. + */ + for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) { + brdp = stl_brds[brdnr]; + if (brdp == NULL) + continue; + if (brdp->state == 0) + continue; + + totalport = brdnr * STL_MAXPORTS; + for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { + panelp = brdp->panels[panelnr]; + if (panelp == NULL) + continue; + + for (portnr = 0; portnr < panelp->nrports; portnr++, + totalport++) { + portp = panelp->ports[portnr]; + if (portp == NULL) + continue; + stl_portinfo(m, portp, totalport); + } + } + } + return 0; +} + +static int stl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, stl_proc_show, NULL); +} + +static const struct file_operations stl_proc_fops = { + .owner = THIS_MODULE, + .open = stl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/*****************************************************************************/ + +/* + * All board interrupts are vectored through here first. This code then + * calls off to the approrpriate board interrupt handlers. + */ + +static irqreturn_t stl_intr(int irq, void *dev_id) +{ + struct stlbrd *brdp = dev_id; + + pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq); + + return IRQ_RETVAL((* brdp->isr)(brdp)); +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for EasyIO board types. + */ + +static int stl_eiointr(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int iobase; + int handled = 0; + + spin_lock(&brd_lock); + panelp = brdp->panels[0]; + iobase = panelp->iobase; + while (inb(brdp->iostatus) & EIO_INTRPEND) { + handled = 1; + (* panelp->isr)(panelp, iobase); + } + spin_unlock(&brd_lock); + return handled; +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for ECH-AT board types. + */ + +static int stl_echatintr(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; + int handled = 0; + + outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); + + while (inb(brdp->iostatus) & ECH_INTRPEND) { + handled = 1; + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { + ioaddr = brdp->bnkstataddr[bnknr]; + if (inb(ioaddr) & ECH_PNLINTRPEND) { + panelp = brdp->bnk2panel[bnknr]; + (* panelp->isr)(panelp, (ioaddr & 0xfffc)); + } + } + } + + outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); + + return handled; +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for ECH-MCA board types. + */ + +static int stl_echmcaintr(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; + int handled = 0; + + while (inb(brdp->iostatus) & ECH_INTRPEND) { + handled = 1; + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { + ioaddr = brdp->bnkstataddr[bnknr]; + if (inb(ioaddr) & ECH_PNLINTRPEND) { + panelp = brdp->bnk2panel[bnknr]; + (* panelp->isr)(panelp, (ioaddr & 0xfffc)); + } + } + } + return handled; +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for ECH-PCI board types. + */ + +static int stl_echpciintr(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int ioaddr, bnknr, recheck; + int handled = 0; + + while (1) { + recheck = 0; + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { + outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl); + ioaddr = brdp->bnkstataddr[bnknr]; + if (inb(ioaddr) & ECH_PNLINTRPEND) { + panelp = brdp->bnk2panel[bnknr]; + (* panelp->isr)(panelp, (ioaddr & 0xfffc)); + recheck++; + handled = 1; + } + } + if (! recheck) + break; + } + return handled; +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for ECH-8/64-PCI board types. + */ + +static int stl_echpci64intr(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; + int handled = 0; + + while (inb(brdp->ioctrl) & 0x1) { + handled = 1; + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { + ioaddr = brdp->bnkstataddr[bnknr]; + if (inb(ioaddr) & ECH_PNLINTRPEND) { + panelp = brdp->bnk2panel[bnknr]; + (* panelp->isr)(panelp, (ioaddr & 0xfffc)); + } + } + } + + return handled; +} + +/*****************************************************************************/ + +/* + * Initialize all the ports on a panel. + */ + +static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) +{ + struct stlport *portp; + unsigned int i; + int chipmask; + + pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp); + + chipmask = stl_panelinit(brdp, panelp); + +/* + * All UART's are initialized (if found!). Now go through and setup + * each ports data structures. + */ + for (i = 0; i < panelp->nrports; i++) { + portp = kzalloc(sizeof(struct stlport), GFP_KERNEL); + if (!portp) { + printk("STALLION: failed to allocate memory " + "(size=%Zd)\n", sizeof(struct stlport)); + break; + } + tty_port_init(&portp->port); + portp->port.ops = &stl_port_ops; + portp->magic = STL_PORTMAGIC; + portp->portnr = i; + portp->brdnr = panelp->brdnr; + portp->panelnr = panelp->panelnr; + portp->uartp = panelp->uartp; + portp->clk = brdp->clk; + portp->baud_base = STL_BAUDBASE; + portp->close_delay = STL_CLOSEDELAY; + portp->closing_wait = 30 * HZ; + init_waitqueue_head(&portp->port.open_wait); + init_waitqueue_head(&portp->port.close_wait); + portp->stats.brd = portp->brdnr; + portp->stats.panel = portp->panelnr; + portp->stats.port = portp->portnr; + panelp->ports[i] = portp; + stl_portinit(brdp, panelp, portp); + } + + return 0; +} + +static void stl_cleanup_panels(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + struct stlport *portp; + unsigned int j, k; + struct tty_struct *tty; + + for (j = 0; j < STL_MAXPANELS; j++) { + panelp = brdp->panels[j]; + if (panelp == NULL) + continue; + for (k = 0; k < STL_PORTSPERPANEL; k++) { + portp = panelp->ports[k]; + if (portp == NULL) + continue; + tty = tty_port_tty_get(&portp->port); + if (tty != NULL) { + stl_hangup(tty); + tty_kref_put(tty); + } + kfree(portp->tx.buf); + kfree(portp); + } + kfree(panelp); + } +} + +/*****************************************************************************/ + +/* + * Try to find and initialize an EasyIO board. + */ + +static int __devinit stl_initeio(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int status; + char *name; + int retval; + + pr_debug("stl_initeio(brdp=%p)\n", brdp); + + brdp->ioctrl = brdp->ioaddr1 + 1; + brdp->iostatus = brdp->ioaddr1 + 2; + + status = inb(brdp->iostatus); + if ((status & EIO_IDBITMASK) == EIO_MK3) + brdp->ioctrl++; + +/* + * Handle board specific stuff now. The real difference is PCI + * or not PCI. + */ + if (brdp->brdtype == BRD_EASYIOPCI) { + brdp->iosize1 = 0x80; + brdp->iosize2 = 0x80; + name = "serial(EIO-PCI)"; + outb(0x41, (brdp->ioaddr2 + 0x4c)); + } else { + brdp->iosize1 = 8; + name = "serial(EIO)"; + if ((brdp->irq < 0) || (brdp->irq > 15) || + (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { + printk("STALLION: invalid irq=%d for brd=%d\n", + brdp->irq, brdp->brdnr); + retval = -EINVAL; + goto err; + } + outb((stl_vecmap[brdp->irq] | EIO_0WS | + ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), + brdp->ioctrl); + } + + retval = -EBUSY; + if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { + printk(KERN_WARNING "STALLION: Warning, board %d I/O address " + "%x conflicts with another device\n", brdp->brdnr, + brdp->ioaddr1); + goto err; + } + + if (brdp->iosize2 > 0) + if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) { + printk(KERN_WARNING "STALLION: Warning, board %d I/O " + "address %x conflicts with another device\n", + brdp->brdnr, brdp->ioaddr2); + printk(KERN_WARNING "STALLION: Warning, also " + "releasing board %d I/O address %x \n", + brdp->brdnr, brdp->ioaddr1); + goto err_rel1; + } + +/* + * Everything looks OK, so let's go ahead and probe for the hardware. + */ + brdp->clk = CD1400_CLK; + brdp->isr = stl_eiointr; + + retval = -ENODEV; + switch (status & EIO_IDBITMASK) { + case EIO_8PORTM: + brdp->clk = CD1400_CLK8M; + /* fall thru */ + case EIO_8PORTRS: + case EIO_8PORTDI: + brdp->nrports = 8; + break; + case EIO_4PORTRS: + brdp->nrports = 4; + break; + case EIO_MK3: + switch (status & EIO_BRDMASK) { + case ID_BRD4: + brdp->nrports = 4; + break; + case ID_BRD8: + brdp->nrports = 8; + break; + case ID_BRD16: + brdp->nrports = 16; + break; + default: + goto err_rel2; + } + break; + default: + goto err_rel2; + } + +/* + * We have verified that the board is actually present, so now we + * can complete the setup. + */ + + panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); + if (!panelp) { + printk(KERN_WARNING "STALLION: failed to allocate memory " + "(size=%Zd)\n", sizeof(struct stlpanel)); + retval = -ENOMEM; + goto err_rel2; + } + + panelp->magic = STL_PANELMAGIC; + panelp->brdnr = brdp->brdnr; + panelp->panelnr = 0; + panelp->nrports = brdp->nrports; + panelp->iobase = brdp->ioaddr1; + panelp->hwid = status; + if ((status & EIO_IDBITMASK) == EIO_MK3) { + panelp->uartp = &stl_sc26198uart; + panelp->isr = stl_sc26198intr; + } else { + panelp->uartp = &stl_cd1400uart; + panelp->isr = stl_cd1400eiointr; + } + + brdp->panels[0] = panelp; + brdp->nrpanels = 1; + brdp->state |= BRD_FOUND; + brdp->hwid = status; + if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { + printk("STALLION: failed to register interrupt " + "routine for %s irq=%d\n", name, brdp->irq); + retval = -ENODEV; + goto err_fr; + } + + return 0; +err_fr: + stl_cleanup_panels(brdp); +err_rel2: + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err_rel1: + release_region(brdp->ioaddr1, brdp->iosize1); +err: + return retval; +} + +/*****************************************************************************/ + +/* + * Try to find an ECH board and initialize it. This code is capable of + * dealing with all types of ECH board. + */ + +static int __devinit stl_initech(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i; + int retval; + char *name; + + pr_debug("stl_initech(brdp=%p)\n", brdp); + + status = 0; + conflict = 0; + +/* + * Set up the initial board register contents for boards. This varies a + * bit between the different board types. So we need to handle each + * separately. Also do a check that the supplied IRQ is good. + */ + switch (brdp->brdtype) { + + case BRD_ECH: + brdp->isr = stl_echatintr; + brdp->ioctrl = brdp->ioaddr1 + 1; + brdp->iostatus = brdp->ioaddr1 + 1; + status = inb(brdp->iostatus); + if ((status & ECH_IDBITMASK) != ECH_ID) { + retval = -ENODEV; + goto err; + } + if ((brdp->irq < 0) || (brdp->irq > 15) || + (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { + printk("STALLION: invalid irq=%d for brd=%d\n", + brdp->irq, brdp->brdnr); + retval = -EINVAL; + goto err; + } + status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); + status |= (stl_vecmap[brdp->irq] << 1); + outb((status | ECH_BRDRESET), brdp->ioaddr1); + brdp->ioctrlval = ECH_INTENABLE | + ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE); + for (i = 0; i < 10; i++) + outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); + brdp->iosize1 = 2; + brdp->iosize2 = 32; + name = "serial(EC8/32)"; + outb(status, brdp->ioaddr1); + break; + + case BRD_ECHMC: + brdp->isr = stl_echmcaintr; + brdp->ioctrl = brdp->ioaddr1 + 0x20; + brdp->iostatus = brdp->ioctrl; + status = inb(brdp->iostatus); + if ((status & ECH_IDBITMASK) != ECH_ID) { + retval = -ENODEV; + goto err; + } + if ((brdp->irq < 0) || (brdp->irq > 15) || + (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { + printk("STALLION: invalid irq=%d for brd=%d\n", + brdp->irq, brdp->brdnr); + retval = -EINVAL; + goto err; + } + outb(ECHMC_BRDRESET, brdp->ioctrl); + outb(ECHMC_INTENABLE, brdp->ioctrl); + brdp->iosize1 = 64; + name = "serial(EC8/32-MC)"; + break; + + case BRD_ECHPCI: + brdp->isr = stl_echpciintr; + brdp->ioctrl = brdp->ioaddr1 + 2; + brdp->iosize1 = 4; + brdp->iosize2 = 8; + name = "serial(EC8/32-PCI)"; + break; + + case BRD_ECH64PCI: + brdp->isr = stl_echpci64intr; + brdp->ioctrl = brdp->ioaddr2 + 0x40; + outb(0x43, (brdp->ioaddr1 + 0x4c)); + brdp->iosize1 = 0x80; + brdp->iosize2 = 0x80; + name = "serial(EC8/64-PCI)"; + break; + + default: + printk("STALLION: unknown board type=%d\n", brdp->brdtype); + retval = -EINVAL; + goto err; + } + +/* + * Check boards for possible IO address conflicts and return fail status + * if an IO conflict found. + */ + retval = -EBUSY; + if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { + printk(KERN_WARNING "STALLION: Warning, board %d I/O address " + "%x conflicts with another device\n", brdp->brdnr, + brdp->ioaddr1); + goto err; + } + + if (brdp->iosize2 > 0) + if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) { + printk(KERN_WARNING "STALLION: Warning, board %d I/O " + "address %x conflicts with another device\n", + brdp->brdnr, brdp->ioaddr2); + printk(KERN_WARNING "STALLION: Warning, also " + "releasing board %d I/O address %x \n", + brdp->brdnr, brdp->ioaddr1); + goto err_rel1; + } + +/* + * Scan through the secondary io address space looking for panels. + * As we find'em allocate and initialize panel structures for each. + */ + brdp->clk = CD1400_CLK; + brdp->hwid = status; + + ioaddr = brdp->ioaddr2; + banknr = 0; + panelnr = 0; + nxtid = 0; + + for (i = 0; i < STL_MAXPANELS; i++) { + if (brdp->brdtype == BRD_ECHPCI) { + outb(nxtid, brdp->ioctrl); + ioaddr = brdp->ioaddr2; + } + status = inb(ioaddr + ECH_PNLSTATUS); + if ((status & ECH_PNLIDMASK) != nxtid) + break; + panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); + if (!panelp) { + printk("STALLION: failed to allocate memory " + "(size=%Zd)\n", sizeof(struct stlpanel)); + retval = -ENOMEM; + goto err_fr; + } + panelp->magic = STL_PANELMAGIC; + panelp->brdnr = brdp->brdnr; + panelp->panelnr = panelnr; + panelp->iobase = ioaddr; + panelp->pagenr = nxtid; + panelp->hwid = status; + brdp->bnk2panel[banknr] = panelp; + brdp->bnkpageaddr[banknr] = nxtid; + brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; + + if (status & ECH_PNLXPID) { + panelp->uartp = &stl_sc26198uart; + panelp->isr = stl_sc26198intr; + if (status & ECH_PNL16PORT) { + panelp->nrports = 16; + brdp->bnk2panel[banknr] = panelp; + brdp->bnkpageaddr[banknr] = nxtid; + brdp->bnkstataddr[banknr++] = ioaddr + 4 + + ECH_PNLSTATUS; + } else + panelp->nrports = 8; + } else { + panelp->uartp = &stl_cd1400uart; + panelp->isr = stl_cd1400echintr; + if (status & ECH_PNL16PORT) { + panelp->nrports = 16; + panelp->ackmask = 0x80; + if (brdp->brdtype != BRD_ECHPCI) + ioaddr += EREG_BANKSIZE; + brdp->bnk2panel[banknr] = panelp; + brdp->bnkpageaddr[banknr] = ++nxtid; + brdp->bnkstataddr[banknr++] = ioaddr + + ECH_PNLSTATUS; + } else { + panelp->nrports = 8; + panelp->ackmask = 0xc0; + } + } + + nxtid++; + ioaddr += EREG_BANKSIZE; + brdp->nrports += panelp->nrports; + brdp->panels[panelnr++] = panelp; + if ((brdp->brdtype != BRD_ECHPCI) && + (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) { + retval = -EINVAL; + goto err_fr; + } + } + + brdp->nrpanels = panelnr; + brdp->nrbnks = banknr; + if (brdp->brdtype == BRD_ECH) + outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); + + brdp->state |= BRD_FOUND; + if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { + printk("STALLION: failed to register interrupt " + "routine for %s irq=%d\n", name, brdp->irq); + retval = -ENODEV; + goto err_fr; + } + + return 0; +err_fr: + stl_cleanup_panels(brdp); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err_rel1: + release_region(brdp->ioaddr1, brdp->iosize1); +err: + return retval; +} + +/*****************************************************************************/ + +/* + * Initialize and configure the specified board. + * Scan through all the boards in the configuration and see what we + * can find. Handle EIO and the ECH boards a little differently here + * since the initial search and setup is very different. + */ + +static int __devinit stl_brdinit(struct stlbrd *brdp) +{ + int i, retval; + + pr_debug("stl_brdinit(brdp=%p)\n", brdp); + + switch (brdp->brdtype) { + case BRD_EASYIO: + case BRD_EASYIOPCI: + retval = stl_initeio(brdp); + if (retval) + goto err; + break; + case BRD_ECH: + case BRD_ECHMC: + case BRD_ECHPCI: + case BRD_ECH64PCI: + retval = stl_initech(brdp); + if (retval) + goto err; + break; + default: + printk("STALLION: board=%d is unknown board type=%d\n", + brdp->brdnr, brdp->brdtype); + retval = -ENODEV; + goto err; + } + + if ((brdp->state & BRD_FOUND) == 0) { + printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", + stl_brdnames[brdp->brdtype], brdp->brdnr, + brdp->ioaddr1, brdp->irq); + goto err_free; + } + + for (i = 0; i < STL_MAXPANELS; i++) + if (brdp->panels[i] != NULL) + stl_initports(brdp, brdp->panels[i]); + + printk("STALLION: %s found, board=%d io=%x irq=%d " + "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], + brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, + brdp->nrports); + + return 0; +err_free: + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err: + return retval; +} + +/*****************************************************************************/ + +/* + * Find the next available board number that is free. + */ + +static int __devinit stl_getbrdnr(void) +{ + unsigned int i; + + for (i = 0; i < STL_MAXBRDS; i++) + if (stl_brds[i] == NULL) { + if (i >= stl_nrbrds) + stl_nrbrds = i + 1; + return i; + } + + return -1; +} + +/*****************************************************************************/ +/* + * We have a Stallion board. Allocate a board structure and + * initialize it. Read its IO and IRQ resources from PCI + * configuration space. + */ + +static int __devinit stl_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct stlbrd *brdp; + unsigned int i, brdtype = ent->driver_data; + int brdnr, retval = -ENODEV; + + if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) + goto err; + + retval = pci_enable_device(pdev); + if (retval) + goto err; + brdp = stl_allocbrd(); + if (brdp == NULL) { + retval = -ENOMEM; + goto err; + } + mutex_lock(&stl_brdslock); + brdnr = stl_getbrdnr(); + if (brdnr < 0) { + dev_err(&pdev->dev, "too many boards found, " + "maximum supported %d\n", STL_MAXBRDS); + mutex_unlock(&stl_brdslock); + retval = -ENODEV; + goto err_fr; + } + brdp->brdnr = (unsigned int)brdnr; + stl_brds[brdp->brdnr] = brdp; + mutex_unlock(&stl_brdslock); + + brdp->brdtype = brdtype; + brdp->state |= STL_PROBED; + +/* + * We have all resources from the board, so let's setup the actual + * board structure now. + */ + switch (brdtype) { + case BRD_ECHPCI: + brdp->ioaddr2 = pci_resource_start(pdev, 0); + brdp->ioaddr1 = pci_resource_start(pdev, 1); + break; + case BRD_ECH64PCI: + brdp->ioaddr2 = pci_resource_start(pdev, 2); + brdp->ioaddr1 = pci_resource_start(pdev, 1); + break; + case BRD_EASYIOPCI: + brdp->ioaddr1 = pci_resource_start(pdev, 2); + brdp->ioaddr2 = pci_resource_start(pdev, 1); + break; + default: + dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype); + break; + } + + brdp->irq = pdev->irq; + retval = stl_brdinit(brdp); + if (retval) + goto err_null; + + pci_set_drvdata(pdev, brdp); + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + i, &pdev->dev); + + return 0; +err_null: + stl_brds[brdp->brdnr] = NULL; +err_fr: + kfree(brdp); +err: + return retval; +} + +static void __devexit stl_pciremove(struct pci_dev *pdev) +{ + struct stlbrd *brdp = pci_get_drvdata(pdev); + unsigned int i; + + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); + + for (i = 0; i < brdp->nrports; i++) + tty_unregister_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + i); + + stl_brds[brdp->brdnr] = NULL; + kfree(brdp); +} + +static struct pci_driver stl_pcidriver = { + .name = "stallion", + .id_table = stl_pcibrds, + .probe = stl_pciprobe, + .remove = __devexit_p(stl_pciremove) +}; + +/*****************************************************************************/ + +/* + * Return the board stats structure to user app. + */ + +static int stl_getbrdstats(combrd_t __user *bp) +{ + combrd_t stl_brdstats; + struct stlbrd *brdp; + struct stlpanel *panelp; + unsigned int i; + + if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t))) + return -EFAULT; + if (stl_brdstats.brd >= STL_MAXBRDS) + return -ENODEV; + brdp = stl_brds[stl_brdstats.brd]; + if (brdp == NULL) + return -ENODEV; + + memset(&stl_brdstats, 0, sizeof(combrd_t)); + stl_brdstats.brd = brdp->brdnr; + stl_brdstats.type = brdp->brdtype; + stl_brdstats.hwid = brdp->hwid; + stl_brdstats.state = brdp->state; + stl_brdstats.ioaddr = brdp->ioaddr1; + stl_brdstats.ioaddr2 = brdp->ioaddr2; + stl_brdstats.irq = brdp->irq; + stl_brdstats.nrpanels = brdp->nrpanels; + stl_brdstats.nrports = brdp->nrports; + for (i = 0; i < brdp->nrpanels; i++) { + panelp = brdp->panels[i]; + stl_brdstats.panels[i].panel = i; + stl_brdstats.panels[i].hwid = panelp->hwid; + stl_brdstats.panels[i].nrports = panelp->nrports; + } + + return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Resolve the referenced port number into a port struct pointer. + */ + +static struct stlport *stl_getport(int brdnr, int panelnr, int portnr) +{ + struct stlbrd *brdp; + struct stlpanel *panelp; + + if (brdnr < 0 || brdnr >= STL_MAXBRDS) + return NULL; + brdp = stl_brds[brdnr]; + if (brdp == NULL) + return NULL; + if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels) + return NULL; + panelp = brdp->panels[panelnr]; + if (panelp == NULL) + return NULL; + if (portnr < 0 || (unsigned int)portnr >= panelp->nrports) + return NULL; + return panelp->ports[portnr]; +} + +/*****************************************************************************/ + +/* + * Return the port stats structure to user app. A NULL port struct + * pointer passed in means that we need to find out from the app + * what port to get stats for (used through board control device). + */ + +static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp) +{ + comstats_t stl_comstats; + unsigned char *head, *tail; + unsigned long flags; + + if (!portp) { + if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) + return -EFAULT; + portp = stl_getport(stl_comstats.brd, stl_comstats.panel, + stl_comstats.port); + if (portp == NULL) + return -ENODEV; + } + + mutex_lock(&portp->port.mutex); + portp->stats.state = portp->istate; + portp->stats.flags = portp->port.flags; + portp->stats.hwid = portp->hwid; + + portp->stats.ttystate = 0; + portp->stats.cflags = 0; + portp->stats.iflags = 0; + portp->stats.oflags = 0; + portp->stats.lflags = 0; + portp->stats.rxbuffered = 0; + + spin_lock_irqsave(&stallion_lock, flags); + if (tty != NULL && portp->port.tty == tty) { + portp->stats.ttystate = tty->flags; + /* No longer available as a statistic */ + portp->stats.rxbuffered = 1; /*tty->flip.count; */ + if (tty->termios != NULL) { + portp->stats.cflags = tty->termios->c_cflag; + portp->stats.iflags = tty->termios->c_iflag; + portp->stats.oflags = tty->termios->c_oflag; + portp->stats.lflags = tty->termios->c_lflag; + } + } + spin_unlock_irqrestore(&stallion_lock, flags); + + head = portp->tx.head; + tail = portp->tx.tail; + portp->stats.txbuffered = (head >= tail) ? (head - tail) : + (STL_TXBUFSIZE - (tail - head)); + + portp->stats.signals = (unsigned long) stl_getsignals(portp); + mutex_unlock(&portp->port.mutex); + + return copy_to_user(cp, &portp->stats, + sizeof(comstats_t)) ? -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Clear the port stats structure. We also return it zeroed out... + */ + +static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) +{ + comstats_t stl_comstats; + + if (!portp) { + if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) + return -EFAULT; + portp = stl_getport(stl_comstats.brd, stl_comstats.panel, + stl_comstats.port); + if (portp == NULL) + return -ENODEV; + } + + mutex_lock(&portp->port.mutex); + memset(&portp->stats, 0, sizeof(comstats_t)); + portp->stats.brd = portp->brdnr; + portp->stats.panel = portp->panelnr; + portp->stats.port = portp->portnr; + mutex_unlock(&portp->port.mutex); + return copy_to_user(cp, &portp->stats, + sizeof(comstats_t)) ? -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Return the entire driver ports structure to a user app. + */ + +static int stl_getportstruct(struct stlport __user *arg) +{ + struct stlport stl_dummyport; + struct stlport *portp; + + if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport))) + return -EFAULT; + portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, + stl_dummyport.portnr); + if (!portp) + return -ENODEV; + return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * Return the entire driver board structure to a user app. + */ + +static int stl_getbrdstruct(struct stlbrd __user *arg) +{ + struct stlbrd stl_dummybrd; + struct stlbrd *brdp; + + if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd))) + return -EFAULT; + if (stl_dummybrd.brdnr >= STL_MAXBRDS) + return -ENODEV; + brdp = stl_brds[stl_dummybrd.brdnr]; + if (!brdp) + return -ENODEV; + return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0; +} + +/*****************************************************************************/ + +/* + * The "staliomem" device is also required to do some special operations + * on the board and/or ports. In this driver it is mostly used for stats + * collection. + */ + +static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + int brdnr, rc; + void __user *argp = (void __user *)arg; + + pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); + + brdnr = iminor(fp->f_dentry->d_inode); + if (brdnr >= STL_MAXBRDS) + return -ENODEV; + rc = 0; + + switch (cmd) { + case COM_GETPORTSTATS: + rc = stl_getportstats(NULL, NULL, argp); + break; + case COM_CLRPORTSTATS: + rc = stl_clrportstats(NULL, argp); + break; + case COM_GETBRDSTATS: + rc = stl_getbrdstats(argp); + break; + case COM_READPORT: + rc = stl_getportstruct(argp); + break; + case COM_READBOARD: + rc = stl_getbrdstruct(argp); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + return rc; +} + +static const struct tty_operations stl_ops = { + .open = stl_open, + .close = stl_close, + .write = stl_write, + .put_char = stl_putchar, + .flush_chars = stl_flushchars, + .write_room = stl_writeroom, + .chars_in_buffer = stl_charsinbuffer, + .ioctl = stl_ioctl, + .set_termios = stl_settermios, + .throttle = stl_throttle, + .unthrottle = stl_unthrottle, + .stop = stl_stop, + .start = stl_start, + .hangup = stl_hangup, + .flush_buffer = stl_flushbuffer, + .break_ctl = stl_breakctl, + .wait_until_sent = stl_waituntilsent, + .send_xchar = stl_sendxchar, + .tiocmget = stl_tiocmget, + .tiocmset = stl_tiocmset, + .proc_fops = &stl_proc_fops, +}; + +static const struct tty_port_operations stl_port_ops = { + .carrier_raised = stl_carrier_raised, + .dtr_rts = stl_dtr_rts, + .activate = stl_activate, + .shutdown = stl_shutdown, +}; + +/*****************************************************************************/ +/* CD1400 HARDWARE FUNCTIONS */ +/*****************************************************************************/ + +/* + * These functions get/set/update the registers of the cd1400 UARTs. + * Access to the cd1400 registers is via an address/data io port pair. + * (Maybe should make this inline...) + */ + +static int stl_cd1400getreg(struct stlport *portp, int regnr) +{ + outb((regnr + portp->uartaddr), portp->ioaddr); + return inb(portp->ioaddr + EREG_DATA); +} + +static void stl_cd1400setreg(struct stlport *portp, int regnr, int value) +{ + outb(regnr + portp->uartaddr, portp->ioaddr); + outb(value, portp->ioaddr + EREG_DATA); +} + +static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value) +{ + outb(regnr + portp->uartaddr, portp->ioaddr); + if (inb(portp->ioaddr + EREG_DATA) != value) { + outb(value, portp->ioaddr + EREG_DATA); + return 1; + } + return 0; +} + +/*****************************************************************************/ + +/* + * Inbitialize the UARTs in a panel. We don't care what sort of board + * these ports are on - since the port io registers are almost + * identical when dealing with ports. + */ + +static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp) +{ + unsigned int gfrcr; + int chipmask, i, j; + int nrchips, uartaddr, ioaddr; + unsigned long flags; + + pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(panelp->brdnr, panelp->pagenr); + +/* + * Check that each chip is present and started up OK. + */ + chipmask = 0; + nrchips = panelp->nrports / CD1400_PORTS; + for (i = 0; i < nrchips; i++) { + if (brdp->brdtype == BRD_ECHPCI) { + outb((panelp->pagenr + (i >> 1)), brdp->ioctrl); + ioaddr = panelp->iobase; + } else + ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1)); + uartaddr = (i & 0x01) ? 0x080 : 0; + outb((GFRCR + uartaddr), ioaddr); + outb(0, (ioaddr + EREG_DATA)); + outb((CCR + uartaddr), ioaddr); + outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); + outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); + outb((GFRCR + uartaddr), ioaddr); + for (j = 0; j < CCR_MAXWAIT; j++) + if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) + break; + + if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { + printk("STALLION: cd1400 not responding, " + "brd=%d panel=%d chip=%d\n", + panelp->brdnr, panelp->panelnr, i); + continue; + } + chipmask |= (0x1 << i); + outb((PPR + uartaddr), ioaddr); + outb(PPR_SCALAR, (ioaddr + EREG_DATA)); + } + + BRDDISABLE(panelp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + return chipmask; +} + +/*****************************************************************************/ + +/* + * Initialize hardware specific port registers. + */ + +static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) +{ + unsigned long flags; + pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, + panelp, portp); + + if ((brdp == NULL) || (panelp == NULL) || + (portp == NULL)) + return; + + spin_lock_irqsave(&brd_lock, flags); + portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) || + (portp->portnr < 8)) ? 0 : EREG_BANKSIZE); + portp->uartaddr = (portp->portnr & 0x04) << 5; + portp->pagenr = panelp->pagenr + (portp->portnr >> 3); + + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + stl_cd1400setreg(portp, LIVR, (portp->portnr << 3)); + portp->hwid = stl_cd1400getreg(portp, GFRCR); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Wait for the command register to be ready. We will poll this, + * since it won't usually take too long to be ready. + */ + +static void stl_cd1400ccrwait(struct stlport *portp) +{ + int i; + + for (i = 0; i < CCR_MAXWAIT; i++) + if (stl_cd1400getreg(portp, CCR) == 0) + return; + + printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n", + portp->portnr, portp->panelnr, portp->brdnr); +} + +/*****************************************************************************/ + +/* + * Set up the cd1400 registers for a port based on the termios port + * settings. + */ + +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp) +{ + struct stlbrd *brdp; + unsigned long flags; + unsigned int clkdiv, baudrate; + unsigned char cor1, cor2, cor3; + unsigned char cor4, cor5, ccr; + unsigned char srer, sreron, sreroff; + unsigned char mcor1, mcor2, rtpr; + unsigned char clk, div; + + cor1 = 0; + cor2 = 0; + cor3 = 0; + cor4 = 0; + cor5 = 0; + ccr = 0; + rtpr = 0; + clk = 0; + div = 0; + mcor1 = 0; + mcor2 = 0; + sreron = 0; + sreroff = 0; + + brdp = stl_brds[portp->brdnr]; + if (brdp == NULL) + return; + +/* + * Set up the RX char ignore mask with those RX error types we + * can ignore. We can get the cd1400 to help us out a little here, + * it will ignore parity errors and breaks for us. + */ + portp->rxignoremsk = 0; + if (tiosp->c_iflag & IGNPAR) { + portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN); + cor1 |= COR1_PARIGNORE; + } + if (tiosp->c_iflag & IGNBRK) { + portp->rxignoremsk |= ST_BREAK; + cor4 |= COR4_IGNBRK; + } + + portp->rxmarkmsk = ST_OVERRUN; + if (tiosp->c_iflag & (INPCK | PARMRK)) + portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING); + if (tiosp->c_iflag & BRKINT) + portp->rxmarkmsk |= ST_BREAK; + +/* + * Go through the char size, parity and stop bits and set all the + * option register appropriately. + */ + switch (tiosp->c_cflag & CSIZE) { + case CS5: + cor1 |= COR1_CHL5; + break; + case CS6: + cor1 |= COR1_CHL6; + break; + case CS7: + cor1 |= COR1_CHL7; + break; + default: + cor1 |= COR1_CHL8; + break; + } + + if (tiosp->c_cflag & CSTOPB) + cor1 |= COR1_STOP2; + else + cor1 |= COR1_STOP1; + + if (tiosp->c_cflag & PARENB) { + if (tiosp->c_cflag & PARODD) + cor1 |= (COR1_PARENB | COR1_PARODD); + else + cor1 |= (COR1_PARENB | COR1_PAREVEN); + } else { + cor1 |= COR1_PARNONE; + } + +/* + * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing + * space for hardware flow control and the like. This should be set to + * VMIN. Also here we will set the RX data timeout to 10ms - this should + * really be based on VTIME. + */ + cor3 |= FIFO_RXTHRESHOLD; + rtpr = 2; + +/* + * Calculate the baud rate timers. For now we will just assume that + * the input and output baud are the same. Could have used a baud + * table here, but this way we can generate virtually any baud rate + * we like! + */ + baudrate = tiosp->c_cflag & CBAUD; + if (baudrate & CBAUDEX) { + baudrate &= ~CBAUDEX; + if ((baudrate < 1) || (baudrate > 4)) + tiosp->c_cflag &= ~CBAUDEX; + else + baudrate += 15; + } + baudrate = stl_baudrates[baudrate]; + if ((tiosp->c_cflag & CBAUD) == B38400) { + if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baudrate = 57600; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baudrate = 115200; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + baudrate = 230400; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + baudrate = 460800; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) + baudrate = (portp->baud_base / portp->custom_divisor); + } + if (baudrate > STL_CD1400MAXBAUD) + baudrate = STL_CD1400MAXBAUD; + + if (baudrate > 0) { + for (clk = 0; clk < CD1400_NUMCLKS; clk++) { + clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate; + if (clkdiv < 0x100) + break; + } + div = (unsigned char) clkdiv; + } + +/* + * Check what form of modem signaling is required and set it up. + */ + if ((tiosp->c_cflag & CLOCAL) == 0) { + mcor1 |= MCOR1_DCD; + mcor2 |= MCOR2_DCD; + sreron |= SRER_MODEM; + portp->port.flags |= ASYNC_CHECK_CD; + } else + portp->port.flags &= ~ASYNC_CHECK_CD; + +/* + * Setup cd1400 enhanced modes if we can. In particular we want to + * handle as much of the flow control as possible automatically. As + * well as saving a few CPU cycles it will also greatly improve flow + * control reliability. + */ + if (tiosp->c_iflag & IXON) { + cor2 |= COR2_TXIBE; + cor3 |= COR3_SCD12; + if (tiosp->c_iflag & IXANY) + cor2 |= COR2_IXM; + } + + if (tiosp->c_cflag & CRTSCTS) { + cor2 |= COR2_CTSAE; + mcor1 |= FIFO_RTSTHRESHOLD; + } + +/* + * All cd1400 register values calculated so go through and set + * them all up. + */ + + pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", + portp->portnr, portp->panelnr, portp->brdnr); + pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", + cor1, cor2, cor3, cor4, cor5); + pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", + mcor1, mcor2, rtpr, sreron, sreroff); + pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); + pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", + tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], + tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); + srer = stl_cd1400getreg(portp, SRER); + stl_cd1400setreg(portp, SRER, 0); + if (stl_cd1400updatereg(portp, COR1, cor1)) + ccr = 1; + if (stl_cd1400updatereg(portp, COR2, cor2)) + ccr = 1; + if (stl_cd1400updatereg(portp, COR3, cor3)) + ccr = 1; + if (ccr) { + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, CCR_CORCHANGE); + } + stl_cd1400setreg(portp, COR4, cor4); + stl_cd1400setreg(portp, COR5, cor5); + stl_cd1400setreg(portp, MCOR1, mcor1); + stl_cd1400setreg(portp, MCOR2, mcor2); + if (baudrate > 0) { + stl_cd1400setreg(portp, TCOR, clk); + stl_cd1400setreg(portp, TBPR, div); + stl_cd1400setreg(portp, RCOR, clk); + stl_cd1400setreg(portp, RBPR, div); + } + stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]); + stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]); + stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]); + stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]); + stl_cd1400setreg(portp, RTPR, rtpr); + mcor1 = stl_cd1400getreg(portp, MSVR1); + if (mcor1 & MSVR1_DCD) + portp->sigs |= TIOCM_CD; + else + portp->sigs &= ~TIOCM_CD; + stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron)); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Set the state of the DTR and RTS signals. + */ + +static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts) +{ + unsigned char msvr1, msvr2; + unsigned long flags; + + pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n", + portp, dtr, rts); + + msvr1 = 0; + msvr2 = 0; + if (dtr > 0) + msvr1 = MSVR1_DTR; + if (rts > 0) + msvr2 = MSVR2_RTS; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + if (rts >= 0) + stl_cd1400setreg(portp, MSVR2, msvr2); + if (dtr >= 0) + stl_cd1400setreg(portp, MSVR1, msvr1); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Return the state of the signals. + */ + +static int stl_cd1400getsignals(struct stlport *portp) +{ + unsigned char msvr1, msvr2; + unsigned long flags; + int sigs; + + pr_debug("stl_cd1400getsignals(portp=%p)\n", portp); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + msvr1 = stl_cd1400getreg(portp, MSVR1); + msvr2 = stl_cd1400getreg(portp, MSVR2); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + + sigs = 0; + sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0; + sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0; + sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0; + sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0; +#if 0 + sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0; + sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0; +#else + sigs |= TIOCM_DSR; +#endif + return sigs; +} + +/*****************************************************************************/ + +/* + * Enable/Disable the Transmitter and/or Receiver. + */ + +static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx) +{ + unsigned char ccr; + unsigned long flags; + + pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); + + ccr = 0; + + if (tx == 0) + ccr |= CCR_TXDISABLE; + else if (tx > 0) + ccr |= CCR_TXENABLE; + if (rx == 0) + ccr |= CCR_RXDISABLE; + else if (rx > 0) + ccr |= CCR_RXENABLE; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, ccr); + stl_cd1400ccrwait(portp); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Start/stop the Transmitter and/or Receiver. + */ + +static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx) +{ + unsigned char sreron, sreroff; + unsigned long flags; + + pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); + + sreron = 0; + sreroff = 0; + if (tx == 0) + sreroff |= (SRER_TXDATA | SRER_TXEMPTY); + else if (tx == 1) + sreron |= SRER_TXDATA; + else if (tx >= 2) + sreron |= SRER_TXEMPTY; + if (rx == 0) + sreroff |= SRER_RXDATA; + else if (rx > 0) + sreron |= SRER_RXDATA; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + stl_cd1400setreg(portp, SRER, + ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron)); + BRDDISABLE(portp->brdnr); + if (tx > 0) + set_bit(ASYI_TXBUSY, &portp->istate); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Disable all interrupts from this port. + */ + +static void stl_cd1400disableintrs(struct stlport *portp) +{ + unsigned long flags; + + pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + stl_cd1400setreg(portp, SRER, 0); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +static void stl_cd1400sendbreak(struct stlport *portp, int len) +{ + unsigned long flags; + + pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + stl_cd1400setreg(portp, SRER, + ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) | + SRER_TXEMPTY)); + BRDDISABLE(portp->brdnr); + portp->brklen = len; + if (len == 1) + portp->stats.txbreaks++; + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Take flow control actions... + */ + +static void stl_cd1400flowctrl(struct stlport *portp, int state) +{ + struct tty_struct *tty; + unsigned long flags; + + pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state); + + if (portp == NULL) + return; + tty = tty_port_tty_get(&portp->port); + if (tty == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + + if (state) { + if (tty->termios->c_iflag & IXOFF) { + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); + portp->stats.rxxon++; + stl_cd1400ccrwait(portp); + } +/* + * Question: should we return RTS to what it was before? It may + * have been set by an ioctl... Suppose not, since if you have + * hardware flow control set then it is pretty silly to go and + * set the RTS line by hand. + */ + if (tty->termios->c_cflag & CRTSCTS) { + stl_cd1400setreg(portp, MCOR1, + (stl_cd1400getreg(portp, MCOR1) | + FIFO_RTSTHRESHOLD)); + stl_cd1400setreg(portp, MSVR2, MSVR2_RTS); + portp->stats.rxrtson++; + } + } else { + if (tty->termios->c_iflag & IXOFF) { + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); + portp->stats.rxxoff++; + stl_cd1400ccrwait(portp); + } + if (tty->termios->c_cflag & CRTSCTS) { + stl_cd1400setreg(portp, MCOR1, + (stl_cd1400getreg(portp, MCOR1) & 0xf0)); + stl_cd1400setreg(portp, MSVR2, 0); + portp->stats.rxrtsoff++; + } + } + + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + tty_kref_put(tty); +} + +/*****************************************************************************/ + +/* + * Send a flow control character... + */ + +static void stl_cd1400sendflow(struct stlport *portp, int state) +{ + struct tty_struct *tty; + unsigned long flags; + + pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state); + + if (portp == NULL) + return; + tty = tty_port_tty_get(&portp->port); + if (tty == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + if (state) { + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); + portp->stats.rxxon++; + stl_cd1400ccrwait(portp); + } else { + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); + portp->stats.rxxoff++; + stl_cd1400ccrwait(portp); + } + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + tty_kref_put(tty); +} + +/*****************************************************************************/ + +static void stl_cd1400flush(struct stlport *portp) +{ + unsigned long flags; + + pr_debug("stl_cd1400flush(portp=%p)\n", portp); + + if (portp == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); + stl_cd1400ccrwait(portp); + stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO); + stl_cd1400ccrwait(portp); + portp->tx.tail = portp->tx.head; + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Return the current state of data flow on this port. This is only + * really interesting when determining if data has fully completed + * transmission or not... This is easy for the cd1400, it accurately + * maintains the busy port flag. + */ + +static int stl_cd1400datastate(struct stlport *portp) +{ + pr_debug("stl_cd1400datastate(portp=%p)\n", portp); + + if (portp == NULL) + return 0; + + return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0; +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for cd1400 EasyIO boards. + */ + +static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase) +{ + unsigned char svrtype; + + pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase); + + spin_lock(&brd_lock); + outb(SVRR, iobase); + svrtype = inb(iobase + EREG_DATA); + if (panelp->nrports > 4) { + outb((SVRR + 0x80), iobase); + svrtype |= inb(iobase + EREG_DATA); + } + + if (svrtype & SVRR_RX) + stl_cd1400rxisr(panelp, iobase); + else if (svrtype & SVRR_TX) + stl_cd1400txisr(panelp, iobase); + else if (svrtype & SVRR_MDM) + stl_cd1400mdmisr(panelp, iobase); + + spin_unlock(&brd_lock); +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for cd1400 panels. + */ + +static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase) +{ + unsigned char svrtype; + + pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase); + + outb(SVRR, iobase); + svrtype = inb(iobase + EREG_DATA); + outb((SVRR + 0x80), iobase); + svrtype |= inb(iobase + EREG_DATA); + if (svrtype & SVRR_RX) + stl_cd1400rxisr(panelp, iobase); + else if (svrtype & SVRR_TX) + stl_cd1400txisr(panelp, iobase); + else if (svrtype & SVRR_MDM) + stl_cd1400mdmisr(panelp, iobase); +} + + +/*****************************************************************************/ + +/* + * Unfortunately we need to handle breaks in the TX data stream, since + * this is the only way to generate them on the cd1400. + */ + +static int stl_cd1400breakisr(struct stlport *portp, int ioaddr) +{ + if (portp->brklen == 1) { + outb((COR2 + portp->uartaddr), ioaddr); + outb((inb(ioaddr + EREG_DATA) | COR2_ETC), + (ioaddr + EREG_DATA)); + outb((TDR + portp->uartaddr), ioaddr); + outb(ETC_CMD, (ioaddr + EREG_DATA)); + outb(ETC_STARTBREAK, (ioaddr + EREG_DATA)); + outb((SRER + portp->uartaddr), ioaddr); + outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)), + (ioaddr + EREG_DATA)); + return 1; + } else if (portp->brklen > 1) { + outb((TDR + portp->uartaddr), ioaddr); + outb(ETC_CMD, (ioaddr + EREG_DATA)); + outb(ETC_STOPBREAK, (ioaddr + EREG_DATA)); + portp->brklen = -1; + return 1; + } else { + outb((COR2 + portp->uartaddr), ioaddr); + outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC), + (ioaddr + EREG_DATA)); + portp->brklen = 0; + } + return 0; +} + +/*****************************************************************************/ + +/* + * Transmit interrupt handler. This has gotta be fast! Handling TX + * chars is pretty simple, stuff as many as possible from the TX buffer + * into the cd1400 FIFO. Must also handle TX breaks here, since they + * are embedded as commands in the data stream. Oh no, had to use a goto! + * This could be optimized more, will do when I get time... + * In practice it is possible that interrupts are enabled but that the + * port has been hung up. Need to handle not having any TX buffer here, + * this is done by using the side effect that head and tail will also + * be NULL if the buffer has been freed. + */ + +static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) +{ + struct stlport *portp; + int len, stlen; + char *head, *tail; + unsigned char ioack, srer; + struct tty_struct *tty; + + pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); + + ioack = inb(ioaddr + EREG_TXACK); + if (((ioack & panelp->ackmask) != 0) || + ((ioack & ACK_TYPMASK) != ACK_TYPTX)) { + printk("STALLION: bad TX interrupt ack value=%x\n", ioack); + return; + } + portp = panelp->ports[(ioack >> 3)]; + +/* + * Unfortunately we need to handle breaks in the data stream, since + * this is the only way to generate them on the cd1400. Do it now if + * a break is to be sent. + */ + if (portp->brklen != 0) + if (stl_cd1400breakisr(portp, ioaddr)) + goto stl_txalldone; + + head = portp->tx.head; + tail = portp->tx.tail; + len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); + if ((len == 0) || ((len < STL_TXBUFLOW) && + (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { + set_bit(ASYI_TXLOW, &portp->istate); + tty = tty_port_tty_get(&portp->port); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } + } + + if (len == 0) { + outb((SRER + portp->uartaddr), ioaddr); + srer = inb(ioaddr + EREG_DATA); + if (srer & SRER_TXDATA) { + srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY; + } else { + srer &= ~(SRER_TXDATA | SRER_TXEMPTY); + clear_bit(ASYI_TXBUSY, &portp->istate); + } + outb(srer, (ioaddr + EREG_DATA)); + } else { + len = min(len, CD1400_TXFIFOSIZE); + portp->stats.txtotal += len; + stlen = min_t(unsigned int, len, + (portp->tx.buf + STL_TXBUFSIZE) - tail); + outb((TDR + portp->uartaddr), ioaddr); + outsb((ioaddr + EREG_DATA), tail, stlen); + len -= stlen; + tail += stlen; + if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) + tail = portp->tx.buf; + if (len > 0) { + outsb((ioaddr + EREG_DATA), tail, len); + tail += len; + } + portp->tx.tail = tail; + } + +stl_txalldone: + outb((EOSRR + portp->uartaddr), ioaddr); + outb(0, (ioaddr + EREG_DATA)); +} + +/*****************************************************************************/ + +/* + * Receive character interrupt handler. Determine if we have good chars + * or bad chars and then process appropriately. Good chars are easy + * just shove the lot into the RX buffer and set all status byte to 0. + * If a bad RX char then process as required. This routine needs to be + * fast! In practice it is possible that we get an interrupt on a port + * that is closed. This can happen on hangups - since they completely + * shutdown a port not in user context. Need to handle this case. + */ + +static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) +{ + struct stlport *portp; + struct tty_struct *tty; + unsigned int ioack, len, buflen; + unsigned char status; + char ch; + + pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); + + ioack = inb(ioaddr + EREG_RXACK); + if ((ioack & panelp->ackmask) != 0) { + printk("STALLION: bad RX interrupt ack value=%x\n", ioack); + return; + } + portp = panelp->ports[(ioack >> 3)]; + tty = tty_port_tty_get(&portp->port); + + if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) { + outb((RDCR + portp->uartaddr), ioaddr); + len = inb(ioaddr + EREG_DATA); + if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { + len = min_t(unsigned int, len, sizeof(stl_unwanted)); + outb((RDSR + portp->uartaddr), ioaddr); + insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); + portp->stats.rxlost += len; + portp->stats.rxtotal += len; + } else { + len = min(len, buflen); + if (len > 0) { + unsigned char *ptr; + outb((RDSR + portp->uartaddr), ioaddr); + tty_prepare_flip_string(tty, &ptr, len); + insb((ioaddr + EREG_DATA), ptr, len); + tty_schedule_flip(tty); + portp->stats.rxtotal += len; + } + } + } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) { + outb((RDSR + portp->uartaddr), ioaddr); + status = inb(ioaddr + EREG_DATA); + ch = inb(ioaddr + EREG_DATA); + if (status & ST_PARITY) + portp->stats.rxparity++; + if (status & ST_FRAMING) + portp->stats.rxframing++; + if (status & ST_OVERRUN) + portp->stats.rxoverrun++; + if (status & ST_BREAK) + portp->stats.rxbreaks++; + if (status & ST_SCHARMASK) { + if ((status & ST_SCHARMASK) == ST_SCHAR1) + portp->stats.txxon++; + if ((status & ST_SCHARMASK) == ST_SCHAR2) + portp->stats.txxoff++; + goto stl_rxalldone; + } + if (tty != NULL && (portp->rxignoremsk & status) == 0) { + if (portp->rxmarkmsk & status) { + if (status & ST_BREAK) { + status = TTY_BREAK; + if (portp->port.flags & ASYNC_SAK) { + do_SAK(tty); + BRDENABLE(portp->brdnr, portp->pagenr); + } + } else if (status & ST_PARITY) + status = TTY_PARITY; + else if (status & ST_FRAMING) + status = TTY_FRAME; + else if(status & ST_OVERRUN) + status = TTY_OVERRUN; + else + status = 0; + } else + status = 0; + tty_insert_flip_char(tty, ch, status); + tty_schedule_flip(tty); + } + } else { + printk("STALLION: bad RX interrupt ack value=%x\n", ioack); + tty_kref_put(tty); + return; + } + +stl_rxalldone: + tty_kref_put(tty); + outb((EOSRR + portp->uartaddr), ioaddr); + outb(0, (ioaddr + EREG_DATA)); +} + +/*****************************************************************************/ + +/* + * Modem interrupt handler. The is called when the modem signal line + * (DCD) has changed state. Leave most of the work to the off-level + * processing routine. + */ + +static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr) +{ + struct stlport *portp; + unsigned int ioack; + unsigned char misr; + + pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp); + + ioack = inb(ioaddr + EREG_MDACK); + if (((ioack & panelp->ackmask) != 0) || + ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) { + printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack); + return; + } + portp = panelp->ports[(ioack >> 3)]; + + outb((MISR + portp->uartaddr), ioaddr); + misr = inb(ioaddr + EREG_DATA); + if (misr & MISR_DCD) { + stl_cd_change(portp); + portp->stats.modem++; + } + + outb((EOSRR + portp->uartaddr), ioaddr); + outb(0, (ioaddr + EREG_DATA)); +} + +/*****************************************************************************/ +/* SC26198 HARDWARE FUNCTIONS */ +/*****************************************************************************/ + +/* + * These functions get/set/update the registers of the sc26198 UARTs. + * Access to the sc26198 registers is via an address/data io port pair. + * (Maybe should make this inline...) + */ + +static int stl_sc26198getreg(struct stlport *portp, int regnr) +{ + outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); + return inb(portp->ioaddr + XP_DATA); +} + +static void stl_sc26198setreg(struct stlport *portp, int regnr, int value) +{ + outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); + outb(value, (portp->ioaddr + XP_DATA)); +} + +static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value) +{ + outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); + if (inb(portp->ioaddr + XP_DATA) != value) { + outb(value, (portp->ioaddr + XP_DATA)); + return 1; + } + return 0; +} + +/*****************************************************************************/ + +/* + * Functions to get and set the sc26198 global registers. + */ + +static int stl_sc26198getglobreg(struct stlport *portp, int regnr) +{ + outb(regnr, (portp->ioaddr + XP_ADDR)); + return inb(portp->ioaddr + XP_DATA); +} + +#if 0 +static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value) +{ + outb(regnr, (portp->ioaddr + XP_ADDR)); + outb(value, (portp->ioaddr + XP_DATA)); +} +#endif + +/*****************************************************************************/ + +/* + * Inbitialize the UARTs in a panel. We don't care what sort of board + * these ports are on - since the port io registers are almost + * identical when dealing with ports. + */ + +static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp) +{ + int chipmask, i; + int nrchips, ioaddr; + + pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); + + BRDENABLE(panelp->brdnr, panelp->pagenr); + +/* + * Check that each chip is present and started up OK. + */ + chipmask = 0; + nrchips = (panelp->nrports + 4) / SC26198_PORTS; + if (brdp->brdtype == BRD_ECHPCI) + outb(panelp->pagenr, brdp->ioctrl); + + for (i = 0; i < nrchips; i++) { + ioaddr = panelp->iobase + (i * 4); + outb(SCCR, (ioaddr + XP_ADDR)); + outb(CR_RESETALL, (ioaddr + XP_DATA)); + outb(TSTR, (ioaddr + XP_ADDR)); + if (inb(ioaddr + XP_DATA) != 0) { + printk("STALLION: sc26198 not responding, " + "brd=%d panel=%d chip=%d\n", + panelp->brdnr, panelp->panelnr, i); + continue; + } + chipmask |= (0x1 << i); + outb(GCCR, (ioaddr + XP_ADDR)); + outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA)); + outb(WDTRCR, (ioaddr + XP_ADDR)); + outb(0xff, (ioaddr + XP_DATA)); + } + + BRDDISABLE(panelp->brdnr); + return chipmask; +} + +/*****************************************************************************/ + +/* + * Initialize hardware specific port registers. + */ + +static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) +{ + pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, + panelp, portp); + + if ((brdp == NULL) || (panelp == NULL) || + (portp == NULL)) + return; + + portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); + portp->uartaddr = (portp->portnr & 0x07) << 4; + portp->pagenr = panelp->pagenr; + portp->hwid = 0x1; + + BRDENABLE(portp->brdnr, portp->pagenr); + stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS); + BRDDISABLE(portp->brdnr); +} + +/*****************************************************************************/ + +/* + * Set up the sc26198 registers for a port based on the termios port + * settings. + */ + +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp) +{ + struct stlbrd *brdp; + unsigned long flags; + unsigned int baudrate; + unsigned char mr0, mr1, mr2, clk; + unsigned char imron, imroff, iopr, ipr; + + mr0 = 0; + mr1 = 0; + mr2 = 0; + clk = 0; + iopr = 0; + imron = 0; + imroff = 0; + + brdp = stl_brds[portp->brdnr]; + if (brdp == NULL) + return; + +/* + * Set up the RX char ignore mask with those RX error types we + * can ignore. + */ + portp->rxignoremsk = 0; + if (tiosp->c_iflag & IGNPAR) + portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING | + SR_RXOVERRUN); + if (tiosp->c_iflag & IGNBRK) + portp->rxignoremsk |= SR_RXBREAK; + + portp->rxmarkmsk = SR_RXOVERRUN; + if (tiosp->c_iflag & (INPCK | PARMRK)) + portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING); + if (tiosp->c_iflag & BRKINT) + portp->rxmarkmsk |= SR_RXBREAK; + +/* + * Go through the char size, parity and stop bits and set all the + * option register appropriately. + */ + switch (tiosp->c_cflag & CSIZE) { + case CS5: + mr1 |= MR1_CS5; + break; + case CS6: + mr1 |= MR1_CS6; + break; + case CS7: + mr1 |= MR1_CS7; + break; + default: + mr1 |= MR1_CS8; + break; + } + + if (tiosp->c_cflag & CSTOPB) + mr2 |= MR2_STOP2; + else + mr2 |= MR2_STOP1; + + if (tiosp->c_cflag & PARENB) { + if (tiosp->c_cflag & PARODD) + mr1 |= (MR1_PARENB | MR1_PARODD); + else + mr1 |= (MR1_PARENB | MR1_PAREVEN); + } else + mr1 |= MR1_PARNONE; + + mr1 |= MR1_ERRBLOCK; + +/* + * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing + * space for hardware flow control and the like. This should be set to + * VMIN. + */ + mr2 |= MR2_RXFIFOHALF; + +/* + * Calculate the baud rate timers. For now we will just assume that + * the input and output baud are the same. The sc26198 has a fixed + * baud rate table, so only discrete baud rates possible. + */ + baudrate = tiosp->c_cflag & CBAUD; + if (baudrate & CBAUDEX) { + baudrate &= ~CBAUDEX; + if ((baudrate < 1) || (baudrate > 4)) + tiosp->c_cflag &= ~CBAUDEX; + else + baudrate += 15; + } + baudrate = stl_baudrates[baudrate]; + if ((tiosp->c_cflag & CBAUD) == B38400) { + if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baudrate = 57600; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baudrate = 115200; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + baudrate = 230400; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + baudrate = 460800; + else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) + baudrate = (portp->baud_base / portp->custom_divisor); + } + if (baudrate > STL_SC26198MAXBAUD) + baudrate = STL_SC26198MAXBAUD; + + if (baudrate > 0) + for (clk = 0; clk < SC26198_NRBAUDS; clk++) + if (baudrate <= sc26198_baudtable[clk]) + break; + +/* + * Check what form of modem signaling is required and set it up. + */ + if (tiosp->c_cflag & CLOCAL) { + portp->port.flags &= ~ASYNC_CHECK_CD; + } else { + iopr |= IOPR_DCDCOS; + imron |= IR_IOPORT; + portp->port.flags |= ASYNC_CHECK_CD; + } + +/* + * Setup sc26198 enhanced modes if we can. In particular we want to + * handle as much of the flow control as possible automatically. As + * well as saving a few CPU cycles it will also greatly improve flow + * control reliability. + */ + if (tiosp->c_iflag & IXON) { + mr0 |= MR0_SWFTX | MR0_SWFT; + imron |= IR_XONXOFF; + } else + imroff |= IR_XONXOFF; + + if (tiosp->c_iflag & IXOFF) + mr0 |= MR0_SWFRX; + + if (tiosp->c_cflag & CRTSCTS) { + mr2 |= MR2_AUTOCTS; + mr1 |= MR1_AUTORTS; + } + +/* + * All sc26198 register values calculated so go through and set + * them all up. + */ + + pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", + portp->portnr, portp->panelnr, portp->brdnr); + pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); + pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); + pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", + tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], + tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_sc26198setreg(portp, IMR, 0); + stl_sc26198updatereg(portp, MR0, mr0); + stl_sc26198updatereg(portp, MR1, mr1); + stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK); + stl_sc26198updatereg(portp, MR2, mr2); + stl_sc26198updatereg(portp, IOPIOR, + ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr)); + + if (baudrate > 0) { + stl_sc26198setreg(portp, TXCSR, clk); + stl_sc26198setreg(portp, RXCSR, clk); + } + + stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]); + stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); + + ipr = stl_sc26198getreg(portp, IPR); + if (ipr & IPR_DCD) + portp->sigs &= ~TIOCM_CD; + else + portp->sigs |= TIOCM_CD; + + portp->imr = (portp->imr & ~imroff) | imron; + stl_sc26198setreg(portp, IMR, portp->imr); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Set the state of the DTR and RTS signals. + */ + +static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts) +{ + unsigned char iopioron, iopioroff; + unsigned long flags; + + pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp, + dtr, rts); + + iopioron = 0; + iopioroff = 0; + if (dtr == 0) + iopioroff |= IPR_DTR; + else if (dtr > 0) + iopioron |= IPR_DTR; + if (rts == 0) + iopioroff |= IPR_RTS; + else if (rts > 0) + iopioron |= IPR_RTS; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_sc26198setreg(portp, IOPIOR, + ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron)); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Return the state of the signals. + */ + +static int stl_sc26198getsignals(struct stlport *portp) +{ + unsigned char ipr; + unsigned long flags; + int sigs; + + pr_debug("stl_sc26198getsignals(portp=%p)\n", portp); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + ipr = stl_sc26198getreg(portp, IPR); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + + sigs = 0; + sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD; + sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS; + sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR; + sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS; + sigs |= TIOCM_DSR; + return sigs; +} + +/*****************************************************************************/ + +/* + * Enable/Disable the Transmitter and/or Receiver. + */ + +static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx) +{ + unsigned char ccr; + unsigned long flags; + + pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx); + + ccr = portp->crenable; + if (tx == 0) + ccr &= ~CR_TXENABLE; + else if (tx > 0) + ccr |= CR_TXENABLE; + if (rx == 0) + ccr &= ~CR_RXENABLE; + else if (rx > 0) + ccr |= CR_RXENABLE; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_sc26198setreg(portp, SCCR, ccr); + BRDDISABLE(portp->brdnr); + portp->crenable = ccr; + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Start/stop the Transmitter and/or Receiver. + */ + +static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx) +{ + unsigned char imr; + unsigned long flags; + + pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); + + imr = portp->imr; + if (tx == 0) + imr &= ~IR_TXRDY; + else if (tx == 1) + imr |= IR_TXRDY; + if (rx == 0) + imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG); + else if (rx > 0) + imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_sc26198setreg(portp, IMR, imr); + BRDDISABLE(portp->brdnr); + portp->imr = imr; + if (tx > 0) + set_bit(ASYI_TXBUSY, &portp->istate); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Disable all interrupts from this port. + */ + +static void stl_sc26198disableintrs(struct stlport *portp) +{ + unsigned long flags; + + pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + portp->imr = 0; + stl_sc26198setreg(portp, IMR, 0); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +static void stl_sc26198sendbreak(struct stlport *portp, int len) +{ + unsigned long flags; + + pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len); + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + if (len == 1) { + stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); + portp->stats.txbreaks++; + } else + stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); + + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Take flow control actions... + */ + +static void stl_sc26198flowctrl(struct stlport *portp, int state) +{ + struct tty_struct *tty; + unsigned long flags; + unsigned char mr0; + + pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state); + + if (portp == NULL) + return; + tty = tty_port_tty_get(&portp->port); + if (tty == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + + if (state) { + if (tty->termios->c_iflag & IXOFF) { + mr0 = stl_sc26198getreg(portp, MR0); + stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); + stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); + mr0 |= MR0_SWFRX; + portp->stats.rxxon++; + stl_sc26198wait(portp); + stl_sc26198setreg(portp, MR0, mr0); + } +/* + * Question: should we return RTS to what it was before? It may + * have been set by an ioctl... Suppose not, since if you have + * hardware flow control set then it is pretty silly to go and + * set the RTS line by hand. + */ + if (tty->termios->c_cflag & CRTSCTS) { + stl_sc26198setreg(portp, MR1, + (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS)); + stl_sc26198setreg(portp, IOPIOR, + (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS)); + portp->stats.rxrtson++; + } + } else { + if (tty->termios->c_iflag & IXOFF) { + mr0 = stl_sc26198getreg(portp, MR0); + stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); + stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); + mr0 &= ~MR0_SWFRX; + portp->stats.rxxoff++; + stl_sc26198wait(portp); + stl_sc26198setreg(portp, MR0, mr0); + } + if (tty->termios->c_cflag & CRTSCTS) { + stl_sc26198setreg(portp, MR1, + (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); + stl_sc26198setreg(portp, IOPIOR, + (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS)); + portp->stats.rxrtsoff++; + } + } + + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + tty_kref_put(tty); +} + +/*****************************************************************************/ + +/* + * Send a flow control character. + */ + +static void stl_sc26198sendflow(struct stlport *portp, int state) +{ + struct tty_struct *tty; + unsigned long flags; + unsigned char mr0; + + pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state); + + if (portp == NULL) + return; + tty = tty_port_tty_get(&portp->port); + if (tty == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + if (state) { + mr0 = stl_sc26198getreg(portp, MR0); + stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); + stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); + mr0 |= MR0_SWFRX; + portp->stats.rxxon++; + stl_sc26198wait(portp); + stl_sc26198setreg(portp, MR0, mr0); + } else { + mr0 = stl_sc26198getreg(portp, MR0); + stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); + stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); + mr0 &= ~MR0_SWFRX; + portp->stats.rxxoff++; + stl_sc26198wait(portp); + stl_sc26198setreg(portp, MR0, mr0); + } + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + tty_kref_put(tty); +} + +/*****************************************************************************/ + +static void stl_sc26198flush(struct stlport *portp) +{ + unsigned long flags; + + pr_debug("stl_sc26198flush(portp=%p)\n", portp); + + if (portp == NULL) + return; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + stl_sc26198setreg(portp, SCCR, CR_TXRESET); + stl_sc26198setreg(portp, SCCR, portp->crenable); + BRDDISABLE(portp->brdnr); + portp->tx.tail = portp->tx.head; + spin_unlock_irqrestore(&brd_lock, flags); +} + +/*****************************************************************************/ + +/* + * Return the current state of data flow on this port. This is only + * really interesting when determining if data has fully completed + * transmission or not... The sc26198 interrupt scheme cannot + * determine when all data has actually drained, so we need to + * check the port statusy register to be sure. + */ + +static int stl_sc26198datastate(struct stlport *portp) +{ + unsigned long flags; + unsigned char sr; + + pr_debug("stl_sc26198datastate(portp=%p)\n", portp); + + if (portp == NULL) + return 0; + if (test_bit(ASYI_TXBUSY, &portp->istate)) + return 1; + + spin_lock_irqsave(&brd_lock, flags); + BRDENABLE(portp->brdnr, portp->pagenr); + sr = stl_sc26198getreg(portp, SR); + BRDDISABLE(portp->brdnr); + spin_unlock_irqrestore(&brd_lock, flags); + + return (sr & SR_TXEMPTY) ? 0 : 1; +} + +/*****************************************************************************/ + +/* + * Delay for a small amount of time, to give the sc26198 a chance + * to process a command... + */ + +static void stl_sc26198wait(struct stlport *portp) +{ + int i; + + pr_debug("stl_sc26198wait(portp=%p)\n", portp); + + if (portp == NULL) + return; + + for (i = 0; i < 20; i++) + stl_sc26198getglobreg(portp, TSTR); +} + +/*****************************************************************************/ + +/* + * If we are TX flow controlled and in IXANY mode then we may + * need to unflow control here. We gotta do this because of the + * automatic flow control modes of the sc26198. + */ + +static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty) +{ + unsigned char mr0; + + mr0 = stl_sc26198getreg(portp, MR0); + stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); + stl_sc26198setreg(portp, SCCR, CR_HOSTXON); + stl_sc26198wait(portp); + stl_sc26198setreg(portp, MR0, mr0); + clear_bit(ASYI_TXFLOWED, &portp->istate); +} + +/*****************************************************************************/ + +/* + * Interrupt service routine for sc26198 panels. + */ + +static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase) +{ + struct stlport *portp; + unsigned int iack; + + spin_lock(&brd_lock); + +/* + * Work around bug in sc26198 chip... Cannot have A6 address + * line of UART high, else iack will be returned as 0. + */ + outb(0, (iobase + 1)); + + iack = inb(iobase + XP_IACK); + portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)]; + + if (iack & IVR_RXDATA) + stl_sc26198rxisr(portp, iack); + else if (iack & IVR_TXDATA) + stl_sc26198txisr(portp); + else + stl_sc26198otherisr(portp, iack); + + spin_unlock(&brd_lock); +} + +/*****************************************************************************/ + +/* + * Transmit interrupt handler. This has gotta be fast! Handling TX + * chars is pretty simple, stuff as many as possible from the TX buffer + * into the sc26198 FIFO. + * In practice it is possible that interrupts are enabled but that the + * port has been hung up. Need to handle not having any TX buffer here, + * this is done by using the side effect that head and tail will also + * be NULL if the buffer has been freed. + */ + +static void stl_sc26198txisr(struct stlport *portp) +{ + struct tty_struct *tty; + unsigned int ioaddr; + unsigned char mr0; + int len, stlen; + char *head, *tail; + + pr_debug("stl_sc26198txisr(portp=%p)\n", portp); + + ioaddr = portp->ioaddr; + head = portp->tx.head; + tail = portp->tx.tail; + len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); + if ((len == 0) || ((len < STL_TXBUFLOW) && + (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { + set_bit(ASYI_TXLOW, &portp->istate); + tty = tty_port_tty_get(&portp->port); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } + } + + if (len == 0) { + outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR)); + mr0 = inb(ioaddr + XP_DATA); + if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) { + portp->imr &= ~IR_TXRDY; + outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR)); + outb(portp->imr, (ioaddr + XP_DATA)); + clear_bit(ASYI_TXBUSY, &portp->istate); + } else { + mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY); + outb(mr0, (ioaddr + XP_DATA)); + } + } else { + len = min(len, SC26198_TXFIFOSIZE); + portp->stats.txtotal += len; + stlen = min_t(unsigned int, len, + (portp->tx.buf + STL_TXBUFSIZE) - tail); + outb(GTXFIFO, (ioaddr + XP_ADDR)); + outsb((ioaddr + XP_DATA), tail, stlen); + len -= stlen; + tail += stlen; + if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) + tail = portp->tx.buf; + if (len > 0) { + outsb((ioaddr + XP_DATA), tail, len); + tail += len; + } + portp->tx.tail = tail; + } +} + +/*****************************************************************************/ + +/* + * Receive character interrupt handler. Determine if we have good chars + * or bad chars and then process appropriately. Good chars are easy + * just shove the lot into the RX buffer and set all status byte to 0. + * If a bad RX char then process as required. This routine needs to be + * fast! In practice it is possible that we get an interrupt on a port + * that is closed. This can happen on hangups - since they completely + * shutdown a port not in user context. Need to handle this case. + */ + +static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) +{ + struct tty_struct *tty; + unsigned int len, buflen, ioaddr; + + pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); + + tty = tty_port_tty_get(&portp->port); + ioaddr = portp->ioaddr; + outb(GIBCR, (ioaddr + XP_ADDR)); + len = inb(ioaddr + XP_DATA) + 1; + + if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { + if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { + len = min_t(unsigned int, len, sizeof(stl_unwanted)); + outb(GRXFIFO, (ioaddr + XP_ADDR)); + insb((ioaddr + XP_DATA), &stl_unwanted[0], len); + portp->stats.rxlost += len; + portp->stats.rxtotal += len; + } else { + len = min(len, buflen); + if (len > 0) { + unsigned char *ptr; + outb(GRXFIFO, (ioaddr + XP_ADDR)); + tty_prepare_flip_string(tty, &ptr, len); + insb((ioaddr + XP_DATA), ptr, len); + tty_schedule_flip(tty); + portp->stats.rxtotal += len; + } + } + } else { + stl_sc26198rxbadchars(portp); + } + +/* + * If we are TX flow controlled and in IXANY mode then we may need + * to unflow control here. We gotta do this because of the automatic + * flow control modes of the sc26198. + */ + if (test_bit(ASYI_TXFLOWED, &portp->istate)) { + if ((tty != NULL) && + (tty->termios != NULL) && + (tty->termios->c_iflag & IXANY)) { + stl_sc26198txunflow(portp, tty); + } + } + tty_kref_put(tty); +} + +/*****************************************************************************/ + +/* + * Process an RX bad character. + */ + +static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch) +{ + struct tty_struct *tty; + unsigned int ioaddr; + + tty = tty_port_tty_get(&portp->port); + ioaddr = portp->ioaddr; + + if (status & SR_RXPARITY) + portp->stats.rxparity++; + if (status & SR_RXFRAMING) + portp->stats.rxframing++; + if (status & SR_RXOVERRUN) + portp->stats.rxoverrun++; + if (status & SR_RXBREAK) + portp->stats.rxbreaks++; + + if ((tty != NULL) && + ((portp->rxignoremsk & status) == 0)) { + if (portp->rxmarkmsk & status) { + if (status & SR_RXBREAK) { + status = TTY_BREAK; + if (portp->port.flags & ASYNC_SAK) { + do_SAK(tty); + BRDENABLE(portp->brdnr, portp->pagenr); + } + } else if (status & SR_RXPARITY) + status = TTY_PARITY; + else if (status & SR_RXFRAMING) + status = TTY_FRAME; + else if(status & SR_RXOVERRUN) + status = TTY_OVERRUN; + else + status = 0; + } else + status = 0; + + tty_insert_flip_char(tty, ch, status); + tty_schedule_flip(tty); + + if (status == 0) + portp->stats.rxtotal++; + } + tty_kref_put(tty); +} + +/*****************************************************************************/ + +/* + * Process all characters in the RX FIFO of the UART. Check all char + * status bytes as well, and process as required. We need to check + * all bytes in the FIFO, in case some more enter the FIFO while we + * are here. To get the exact character error type we need to switch + * into CHAR error mode (that is why we need to make sure we empty + * the FIFO). + */ + +static void stl_sc26198rxbadchars(struct stlport *portp) +{ + unsigned char status, mr1; + char ch; + +/* + * To get the precise error type for each character we must switch + * back into CHAR error mode. + */ + mr1 = stl_sc26198getreg(portp, MR1); + stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); + + while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { + stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR); + ch = stl_sc26198getreg(portp, RXFIFO); + stl_sc26198rxbadch(portp, status, ch); + } + +/* + * To get correct interrupt class we must switch back into BLOCK + * error mode. + */ + stl_sc26198setreg(portp, MR1, mr1); +} + +/*****************************************************************************/ + +/* + * Other interrupt handler. This includes modem signals, flow + * control actions, etc. Most stuff is left to off-level interrupt + * processing time. + */ + +static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) +{ + unsigned char cir, ipr, xisr; + + pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack); + + cir = stl_sc26198getglobreg(portp, CIR); + + switch (cir & CIR_SUBTYPEMASK) { + case CIR_SUBCOS: + ipr = stl_sc26198getreg(portp, IPR); + if (ipr & IPR_DCDCHANGE) { + stl_cd_change(portp); + portp->stats.modem++; + } + break; + case CIR_SUBXONXOFF: + xisr = stl_sc26198getreg(portp, XISR); + if (xisr & XISR_RXXONGOT) { + set_bit(ASYI_TXFLOWED, &portp->istate); + portp->stats.txxoff++; + } + if (xisr & XISR_RXXOFFGOT) { + clear_bit(ASYI_TXFLOWED, &portp->istate); + portp->stats.txxon++; + } + break; + case CIR_SUBBREAK: + stl_sc26198setreg(portp, SCCR, CR_BREAKRESET); + stl_sc26198rxbadchars(portp); + break; + default: + break; + } +} + +static void stl_free_isabrds(void) +{ + struct stlbrd *brdp; + unsigned int i; + + for (i = 0; i < stl_nrbrds; i++) { + if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) + continue; + + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); + + kfree(brdp); + stl_brds[i] = NULL; + } +} + +/* + * Loadable module initialization stuff. + */ +static int __init stallion_module_init(void) +{ + struct stlbrd *brdp; + struct stlconf conf; + unsigned int i, j; + int retval; + + printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); + + spin_lock_init(&stallion_lock); + spin_lock_init(&brd_lock); + + stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); + if (!stl_serial) { + retval = -ENOMEM; + goto err; + } + + stl_serial->owner = THIS_MODULE; + stl_serial->driver_name = stl_drvname; + stl_serial->name = "ttyE"; + stl_serial->major = STL_SERIALMAJOR; + stl_serial->minor_start = 0; + stl_serial->type = TTY_DRIVER_TYPE_SERIAL; + stl_serial->subtype = SERIAL_TYPE_NORMAL; + stl_serial->init_termios = stl_deftermios; + stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(stl_serial, &stl_ops); + + retval = tty_register_driver(stl_serial); + if (retval) { + printk("STALLION: failed to register serial driver\n"); + goto err_frtty; + } + +/* + * Find any dynamically supported boards. That is via module load + * line options. + */ + for (i = stl_nrbrds; i < stl_nargs; i++) { + memset(&conf, 0, sizeof(conf)); + if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) + continue; + if ((brdp = stl_allocbrd()) == NULL) + continue; + brdp->brdnr = i; + brdp->brdtype = conf.brdtype; + brdp->ioaddr1 = conf.ioaddr1; + brdp->ioaddr2 = conf.ioaddr2; + brdp->irq = conf.irq; + brdp->irqtype = conf.irqtype; + stl_brds[brdp->brdnr] = brdp; + if (stl_brdinit(brdp)) { + stl_brds[brdp->brdnr] = NULL; + kfree(brdp); + } else { + for (j = 0; j < brdp->nrports; j++) + tty_register_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + j, NULL); + stl_nrbrds = i + 1; + } + } + + /* this has to be _after_ isa finding because of locking */ + retval = pci_register_driver(&stl_pcidriver); + if (retval && stl_nrbrds == 0) { + printk(KERN_ERR "STALLION: can't register pci driver\n"); + goto err_unrtty; + } + +/* + * Set up a character driver for per board stuff. This is mainly used + * to do stats ioctls on the ports. + */ + if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) + printk("STALLION: failed to register serial board device\n"); + + stallion_class = class_create(THIS_MODULE, "staliomem"); + if (IS_ERR(stallion_class)) + printk("STALLION: failed to create class\n"); + for (i = 0; i < 4; i++) + device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); + + return 0; +err_unrtty: + tty_unregister_driver(stl_serial); +err_frtty: + put_tty_driver(stl_serial); +err: + return retval; +} + +static void __exit stallion_module_exit(void) +{ + struct stlbrd *brdp; + unsigned int i, j; + + pr_debug("cleanup_module()\n"); + + printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, + stl_drvversion); + +/* + * Free up all allocated resources used by the ports. This includes + * memory and interrupts. As part of this process we will also do + * a hangup on every open port - to try to flush out any processes + * hanging onto ports. + */ + for (i = 0; i < stl_nrbrds; i++) { + if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) + continue; + for (j = 0; j < brdp->nrports; j++) + tty_unregister_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + j); + } + + for (i = 0; i < 4; i++) + device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); + unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); + class_destroy(stallion_class); + + pci_unregister_driver(&stl_pcidriver); + + stl_free_isabrds(); + + tty_unregister_driver(stl_serial); + put_tty_driver(stl_serial); +} + +module_init(stallion_module_init); +module_exit(stallion_module_exit); + +MODULE_AUTHOR("Greg Ungerer"); +MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4c37705877e74c02c968735c2eee0f84914cf557 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Feb 2011 17:09:33 -0800 Subject: tty: move obsolete and broken generic_serial drivers to drivers/staging/generic_serial/ As planned by Arnd Bergmann, this moves the following drivers to the drivers/staging/generic_serial directory where they will be removed after 2.6.41 if no one steps up to claim them. generic_serial rio ser_a2232 sx vme_scc Cc: Arnd Bergmann Cc: Alan Cox Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 44 - drivers/char/Makefile | 6 - drivers/char/generic_serial.c | 844 ------ drivers/char/rio/Makefile | 12 - drivers/char/rio/board.h | 132 - drivers/char/rio/cirrus.h | 210 -- drivers/char/rio/cmdblk.h | 53 - drivers/char/rio/cmdpkt.h | 177 -- drivers/char/rio/daemon.h | 307 --- drivers/char/rio/errors.h | 98 - drivers/char/rio/func.h | 143 - drivers/char/rio/host.h | 123 - drivers/char/rio/link.h | 96 - drivers/char/rio/linux_compat.h | 77 - drivers/char/rio/map.h | 98 - drivers/char/rio/param.h | 55 - drivers/char/rio/parmmap.h | 81 - drivers/char/rio/pci.h | 72 - drivers/char/rio/phb.h | 142 - drivers/char/rio/pkt.h | 77 - drivers/char/rio/port.h | 179 -- drivers/char/rio/protsts.h | 110 - drivers/char/rio/rio.h | 208 -- drivers/char/rio/rio_linux.c | 1204 --------- drivers/char/rio/rio_linux.h | 197 -- drivers/char/rio/rioboard.h | 275 -- drivers/char/rio/rioboot.c | 1113 -------- drivers/char/rio/riocmd.c | 939 ------- drivers/char/rio/rioctrl.c | 1504 ----------- drivers/char/rio/riodrvr.h | 138 - drivers/char/rio/rioinfo.h | 92 - drivers/char/rio/rioinit.c | 421 --- drivers/char/rio/riointr.c | 645 ----- drivers/char/rio/rioioctl.h | 57 - drivers/char/rio/rioparam.c | 663 ----- drivers/char/rio/rioroute.c | 1039 -------- drivers/char/rio/riospace.h | 154 -- drivers/char/rio/riotable.c | 941 ------- drivers/char/rio/riotty.c | 654 ----- drivers/char/rio/route.h | 101 - drivers/char/rio/rup.h | 69 - drivers/char/rio/unixrup.h | 51 - drivers/char/ser_a2232.c | 831 ------ drivers/char/ser_a2232.h | 202 -- drivers/char/ser_a2232fw.ax | 529 ---- drivers/char/ser_a2232fw.h | 306 --- drivers/char/sx.c | 2894 --------------------- drivers/char/sx.h | 201 -- drivers/char/sxboards.h | 206 -- drivers/char/sxwindow.h | 393 --- drivers/char/vme_scc.c | 1145 -------- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/generic_serial/Kconfig | 45 + drivers/staging/generic_serial/Makefile | 6 + drivers/staging/generic_serial/TODO | 6 + drivers/staging/generic_serial/generic_serial.c | 844 ++++++ drivers/staging/generic_serial/rio/Makefile | 12 + drivers/staging/generic_serial/rio/board.h | 132 + drivers/staging/generic_serial/rio/cirrus.h | 210 ++ drivers/staging/generic_serial/rio/cmdblk.h | 53 + drivers/staging/generic_serial/rio/cmdpkt.h | 177 ++ drivers/staging/generic_serial/rio/daemon.h | 307 +++ drivers/staging/generic_serial/rio/errors.h | 98 + drivers/staging/generic_serial/rio/func.h | 143 + drivers/staging/generic_serial/rio/host.h | 123 + drivers/staging/generic_serial/rio/link.h | 96 + drivers/staging/generic_serial/rio/linux_compat.h | 77 + drivers/staging/generic_serial/rio/map.h | 98 + drivers/staging/generic_serial/rio/param.h | 55 + drivers/staging/generic_serial/rio/parmmap.h | 81 + drivers/staging/generic_serial/rio/pci.h | 72 + drivers/staging/generic_serial/rio/phb.h | 142 + drivers/staging/generic_serial/rio/pkt.h | 77 + drivers/staging/generic_serial/rio/port.h | 179 ++ drivers/staging/generic_serial/rio/protsts.h | 110 + drivers/staging/generic_serial/rio/rio.h | 208 ++ drivers/staging/generic_serial/rio/rio_linux.c | 1204 +++++++++ drivers/staging/generic_serial/rio/rio_linux.h | 197 ++ drivers/staging/generic_serial/rio/rioboard.h | 275 ++ drivers/staging/generic_serial/rio/rioboot.c | 1113 ++++++++ drivers/staging/generic_serial/rio/riocmd.c | 939 +++++++ drivers/staging/generic_serial/rio/rioctrl.c | 1504 +++++++++++ drivers/staging/generic_serial/rio/riodrvr.h | 138 + drivers/staging/generic_serial/rio/rioinfo.h | 92 + drivers/staging/generic_serial/rio/rioinit.c | 421 +++ drivers/staging/generic_serial/rio/riointr.c | 645 +++++ drivers/staging/generic_serial/rio/rioioctl.h | 57 + drivers/staging/generic_serial/rio/rioparam.c | 663 +++++ drivers/staging/generic_serial/rio/rioroute.c | 1039 ++++++++ drivers/staging/generic_serial/rio/riospace.h | 154 ++ drivers/staging/generic_serial/rio/riotable.c | 941 +++++++ drivers/staging/generic_serial/rio/riotty.c | 654 +++++ drivers/staging/generic_serial/rio/route.h | 101 + drivers/staging/generic_serial/rio/rup.h | 69 + drivers/staging/generic_serial/rio/unixrup.h | 51 + drivers/staging/generic_serial/ser_a2232.c | 831 ++++++ drivers/staging/generic_serial/ser_a2232.h | 202 ++ drivers/staging/generic_serial/ser_a2232fw.ax | 529 ++++ drivers/staging/generic_serial/ser_a2232fw.h | 306 +++ drivers/staging/generic_serial/sx.c | 2894 +++++++++++++++++++++ drivers/staging/generic_serial/sx.h | 201 ++ drivers/staging/generic_serial/sxboards.h | 206 ++ drivers/staging/generic_serial/sxwindow.h | 393 +++ drivers/staging/generic_serial/vme_scc.c | 1145 ++++++++ 105 files changed, 20318 insertions(+), 20308 deletions(-) delete mode 100644 drivers/char/generic_serial.c delete mode 100644 drivers/char/rio/Makefile delete mode 100644 drivers/char/rio/board.h delete mode 100644 drivers/char/rio/cirrus.h delete mode 100644 drivers/char/rio/cmdblk.h delete mode 100644 drivers/char/rio/cmdpkt.h delete mode 100644 drivers/char/rio/daemon.h delete mode 100644 drivers/char/rio/errors.h delete mode 100644 drivers/char/rio/func.h delete mode 100644 drivers/char/rio/host.h delete mode 100644 drivers/char/rio/link.h delete mode 100644 drivers/char/rio/linux_compat.h delete mode 100644 drivers/char/rio/map.h delete mode 100644 drivers/char/rio/param.h delete mode 100644 drivers/char/rio/parmmap.h delete mode 100644 drivers/char/rio/pci.h delete mode 100644 drivers/char/rio/phb.h delete mode 100644 drivers/char/rio/pkt.h delete mode 100644 drivers/char/rio/port.h delete mode 100644 drivers/char/rio/protsts.h delete mode 100644 drivers/char/rio/rio.h delete mode 100644 drivers/char/rio/rio_linux.c delete mode 100644 drivers/char/rio/rio_linux.h delete mode 100644 drivers/char/rio/rioboard.h delete mode 100644 drivers/char/rio/rioboot.c delete mode 100644 drivers/char/rio/riocmd.c delete mode 100644 drivers/char/rio/rioctrl.c delete mode 100644 drivers/char/rio/riodrvr.h delete mode 100644 drivers/char/rio/rioinfo.h delete mode 100644 drivers/char/rio/rioinit.c delete mode 100644 drivers/char/rio/riointr.c delete mode 100644 drivers/char/rio/rioioctl.h delete mode 100644 drivers/char/rio/rioparam.c delete mode 100644 drivers/char/rio/rioroute.c delete mode 100644 drivers/char/rio/riospace.h delete mode 100644 drivers/char/rio/riotable.c delete mode 100644 drivers/char/rio/riotty.c delete mode 100644 drivers/char/rio/route.h delete mode 100644 drivers/char/rio/rup.h delete mode 100644 drivers/char/rio/unixrup.h delete mode 100644 drivers/char/ser_a2232.c delete mode 100644 drivers/char/ser_a2232.h delete mode 100644 drivers/char/ser_a2232fw.ax delete mode 100644 drivers/char/ser_a2232fw.h delete mode 100644 drivers/char/sx.c delete mode 100644 drivers/char/sx.h delete mode 100644 drivers/char/sxboards.h delete mode 100644 drivers/char/sxwindow.h delete mode 100644 drivers/char/vme_scc.c create mode 100644 drivers/staging/generic_serial/Kconfig create mode 100644 drivers/staging/generic_serial/Makefile create mode 100644 drivers/staging/generic_serial/TODO create mode 100644 drivers/staging/generic_serial/generic_serial.c create mode 100644 drivers/staging/generic_serial/rio/Makefile create mode 100644 drivers/staging/generic_serial/rio/board.h create mode 100644 drivers/staging/generic_serial/rio/cirrus.h create mode 100644 drivers/staging/generic_serial/rio/cmdblk.h create mode 100644 drivers/staging/generic_serial/rio/cmdpkt.h create mode 100644 drivers/staging/generic_serial/rio/daemon.h create mode 100644 drivers/staging/generic_serial/rio/errors.h create mode 100644 drivers/staging/generic_serial/rio/func.h create mode 100644 drivers/staging/generic_serial/rio/host.h create mode 100644 drivers/staging/generic_serial/rio/link.h create mode 100644 drivers/staging/generic_serial/rio/linux_compat.h create mode 100644 drivers/staging/generic_serial/rio/map.h create mode 100644 drivers/staging/generic_serial/rio/param.h create mode 100644 drivers/staging/generic_serial/rio/parmmap.h create mode 100644 drivers/staging/generic_serial/rio/pci.h create mode 100644 drivers/staging/generic_serial/rio/phb.h create mode 100644 drivers/staging/generic_serial/rio/pkt.h create mode 100644 drivers/staging/generic_serial/rio/port.h create mode 100644 drivers/staging/generic_serial/rio/protsts.h create mode 100644 drivers/staging/generic_serial/rio/rio.h create mode 100644 drivers/staging/generic_serial/rio/rio_linux.c create mode 100644 drivers/staging/generic_serial/rio/rio_linux.h create mode 100644 drivers/staging/generic_serial/rio/rioboard.h create mode 100644 drivers/staging/generic_serial/rio/rioboot.c create mode 100644 drivers/staging/generic_serial/rio/riocmd.c create mode 100644 drivers/staging/generic_serial/rio/rioctrl.c create mode 100644 drivers/staging/generic_serial/rio/riodrvr.h create mode 100644 drivers/staging/generic_serial/rio/rioinfo.h create mode 100644 drivers/staging/generic_serial/rio/rioinit.c create mode 100644 drivers/staging/generic_serial/rio/riointr.c create mode 100644 drivers/staging/generic_serial/rio/rioioctl.h create mode 100644 drivers/staging/generic_serial/rio/rioparam.c create mode 100644 drivers/staging/generic_serial/rio/rioroute.c create mode 100644 drivers/staging/generic_serial/rio/riospace.h create mode 100644 drivers/staging/generic_serial/rio/riotable.c create mode 100644 drivers/staging/generic_serial/rio/riotty.c create mode 100644 drivers/staging/generic_serial/rio/route.h create mode 100644 drivers/staging/generic_serial/rio/rup.h create mode 100644 drivers/staging/generic_serial/rio/unixrup.h create mode 100644 drivers/staging/generic_serial/ser_a2232.c create mode 100644 drivers/staging/generic_serial/ser_a2232.h create mode 100644 drivers/staging/generic_serial/ser_a2232fw.ax create mode 100644 drivers/staging/generic_serial/ser_a2232fw.h create mode 100644 drivers/staging/generic_serial/sx.c create mode 100644 drivers/staging/generic_serial/sx.h create mode 100644 drivers/staging/generic_serial/sxboards.h create mode 100644 drivers/staging/generic_serial/sxwindow.h create mode 100644 drivers/staging/generic_serial/vme_scc.c (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7b8cf0295f6c..04f8b2d083c6 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -15,34 +15,6 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". -config SX - tristate "Specialix SX (and SI) card support" - depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN - help - This is a driver for the SX and SI multiport serial cards. - Please read the file for details. - - This driver can only be built as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called sx. If you want to do that, say M here. - -config RIO - tristate "Specialix RIO system support" - depends on SERIAL_NONSTANDARD && BROKEN - help - This is a driver for the Specialix RIO, a smart serial card which - drives an outboard box that can support up to 128 ports. Product - information is at . - There are both ISA and PCI versions. - -config RIO_OLDPCI - bool "Support really old RIO/PCI cards" - depends on RIO - help - Older RIO PCI cards need some initialization-time configuration to - determine the IRQ and some control addresses. If you have a RIO and - this doesn't seem to work, try setting this to Y. - config STALDRV bool "Stallion multiport serial support" depends on SERIAL_NONSTANDARD @@ -55,22 +27,6 @@ config STALDRV in this case. If you have never heard about all this, it's safe to say N. -config A2232 - tristate "Commodore A2232 serial support (EXPERIMENTAL)" - depends on EXPERIMENTAL && ZORRO && BROKEN - ---help--- - This option supports the 2232 7-port serial card shipped with the - Amiga 2000 and other Zorro-bus machines, dating from 1989. At - a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip - each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The - ports were connected with 8 pin DIN connectors on the card bracket, - for which 8 pin to DB25 adapters were supplied. The card also had - jumpers internally to toggle various pinning configurations. - - This driver can be built as a module; but then "generic_serial" - will also be built as a module. This has to be loaded before - "ser_a2232". If you want to do this, answer M here. - config SGI_SNSC bool "SGI Altix system controller communication support" depends on (IA64_SGI_SN2 || IA64_GENERIC) diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 48bb8acbea49..3ca1f627be8a 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -5,13 +5,7 @@ obj-y += mem.o random.o obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o -obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o -obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o -obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o -obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o -obj-$(CONFIG_SX) += sx.o generic_serial.o -obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MSPEC) += mspec.o diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c deleted file mode 100644 index 5954ee1dc953..000000000000 --- a/drivers/char/generic_serial.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * generic_serial.c - * - * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl - * - * written for the SX serial driver. - * Contains the code that should be shared over all the serial drivers. - * - * Credit for the idea to do it this way might go to Alan Cox. - * - * - * Version 0.1 -- December, 1998. Initial version. - * Version 0.2 -- March, 1999. Some more routines. Bugfixes. Etc. - * Version 0.5 -- August, 1999. Some more fixes. Reformat for Linus. - * - * BitWizard is actively maintaining this file. We sometimes find - * that someone submitted changes to this file. We really appreciate - * your help, but please submit changes through us. We're doing our - * best to be responsive. -- REW - * */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG - -static int gs_debug; - -#ifdef DEBUG -#define gs_dprintk(f, str...) if (gs_debug & f) printk (str) -#else -#define gs_dprintk(f, str...) /* nothing */ -#endif - -#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__) -#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __func__) - -#define RS_EVENT_WRITE_WAKEUP 1 - -module_param(gs_debug, int, 0644); - - -int gs_put_char(struct tty_struct * tty, unsigned char ch) -{ - struct gs_port *port; - - func_enter (); - - port = tty->driver_data; - - if (!port) return 0; - - if (! (port->port.flags & ASYNC_INITIALIZED)) return 0; - - /* Take a lock on the serial tranmit buffer! */ - mutex_lock(& port->port_write_mutex); - - if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ - mutex_unlock(&port->port_write_mutex); - return 0; - } - - port->xmit_buf[port->xmit_head++] = ch; - port->xmit_head &= SERIAL_XMIT_SIZE - 1; - port->xmit_cnt++; /* Characters in buffer */ - - mutex_unlock(&port->port_write_mutex); - func_exit (); - return 1; -} - - -/* -> Problems to take into account are: -> -1- Interrupts that empty part of the buffer. -> -2- page faults on the access to userspace. -> -3- Other processes that are also trying to do a "write". -*/ - -int gs_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - struct gs_port *port; - int c, total = 0; - int t; - - func_enter (); - - port = tty->driver_data; - - if (!port) return 0; - - if (! (port->port.flags & ASYNC_INITIALIZED)) - return 0; - - /* get exclusive "write" access to this port (problem 3) */ - /* This is not a spinlock because we can have a disk access (page - fault) in copy_from_user */ - mutex_lock(& port->port_write_mutex); - - while (1) { - - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_mutex. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) break; - - memcpy (port->xmit_buf + port->xmit_head, buf, c); - - port -> xmit_cnt += c; - port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1); - buf += c; - count -= c; - total += c; - } - mutex_unlock(& port->port_write_mutex); - - gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", - (port->port.flags & GS_TX_INTEN)?"enabled": "disabled"); - - if (port->xmit_cnt && - !tty->stopped && - !tty->hw_stopped && - !(port->port.flags & GS_TX_INTEN)) { - port->port.flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - } - func_exit (); - return total; -} - - - -int gs_write_room(struct tty_struct * tty) -{ - struct gs_port *port = tty->driver_data; - int ret; - - func_enter (); - ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; - if (ret < 0) - ret = 0; - func_exit (); - return ret; -} - - -int gs_chars_in_buffer(struct tty_struct *tty) -{ - struct gs_port *port = tty->driver_data; - func_enter (); - - func_exit (); - return port->xmit_cnt; -} - - -static int gs_real_chars_in_buffer(struct tty_struct *tty) -{ - struct gs_port *port; - func_enter (); - - port = tty->driver_data; - - if (!port->rd) return 0; - if (!port->rd->chars_in_buffer) return 0; - - func_exit (); - return port->xmit_cnt + port->rd->chars_in_buffer (port); -} - - -static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) -{ - struct gs_port *port = ptr; - unsigned long end_jiffies; - int jiffies_to_transmit, charsleft = 0, rv = 0; - int rcib; - - func_enter(); - - gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port); - if (port) { - gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", - port->xmit_cnt, port->xmit_buf, port->port.tty); - } - - if (!port || port->xmit_cnt < 0 || !port->xmit_buf) { - gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n"); - func_exit(); - return -EINVAL; /* This is an error which we don't know how to handle. */ - } - - rcib = gs_real_chars_in_buffer(port->port.tty); - - if(rcib <= 0) { - gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n"); - func_exit(); - return rv; - } - /* stop trying: now + twice the time it would normally take + seconds */ - if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT; - end_jiffies = jiffies; - if (timeout != MAX_SCHEDULE_TIMEOUT) - end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0; - end_jiffies += timeout; - - gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", - jiffies, end_jiffies, end_jiffies-jiffies); - - /* the expression is actually jiffies < end_jiffies, but that won't - work around the wraparound. Tricky eh? */ - while ((charsleft = gs_real_chars_in_buffer (port->port.tty)) && - time_after (end_jiffies, jiffies)) { - /* Units check: - chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies! - check! */ - - charsleft += 16; /* Allow 16 chars more to be transmitted ... */ - jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0; - /* ^^^ Round up.... */ - if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1; - - gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies " - "(%d chars).\n", jiffies_to_transmit, charsleft); - - msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit)); - if (signal_pending (current)) { - gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); - rv = -EINTR; - break; - } - } - - gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); - set_current_state (TASK_RUNNING); - - func_exit(); - return rv; -} - - - -void gs_flush_buffer(struct tty_struct *tty) -{ - struct gs_port *port; - unsigned long flags; - - func_enter (); - - port = tty->driver_data; - - if (!port) return; - - /* XXX Would the write semaphore do? */ - spin_lock_irqsave (&port->driver_lock, flags); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - spin_unlock_irqrestore (&port->driver_lock, flags); - - tty_wakeup(tty); - func_exit (); -} - - -void gs_flush_chars(struct tty_struct * tty) -{ - struct gs_port *port; - - func_enter (); - - port = tty->driver_data; - - if (!port) return; - - if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !port->xmit_buf) { - func_exit (); - return; - } - - /* Beats me -- REW */ - port->port.flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - func_exit (); -} - - -void gs_stop(struct tty_struct * tty) -{ - struct gs_port *port; - - func_enter (); - - port = tty->driver_data; - - if (!port) return; - - if (port->xmit_cnt && - port->xmit_buf && - (port->port.flags & GS_TX_INTEN) ) { - port->port.flags &= ~GS_TX_INTEN; - port->rd->disable_tx_interrupts (port); - } - func_exit (); -} - - -void gs_start(struct tty_struct * tty) -{ - struct gs_port *port; - - port = tty->driver_data; - - if (!port) return; - - if (port->xmit_cnt && - port->xmit_buf && - !(port->port.flags & GS_TX_INTEN) ) { - port->port.flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - } - func_exit (); -} - - -static void gs_shutdown_port (struct gs_port *port) -{ - unsigned long flags; - - func_enter(); - - if (!port) return; - - if (!(port->port.flags & ASYNC_INITIALIZED)) - return; - - spin_lock_irqsave(&port->driver_lock, flags); - - if (port->xmit_buf) { - free_page((unsigned long) port->xmit_buf); - port->xmit_buf = NULL; - } - - if (port->port.tty) - set_bit(TTY_IO_ERROR, &port->port.tty->flags); - - port->rd->shutdown_port (port); - - port->port.flags &= ~ASYNC_INITIALIZED; - spin_unlock_irqrestore(&port->driver_lock, flags); - - func_exit(); -} - - -void gs_hangup(struct tty_struct *tty) -{ - struct gs_port *port; - unsigned long flags; - - func_enter (); - - port = tty->driver_data; - tty = port->port.tty; - if (!tty) - return; - - gs_shutdown_port (port); - spin_lock_irqsave(&port->port.lock, flags); - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE); - port->port.tty = NULL; - port->port.count = 0; - spin_unlock_irqrestore(&port->port.lock, flags); - - wake_up_interruptible(&port->port.open_wait); - func_exit (); -} - - -int gs_block_til_ready(void *port_, struct file * filp) -{ - struct gs_port *gp = port_; - struct tty_port *port = &gp->port; - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - int CD; - struct tty_struct *tty; - unsigned long flags; - - func_enter (); - - if (!port) return 0; - - tty = port->tty; - - gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&port->close_wait); - if (port->flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; - } - - gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); - - if (C_CLOCAL(tty)) - do_clocal = 1; - - /* - * 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, port->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - - add_wait_queue(&port->open_wait, &wait); - - gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) { - port->count--; - } - port->blocked_open++; - spin_unlock_irqrestore(&port->lock, flags); - while (1) { - CD = tty_port_carrier_raised(port); - gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); - set_current_state (TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(port->flags & ASYNC_INITIALIZED)) { - if (port->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(port->flags & ASYNC_CLOSING) && - (do_clocal || CD)) - break; - gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", - (int)signal_pending (current), *(long*)(¤t->blocked)); - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", - port->blocked_open); - set_current_state (TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) { - port->count++; - } - port->blocked_open--; - if (retval == 0) - port->flags |= ASYNC_NORMAL_ACTIVE; - spin_unlock_irqrestore(&port->lock, flags); - func_exit (); - return retval; -} - - -void gs_close(struct tty_struct * tty, struct file * filp) -{ - unsigned long flags; - struct gs_port *port; - - func_enter (); - - port = tty->driver_data; - - if (!port) return; - - if (!port->port.tty) { - /* This seems to happen when this is called from vhangup. */ - gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->port.tty is NULL\n"); - port->port.tty = tty; - } - - spin_lock_irqsave(&port->port.lock, flags); - - if (tty_hung_up_p(filp)) { - spin_unlock_irqrestore(&port->port.lock, flags); - if (port->rd->hungup) - port->rd->hungup (port); - func_exit (); - return; - } - - if ((tty->count == 1) && (port->port.count != 1)) { - printk(KERN_ERR "gs: gs_close port %p: bad port count;" - " tty->count is 1, port count is %d\n", port, port->port.count); - port->port.count = 1; - } - if (--port->port.count < 0) { - printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->port.count); - port->port.count = 0; - } - - if (port->port.count) { - gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count); - spin_unlock_irqrestore(&port->port.lock, flags); - func_exit (); - return; - } - port->port.flags |= ASYNC_CLOSING; - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - /* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, port->closing_wait); */ - - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - - spin_lock_irqsave(&port->driver_lock, flags); - port->rd->disable_rx_interrupts (port); - spin_unlock_irqrestore(&port->driver_lock, flags); - spin_unlock_irqrestore(&port->port.lock, flags); - - /* close has no way of returning "EINTR", so discard return value */ - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - gs_wait_tx_flushed (port, port->closing_wait); - - port->port.flags &= ~GS_ACTIVE; - - gs_flush_buffer(tty); - - tty_ldisc_flush(tty); - tty->closing = 0; - - spin_lock_irqsave(&port->driver_lock, flags); - port->event = 0; - port->rd->close (port); - port->rd->shutdown_port (port); - spin_unlock_irqrestore(&port->driver_lock, flags); - - spin_lock_irqsave(&port->port.lock, flags); - port->port.tty = NULL; - - if (port->port.blocked_open) { - if (port->close_delay) { - spin_unlock_irqrestore(&port->port.lock, flags); - msleep_interruptible(jiffies_to_msecs(port->close_delay)); - spin_lock_irqsave(&port->port.lock, flags); - } - wake_up_interruptible(&port->port.open_wait); - } - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED); - spin_unlock_irqrestore(&port->port.lock, flags); - wake_up_interruptible(&port->port.close_wait); - - func_exit (); -} - - -void gs_set_termios (struct tty_struct * tty, - struct ktermios * old_termios) -{ - struct gs_port *port; - int baudrate, tmp, rv; - struct ktermios *tiosp; - - func_enter(); - - port = tty->driver_data; - - if (!port) return; - if (!port->port.tty) { - /* This seems to happen when this is called after gs_close. */ - gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->port.tty is NULL\n"); - port->port.tty = tty; - } - - - tiosp = tty->termios; - - if (gs_debug & GS_DEBUG_TERMIOS) { - gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); - } - - if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { - if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); - if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); - if(tiosp->c_cflag != old_termios->c_cflag) printk("c_cflag changed\n"); - if(tiosp->c_lflag != old_termios->c_lflag) printk("c_lflag changed\n"); - if(tiosp->c_line != old_termios->c_line) printk("c_line changed\n"); - if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); - } - - baudrate = tty_get_baud_rate(tty); - - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ( (port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baudrate = 57600; - else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baudrate = 115200; - else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baudrate = 230400; - else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baudrate = 460800; - else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - baudrate = (port->baud_base / port->custom_divisor); - } - - /* I recommend using THIS instead of the mess in termios (and - duplicating the above code). Next we should create a clean - interface towards this variable. If your card supports arbitrary - baud rates, (e.g. CD1400 or 16550 based cards) then everything - will be very easy..... */ - port->baud = baudrate; - - /* Two timer ticks seems enough to wakeup something like SLIP driver */ - /* Baudrate/10 is cps. Divide by HZ to get chars per tick. */ - tmp = (baudrate / 10 / HZ) * 2; - - if (tmp < 0) tmp = 0; - if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1; - - port->wakeup_chars = tmp; - - /* We should really wait for the characters to be all sent before - changing the settings. -- CAL */ - rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT); - if (rv < 0) return /* rv */; - - rv = port->rd->set_real_termios(port); - if (rv < 0) return /* rv */; - - if ((!old_termios || - (old_termios->c_cflag & CRTSCTS)) && - !( tiosp->c_cflag & CRTSCTS)) { - tty->stopped = 0; - gs_start(tty); - } - -#ifdef tytso_patch_94Nov25_1726 - /* This "makes sense", Why is it commented out? */ - - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&port->gs.open_wait); -#endif - - func_exit(); - return /* 0 */; -} - - - -/* Must be called with interrupts enabled */ -int gs_init_port(struct gs_port *port) -{ - unsigned long flags; - - func_enter (); - - if (port->port.flags & ASYNC_INITIALIZED) { - func_exit (); - return 0; - } - if (!port->xmit_buf) { - /* We may sleep in get_zeroed_page() */ - unsigned long tmp; - - tmp = get_zeroed_page(GFP_KERNEL); - spin_lock_irqsave (&port->driver_lock, flags); - if (port->xmit_buf) - free_page (tmp); - else - port->xmit_buf = (unsigned char *) tmp; - spin_unlock_irqrestore(&port->driver_lock, flags); - if (!port->xmit_buf) { - func_exit (); - return -ENOMEM; - } - } - - spin_lock_irqsave (&port->driver_lock, flags); - if (port->port.tty) - clear_bit(TTY_IO_ERROR, &port->port.tty->flags); - mutex_init(&port->port_write_mutex); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - spin_unlock_irqrestore(&port->driver_lock, flags); - gs_set_termios(port->port.tty, NULL); - spin_lock_irqsave (&port->driver_lock, flags); - port->port.flags |= ASYNC_INITIALIZED; - port->port.flags &= ~GS_TX_INTEN; - - spin_unlock_irqrestore(&port->driver_lock, flags); - func_exit (); - return 0; -} - - -int gs_setserial(struct gs_port *port, struct serial_struct __user *sp) -{ - struct serial_struct sio; - - if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) - return(-EFAULT); - - if (!capable(CAP_SYS_ADMIN)) { - if ((sio.baud_base != port->baud_base) || - (sio.close_delay != port->close_delay) || - ((sio.flags & ~ASYNC_USR_MASK) != - (port->port.flags & ~ASYNC_USR_MASK))) - return(-EPERM); - } - - port->port.flags = (port->port.flags & ~ASYNC_USR_MASK) | - (sio.flags & ASYNC_USR_MASK); - - port->baud_base = sio.baud_base; - port->close_delay = sio.close_delay; - port->closing_wait = sio.closing_wait; - port->custom_divisor = sio.custom_divisor; - - gs_set_termios (port->port.tty, NULL); - - return 0; -} - - -/*****************************************************************************/ - -/* - * Generate the serial struct info. - */ - -int gs_getserial(struct gs_port *port, struct serial_struct __user *sp) -{ - struct serial_struct sio; - - memset(&sio, 0, sizeof(struct serial_struct)); - sio.flags = port->port.flags; - sio.baud_base = port->baud_base; - sio.close_delay = port->close_delay; - sio.closing_wait = port->closing_wait; - sio.custom_divisor = port->custom_divisor; - sio.hub6 = 0; - - /* If you want you can override these. */ - sio.type = PORT_UNKNOWN; - sio.xmit_fifo_size = -1; - sio.line = -1; - sio.port = -1; - sio.irq = -1; - - if (port->rd->getserial) - port->rd->getserial (port, &sio); - - if (copy_to_user(sp, &sio, sizeof(struct serial_struct))) - return -EFAULT; - return 0; - -} - - -void gs_got_break(struct gs_port *port) -{ - func_enter (); - - tty_insert_flip_char(port->port.tty, 0, TTY_BREAK); - tty_schedule_flip(port->port.tty); - if (port->port.flags & ASYNC_SAK) { - do_SAK (port->port.tty); - } - - func_exit (); -} - - -EXPORT_SYMBOL(gs_put_char); -EXPORT_SYMBOL(gs_write); -EXPORT_SYMBOL(gs_write_room); -EXPORT_SYMBOL(gs_chars_in_buffer); -EXPORT_SYMBOL(gs_flush_buffer); -EXPORT_SYMBOL(gs_flush_chars); -EXPORT_SYMBOL(gs_stop); -EXPORT_SYMBOL(gs_start); -EXPORT_SYMBOL(gs_hangup); -EXPORT_SYMBOL(gs_block_til_ready); -EXPORT_SYMBOL(gs_close); -EXPORT_SYMBOL(gs_set_termios); -EXPORT_SYMBOL(gs_init_port); -EXPORT_SYMBOL(gs_setserial); -EXPORT_SYMBOL(gs_getserial); -EXPORT_SYMBOL(gs_got_break); - -MODULE_LICENSE("GPL"); diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile deleted file mode 100644 index 1661875883fb..000000000000 --- a/drivers/char/rio/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for the linux rio-subsystem. -# -# (C) R.E.Wolff@BitWizard.nl -# -# This file is GPL. See other files for the full Blurb. I'm lazy today. -# - -obj-$(CONFIG_RIO) += rio.o - -rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ - rioparam.o rioroute.o riotable.o riotty.o diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h deleted file mode 100644 index bdea633a9076..000000000000 --- a/drivers/char/rio/board.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : board.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:07 -** Retrieved : 11/6/98 11:34:20 -** -** ident @(#)board.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_board_h__ -#define __rio_board_h__ - -/* -** board.h contains the definitions for the *hardware* of the host cards. -** It describes the memory overlay for the dual port RAM area. -*/ - -#define DP_SRAM1_SIZE 0x7C00 -#define DP_SRAM2_SIZE 0x0200 -#define DP_SRAM3_SIZE 0x7000 -#define DP_SCRATCH_SIZE 0x1000 -#define DP_PARMMAP_ADDR 0x01FE /* offset into SRAM2 */ -#define DP_STARTUP_ADDR 0x01F8 /* offset into SRAM2 */ - -/* -** The shape of the Host Control area, at offset 0x7C00, Write Only -*/ -struct s_Ctrl { - u8 DpCtl; /* 7C00 */ - u8 Dp_Unused2_[127]; - u8 DpIntSet; /* 7C80 */ - u8 Dp_Unused3_[127]; - u8 DpTpuReset; /* 7D00 */ - u8 Dp_Unused4_[127]; - u8 DpIntReset; /* 7D80 */ - u8 Dp_Unused5_[127]; -}; - -/* -** The PROM data area on the host (0x7C00), Read Only -*/ -struct s_Prom { - u16 DpSlxCode[2]; - u16 DpRev; - u16 Dp_Unused6_; - u16 DpUniq[4]; - u16 DpJahre; - u16 DpWoche; - u16 DpHwFeature[5]; - u16 DpOemId; - u16 DpSiggy[16]; -}; - -/* -** Union of the Ctrl and Prom areas -*/ -union u_CtrlProm { /* This is the control/PROM area (0x7C00) */ - struct s_Ctrl DpCtrl; - struct s_Prom DpProm; -}; - -/* -** The top end of memory! -*/ -struct s_ParmMapS { /* Area containing Parm Map Pointer */ - u8 Dp_Unused8_[DP_PARMMAP_ADDR]; - u16 DpParmMapAd; -}; - -struct s_StartUpS { - u8 Dp_Unused9_[DP_STARTUP_ADDR]; - u8 Dp_LongJump[0x4]; - u8 Dp_Unused10_[2]; - u8 Dp_ShortJump[0x2]; -}; - -union u_Sram2ParmMap { /* This is the top of memory (0x7E00-0x7FFF) */ - u8 DpSramMem[DP_SRAM2_SIZE]; - struct s_ParmMapS DpParmMapS; - struct s_StartUpS DpStartUpS; -}; - -/* -** This is the DP RAM overlay. -*/ -struct DpRam { - u8 DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */ - union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */ - union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */ - u8 DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */ - u8 DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */ -}; - -#define DpControl DpCtrlProm.DpCtrl.DpCtl -#define DpSetInt DpCtrlProm.DpCtrl.DpIntSet -#define DpResetTpu DpCtrlProm.DpCtrl.DpTpuReset -#define DpResetInt DpCtrlProm.DpCtrl.DpIntReset - -#define DpSlx DpCtrlProm.DpProm.DpSlxCode -#define DpRevision DpCtrlProm.DpProm.DpRev -#define DpUnique DpCtrlProm.DpProm.DpUniq -#define DpYear DpCtrlProm.DpProm.DpJahre -#define DpWeek DpCtrlProm.DpProm.DpWoche -#define DpSignature DpCtrlProm.DpProm.DpSiggy - -#define DpParmMapR DpSram2ParmMap.DpParmMapS.DpParmMapAd -#define DpSram2 DpSram2ParmMap.DpSramMem - -#endif diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h deleted file mode 100644 index 5ab51679caa2..000000000000 --- a/drivers/char/rio/cirrus.h +++ /dev/null @@ -1,210 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* CIRRUS.H ******* - ******* ******* - **************************************************************************** - - Author : Jeremy Rolls - Date : 3 Aug 1990 - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _cirrus_h -#define _cirrus_h 1 - -/* Bit fields for particular registers shared with driver */ - -/* COR1 - driver and RTA */ -#define RIOC_COR1_ODD 0x80 /* Odd parity */ -#define RIOC_COR1_EVEN 0x00 /* Even parity */ -#define RIOC_COR1_NOP 0x00 /* No parity */ -#define RIOC_COR1_FORCE 0x20 /* Force parity */ -#define RIOC_COR1_NORMAL 0x40 /* With parity */ -#define RIOC_COR1_1STOP 0x00 /* 1 stop bit */ -#define RIOC_COR1_15STOP 0x04 /* 1.5 stop bits */ -#define RIOC_COR1_2STOP 0x08 /* 2 stop bits */ -#define RIOC_COR1_5BITS 0x00 /* 5 data bits */ -#define RIOC_COR1_6BITS 0x01 /* 6 data bits */ -#define RIOC_COR1_7BITS 0x02 /* 7 data bits */ -#define RIOC_COR1_8BITS 0x03 /* 8 data bits */ - -#define RIOC_COR1_HOST 0xef /* Safe host bits */ - -/* RTA only */ -#define RIOC_COR1_CINPCK 0x00 /* Check parity of received characters */ -#define RIOC_COR1_CNINPCK 0x10 /* Don't check parity */ - -/* COR2 bits for both RTA and driver use */ -#define RIOC_COR2_IXANY 0x80 /* IXANY - any character is XON */ -#define RIOC_COR2_IXON 0x40 /* IXON - enable tx soft flowcontrol */ -#define RIOC_COR2_RTSFLOW 0x02 /* Enable tx hardware flow control */ - -/* Additional driver bits */ -#define RIOC_COR2_HUPCL 0x20 /* Hang up on close */ -#define RIOC_COR2_CTSFLOW 0x04 /* Enable rx hardware flow control */ -#define RIOC_COR2_IXOFF 0x01 /* Enable rx software flow control */ -#define RIOC_COR2_DTRFLOW 0x08 /* Enable tx hardware flow control */ - -/* RTA use only */ -#define RIOC_COR2_ETC 0x20 /* Embedded transmit options */ -#define RIOC_COR2_LOCAL 0x10 /* Local loopback mode */ -#define RIOC_COR2_REMOTE 0x08 /* Remote loopback mode */ -#define RIOC_COR2_HOST 0xc2 /* Safe host bits */ - -/* COR3 - RTA use only */ -#define RIOC_COR3_SCDRNG 0x80 /* Enable special char detect for range */ -#define RIOC_COR3_SCD34 0x40 /* Special character detect for SCHR's 3 + 4 */ -#define RIOC_COR3_FCT 0x20 /* Flow control transparency */ -#define RIOC_COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */ -#define RIOC_COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */ -#define RIOC_COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */ -#define RIOC_COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */ -#define RIOC_COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */ - -#define RIOC_COR3_THRESHOLD RIOC_COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */ - -#define RIOC_COR3_DEFAULT (RIOC_COR3_FCT | RIOC_COR3_THRESHOLD) - /* Default bits for COR3 */ - -/* COR4 driver and RTA use */ -#define RIOC_COR4_IGNCR 0x80 /* Throw away CR's on input */ -#define RIOC_COR4_ICRNL 0x40 /* Map CR -> NL on input */ -#define RIOC_COR4_INLCR 0x20 /* Map NL -> CR on input */ -#define RIOC_COR4_IGNBRK 0x10 /* Ignore Break */ -#define RIOC_COR4_NBRKINT 0x08 /* No interrupt on break (-BRKINT) */ -#define RIOC_COR4_RAISEMOD 0x01 /* Raise modem output lines on non-zero baud */ - - -/* COR4 driver only */ -#define RIOC_COR4_IGNPAR 0x04 /* IGNPAR (ignore characters with errors) */ -#define RIOC_COR4_PARMRK 0x02 /* PARMRK */ - -#define RIOC_COR4_HOST 0xf8 /* Safe host bits */ - -/* COR4 RTA only */ -#define RIOC_COR4_CIGNPAR 0x02 /* Thrown away bad characters */ -#define RIOC_COR4_CPARMRK 0x04 /* PARMRK characters */ -#define RIOC_COR4_CNPARMRK 0x03 /* Don't PARMRK */ - -/* COR5 driver and RTA use */ -#define RIOC_COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */ -#define RIOC_COR5_LNE 0x40 /* Enable LNEXT processing */ -#define RIOC_COR5_CMOE 0x20 /* Match good and errored characters */ -#define RIOC_COR5_ONLCR 0x02 /* NL -> CR NL on output */ -#define RIOC_COR5_OCRNL 0x01 /* CR -> NL on output */ - -/* -** Spare bits - these are not used in the CIRRUS registers, so we use -** them to set various other features. -*/ -/* -** tstop and tbusy indication -*/ -#define RIOC_COR5_TSTATE_ON 0x08 /* Turn on monitoring of tbusy and tstop */ -#define RIOC_COR5_TSTATE_OFF 0x04 /* Turn off monitoring of tbusy and tstop */ -/* -** TAB3 -*/ -#define RIOC_COR5_TAB3 0x10 /* TAB3 mode */ - -#define RIOC_COR5_HOST 0xc3 /* Safe host bits */ - -/* CCSR */ -#define RIOC_CCSR_TXFLOFF 0x04 /* Tx is xoffed */ - -/* MSVR1 */ -/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the - RTA. This is because otherwise DCD would get lost on the 1 parallel / 3 - serial option. -*/ -#define RIOC_MSVR1_CD 0x80 /* CD (DSR on Cirrus) */ -#define RIOC_MSVR1_RTS 0x40 /* RTS (CTS on Cirrus) */ -#define RIOC_MSVR1_RI 0x20 /* RI */ -#define RIOC_MSVR1_DTR 0x10 /* DTR (CD on Cirrus) */ -#define RIOC_MSVR1_CTS 0x01 /* CTS output pin (RTS on Cirrus) */ -/* Next two used to indicate state of tbusy and tstop to driver */ -#define RIOC_MSVR1_TSTOP 0x08 /* Set if port flow controlled */ -#define RIOC_MSVR1_TEMPTY 0x04 /* Set if port tx buffer empty */ - -#define RIOC_MSVR1_HOST 0xf3 /* The bits the host wants */ - -/* Defines for the subscripts of a CONFIG packet */ -#define RIOC_CONFIG_COR1 1 /* Option register 1 */ -#define RIOC_CONFIG_COR2 2 /* Option register 2 */ -#define RIOC_CONFIG_COR4 3 /* Option register 4 */ -#define RIOC_CONFIG_COR5 4 /* Option register 5 */ -#define RIOC_CONFIG_TXXON 5 /* Tx XON character */ -#define RIOC_CONFIG_TXXOFF 6 /* Tx XOFF character */ -#define RIOC_CONFIG_RXXON 7 /* Rx XON character */ -#define RIOC_CONFIG_RXXOFF 8 /* Rx XOFF character */ -#define RIOC_CONFIG_LNEXT 9 /* LNEXT character */ -#define RIOC_CONFIG_TXBAUD 10 /* Tx baud rate */ -#define RIOC_CONFIG_RXBAUD 11 /* Rx baud rate */ - -#define RIOC_PRE_EMPTIVE 0x80 /* Pre-emptive bit in command field */ - -/* Packet types going from Host to remote - with the exception of OPEN, MOPEN, - CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not - be used -*/ -#define RIOC_OPEN 0x00 /* Open a port */ -#define RIOC_CONFIG 0x01 /* Configure a port */ -#define RIOC_MOPEN 0x02 /* Modem open (block for DCD) */ -#define RIOC_CLOSE 0x03 /* Close a port */ -#define RIOC_WFLUSH (0x04 | RIOC_PRE_EMPTIVE) /* Write flush */ -#define RIOC_RFLUSH (0x05 | RIOC_PRE_EMPTIVE) /* Read flush */ -#define RIOC_RESUME (0x06 | RIOC_PRE_EMPTIVE) /* Resume if xoffed */ -#define RIOC_SBREAK 0x07 /* Start break */ -#define RIOC_EBREAK 0x08 /* End break */ -#define RIOC_SUSPEND (0x09 | RIOC_PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */ -#define RIOC_FCLOSE (0x0a | RIOC_PRE_EMPTIVE) /* Force close */ -#define RIOC_XPRINT 0x0b /* Xprint packet */ -#define RIOC_MBIS (0x0c | RIOC_PRE_EMPTIVE) /* Set modem lines */ -#define RIOC_MBIC (0x0d | RIOC_PRE_EMPTIVE) /* Clear modem lines */ -#define RIOC_MSET (0x0e | RIOC_PRE_EMPTIVE) /* Set modem lines */ -#define RIOC_PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */ -#define RIOC_MGET (0x10 | RIOC_PRE_EMPTIVE) /* Force update of modem status */ -#define RIOC_MEMDUMP (0x11 | RIOC_PRE_EMPTIVE) /* Send back mem from addr supplied */ -#define RIOC_READ_REGISTER (0x12 | RIOC_PRE_EMPTIVE) /* Read CD1400 register (debug) */ - -/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS - use data[4] / data[3] to indicate current state and modem status respectively -*/ - -#define RIOC_COMPLETE (0x20 | RIOC_PRE_EMPTIVE) - /* Command complete */ -#define RIOC_BREAK_RECEIVED (0x21 | RIOC_PRE_EMPTIVE) - /* Break received */ -#define RIOC_MODEM_STATUS (0x22 | RIOC_PRE_EMPTIVE) - /* Change in modem status */ - -/* "Command" packet that could go either way - handshake wake-up */ -#define RIOC_HANDSHAKE (0x23 | RIOC_PRE_EMPTIVE) - /* Wake-up to HOST / RTA */ - -#endif diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h deleted file mode 100644 index 9ed4f861675a..000000000000 --- a/drivers/char/rio/cmdblk.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : cmdblk.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:09 -** Retrieved : 11/6/98 11:34:20 -** -** ident @(#)cmdblk.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_cmdblk_h__ -#define __rio_cmdblk_h__ - -/* -** the structure of a command block, used to queue commands destined for -** a rup. -*/ - -struct CmdBlk { - struct CmdBlk *NextP; /* Pointer to next command block */ - struct PKT Packet; /* A packet, to copy to the rup */ - /* The func to call to check if OK */ - int (*PreFuncP) (unsigned long, struct CmdBlk *); - int PreArg; /* The arg for the func */ - /* The func to call when completed */ - int (*PostFuncP) (unsigned long, struct CmdBlk *); - int PostArg; /* The arg for the func */ -}; - -#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4)) -#endif diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h deleted file mode 100644 index c1e7a2798070..000000000000 --- a/drivers/char/rio/cmdpkt.h +++ /dev/null @@ -1,177 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : cmdpkt.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:09 -** Retrieved : 11/6/98 11:34:20 -** -** ident @(#)cmdpkt.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ -#ifndef __rio_cmdpkt_h__ -#define __rio_cmdpkt_h__ - -/* -** overlays for the data area of a packet. Used in both directions -** (to build a packet to send, and to interpret a packet that arrives) -** and is very inconvenient for MIPS, so they appear as two separate -** structures - those used for modifying/reading packets on the card -** and those for modifying/reading packets in real memory, which have an _M -** suffix. -*/ - -#define RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2) - -/* -** The boot information packet looks like this: -** This structure overlays a PktCmd->CmdData structure, and so starts -** at Data[2] in the actual pkt! -*/ -struct BootSequence { - u16 NumPackets; - u16 LoadBase; - u16 CodeSize; -}; - -#define BOOT_SEQUENCE_LEN 8 - -struct SamTop { - u8 Unit; - u8 Link; -}; - -struct CmdHdr { - u8 PcCommand; - union { - u8 PcPhbNum; - u8 PcLinkNum; - u8 PcIDNum; - } U0; -}; - - -struct PktCmd { - union { - struct { - struct CmdHdr CmdHdr; - struct BootSequence PcBootSequence; - } S1; - struct { - u16 PcSequence; - u8 PcBootData[RTA_BOOT_DATA_SIZE]; - } S2; - struct { - u16 __crud__; - u8 PcUniqNum[4]; /* this is really a uint. */ - u8 PcModuleTypes; /* what modules are fitted */ - } S3; - struct { - struct CmdHdr CmdHdr; - u8 __undefined__; - u8 PcModemStatus; - u8 PcPortStatus; - u8 PcSubCommand; /* commands like mem or register dump */ - u16 PcSubAddr; /* Address for command */ - u8 PcSubData[64]; /* Date area for command */ - } S4; - struct { - struct CmdHdr CmdHdr; - u8 PcCommandText[1]; - u8 __crud__[20]; - u8 PcIDNum2; /* It had to go somewhere! */ - } S5; - struct { - struct CmdHdr CmdHdr; - struct SamTop Topology[LINKS_PER_UNIT]; - } S6; - } U1; -}; - -struct PktCmd_M { - union { - struct { - struct { - u8 PcCommand; - union { - u8 PcPhbNum; - u8 PcLinkNum; - u8 PcIDNum; - } U0; - } CmdHdr; - struct { - u16 NumPackets; - u16 LoadBase; - u16 CodeSize; - } PcBootSequence; - } S1; - struct { - u16 PcSequence; - u8 PcBootData[RTA_BOOT_DATA_SIZE]; - } S2; - struct { - u16 __crud__; - u8 PcUniqNum[4]; /* this is really a uint. */ - u8 PcModuleTypes; /* what modules are fitted */ - } S3; - struct { - u16 __cmd_hdr__; - u8 __undefined__; - u8 PcModemStatus; - u8 PcPortStatus; - u8 PcSubCommand; - u16 PcSubAddr; - u8 PcSubData[64]; - } S4; - struct { - u16 __cmd_hdr__; - u8 PcCommandText[1]; - u8 __crud__[20]; - u8 PcIDNum2; /* Tacked on end */ - } S5; - struct { - u16 __cmd_hdr__; - struct Top Topology[LINKS_PER_UNIT]; - } S6; - } U1; -}; - -#define Command U1.S1.CmdHdr.PcCommand -#define PhbNum U1.S1.CmdHdr.U0.PcPhbNum -#define IDNum U1.S1.CmdHdr.U0.PcIDNum -#define IDNum2 U1.S5.PcIDNum2 -#define LinkNum U1.S1.CmdHdr.U0.PcLinkNum -#define Sequence U1.S2.PcSequence -#define BootData U1.S2.PcBootData -#define BootSequence U1.S1.PcBootSequence -#define UniqNum U1.S3.PcUniqNum -#define ModemStatus U1.S4.PcModemStatus -#define PortStatus U1.S4.PcPortStatus -#define SubCommand U1.S4.PcSubCommand -#define SubAddr U1.S4.PcSubAddr -#define SubData U1.S4.PcSubData -#define CommandText U1.S5.PcCommandText -#define RouteTopology U1.S6.Topology -#define ModuleTypes U1.S3.PcModuleTypes - -#endif diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h deleted file mode 100644 index 4af90323fd00..000000000000 --- a/drivers/char/rio/daemon.h +++ /dev/null @@ -1,307 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : daemon.h -** SID : 1.3 -** Last Modified : 11/6/98 11:34:09 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)daemon.h 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_daemon_h__ -#define __rio_daemon_h__ - - -/* -** structures used on /dev/rio -*/ - -struct Error { - unsigned int Error; - unsigned int Entry; - unsigned int Other; -}; - -struct DownLoad { - char __user *DataP; - unsigned int Count; - unsigned int ProductCode; -}; - -/* -** A few constants.... -*/ -#ifndef MAX_VERSION_LEN -#define MAX_VERSION_LEN 256 -#endif - -#ifndef MAX_XP_CTRL_LEN -#define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */ -#endif - -struct PortSetup { - unsigned int From; /* Set/Clear XP & IXANY Control from this port.... */ - unsigned int To; /* .... to this port */ - unsigned int XpCps; /* at this speed */ - char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */ - char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */ - u8 IxAny; /* enable/disable IXANY */ - u8 IxOn; /* enable/disable IXON */ - u8 Lock; /* lock port params */ - u8 Store; /* store params across closes */ - u8 Drain; /* close only when drained */ -}; - -struct LpbReq { - unsigned int Host; - unsigned int Link; - struct LPB __user *LpbP; -}; - -struct RupReq { - unsigned int HostNum; - unsigned int RupNum; - struct RUP __user *RupP; -}; - -struct PortReq { - unsigned int SysPort; - struct Port __user *PortP; -}; - -struct StreamInfo { - unsigned int SysPort; - int RQueue; - int WQueue; -}; - -struct HostReq { - unsigned int HostNum; - struct Host __user *HostP; -}; - -struct HostDpRam { - unsigned int HostNum; - struct DpRam __user *DpRamP; -}; - -struct DebugCtrl { - unsigned int SysPort; - unsigned int Debug; - unsigned int Wait; -}; - -struct MapInfo { - unsigned int FirstPort; /* 8 ports, starting from this (tty) number */ - unsigned int RtaUnique; /* reside on this RTA (unique number) */ -}; - -struct MapIn { - unsigned int NumEntries; /* How many port sets are we mapping? */ - struct MapInfo *MapInfoP; /* Pointer to (user space) info */ -}; - -struct SendPack { - unsigned int PortNum; - unsigned char Len; - unsigned char Data[PKT_MAX_DATA_LEN]; -}; - -struct SpecialRupCmd { - struct PKT Packet; - unsigned short Host; - unsigned short RupNum; -}; - -struct IdentifyRta { - unsigned long RtaUnique; - u8 ID; -}; - -struct KillNeighbour { - unsigned long UniqueNum; - u8 Link; -}; - -struct rioVersion { - char version[MAX_VERSION_LEN]; - char relid[MAX_VERSION_LEN]; - int buildLevel; - char buildDate[MAX_VERSION_LEN]; -}; - - -/* -** RIOC commands are for the daemon type operations -** -** 09.12.1998 ARG - ESIL 0776 part fix -** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a -** #ifndef here first. -** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now -** allowed to be used by customers. -*/ -#ifndef RIOC -#define RIOC ('R'<<8)|('i'<<16)|('o'<<24) -#endif - -/* -** Boot stuff -*/ -#define RIO_GET_TABLE (RIOC | 100) -#define RIO_PUT_TABLE (RIOC | 101) -#define RIO_ASSIGN_RTA (RIOC | 102) -#define RIO_DELETE_RTA (RIOC | 103) -#define RIO_HOST_FOAD (RIOC | 104) -#define RIO_QUICK_CHECK (RIOC | 105) -#define RIO_SIGNALS_ON (RIOC | 106) -#define RIO_SIGNALS_OFF (RIOC | 107) -#define RIO_CHANGE_NAME (RIOC | 108) -#define RIO_DOWNLOAD (RIOC | 109) -#define RIO_GET_LOG (RIOC | 110) -#define RIO_SETUP_PORTS (RIOC | 111) -#define RIO_ALL_MODEM (RIOC | 112) - -/* -** card state, debug stuff -*/ -#define RIO_NUM_HOSTS (RIOC | 120) -#define RIO_HOST_LPB (RIOC | 121) -#define RIO_HOST_RUP (RIOC | 122) -#define RIO_HOST_PORT (RIOC | 123) -#define RIO_PARMS (RIOC | 124) -#define RIO_HOST_REQ (RIOC | 125) -#define RIO_READ_CONFIG (RIOC | 126) -#define RIO_SET_CONFIG (RIOC | 127) -#define RIO_VERSID (RIOC | 128) -#define RIO_FLAGS (RIOC | 129) -#define RIO_SETDEBUG (RIOC | 130) -#define RIO_GETDEBUG (RIOC | 131) -#define RIO_READ_LEVELS (RIOC | 132) -#define RIO_SET_FAST_BUS (RIOC | 133) -#define RIO_SET_SLOW_BUS (RIOC | 134) -#define RIO_SET_BYTE_MODE (RIOC | 135) -#define RIO_SET_WORD_MODE (RIOC | 136) -#define RIO_STREAM_INFO (RIOC | 137) -#define RIO_START_POLLER (RIOC | 138) -#define RIO_STOP_POLLER (RIOC | 139) -#define RIO_LAST_ERROR (RIOC | 140) -#define RIO_TICK (RIOC | 141) -#define RIO_TOCK (RIOC | 241) /* I did this on purpose, you know. */ -#define RIO_SEND_PACKET (RIOC | 142) -#define RIO_SET_BUSY (RIOC | 143) -#define SPECIAL_RUP_CMD (RIOC | 144) -#define RIO_FOAD_RTA (RIOC | 145) -#define RIO_ZOMBIE_RTA (RIOC | 146) -#define RIO_IDENTIFY_RTA (RIOC | 147) -#define RIO_KILL_NEIGHBOUR (RIOC | 148) -#define RIO_DEBUG_MEM (RIOC | 149) -/* -** 150 - 167 used..... See below -*/ -#define RIO_GET_PORT_SETUP (RIOC | 168) -#define RIO_RESUME (RIOC | 169) -#define RIO_MESG (RIOC | 170) -#define RIO_NO_MESG (RIOC | 171) -#define RIO_WHAT_MESG (RIOC | 172) -#define RIO_HOST_DPRAM (RIOC | 173) -#define RIO_MAP_B50_TO_50 (RIOC | 174) -#define RIO_MAP_B50_TO_57600 (RIOC | 175) -#define RIO_MAP_B110_TO_110 (RIOC | 176) -#define RIO_MAP_B110_TO_115200 (RIOC | 177) -#define RIO_GET_PORT_PARAMS (RIOC | 178) -#define RIO_SET_PORT_PARAMS (RIOC | 179) -#define RIO_GET_PORT_TTY (RIOC | 180) -#define RIO_SET_PORT_TTY (RIOC | 181) -#define RIO_SYSLOG_ONLY (RIOC | 182) -#define RIO_SYSLOG_CONS (RIOC | 183) -#define RIO_CONS_ONLY (RIOC | 184) -#define RIO_BLOCK_OPENS (RIOC | 185) - -/* -** 02.03.1999 ARG - ESIL 0820 fix : -** RIOBootMode is no longer use by the driver, so these ioctls -** are now obsolete : -** -#define RIO_GET_BOOT_MODE (RIOC | 186) -#define RIO_SET_BOOT_MODE (RIOC | 187) -** -*/ - -#define RIO_MEM_DUMP (RIOC | 189) -#define RIO_READ_REGISTER (RIOC | 190) -#define RIO_GET_MODTYPE (RIOC | 191) -#define RIO_SET_TIMER (RIOC | 192) -#define RIO_READ_CHECK (RIOC | 196) -#define RIO_WAITING_FOR_RESTART (RIOC | 197) -#define RIO_BIND_RTA (RIOC | 198) -#define RIO_GET_BINDINGS (RIOC | 199) -#define RIO_PUT_BINDINGS (RIOC | 200) - -#define RIO_MAKE_DEV (RIOC | 201) -#define RIO_MINOR (RIOC | 202) - -#define RIO_IDENTIFY_DRIVER (RIOC | 203) -#define RIO_DISPLAY_HOST_CFG (RIOC | 204) - - -/* -** MAKE_DEV / MINOR stuff -*/ -#define RIO_DEV_DIRECT 0x0000 -#define RIO_DEV_MODEM 0x0200 -#define RIO_DEV_XPRINT 0x0400 -#define RIO_DEV_MASK 0x0600 - -/* -** port management, xprint stuff -*/ -#define rIOCN(N) (RIOC|(N)) -#define rIOCR(N,T) (RIOC|(N)) -#define rIOCW(N,T) (RIOC|(N)) - -#define RIO_GET_XP_ON rIOCR(150,char[16]) /* start xprint string */ -#define RIO_SET_XP_ON rIOCW(151,char[16]) -#define RIO_GET_XP_OFF rIOCR(152,char[16]) /* finish xprint string */ -#define RIO_SET_XP_OFF rIOCW(153,char[16]) -#define RIO_GET_XP_CPS rIOCR(154,int) /* xprint CPS */ -#define RIO_SET_XP_CPS rIOCW(155,int) -#define RIO_GET_IXANY rIOCR(156,int) /* ixany allowed? */ -#define RIO_SET_IXANY rIOCW(157,int) -#define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */ -#define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */ -#define RIO_GET_MODEM rIOCR(160,int) /* port is modem/direct line? */ -#define RIO_SET_MODEM rIOCW(161,int) -#define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */ -#define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */ -#define RIO_GET_IXON rIOCR(164,int) /* ixon allowed? */ -#define RIO_SET_IXON rIOCW(165,int) -#define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */ -#define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */ - -#define RIO_GET_SIVIEW ((('s')<<8) | 106) /* backwards compatible with SI */ - -#define RIO_IOCTL_UNKNOWN -2 - -#endif diff --git a/drivers/char/rio/errors.h b/drivers/char/rio/errors.h deleted file mode 100644 index bdb05234090a..000000000000 --- a/drivers/char/rio/errors.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : errors.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:10 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)errors.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_errors_h__ -#define __rio_errors_h__ - -/* -** error codes -*/ - -#define NOTHING_WRONG_AT_ALL 0 -#define BAD_CHARACTER_IN_NAME 1 -#define TABLE_ENTRY_ISNT_PROPERLY_NULL 2 -#define UNKNOWN_HOST_NUMBER 3 -#define ZERO_RTA_ID 4 -#define BAD_RTA_ID 5 -#define DUPLICATED_RTA_ID 6 -#define DUPLICATE_UNIQUE_NUMBER 7 -#define BAD_TTY_NUMBER 8 -#define TTY_NUMBER_IN_USE 9 -#define NAME_USED_TWICE 10 -#define HOST_ID_NOT_ZERO 11 -#define BOOT_IN_PROGRESS 12 -#define COPYIN_FAILED 13 -#define HOST_FILE_TOO_LARGE 14 -#define COPYOUT_FAILED 15 -#define NOT_SUPER_USER 16 -#define RIO_ALREADY_POLLING 17 - -#define ID_NUMBER_OUT_OF_RANGE 18 -#define PORT_NUMBER_OUT_OF_RANGE 19 -#define HOST_NUMBER_OUT_OF_RANGE 20 -#define RUP_NUMBER_OUT_OF_RANGE 21 -#define TTY_NUMBER_OUT_OF_RANGE 22 -#define LINK_NUMBER_OUT_OF_RANGE 23 - -#define HOST_NOT_RUNNING 24 -#define IOCTL_COMMAND_UNKNOWN 25 -#define RIO_SYSTEM_HALTED 26 -#define WAIT_FOR_DRAIN_BROKEN 27 -#define PORT_NOT_MAPPED_INTO_SYSTEM 28 -#define EXCLUSIVE_USE_SET 29 -#define WAIT_FOR_NOT_CLOSING_BROKEN 30 -#define WAIT_FOR_PORT_TO_OPEN_BROKEN 31 -#define WAIT_FOR_CARRIER_BROKEN 32 -#define WAIT_FOR_NOT_IN_USE_BROKEN 33 -#define WAIT_FOR_CAN_ADD_COMMAND_BROKEN 34 -#define WAIT_FOR_ADD_COMMAND_BROKEN 35 -#define WAIT_FOR_NOT_PARAM_BROKEN 36 -#define WAIT_FOR_RETRY_BROKEN 37 -#define HOST_HAS_ALREADY_BEEN_BOOTED 38 -#define UNIT_IS_IN_USE 39 -#define COULDNT_FIND_ENTRY 40 -#define RTA_UNIQUE_NUMBER_ZERO 41 -#define CLOSE_COMMAND_FAILED 42 -#define WAIT_FOR_CLOSE_BROKEN 43 -#define CPS_VALUE_OUT_OF_RANGE 44 -#define ID_ALREADY_IN_USE 45 -#define SIGNALS_ALREADY_SET 46 -#define NOT_RECEIVING_PROCESS 47 -#define RTA_NUMBER_WRONG 48 -#define NO_SUCH_PRODUCT 49 -#define HOST_SYSPORT_BAD 50 -#define ID_NOT_TENTATIVE 51 -#define XPRINT_CPS_OUT_OF_RANGE 52 -#define NOT_ENOUGH_CORE_FOR_PCI_COPY 53 - - -#endif /* __rio_errors_h__ */ diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h deleted file mode 100644 index 078d44f85e45..000000000000 --- a/drivers/char/rio/func.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : func.h -** SID : 1.3 -** Last Modified : 11/6/98 11:34:10 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)func.h 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __func_h_def -#define __func_h_def - -#include - -/* rioboot.c */ -int RIOBootCodeRTA(struct rio_info *, struct DownLoad *); -int RIOBootCodeHOST(struct rio_info *, struct DownLoad *); -int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *); -void msec_timeout(struct Host *); -int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *); -int RIOBootOk(struct rio_info *, struct Host *, unsigned long); -int RIORtaBound(struct rio_info *, unsigned int); -void rio_fill_host_slot(int, int, unsigned int, struct Host *); - -/* riocmd.c */ -int RIOFoadRta(struct Host *, struct Map *); -int RIOZombieRta(struct Host *, struct Map *); -int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *)); -int RIOIdentifyRta(struct rio_info *, void __user *); -int RIOKillNeighbour(struct rio_info *, void __user *); -int RIOSuspendBootRta(struct Host *, int, int); -int RIOFoadWakeup(struct rio_info *); -struct CmdBlk *RIOGetCmdBlk(void); -void RIOFreeCmdBlk(struct CmdBlk *); -int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *); -void RIOPollHostCommands(struct rio_info *, struct Host *); -int RIOWFlushMark(unsigned long, struct CmdBlk *); -int RIORFlushEnable(unsigned long, struct CmdBlk *); -int RIOUnUse(unsigned long, struct CmdBlk *); - -/* rioctrl.c */ -int riocontrol(struct rio_info *, dev_t, int, unsigned long, int); - -int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char); - -/* rioinit.c */ -void rioinit(struct rio_info *, struct RioHostInfo *); -void RIOInitHosts(struct rio_info *, struct RioHostInfo *); -void RIOISAinit(struct rio_info *, int); -int RIODoAT(struct rio_info *, int, int); -caddr_t RIOCheckForATCard(int); -int RIOAssignAT(struct rio_info *, int, void __iomem *, int); -int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int); -void RIOAllocDataStructs(struct rio_info *); -void RIOSetupDataStructs(struct rio_info *); -int RIODefaultName(struct rio_info *, struct Host *, unsigned int); -struct rioVersion *RIOVersid(void); -void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int); - -/* riointr.c */ -void RIOTxEnable(char *); -void RIOServiceHost(struct rio_info *, struct Host *); -int riotproc(struct rio_info *, struct ttystatics *, int, int); - -/* rioparam.c */ -int RIOParam(struct Port *, int, int, int); -int RIODelay(struct Port *PortP, int); -int RIODelay_ni(struct Port *PortP, int); -void ms_timeout(struct Port *); -int can_add_transmit(struct PKT __iomem **, struct Port *); -void add_transmit(struct Port *); -void put_free_end(struct Host *, struct PKT __iomem *); -int can_remove_receive(struct PKT __iomem **, struct Port *); -void remove_receive(struct Port *); - -/* rioroute.c */ -int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *); -void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int); -unsigned int GetUnitType(unsigned int); -int RIOSetChange(struct rio_info *); -int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *); - - -/* riotty.c */ - -int riotopen(struct tty_struct *tty, struct file *filp); -int riotclose(void *ptr); -int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t); -void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg); - -/* riotable.c */ -int RIONewTable(struct rio_info *); -int RIOApel(struct rio_info *); -int RIODeleteRta(struct rio_info *, struct Map *); -int RIOAssignRta(struct rio_info *, struct Map *); -int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *); -int RIOChangeName(struct rio_info *, struct Map *); - -#if 0 -/* riodrvr.c */ -struct rio_info *rio_install(struct RioHostInfo *); -int rio_uninstall(struct rio_info *); -int rio_open(struct rio_info *, int, struct file *); -int rio_close(struct rio_info *, struct file *); -int rio_read(struct rio_info *, struct file *, char *, int); -int rio_write(struct rio_info *, struct file *f, char *, int); -int rio_ioctl(struct rio_info *, struct file *, int, char *); -int rio_select(struct rio_info *, struct file *f, int, struct sel *); -int rio_intr(char *); -int rio_isr_thread(char *); -struct rio_info *rio_info_store(int cmd, struct rio_info *p); -#endif - -extern void rio_copy_to_card(void *from, void __iomem *to, int len); -extern int rio_minor(struct tty_struct *tty); -extern int rio_ismodem(struct tty_struct *tty); - -extern void rio_start_card_running(struct Host *HostP); - -#endif /* __func_h_def */ diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h deleted file mode 100644 index 78f24540c224..000000000000 --- a/drivers/char/rio/host.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : host.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:10 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)host.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_host_h__ -#define __rio_host_h__ - -/* -** the host structure - one per host card in the system. -*/ - -#define MAX_EXTRA_UNITS 64 - -/* -** Host data structure. This is used for the software equiv. of -** the host. -*/ -struct Host { - struct pci_dev *pdev; - unsigned char Type; /* RIO_EISA, RIO_MCA, ... */ - unsigned char Ivec; /* POLLED or ivec number */ - unsigned char Mode; /* Control stuff */ - unsigned char Slot; /* Slot */ - void __iomem *Caddr; /* KV address of DPRAM */ - struct DpRam __iomem *CardP; /* KV address of DPRAM, with overlay */ - unsigned long PaddrP; /* Phys. address of DPRAM */ - char Name[MAX_NAME_LEN]; /* The name of the host */ - unsigned int UniqueNum; /* host unique number */ - spinlock_t HostLock; /* Lock structure for MPX */ - unsigned int WorkToBeDone; /* set to true each interrupt */ - unsigned int InIntr; /* Being serviced? */ - unsigned int IntSrvDone; /* host's interrupt has been serviced */ - void (*Copy) (void *, void __iomem *, int); /* copy func */ - struct timer_list timer; - /* - ** I M P O R T A N T ! - ** - ** The rest of this data structure is cleared to zero after - ** a RIO_HOST_FOAD command. - */ - - unsigned long Flags; /* Whats going down */ -#define RC_WAITING 0 -#define RC_STARTUP 1 -#define RC_RUNNING 2 -#define RC_STUFFED 3 -#define RC_READY 7 -#define RUN_STATE 7 -/* -** Boot mode applies to the way in which hosts in this system will -** boot RTAs -*/ -#define RC_BOOT_ALL 0x8 /* Boot all RTAs attached */ -#define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */ -#define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */ - - struct Top Topology[LINKS_PER_UNIT]; /* one per link */ - struct Map Mapping[MAX_RUP]; /* Mappings for host */ - struct PHB __iomem *PhbP; /* Pointer to the PHB array */ - unsigned short __iomem *PhbNumP; /* Ptr to Number of PHB's */ - struct LPB __iomem *LinkStrP; /* Link Structure Array */ - struct RUP __iomem *RupP; /* Sixteen real rups here */ - struct PARM_MAP __iomem *ParmMapP; /* points to the parmmap */ - unsigned int ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */ - unsigned int NumExtraBooted; /* how many of the above */ - /* - ** Twenty logical rups. - ** The first sixteen are the real Rup entries (above), the last four - ** are the link RUPs. - */ - struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT]; - int timeout_id; /* For calling 100 ms delays */ - int timeout_sem; /* For calling 100 ms delays */ - unsigned long locks; /* long req'd for set_bit --RR */ - char ____end_marker____; -}; -#define Control CardP->DpControl -#define SetInt CardP->DpSetInt -#define ResetTpu CardP->DpResetTpu -#define ResetInt CardP->DpResetInt -#define Signature CardP->DpSignature -#define Sram1 CardP->DpSram1 -#define Sram2 CardP->DpSram2 -#define Sram3 CardP->DpSram3 -#define Scratch CardP->DpScratch -#define __ParmMapR CardP->DpParmMapR -#define SLX CardP->DpSlx -#define Revision CardP->DpRevision -#define Unique CardP->DpUnique -#define Year CardP->DpYear -#define Week CardP->DpWeek - -#define RIO_DUMBPARM 0x0860 /* what not to expect */ - -#endif diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h deleted file mode 100644 index f3bf11a04d41..000000000000 --- a/drivers/char/rio/link.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* L I N K - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _link_h -#define _link_h 1 - -/************************************************* - * Define the Link Status stuff - ************************************************/ -/* Boot request stuff */ -#define BOOT_REQUEST ((ushort) 0) /* Request for a boot */ -#define BOOT_ABORT ((ushort) 1) /* Abort a boot */ -#define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets - and load address */ -#define BOOT_COMPLETED ((ushort) 3) /* Boot completed */ - - -struct LPB { - u16 link_number; /* Link Number */ - u16 in_ch; /* Link In Channel */ - u16 out_ch; /* Link Out Channel */ - u8 attached_serial[4]; /* Attached serial number */ - u8 attached_host_serial[4]; - /* Serial number of Host who - booted the other end */ - u16 descheduled; /* Currently Descheduled */ - u16 state; /* Current state */ - u16 send_poll; /* Send a Poll Packet */ - u16 ltt_p; /* Process Descriptor */ - u16 lrt_p; /* Process Descriptor */ - u16 lrt_status; /* Current lrt status */ - u16 ltt_status; /* Current ltt status */ - u16 timeout; /* Timeout value */ - u16 topology; /* Topology bits */ - u16 mon_ltt; - u16 mon_lrt; - u16 WaitNoBoot; /* Secs to hold off booting */ - u16 add_packet_list; /* Add packets to here */ - u16 remove_packet_list; /* Send packets from here */ - - u16 lrt_fail_chan; /* Lrt's failure channel */ - u16 ltt_fail_chan; /* Ltt's failure channel */ - - /* RUP structure for HOST to driver communications */ - struct RUP rup; - struct RUP link_rup; /* RUP for the link (POLL, - topology etc.) */ - u16 attached_link; /* Number of attached link */ - u16 csum_errors; /* csum errors */ - u16 num_disconnects; /* number of disconnects */ - u16 num_sync_rcvd; /* # sync's received */ - u16 num_sync_rqst; /* # sync requests */ - u16 num_tx; /* Num pkts sent */ - u16 num_rx; /* Num pkts received */ - u16 module_attached; /* Module tpyes of attached */ - u16 led_timeout; /* LED timeout */ - u16 first_port; /* First port to service */ - u16 last_port; /* Last port to service */ -}; - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h deleted file mode 100644 index 34c0d2899ef1..000000000000 --- a/drivers/char/rio/linux_compat.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * (C) 2000 R.E.Wolff@BitWizard.nl - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - - -#define DEBUG_ALL - -struct ttystatics { - struct termios tm; -}; - -extern int rio_debug; - -#define RIO_DEBUG_INIT 0x000001 -#define RIO_DEBUG_BOOT 0x000002 -#define RIO_DEBUG_CMD 0x000004 -#define RIO_DEBUG_CTRL 0x000008 -#define RIO_DEBUG_INTR 0x000010 -#define RIO_DEBUG_PARAM 0x000020 -#define RIO_DEBUG_ROUTE 0x000040 -#define RIO_DEBUG_TABLE 0x000080 -#define RIO_DEBUG_TTY 0x000100 -#define RIO_DEBUG_FLOW 0x000200 -#define RIO_DEBUG_MODEMSIGNALS 0x000400 -#define RIO_DEBUG_PROBE 0x000800 -#define RIO_DEBUG_CLEANUP 0x001000 -#define RIO_DEBUG_IFLOW 0x002000 -#define RIO_DEBUG_PFE 0x004000 -#define RIO_DEBUG_REC 0x008000 -#define RIO_DEBUG_SPINLOCK 0x010000 -#define RIO_DEBUG_DELAY 0x020000 -#define RIO_DEBUG_MOD_COUNT 0x040000 - - -/* Copied over from riowinif.h . This is ugly. The winif file declares -also much other stuff which is incompatible with the headers from -the older driver. The older driver includes "brates.h" which shadows -the definitions from Linux, and is incompatible... */ - -/* RxBaud and TxBaud definitions... */ -#define RIO_B0 0x00 /* RTS / DTR signals dropped */ -#define RIO_B50 0x01 /* 50 baud */ -#define RIO_B75 0x02 /* 75 baud */ -#define RIO_B110 0x03 /* 110 baud */ -#define RIO_B134 0x04 /* 134.5 baud */ -#define RIO_B150 0x05 /* 150 baud */ -#define RIO_B200 0x06 /* 200 baud */ -#define RIO_B300 0x07 /* 300 baud */ -#define RIO_B600 0x08 /* 600 baud */ -#define RIO_B1200 0x09 /* 1200 baud */ -#define RIO_B1800 0x0A /* 1800 baud */ -#define RIO_B2400 0x0B /* 2400 baud */ -#define RIO_B4800 0x0C /* 4800 baud */ -#define RIO_B9600 0x0D /* 9600 baud */ -#define RIO_B19200 0x0E /* 19200 baud */ -#define RIO_B38400 0x0F /* 38400 baud */ -#define RIO_B56000 0x10 /* 56000 baud */ -#define RIO_B57600 0x11 /* 57600 baud */ -#define RIO_B64000 0x12 /* 64000 baud */ -#define RIO_B115200 0x13 /* 115200 baud */ -#define RIO_B2000 0x14 /* 2000 baud */ diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h deleted file mode 100644 index 8366978578c1..000000000000 --- a/drivers/char/rio/map.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : map.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:11 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)map.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_map_h__ -#define __rio_map_h__ - -/* -** mapping structure passed to and from the config.rio program to -** determine the current topology of the world -*/ - -#define MAX_MAP_ENTRY 17 -#define TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS) -#define MAX_NAME_LEN 32 - -struct Map { - unsigned int HostUniqueNum; /* Supporting hosts unique number */ - unsigned int RtaUniqueNum; /* Unique number */ - /* - ** The next two IDs must be swapped on big-endian architectures - ** when using a v2.04 /etc/rio/config with a v3.00 driver (when - ** upgrading for example). - */ - unsigned short ID; /* ID used in the subnet */ - unsigned short ID2; /* ID of 2nd block of 8 for 16 port */ - unsigned long Flags; /* Booted, ID Given, Disconnected */ - unsigned long SysPort; /* First tty mapped to this port */ - struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */ - char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */ -}; - -/* -** Flag values: -*/ -#define RTA_BOOTED 0x00000001 -#define RTA_NEWBOOT 0x00000010 -#define MSG_DONE 0x00000020 -#define RTA_INTERCONNECT 0x00000040 -#define RTA16_SECOND_SLOT 0x00000080 -#define BEEN_HERE 0x00000100 -#define SLOT_TENTATIVE 0x40000000 -#define SLOT_IN_USE 0x80000000 - -/* -** HostUniqueNum is the unique number from the host card that this RTA -** is to be connected to. -** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO -** if the slot in the table is unused. If it is the same as the HostUniqueNum -** then this slot represents a host card. -** Flags contains current boot/route state info -** SysPort is a value in the range 0-504, being the number of the first tty -** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8. -** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor -** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256, -** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511 -** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an -** unused slot/unknown ID etc. -** The Topology array contains the ID of the unit connected to each of the -** four links on this unit. The entry will be 0xFFFF if NOTHING is connected -** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link. -** The Name field is a null-terminated string, upto 31 characters, containing -** the 'cute' name that the sysadmin/users know the RTA by. It is permissible -** for this string to contain any character in the range \040 to \176 inclusive. -** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The -** special character '%' IS allowable, and needs no special action. -** -*/ - -#endif diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h deleted file mode 100644 index 7e9b6283e8aa..000000000000 --- a/drivers/char/rio/param.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : param.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:12 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)param.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_param_h__ -#define __rio_param_h__ - -/* -** the param command block, as used in OPEN and PARAM calls. -*/ - -struct phb_param { - u8 Cmd; /* It is very important that these line up */ - u8 Cor1; /* with what is expected at the other end. */ - u8 Cor2; /* to confirm that you've got it right, */ - u8 Cor4; /* check with cirrus/cirrus.h */ - u8 Cor5; - u8 TxXon; /* Transmit X-On character */ - u8 TxXoff; /* Transmit X-Off character */ - u8 RxXon; /* Receive X-On character */ - u8 RxXoff; /* Receive X-Off character */ - u8 LNext; /* Literal-next character */ - u8 TxBaud; /* Transmit baudrate */ - u8 RxBaud; /* Receive baudrate */ -}; - -#endif diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h deleted file mode 100644 index acc8fa439df5..000000000000 --- a/drivers/char/rio/parmmap.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* H O S T M E M O R Y M A P - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- -6/4/1991 jonb Made changes to accommodate Mips R3230 bus - ***************************************************************************/ - -#ifndef _parmap_h -#define _parmap_h - -typedef struct PARM_MAP PARM_MAP; - -struct PARM_MAP { - u16 phb_ptr; /* Pointer to the PHB array */ - u16 phb_num_ptr; /* Ptr to Number of PHB's */ - u16 free_list; /* Free List pointer */ - u16 free_list_end; /* Free List End pointer */ - u16 q_free_list_ptr; /* Ptr to Q_BUF variable */ - u16 unit_id_ptr; /* Unit Id */ - u16 link_str_ptr; /* Link Structure Array */ - u16 bootloader_1; /* 1st Stage Boot Loader */ - u16 bootloader_2; /* 2nd Stage Boot Loader */ - u16 port_route_map_ptr; /* Port Route Map */ - u16 route_ptr; /* Unit Route Map */ - u16 map_present; /* Route Map present */ - s16 pkt_num; /* Total number of packets */ - s16 q_num; /* Total number of Q packets */ - u16 buffers_per_port; /* Number of buffers per port */ - u16 heap_size; /* Initial size of heap */ - u16 heap_left; /* Current Heap left */ - u16 error; /* Error code */ - u16 tx_max; /* Max number of tx pkts per phb */ - u16 rx_max; /* Max number of rx pkts per phb */ - u16 rx_limit; /* For high / low watermarks */ - s16 links; /* Links to use */ - s16 timer; /* Interrupts per second */ - u16 rups; /* Pointer to the RUPs */ - u16 max_phb; /* Mostly for debugging */ - u16 living; /* Just increments!! */ - u16 init_done; /* Initialisation over */ - u16 booting_link; - u16 idle_count; /* Idle time counter */ - u16 busy_count; /* Busy counter */ - u16 idle_control; /* Control Idle Process */ - u16 tx_intr; /* TX interrupt pending */ - u16 rx_intr; /* RX interrupt pending */ - u16 rup_intr; /* RUP interrupt pending */ -}; - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/pci.h b/drivers/char/rio/pci.h deleted file mode 100644 index 6032f9135956..000000000000 --- a/drivers/char/rio/pci.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : pci.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:12 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)pci.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_pci_h__ -#define __rio_pci_h__ - -/* -** PCI stuff -*/ - -#define PCITpFastClock 0x80 -#define PCITpSlowClock 0x00 -#define PCITpFastLinks 0x40 -#define PCITpSlowLinks 0x00 -#define PCITpIntEnable 0x04 -#define PCITpIntDisable 0x00 -#define PCITpBusEnable 0x02 -#define PCITpBusDisable 0x00 -#define PCITpBootFromRam 0x01 -#define PCITpBootFromLink 0x00 - -#define RIO_PCI_VENDOR 0x11CB -#define RIO_PCI_DEVICE 0x8000 -#define RIO_PCI_BASE_CLASS 0x02 -#define RIO_PCI_SUB_CLASS 0x80 -#define RIO_PCI_PROG_IFACE 0x00 - -#define RIO_PCI_RID 0x0008 -#define RIO_PCI_BADR0 0x0010 -#define RIO_PCI_INTLN 0x003C -#define RIO_PCI_INTPIN 0x003D - -#define RIO_PCI_MEM_SIZE 65536 - -#define RIO_PCI_TURBO_TP 0x80 -#define RIO_PCI_FAST_LINKS 0x40 -#define RIO_PCI_INT_ENABLE 0x04 -#define RIO_PCI_TP_BUS_ENABLE 0x02 -#define RIO_PCI_BOOT_FROM_RAM 0x01 - -#define RIO_PCI_DEFAULT_MODE 0x05 - -#endif /* __rio_pci_h__ */ diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h deleted file mode 100644 index a4c48ae4e365..000000000000 --- a/drivers/char/rio/phb.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* P H B H E A D E R ******* - ******* ******* - **************************************************************************** - - Author : Ian Nandhra, Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _phb_h -#define _phb_h 1 - -/************************************************* - * Handshake asserted. Deasserted by the LTT(s) - ************************************************/ -#define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */ - -#define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */ - -#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET) - /* Reset by ltt */ - - -/************************************************* - * Maximum number of PHB's - ************************************************/ -#define MAX_PHB ((ushort) 128) /* range 0-127 */ - -/************************************************* - * Defines for the mode fields - ************************************************/ -#define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */ -#define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */ -#define TX_TAB3 0x0004 /* TAB3 mode */ -#define TX_OCRNL 0x0008 /* OCRNL mode */ -#define TX_ONLCR 0x0010 /* ONLCR mode */ -#define TX_SENDSPACES 0x0020 /* Send n spaces command needs - completing */ -#define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */ -#define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */ -#define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel - port */ -#define TX_HANGOVER (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL) -#define TX_DTRFLOW 0x0200 /* DTR tx flow control */ -#define TX_DTRFLOWED 0x0400 /* DTR is low - don't allow more data - into the FIFO */ -#define TX_DATAINFIFO 0x0800 /* There is data in the FIFO */ -#define TX_BUSY 0x1000 /* Data in FIFO, shift or holding regs */ - -#define RX_SPARE 0x0001 /* SPARE */ -#define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */ -#define RX_ICRNL 0x0008 /* ICRNL mode */ -#define RX_INLCR 0x0010 /* INLCR mode */ -#define RX_IGNCR 0x0020 /* IGNCR mode */ -#define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */ -#define RX_IXOFF 0x0080 /* IXOFF enabled */ -#define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */ -#define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */ -#define RX_BUFFERED 0x0400 /* Try and pass on complete packets */ - -#define PORT_ISOPEN 0x0001 /* Port open? */ -#define PORT_HUPCL 0x0002 /* Hangup on close? */ -#define PORT_MOPENPEND 0x0004 /* Modem open pending */ -#define PORT_ISPARALLEL 0x0008 /* Parallel port */ -#define PORT_BREAK 0x0010 /* Port on break */ -#define PORT_STATUSPEND 0x0020 /* Status packet pending */ -#define PORT_BREAKPEND 0x0040 /* Break packet pending */ -#define PORT_MODEMPEND 0x0080 /* Modem status packet pending */ -#define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel - port */ -#define PORT_FULLMODEM 0x0200 /* Full modem signals */ -#define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */ -#define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */ - -#define PORT_MODEMBITS 0x0600 /* Mask for modem fields */ - -#define PORT_WCLOSE 0x0800 /* Waiting for close */ -#define PORT_HANDSHAKEFIX 0x1000 /* Port has H/W flow control fix */ -#define PORT_WASPCLOSED 0x2000 /* Port closed with PCLOSE */ -#define DUMPMODE 0x4000 /* Dump RTA mem */ -#define READ_REG 0x8000 /* Read CD1400 register */ - - - -/************************************************************************** - * PHB Structure - * A few words. - * - * Normally Packets are added to the end of the list and removed from - * the start. The pointer tx_add points to a SPACE to put a Packet. - * The pointer tx_remove points to the next Packet to remove - *************************************************************************/ - -struct PHB { - u8 source; - u8 handshake; - u8 status; - u16 timeout; /* Maximum of 1.9 seconds */ - u8 link; /* Send down this link */ - u8 destination; - u16 tx_start; - u16 tx_end; - u16 tx_add; - u16 tx_remove; - - u16 rx_start; - u16 rx_end; - u16 rx_add; - u16 rx_remove; - -}; - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h deleted file mode 100644 index a9458164f02f..000000000000 --- a/drivers/char/rio/pkt.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* P A C K E T H E A D E R F I L E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _pkt_h -#define _pkt_h 1 - -#define PKT_CMD_BIT ((ushort) 0x080) -#define PKT_CMD_DATA ((ushort) 0x080) - -#define PKT_ACK ((ushort) 0x040) - -#define PKT_TGL ((ushort) 0x020) - -#define PKT_LEN_MASK ((ushort) 0x07f) - -#define DATA_WNDW ((ushort) 0x10) -#define PKT_TTL_MASK ((ushort) 0x0f) - -#define PKT_MAX_DATA_LEN 72 - -#define PKT_LENGTH sizeof(struct PKT) -#define SYNC_PKT_LENGTH (PKT_LENGTH + 4) - -#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK -#define CONTROL_PKT_CMD_BIT PKT_CMD_BIT -#define CONTROL_PKT_ACK (PKT_ACK << 8) -#define CONTROL_PKT_TGL (PKT_TGL << 8) -#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8) -#define CONTROL_DATA_WNDW (DATA_WNDW << 8) - -struct PKT { - u8 dest_unit; /* Destination Unit Id */ - u8 dest_port; /* Destination POrt */ - u8 src_unit; /* Source Unit Id */ - u8 src_port; /* Source POrt */ - u8 len; - u8 control; - u8 data[PKT_MAX_DATA_LEN]; - /* Actual data :-) */ - u16 csum; /* C-SUM */ -}; -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h deleted file mode 100644 index 49cf6d15ee54..000000000000 --- a/drivers/char/rio/port.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : port.h -** SID : 1.3 -** Last Modified : 11/6/98 11:34:12 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)port.h 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_port_h__ -#define __rio_port_h__ - -/* -** Port data structure -*/ -struct Port { - struct gs_port gs; - int PortNum; /* RIO port no., 0-511 */ - struct Host *HostP; - void __iomem *Caddr; - unsigned short HostPort; /* Port number on host card */ - unsigned char RupNum; /* Number of RUP for port */ - unsigned char ID2; /* Second ID of RTA for port */ - unsigned long State; /* FLAGS for open & xopen */ -#define RIO_LOPEN 0x00001 /* Local open */ -#define RIO_MOPEN 0x00002 /* Modem open */ -#define RIO_WOPEN 0x00004 /* Waiting for open */ -#define RIO_CLOSING 0x00008 /* The port is being close */ -#define RIO_XPBUSY 0x00010 /* Transparent printer busy */ -#define RIO_BREAKING 0x00020 /* Break in progress */ -#define RIO_DIRECT 0x00040 /* Doing Direct output */ -#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */ -#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */ -#define RIO_CARR_ON 0x00200 /* Stream has carrier present */ -#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */ -#define RIO_RBLK 0x00800 /* Stream is read-blocked */ -#define RIO_BUSY 0x01000 /* Stream is BUSY for write */ -#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */ -#define RIO_TXSTOP 0x04000 /* Stream output is stopped */ -#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */ -#define RIO_DYNOROD 0x10000 /* Drain failed */ -#define RIO_DELETED 0x20000 /* RTA has been deleted */ -#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */ -#define RIO_USING_EUC 0x100000 /* Using extended Unix chars */ -#define RIO_CAN_COOK 0x200000 /* This line can do cooking */ -#define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */ -#define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */ -#define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */ -#define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */ - - unsigned long Config; /* FLAGS for NOREAD.... */ -#define RIO_NOREAD 0x0001 /* Are not allowed to read port */ -#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */ -#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */ -#define RIO_NOMASK 0x0007 /* All not allowed things */ -#define RIO_IXANY 0x0008 /* Port is allowed ixany */ -#define RIO_MODEM 0x0010 /* Stream is a modem device */ -#define RIO_IXON 0x0020 /* Port is allowed ixon */ -#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */ -#define RIO_MAP_50_TO_50 0x0080 /* Map 50 baud to 50 baud */ -#define RIO_MAP_110_TO_110 0x0100 /* Map 110 baud to 110 baud */ - -/* -** 15.10.1998 ARG - ESIL 0761 prt fix -** As LynxOS does not appear to support Hardware Flow Control ..... -** Define our own flow control flags in 'Config'. -*/ -#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */ -#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */ - - - struct PHB __iomem *PhbP; /* pointer to PHB for port */ - u16 __iomem *TxAdd; /* Add packets here */ - u16 __iomem *TxStart; /* Start of add array */ - u16 __iomem *TxEnd; /* End of add array */ - u16 __iomem *RxRemove; /* Remove packets here */ - u16 __iomem *RxStart; /* Start of remove array */ - u16 __iomem *RxEnd; /* End of remove array */ - unsigned int RtaUniqueNum; /* Unique number of RTA */ - unsigned short PortState; /* status of port */ - unsigned short ModemState; /* status of modem lines */ - unsigned long ModemLines; /* Modem bits sent to RTA */ - unsigned char CookMode; /* who expands CR/LF? */ - unsigned char ParamSem; /* Prevent write during param */ - unsigned char Mapped; /* if port mapped onto host */ - unsigned char SecondBlock; /* if port belongs to 2nd block - of 16 port RTA */ - unsigned char InUse; /* how many pre-emptive cmds */ - unsigned char Lock; /* if params locked */ - unsigned char Store; /* if params stored across closes */ - unsigned char FirstOpen; /* TRUE if first time port opened */ - unsigned char FlushCmdBodge; /* if doing a (non)flush */ - unsigned char MagicFlags; /* require intr processing */ -#define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */ -#define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */ -#define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */ - unsigned char WflushFlag; /* 1 How many WFLUSHs active */ -/* -** Transparent print stuff -*/ - struct Xprint { -#ifndef MAX_XP_CTRL_LEN -#define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */ -#endif - unsigned int XpCps; - char XpOn[MAX_XP_CTRL_LEN]; - char XpOff[MAX_XP_CTRL_LEN]; - unsigned short XpLen; /* strlen(XpOn)+strlen(XpOff) */ - unsigned char XpActive; - unsigned char XpLastTickOk; /* TRUE if we can process */ -#define XP_OPEN 00001 -#define XP_RUNABLE 00002 - struct ttystatics *XttyP; - } Xprint; - unsigned char RxDataStart; - unsigned char Cor2Copy; /* copy of COR2 */ - char *Name; /* points to the Rta's name */ - char *TxRingBuffer; - unsigned short TxBufferIn; /* New data arrives here */ - unsigned short TxBufferOut; /* Intr removes data here */ - unsigned short OldTxBufferOut; /* Indicates if draining */ - int TimeoutId; /* Timeout ID */ - unsigned int Debug; - unsigned char WaitUntilBooted; /* True if open should block */ - unsigned int statsGather; /* True if gathering stats */ - unsigned long txchars; /* Chars transmitted */ - unsigned long rxchars; /* Chars received */ - unsigned long opens; /* port open count */ - unsigned long closes; /* port close count */ - unsigned long ioctls; /* ioctl count */ - unsigned char LastRxTgl; /* Last state of rx toggle bit */ - spinlock_t portSem; /* Lock using this sem */ - int MonitorTstate; /* Monitoring ? */ - int timeout_id; /* For calling 100 ms delays */ - int timeout_sem; /* For calling 100 ms delays */ - int firstOpen; /* First time open ? */ - char *p; /* save the global struc here .. */ -}; - -struct ModuleInfo { - char *Name; - unsigned int Flags[4]; /* one per port on a module */ -}; - -/* -** This struct is required because trying to grab an entire Port structure -** runs into problems with differing struct sizes between driver and config. -*/ -struct PortParams { - unsigned int Port; - unsigned long Config; - unsigned long State; - struct ttystatics *TtyP; -}; - -#endif diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h deleted file mode 100644 index 8ab79401d3ee..000000000000 --- a/drivers/char/rio/protsts.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* P R O T O C O L S T A T U S S T R U C T U R E ******* - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _protsts_h -#define _protsts_h 1 - -/************************************************* - * ACK bit. Last Packet received OK. Set by - * rxpkt to indicate that the Packet has been - * received OK and that the LTT must set the ACK - * bit in the next outward bound Packet - * and re-set by LTT's after xmit. - * - * Gets shoved into rx_status - ************************************************/ -#define PHB_RX_LAST_PKT_ACKED ((ushort) 0x080) - -/******************************************************* - * The Rx TOGGLE bit. - * Stuffed into rx_status by RXPKT - ******************************************************/ -#define PHB_RX_DATA_WNDW ((ushort) 0x040) - -/******************************************************* - * The Rx TOGGLE bit. Matches the setting in PKT.H - * Stuffed into rx_status - ******************************************************/ -#define PHB_RX_TGL ((ushort) 0x2000) - - -/************************************************* - * This bit is set by the LRT to indicate that - * an ACK (packet) must be returned. - * - * Gets shoved into tx_status - ************************************************/ -#define PHB_TX_SEND_PKT_ACK ((ushort) 0x08) - -/************************************************* - * Set by LTT to indicate that an ACK is required - *************************************************/ -#define PHB_TX_ACK_RQRD ((ushort) 0x01) - - -/******************************************************* - * The Tx TOGGLE bit. - * Stuffed into tx_status by RXPKT from the PKT WndW - * field. Looked by the LTT when the NEXT Packet - * is going to be sent. - ******************************************************/ -#define PHB_TX_DATA_WNDW ((ushort) 0x04) - - -/******************************************************* - * The Tx TOGGLE bit. Matches the setting in PKT.H - * Stuffed into tx_status - ******************************************************/ -#define PHB_TX_TGL ((ushort) 0x02) - -/******************************************************* - * Request intr bit. Set when the queue has gone quiet - * and the PHB has requested an interrupt. - ******************************************************/ -#define PHB_TX_INTR ((ushort) 0x100) - -/******************************************************* - * SET if the PHB cannot send any more data down the - * Link - ******************************************************/ -#define PHB_TX_HANDSHAKE ((ushort) 0x010) - - -#define RUP_SEND_WNDW ((ushort) 0x08) ; - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h deleted file mode 100644 index 1bf36223a4e8..000000000000 --- a/drivers/char/rio/rio.h +++ /dev/null @@ -1,208 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rio.h -** SID : 1.3 -** Last Modified : 11/6/98 11:34:13 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)rio.h 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_rio_h__ -#define __rio_rio_h__ - -/* -** Maximum numbers of things -*/ -#define RIO_SLOTS 4 /* number of configuration slots */ -#define RIO_HOSTS 4 /* number of hosts that can be found */ -#define PORTS_PER_HOST 128 /* number of ports per host */ -#define LINKS_PER_UNIT 4 /* number of links from a host */ -#define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */ -#define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */ -#define PORTS_PER_RTA (PORTS_PER_HOST/RTAS_PER_HOST) /* ports on a rta */ -#define PORTS_PER_MODULE 4 /* number of ports on a plug-in module */ - /* number of modules on an RTA */ -#define MODULES_PER_RTA (PORTS_PER_RTA/PORTS_PER_MODULE) -#define MAX_PRODUCT 16 /* numbr of different product codes */ -#define MAX_MODULE_TYPES 16 /* number of different types of module */ - -#define RIO_CONTROL_DEV 128 /* minor number of host/control device */ -#define RIO_INVALID_MAJOR 0 /* test first host card's major no for validity */ - -/* -** number of RTAs that can be bound to a master -*/ -#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS) - -/* -** Unit types -*/ -#define PC_RTA16 0x90000000 -#define PC_RTA8 0xe0000000 -#define TYPE_HOST 0 -#define TYPE_RTA8 1 -#define TYPE_RTA16 2 - -/* -** Flag values returned by functions -*/ - -#define RIO_FAIL -1 - -/* -** SysPort value for something that hasn't any ports -*/ -#define NO_PORT 0xFFFFFFFF - -/* -** Unit ID Of all hosts -*/ -#define HOST_ID 0 - -/* -** Break bytes into nybles -*/ -#define LONYBLE(X) ((X) & 0xF) -#define HINYBLE(X) (((X)>>4) & 0xF) - -/* -** Flag values passed into some functions -*/ -#define DONT_SLEEP 0 -#define OK_TO_SLEEP 1 - -#define DONT_PRINT 1 -#define DO_PRINT 0 - -#define PRINT_TO_LOG_CONS 0 -#define PRINT_TO_CONS 1 -#define PRINT_TO_LOG 2 - -/* -** Timeout has trouble with times of less than 3 ticks... -*/ -#define MIN_TIMEOUT 3 - -/* -** Generally useful constants -*/ - -#define HUNDRED_MS ((HZ/10)?(HZ/10):1) -#define ONE_MEG 0x100000 -#define SIXTY_FOUR_K 0x10000 - -#define RIO_AT_MEM_SIZE SIXTY_FOUR_K -#define RIO_EISA_MEM_SIZE SIXTY_FOUR_K -#define RIO_MCA_MEM_SIZE SIXTY_FOUR_K - -#define COOK_WELL 0 -#define COOK_MEDIUM 1 -#define COOK_RAW 2 - -/* -** Pointer manipulation stuff -** RIO_PTR takes hostp->Caddr and the offset into the DP RAM area -** and produces a UNIX caddr_t (pointer) to the object -** RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and -** returns the offset into the DP RAM area. -*/ -#define RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O))) -#define RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C)) - -/* -** How to convert from various different device number formats: -** DEV is a dev number, as passed to open, close etc - NOT a minor -** number! -**/ - -#define RIO_MODEM_MASK 0x1FF -#define RIO_MODEM_BIT 0x200 -#define RIO_UNMODEM(DEV) (MINOR(DEV) & RIO_MODEM_MASK) -#define RIO_ISMODEM(DEV) (MINOR(DEV) & RIO_MODEM_BIT) -#define RIO_PORT(DEV,FIRST_MAJ) ( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \ - + MINOR(DEV) -#define CSUM(pkt_ptr) (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \ - ((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \ - ((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \ - ((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \ - ((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] ) - -#define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */ - /* prevent a really stupid race condition. */ - -#define NOT_INITIALISED 0 -#define INITIALISED 1 - -#define NOT_POLLING 0 -#define POLLING 1 - -#define NOT_CHANGED 0 -#define CHANGED 1 - -#define NOT_INUSE 0 - -#define DISCONNECT 0 -#define CONNECT 1 - -/* ------ Control Codes ------ */ - -#define CONTROL '^' -#define IFOAD ( CONTROL + 1 ) -#define IDENTIFY ( CONTROL + 2 ) -#define ZOMBIE ( CONTROL + 3 ) -#define UFOAD ( CONTROL + 4 ) -#define IWAIT ( CONTROL + 5 ) - -#define IFOAD_MAGIC 0xF0AD /* of course */ -#define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */ -#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */ -#define IWAIT_MAGIC 0xB1DE /* Bide your time */ - -/* ------ Error Codes ------ */ - -#define E_NO_ERROR ((ushort) 0) - -/* ------ Free Lists ------ */ - -struct rio_free_list { - u16 next; - u16 prev; -}; - -/* NULL for card side linked lists */ -#define TPNULL ((ushort)(0x8000)) -/* We can add another packet to a transmit queue if the packet pointer pointed - * to by the TxAdd pointer has PKT_IN_USE clear in its address. */ -#define PKT_IN_USE 0x1 - -/* ------ Topology ------ */ - -struct Top { - u8 Unit; - u8 Link; -}; - -#endif /* __rio_h__ */ diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c deleted file mode 100644 index 5e33293d24e3..000000000000 --- a/drivers/char/rio/rio_linux.c +++ /dev/null @@ -1,1204 +0,0 @@ - -/* rio_linux.c -- Linux driver for the Specialix RIO series cards. - * - * - * (C) 1999 R.E.Wolff@BitWizard.nl - * - * Specialix pays for the development and support of this driver. - * Please DO contact support@specialix.co.uk if you require - * support. But please read the documentation (rio.txt) first. - * - * - * - * 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., 675 Mass Ave, Cambridge, MA 02139, - * USA. - * - * */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "linux_compat.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" -#include "param.h" -#include "protsts.h" -#include "rioboard.h" - - -#include "rio_linux.h" - -/* I don't think that this driver can handle more than 512 ports on -one machine. Specialix specifies max 4 boards in one machine. I don't -know why. If you want to try anyway you'll have to increase the number -of boards in rio.h. You'll have to allocate more majors if you need -more than 512 ports.... */ - -#ifndef RIO_NORMAL_MAJOR0 -/* This allows overriding on the compiler commandline, or in a "major.h" - include or something like that */ -#define RIO_NORMAL_MAJOR0 154 -#define RIO_NORMAL_MAJOR1 156 -#endif - -#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 -#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 -#endif - -#ifndef RIO_WINDOW_LEN -#define RIO_WINDOW_LEN 0x10000 -#endif - - -/* Configurable options: - (Don't be too sure that it'll work if you toggle them) */ - -/* Am I paranoid or not ? ;-) */ -#undef RIO_PARANOIA_CHECK - - -/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000 - Hz, but it is user configurable. I don't recommend going above 1000 - Hz. The interrupt ratelimit might trigger if the interrupt is - shared with a very active other device. - undef this if you want to disable the check.... -*/ -#define IRQ_RATE_LIMIT 200 - - -/* These constants are derived from SCO Source */ -static DEFINE_MUTEX(rio_fw_mutex); -static struct Conf - RIOConf = { - /* locator */ "RIO Config here", - /* startuptime */ HZ * 2, - /* how long to wait for card to run */ - /* slowcook */ 0, - /* TRUE -> always use line disc. */ - /* intrpolltime */ 1, - /* The frequency of OUR polls */ - /* breakinterval */ 25, - /* x10 mS XXX: units seem to be 1ms not 10! -- REW */ - /* timer */ 10, - /* mS */ - /* RtaLoadBase */ 0x7000, - /* HostLoadBase */ 0x7C00, - /* XpHz */ 5, - /* number of Xprint hits per second */ - /* XpCps */ 120, - /* Xprint characters per second */ - /* XpOn */ "\033d#", - /* start Xprint for a wyse 60 */ - /* XpOff */ "\024", - /* end Xprint for a wyse 60 */ - /* MaxXpCps */ 2000, - /* highest Xprint speed */ - /* MinXpCps */ 10, - /* slowest Xprint speed */ - /* SpinCmds */ 1, - /* non-zero for mega fast boots */ - /* First Addr */ 0x0A0000, - /* First address to look at */ - /* Last Addr */ 0xFF0000, - /* Last address looked at */ - /* BufferSize */ 1024, - /* Bytes per port of buffering */ - /* LowWater */ 256, - /* how much data left before wakeup */ - /* LineLength */ 80, - /* how wide is the console? */ - /* CmdTimeout */ HZ, - /* how long a close command may take */ -}; - - - - -/* Function prototypes */ - -static void rio_disable_tx_interrupts(void *ptr); -static void rio_enable_tx_interrupts(void *ptr); -static void rio_disable_rx_interrupts(void *ptr); -static void rio_enable_rx_interrupts(void *ptr); -static int rio_carrier_raised(struct tty_port *port); -static void rio_shutdown_port(void *ptr); -static int rio_set_real_termios(void *ptr); -static void rio_hungup(void *ptr); -static void rio_close(void *ptr); -static int rio_chars_in_buffer(void *ptr); -static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -static int rio_init_drivers(void); - -static void my_hd(void *addr, int len); - -static struct tty_driver *rio_driver, *rio_driver2; - -/* The name "p" is a bit non-descript. But that's what the rio-lynxos -sources use all over the place. */ -struct rio_info *p; - -int rio_debug; - - -/* You can have the driver poll your card. - - Set rio_poll to 1 to poll every timer tick (10ms on Intel). - This is used when the card cannot use an interrupt for some reason. -*/ -static int rio_poll = 1; - - -/* These are the only open spaces in my computer. Yours may have more - or less.... */ -static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 }; - -#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs) - - -/* Set the mask to all-ones. This alas, only supports 32 interrupts. - Some architectures may need more. -- Changed to LONG to - support up to 64 bits on 64bit architectures. -- REW 20/06/99 */ -static long rio_irqmask = -1; - -MODULE_AUTHOR("Rogier Wolff , Patrick van de Lageweg "); -MODULE_DESCRIPTION("RIO driver"); -MODULE_LICENSE("GPL"); -module_param(rio_poll, int, 0); -module_param(rio_debug, int, 0644); -module_param(rio_irqmask, long, 0); - -static struct real_driver rio_real_driver = { - rio_disable_tx_interrupts, - rio_enable_tx_interrupts, - rio_disable_rx_interrupts, - rio_enable_rx_interrupts, - rio_shutdown_port, - rio_set_real_termios, - rio_chars_in_buffer, - rio_close, - rio_hungup, - NULL -}; - -/* - * Firmware loader driver specific routines - * - */ - -static const struct file_operations rio_fw_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = rio_fw_ioctl, - .llseek = noop_llseek, -}; - -static struct miscdevice rio_fw_device = { - RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops -}; - - - - - -#ifdef RIO_PARANOIA_CHECK - -/* This doesn't work. Who's paranoid around here? Not me! */ - -static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine) -{ - - static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n"; - static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n"; - - if (!port) { - printk(badinfo, name, routine); - return 1; - } - if (port->magic != RIO_MAGIC) { - printk(badmagic, name, routine); - return 1; - } - - return 0; -} -#else -#define rio_paranoia_check(a,b,c) 0 -#endif - - -#ifdef DEBUG -static void my_hd(void *ad, int len) -{ - int i, j, ch; - unsigned char *addr = ad; - - for (i = 0; i < len; i += 16) { - rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i); - for (j = 0; j < 16; j++) { - rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : ""); - } - for (j = 0; j < 16; j++) { - ch = addr[j + i]; - rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch)); - } - rio_dprintk(RIO_DEBUG_PARAM, "\n"); - } -} -#else -#define my_hd(ad,len) do{/* nothing*/ } while (0) -#endif - - -/* Delay a number of jiffies, allowing a signal to interrupt */ -int RIODelay(struct Port *PortP, int njiffies) -{ - func_enter(); - - rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies); - msleep_interruptible(jiffies_to_msecs(njiffies)); - func_exit(); - - if (signal_pending(current)) - return RIO_FAIL; - else - return !RIO_FAIL; -} - - -/* Delay a number of jiffies, disallowing a signal to interrupt */ -int RIODelay_ni(struct Port *PortP, int njiffies) -{ - func_enter(); - - rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies); - msleep(jiffies_to_msecs(njiffies)); - func_exit(); - return !RIO_FAIL; -} - -void rio_copy_to_card(void *from, void __iomem *to, int len) -{ - rio_copy_toio(to, from, len); -} - -int rio_minor(struct tty_struct *tty) -{ - return tty->index + ((tty->driver == rio_driver) ? 0 : 256); -} - -static int rio_set_real_termios(void *ptr) -{ - return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1); -} - - -static void rio_reset_interrupt(struct Host *HostP) -{ - func_enter(); - - switch (HostP->Type) { - case RIO_AT: - case RIO_MCA: - case RIO_PCI: - writeb(0xFF, &HostP->ResetInt); - } - - func_exit(); -} - - -static irqreturn_t rio_interrupt(int irq, void *ptr) -{ - struct Host *HostP; - func_enter(); - - HostP = ptr; /* &p->RIOHosts[(long)ptr]; */ - rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec); - - /* AAargh! The order in which to do these things is essential and - not trivial. - - - hardware twiddling goes before "recursive". Otherwise when we - poll the card, and a recursive interrupt happens, we won't - ack the card, so it might keep on interrupting us. (especially - level sensitive interrupt systems like PCI). - - - Rate limit goes before hardware twiddling. Otherwise we won't - catch a card that has gone bonkers. - - - The "initialized" test goes after the hardware twiddling. Otherwise - the card will stick us in the interrupt routine again. - - - The initialized test goes before recursive. - */ - - rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); - if (HostP->Ivec == irq) { - /* Tell the card we've noticed the interrupt. */ - rio_reset_interrupt(HostP); - } - - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) - return IRQ_HANDLED; - - if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) { - printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec); - return IRQ_HANDLED; - } - - RIOServiceHost(p, HostP); - - rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type); - - clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks); - rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec); - func_exit(); - return IRQ_HANDLED; -} - - -static void rio_pollfunc(unsigned long data) -{ - func_enter(); - - rio_interrupt(0, &p->RIOHosts[data]); - mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll); - - func_exit(); -} - - -/* ********************************************************************** * - * Here are the routines that actually * - * interface with the generic_serial driver * - * ********************************************************************** */ - -/* Ehhm. I don't know how to fiddle with interrupts on the Specialix - cards. .... Hmm. Ok I figured it out. You don't. -- REW */ - -static void rio_disable_tx_interrupts(void *ptr) -{ - func_enter(); - - /* port->gs.port.flags &= ~GS_TX_INTEN; */ - - func_exit(); -} - - -static void rio_enable_tx_interrupts(void *ptr) -{ - struct Port *PortP = ptr; - /* int hn; */ - - func_enter(); - - /* hn = PortP->HostP - p->RIOHosts; - - rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn); - rio_interrupt (-1,(void *) hn, NULL); */ - - RIOTxEnable((char *) PortP); - - /* - * In general we cannot count on "tx empty" interrupts, although - * the interrupt routine seems to be able to tell the difference. - */ - PortP->gs.port.flags &= ~GS_TX_INTEN; - - func_exit(); -} - - -static void rio_disable_rx_interrupts(void *ptr) -{ - func_enter(); - func_exit(); -} - -static void rio_enable_rx_interrupts(void *ptr) -{ - /* struct rio_port *port = ptr; */ - func_enter(); - func_exit(); -} - - -/* Jeez. Isn't this simple? */ -static int rio_carrier_raised(struct tty_port *port) -{ - struct Port *PortP = container_of(port, struct Port, gs.port); - int rv; - - func_enter(); - rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0; - - rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv); - - func_exit(); - return rv; -} - - -/* Jeez. Isn't this simple? Actually, we can sync with the actual port - by just pushing stuff into the queue going to the port... */ -static int rio_chars_in_buffer(void *ptr) -{ - func_enter(); - - func_exit(); - return 0; -} - - -/* Nothing special here... */ -static void rio_shutdown_port(void *ptr) -{ - struct Port *PortP; - - func_enter(); - - PortP = (struct Port *) ptr; - PortP->gs.port.tty = NULL; - func_exit(); -} - - -/* I haven't the foggiest why the decrement use count has to happen - here. The whole linux serial drivers stuff needs to be redesigned. - My guess is that this is a hack to minimize the impact of a bug - elsewhere. Thinking about it some more. (try it sometime) Try - running minicom on a serial port that is driven by a modularized - driver. Have the modem hangup. Then remove the driver module. Then - exit minicom. I expect an "oops". -- REW */ -static void rio_hungup(void *ptr) -{ - struct Port *PortP; - - func_enter(); - - PortP = (struct Port *) ptr; - PortP->gs.port.tty = NULL; - - func_exit(); -} - - -/* The standard serial_close would become shorter if you'd wrap it like - this. - rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;} - */ -static void rio_close(void *ptr) -{ - struct Port *PortP; - - func_enter(); - - PortP = (struct Port *) ptr; - - riotclose(ptr); - - if (PortP->gs.port.count) { - printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.port.count); - PortP->gs.port.count = 0; - } - - PortP->gs.port.tty = NULL; - func_exit(); -} - - - -static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int rc = 0; - func_enter(); - - /* The "dev" argument isn't used. */ - mutex_lock(&rio_fw_mutex); - rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); - mutex_unlock(&rio_fw_mutex); - - func_exit(); - return rc; -} - -extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); - -static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int rc; - struct Port *PortP; - int ival; - - func_enter(); - - PortP = (struct Port *) tty->driver_data; - - rc = 0; - switch (cmd) { - case TIOCSSOFTCAR: - if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) { - tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); - } - break; - case TIOCGSERIAL: - rc = -EFAULT; - if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct))) - rc = gs_getserial(&PortP->gs, argp); - break; - case TCSBRK: - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n"); - rc = -EIO; - } else { - if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) == - RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); - rc = -EIO; - } - } - break; - case TCSBRKP: - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n"); - rc = -EIO; - } else { - int l; - l = arg ? arg * 100 : 250; - if (l > 255) - l = 255; - if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, - arg ? arg * 100 : 250) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); - rc = -EIO; - } - } - break; - case TIOCSSERIAL: - rc = -EFAULT; - if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct))) - rc = gs_setserial(&PortP->gs, argp); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - func_exit(); - return rc; -} - - -/* The throttle/unthrottle scheme for the Specialix card is different - * from other drivers and deserves some explanation. - * The Specialix hardware takes care of XON/XOFF - * and CTS/RTS flow control itself. This means that all we have to - * do when signalled by the upper tty layer to throttle/unthrottle is - * to make a note of it here. When we come to read characters from the - * rx buffers on the card (rio_receive_chars()) we look to see if the - * upper layer can accept more (as noted here in rio_rx_throt[]). - * If it can't we simply don't remove chars from the cards buffer. - * When the tty layer can accept chars, we again note that here and when - * rio_receive_chars() is called it will remove them from the cards buffer. - * The card will notice that a ports buffer has drained below some low - * water mark and will unflow control the line itself, using whatever - * flow control scheme is in use for that port. -- Simon Allen - */ - -static void rio_throttle(struct tty_struct *tty) -{ - struct Port *port = (struct Port *) tty->driver_data; - - func_enter(); - /* If the port is using any type of input flow - * control then throttle the port. - */ - - if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) { - port->State |= RIO_THROTTLE_RX; - } - - func_exit(); -} - - -static void rio_unthrottle(struct tty_struct *tty) -{ - struct Port *port = (struct Port *) tty->driver_data; - - func_enter(); - /* Always unthrottle even if flow control is not enabled on - * this port in case we disabled flow control while the port - * was throttled - */ - - port->State &= ~RIO_THROTTLE_RX; - - func_exit(); - return; -} - - - - - -/* ********************************************************************** * - * Here are the initialization routines. * - * ********************************************************************** */ - - -static struct vpd_prom *get_VPD_PROM(struct Host *hp) -{ - static struct vpd_prom vpdp; - char *p; - int i; - - func_enter(); - rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM); - - p = (char *) &vpdp; - for (i = 0; i < sizeof(struct vpd_prom); i++) - *p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2); - /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */ - - /* Terminate the identifier string. - *** requires one extra byte in struct vpd_prom *** */ - *p++ = 0; - - if (rio_debug & RIO_DEBUG_PROBE) - my_hd((char *) &vpdp, 0x20); - - func_exit(); - - return &vpdp; -} - -static const struct tty_operations rio_ops = { - .open = riotopen, - .close = gs_close, - .write = gs_write, - .put_char = gs_put_char, - .flush_chars = gs_flush_chars, - .write_room = gs_write_room, - .chars_in_buffer = gs_chars_in_buffer, - .flush_buffer = gs_flush_buffer, - .ioctl = rio_ioctl, - .throttle = rio_throttle, - .unthrottle = rio_unthrottle, - .set_termios = gs_set_termios, - .stop = gs_stop, - .start = gs_start, - .hangup = gs_hangup, -}; - -static int rio_init_drivers(void) -{ - int error = -ENOMEM; - - rio_driver = alloc_tty_driver(256); - if (!rio_driver) - goto out; - rio_driver2 = alloc_tty_driver(256); - if (!rio_driver2) - goto out1; - - func_enter(); - - rio_driver->owner = THIS_MODULE; - rio_driver->driver_name = "specialix_rio"; - rio_driver->name = "ttySR"; - rio_driver->major = RIO_NORMAL_MAJOR0; - rio_driver->type = TTY_DRIVER_TYPE_SERIAL; - rio_driver->subtype = SERIAL_TYPE_NORMAL; - rio_driver->init_termios = tty_std_termios; - rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - rio_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(rio_driver, &rio_ops); - - rio_driver2->owner = THIS_MODULE; - rio_driver2->driver_name = "specialix_rio"; - rio_driver2->name = "ttySR"; - rio_driver2->major = RIO_NORMAL_MAJOR1; - rio_driver2->type = TTY_DRIVER_TYPE_SERIAL; - rio_driver2->subtype = SERIAL_TYPE_NORMAL; - rio_driver2->init_termios = tty_std_termios; - rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - rio_driver2->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(rio_driver2, &rio_ops); - - rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios); - - if ((error = tty_register_driver(rio_driver))) - goto out2; - if ((error = tty_register_driver(rio_driver2))) - goto out3; - func_exit(); - return 0; - out3: - tty_unregister_driver(rio_driver); - out2: - put_tty_driver(rio_driver2); - out1: - put_tty_driver(rio_driver); - out: - printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error); - return 1; -} - -static const struct tty_port_operations rio_port_ops = { - .carrier_raised = rio_carrier_raised, -}; - -static int rio_init_datastructures(void) -{ - int i; - struct Port *port; - func_enter(); - - /* Many drivers statically allocate the maximum number of ports - There is no reason not to allocate them dynamically. Is there? -- REW */ - /* However, the RIO driver allows users to configure their first - RTA as the ports numbered 504-511. We therefore need to allocate - the whole range. :-( -- REW */ - -#define RI_SZ sizeof(struct rio_info) -#define HOST_SZ sizeof(struct Host) -#define PORT_SZ sizeof(struct Port *) -#define TMIO_SZ sizeof(struct termios *) - rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); - - if (!(p = kzalloc(RI_SZ, GFP_KERNEL))) - goto free0; - if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL))) - goto free1; - if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL))) - goto free2; - p->RIOConf = RIOConf; - rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp); - -#if 1 - for (i = 0; i < RIO_PORTS; i++) { - port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL); - if (!port) { - goto free6; - } - rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); - tty_port_init(&port->gs.port); - port->gs.port.ops = &rio_port_ops; - port->PortNum = i; - port->gs.magic = RIO_MAGIC; - port->gs.close_delay = HZ / 2; - port->gs.closing_wait = 30 * HZ; - port->gs.rd = &rio_real_driver; - spin_lock_init(&port->portSem); - } -#else - /* We could postpone initializing them to when they are configured. */ -#endif - - - - if (rio_debug & RIO_DEBUG_INIT) { - my_hd(&rio_real_driver, sizeof(rio_real_driver)); - } - - - func_exit(); - return 0; - - free6:for (i--; i >= 0; i--) - kfree(p->RIOPortp[i]); -/*free5: - free4: - free3:*/ kfree(p->RIOPortp); - free2:kfree(p->RIOHosts); - free1: - rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp); - kfree(p); - free0: - return -ENOMEM; -} - -static void __exit rio_release_drivers(void) -{ - func_enter(); - tty_unregister_driver(rio_driver2); - tty_unregister_driver(rio_driver); - put_tty_driver(rio_driver2); - put_tty_driver(rio_driver); - func_exit(); -} - - -#ifdef CONFIG_PCI - /* This was written for SX, but applies to RIO too... - (including bugs....) - - There is another bit besides Bit 17. Turning that bit off - (on boards shipped with the fix in the eeprom) results in a - hang on the next access to the card. - */ - - /******************************************************** - * Setting bit 17 in the CNTRL register of the PLX 9050 * - * chip forces a retry on writes while a read is pending.* - * This is to prevent the card locking up on Intel Xeon * - * multiprocessor systems with the NX chipset. -- NV * - ********************************************************/ - -/* Newer cards are produced with this bit set from the configuration - EEprom. As the bit is read/write for the CPU, we can fix it here, - if we detect that it isn't set correctly. -- REW */ - -static void fix_rio_pci(struct pci_dev *pdev) -{ - unsigned long hwbase; - unsigned char __iomem *rebase; - unsigned int t; - -#define CNTRL_REG_OFFSET 0x50 -#define CNTRL_REG_GOODVALUE 0x18260000 - - hwbase = pci_resource_start(pdev, 0); - rebase = ioremap(hwbase, 0x80); - t = readl(rebase + CNTRL_REG_OFFSET); - if (t != CNTRL_REG_GOODVALUE) { - printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); - writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); - } - iounmap(rebase); -} -#endif - - -static int __init rio_init(void) -{ - int found = 0; - int i; - struct Host *hp; - int retval; - struct vpd_prom *vpdp; - int okboard; - -#ifdef CONFIG_PCI - struct pci_dev *pdev = NULL; - unsigned short tshort; -#endif - - func_enter(); - rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug); - - if (abs((long) (&rio_debug) - rio_debug) < 0x10000) { - printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug); - rio_debug = -1; - } - - if (misc_register(&rio_fw_device) < 0) { - printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n"); - return -EIO; - } - - retval = rio_init_datastructures(); - if (retval < 0) { - misc_deregister(&rio_fw_device); - return retval; - } -#ifdef CONFIG_PCI - /* First look for the JET devices: */ - while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { - u32 tint; - - if (pci_enable_device(pdev)) - continue; - - /* Specialix has a whole bunch of cards with - 0x2000 as the device ID. They say its because - the standard requires it. Stupid standard. */ - /* It seems that reading a word doesn't work reliably on 2.0. - Also, reading a non-aligned dword doesn't work. So we read the - whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) - ourselves */ - pci_read_config_dword(pdev, 0x2c, &tint); - tshort = (tint >> 16) & 0xffff; - rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); - if (tshort != 0x0100) { - rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort); - continue; - } - rio_dprintk(RIO_DEBUG_PROBE, "cp1\n"); - - hp = &p->RIOHosts[p->RIONumHosts]; - hp->PaddrP = pci_resource_start(pdev, 2); - hp->Ivec = pdev->irq; - if (((1 << hp->Ivec) & rio_irqmask) == 0) - hp->Ivec = 0; - hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); - hp->CardP = (struct DpRam __iomem *) hp->Caddr; - hp->Type = RIO_PCI; - hp->Copy = rio_copy_to_card; - hp->Mode = RIO_PCI_BOOT_FROM_RAM; - spin_lock_init(&hp->HostLock); - rio_reset_interrupt(hp); - rio_start_card_running(hp); - - rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); - if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) { - rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n"); - writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); - p->RIOHosts[p->RIONumHosts].UniqueNum = - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); - rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); - - fix_rio_pci(pdev); - - p->RIOHosts[p->RIONumHosts].pdev = pdev; - pci_dev_get(pdev); - - p->RIOLastPCISearch = 0; - p->RIONumHosts++; - found++; - } else { - iounmap(p->RIOHosts[p->RIONumHosts].Caddr); - p->RIOHosts[p->RIONumHosts].Caddr = NULL; - } - } - - /* Then look for the older PCI card.... : */ - - /* These older PCI cards have problems (only byte-mode access is - supported), which makes them a bit awkward to support. - They also have problems sharing interrupts. Be careful. - (The driver now refuses to share interrupts for these - cards. This should be sufficient). - */ - - /* Then look for the older RIO/PCI devices: */ - while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) { - if (pci_enable_device(pdev)) - continue; - -#ifdef CONFIG_RIO_OLDPCI - hp = &p->RIOHosts[p->RIONumHosts]; - hp->PaddrP = pci_resource_start(pdev, 0); - hp->Ivec = pdev->irq; - if (((1 << hp->Ivec) & rio_irqmask) == 0) - hp->Ivec = 0; - hp->Ivec |= 0x8000; /* Mark as non-sharable */ - hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); - hp->CardP = (struct DpRam __iomem *) hp->Caddr; - hp->Type = RIO_PCI; - hp->Copy = rio_copy_to_card; - hp->Mode = RIO_PCI_BOOT_FROM_RAM; - spin_lock_init(&hp->HostLock); - - rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); - rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); - - rio_reset_interrupt(hp); - rio_start_card_running(hp); - rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); - if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) { - writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); - p->RIOHosts[p->RIONumHosts].UniqueNum = - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); - rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); - - p->RIOHosts[p->RIONumHosts].pdev = pdev; - pci_dev_get(pdev); - - p->RIOLastPCISearch = 0; - p->RIONumHosts++; - found++; - } else { - iounmap(p->RIOHosts[p->RIONumHosts].Caddr); - p->RIOHosts[p->RIONumHosts].Caddr = NULL; - } -#else - printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n"); -#endif - } -#endif /* PCI */ - - /* Now probe for ISA cards... */ - for (i = 0; i < NR_RIO_ADDRS; i++) { - hp = &p->RIOHosts[p->RIONumHosts]; - hp->PaddrP = rio_probe_addrs[i]; - /* There was something about the IRQs of these cards. 'Forget what.--REW */ - hp->Ivec = 0; - hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); - hp->CardP = (struct DpRam __iomem *) hp->Caddr; - hp->Type = RIO_AT; - hp->Copy = rio_copy_to_card; /* AT card PCI???? - PVDL - * -- YES! this is now a normal copy. Only the - * old PCI card uses the special PCI copy. - * Moreover, the ISA card will work with the - * special PCI copy anyway. -- REW */ - hp->Mode = 0; - spin_lock_init(&hp->HostLock); - - vpdp = get_VPD_PROM(hp); - rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n"); - okboard = 0; - if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) { - /* Board is present... */ - if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) { - /* ... and feeling fine!!!! */ - rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); - if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) { - rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum); - okboard++; - found++; - } - } - - if (!okboard) { - iounmap(hp->Caddr); - hp->Caddr = NULL; - } - } - } - - - for (i = 0; i < p->RIONumHosts; i++) { - hp = &p->RIOHosts[i]; - if (hp->Ivec) { - int mode = IRQF_SHARED; - if (hp->Ivec & 0x8000) { - mode = 0; - hp->Ivec &= 0x7fff; - } - rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode); - retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp); - rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval); - if (retval) { - printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); - hp->Ivec = 0; - } - rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec); - if (hp->Ivec != 0) { - rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); - hp->Mode |= RIO_PCI_INT_ENABLE; - } else - hp->Mode &= ~RIO_PCI_INT_ENABLE; - rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode); - rio_start_card_running(hp); - } - /* Init the timer "always" to make sure that it can safely be - deleted when we unload... */ - - setup_timer(&hp->timer, rio_pollfunc, i); - if (!hp->Ivec) { - rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll); - mod_timer(&hp->timer, jiffies + rio_poll); - } - } - - if (found) { - rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found); - rio_init_drivers(); - } else { - /* deregister the misc device we created earlier */ - misc_deregister(&rio_fw_device); - } - - func_exit(); - return found ? 0 : -EIO; -} - - -static void __exit rio_exit(void) -{ - int i; - struct Host *hp; - - func_enter(); - - for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) { - RIOHostReset(hp->Type, hp->CardP, hp->Slot); - if (hp->Ivec) { - free_irq(hp->Ivec, hp); - rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); - } - /* It is safe/allowed to del_timer a non-active timer */ - del_timer_sync(&hp->timer); - if (hp->Caddr) - iounmap(hp->Caddr); - if (hp->Type == RIO_PCI) - pci_dev_put(hp->pdev); - } - - if (misc_deregister(&rio_fw_device) < 0) { - printk(KERN_INFO "rio: couldn't deregister control-device\n"); - } - - - rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n"); - - rio_release_drivers(); - - /* Release dynamically allocated memory */ - kfree(p->RIOPortp); - kfree(p->RIOHosts); - kfree(p); - - func_exit(); -} - -module_init(rio_init); -module_exit(rio_exit); diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h deleted file mode 100644 index 7f26cd7c815e..000000000000 --- a/drivers/char/rio/rio_linux.h +++ /dev/null @@ -1,197 +0,0 @@ - -/* - * rio_linux.h - * - * Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * RIO serial driver. - * - * Version 1.0 -- July, 1999. - * - */ - -#define RIO_NBOARDS 4 -#define RIO_PORTSPERBOARD 128 -#define RIO_NPORTS (RIO_NBOARDS * RIO_PORTSPERBOARD) - -#define MODEM_SUPPORT - -#ifdef __KERNEL__ - -#define RIO_MAGIC 0x12345678 - - -struct vpd_prom { - unsigned short id; - char hwrev; - char hwass; - int uniqid; - char myear; - char mweek; - char hw_feature[5]; - char oem_id; - char identifier[16]; -}; - - -#define RIO_DEBUG_ALL 0xffffffff - -#define O_OTHER(tty) \ - ((O_OLCUC(tty)) ||\ - (O_ONLCR(tty)) ||\ - (O_OCRNL(tty)) ||\ - (O_ONOCR(tty)) ||\ - (O_ONLRET(tty)) ||\ - (O_OFILL(tty)) ||\ - (O_OFDEL(tty)) ||\ - (O_NLDLY(tty)) ||\ - (O_CRDLY(tty)) ||\ - (O_TABDLY(tty)) ||\ - (O_BSDLY(tty)) ||\ - (O_VTDLY(tty)) ||\ - (O_FFDLY(tty))) - -/* Same for input. */ -#define I_OTHER(tty) \ - ((I_INLCR(tty)) ||\ - (I_IGNCR(tty)) ||\ - (I_ICRNL(tty)) ||\ - (I_IUCLC(tty)) ||\ - (L_ISIG(tty))) - - -#endif /* __KERNEL__ */ - - -#define RIO_BOARD_INTR_LOCK 1 - - -#ifndef RIOCTL_MISC_MINOR -/* Allow others to gather this into "major.h" or something like that */ -#define RIOCTL_MISC_MINOR 169 -#endif - - -/* Allow us to debug "in the field" without requiring clients to - recompile.... */ -#if 1 -#define rio_spin_lock_irqsave(sem, flags) do { \ - rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \ - sem, __FILE__, __LINE__);\ - spin_lock_irqsave(sem, flags);\ - } while (0) - -#define rio_spin_unlock_irqrestore(sem, flags) do { \ - rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\ - sem, __FILE__, __LINE__);\ - spin_unlock_irqrestore(sem, flags);\ - } while (0) - -#define rio_spin_lock(sem) do { \ - rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\ - sem, __FILE__, __LINE__);\ - spin_lock(sem);\ - } while (0) - -#define rio_spin_unlock(sem) do { \ - rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\ - sem, __FILE__, __LINE__);\ - spin_unlock(sem);\ - } while (0) -#else -#define rio_spin_lock_irqsave(sem, flags) \ - spin_lock_irqsave(sem, flags) - -#define rio_spin_unlock_irqrestore(sem, flags) \ - spin_unlock_irqrestore(sem, flags) - -#define rio_spin_lock(sem) \ - spin_lock(sem) - -#define rio_spin_unlock(sem) \ - spin_unlock(sem) - -#endif - - - -#ifdef CONFIG_RIO_OLDPCI -static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n) -{ - char __iomem *dst = dest; - char *src = source; - - while (n--) { - writeb(*src++, dst++); - (void) readb(dummy); - } - - return dest; -} - -static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n) -{ - char __iomem *dst = dest; - char *src = source; - - while (n--) - writeb(*src++, dst++); - - return dest; -} - - -static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n) -{ - char *dst = dest; - char __iomem *src = source; - - while (n--) - *dst++ = readb(src++); - - return dest; -} - -#else -#define rio_memcpy_toio(dummy,dest,source,n) memcpy_toio(dest, source, n) -#define rio_copy_toio memcpy_toio -#define rio_memcpy_fromio memcpy_fromio -#endif - -#define DEBUG 1 - - -/* - This driver can spew a whole lot of debugging output at you. If you - need maximum performance, you should disable the DEBUG define. To - aid in debugging in the field, I'm leaving the compile-time debug - features enabled, and disable them "runtime". That allows me to - instruct people with problems to enable debugging without requiring - them to recompile... -*/ - -#ifdef DEBUG -#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0) -#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__) -#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __func__) -#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line) -#else -#define rio_dprintk(f, str...) /* nothing */ -#define func_enter() -#define func_exit() -#define func_enter2() -#endif diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h deleted file mode 100644 index 252230043c82..000000000000 --- a/drivers/char/rio/rioboard.h +++ /dev/null @@ -1,275 +0,0 @@ -/************************************************************************/ -/* */ -/* Title : RIO Host Card Hardware Definitions */ -/* */ -/* Author : N.P.Vassallo */ -/* */ -/* Creation : 26th April 1999 */ -/* */ -/* Version : 1.0.0 */ -/* */ -/* Copyright : (c) Specialix International Ltd. 1999 * - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ -/* Description : Prototypes, structures and definitions */ -/* describing the RIO board hardware */ -/* */ -/************************************************************************/ - -#ifndef _rioboard_h /* If RIOBOARD.H not already defined */ -#define _rioboard_h 1 - -/***************************************************************************** -*********************** *********************** -*********************** Hardware Control Registers *********************** -*********************** *********************** -*****************************************************************************/ - -/* Hardware Registers... */ - -#define RIO_REG_BASE 0x7C00 /* Base of control registers */ - -#define RIO_CONFIG RIO_REG_BASE + 0x0000 /* WRITE: Configuration Register */ -#define RIO_INTSET RIO_REG_BASE + 0x0080 /* WRITE: Interrupt Set */ -#define RIO_RESET RIO_REG_BASE + 0x0100 /* WRITE: Host Reset */ -#define RIO_INTRESET RIO_REG_BASE + 0x0180 /* WRITE: Interrupt Reset */ - -#define RIO_VPD_ROM RIO_REG_BASE + 0x0000 /* READ: Vital Product Data ROM */ -#define RIO_INTSTAT RIO_REG_BASE + 0x0080 /* READ: Interrupt Status (Jet boards only) */ -#define RIO_RESETSTAT RIO_REG_BASE + 0x0100 /* READ: Reset Status (Jet boards only) */ - -/* RIO_VPD_ROM definitions... */ -#define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */ -#define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */ -#define VPD_HW_REV 0x02 /* READ: Hardware Revision */ -#define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */ -#define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */ -#define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */ -#define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */ -#define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */ -#define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */ -#define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */ -#define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */ -#define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */ -#define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */ -#define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */ -#define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */ -#define VPD_OEMID 0x0F /* READ: OEM Identifier */ -#define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */ -#define VPD_IDENT_LEN 0x10 - -/* VPD ROM Definitions... */ -#define SLX_ID1 0x4D -#define SLX_ID2 0x98 - -#define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */ - -#define ID_SX_ISA 0x2 -#define ID_RIO_EISA 0x3 -#define ID_SX_PCI 0x5 -#define ID_SX_EISA 0x7 -#define ID_RIO_RTA16 0x9 -#define ID_RIO_ISA 0xA -#define ID_RIO_MCA 0xB -#define ID_RIO_SBUS 0xC -#define ID_RIO_PCI 0xD -#define ID_RIO_RTA8 0xE - -/* Transputer bootstrap definitions... */ - -#define BOOTLOADADDR (0x8000 - 6) -#define BOOTINDICATE (0x8000 - 2) - -/* Firmware load position... */ - -#define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */ - -/***************************************************************************** -***************************** ***************************** -***************************** RIO (Rev1) ISA ***************************** -***************************** ***************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_ISA_IDENT "JBJGPGGHINSMJPJR" - -#define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ -#define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */ -#define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */ -#define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */ -#define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */ -#define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ -#define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */ - -/***************************************************************************** -***************************** ***************************** -***************************** RIO (Rev2) ISA ***************************** -***************************** ***************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_ISA2_IDENT "JBJGPGGHINSMJPJR" - -#define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ -#define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ -#define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */ -#define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */ -#define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */ -#define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */ -#define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */ -#define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */ -#define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ -#define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */ - -/***************************************************************************** -***************************** ****************************** -***************************** RIO (Jet) ISA ****************************** -***************************** ****************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_ISA3_IDENT "JET HOST BY KEV#" - -#define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ -#define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */ -#define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */ -#define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */ -#define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */ -#define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */ -#define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */ - -/***************************************************************************** -********************************* ******************************** -********************************* RIO MCA ******************************** -********************************* ******************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_MCA_IDENT "JBJGPGGHINSMJPJR" - -#define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ -#define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ - -/***************************************************************************** -******************************** ******************************** -******************************** RIO EISA ******************************** -******************************** ******************************** -*****************************************************************************/ - -/* EISA Configuration Space Definitions... */ -#define EISA_PRODUCT_ID1 0xC80 -#define EISA_PRODUCT_ID2 0xC81 -#define EISA_PRODUCT_NUMBER 0xC82 -#define EISA_REVISION_NUMBER 0xC83 -#define EISA_CARD_ENABLE 0xC84 -#define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */ -#define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */ -#define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */ -#define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */ -#define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */ -#define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */ -#define EISA_MEM_ADDR_23_16 0xC00 -#define EISA_MEM_ADDR_31_24 0xC01 -#define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */ -#define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */ -#define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */ - -/* Control Register Definitions... */ -#define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ -#define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */ -#define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */ -#define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */ -#define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */ -#define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */ -#define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */ -#define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */ -#define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */ -#define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */ -#define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */ -#define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */ -#define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */ -#define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */ -#define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */ -#define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */ - -/***************************************************************************** -******************************** ******************************** -******************************** RIO SBus ******************************** -******************************** ******************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_SBUS_IDENT "JBPGK#\0\0\0\0\0\0\0\0\0\0" - -#define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ -#define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ -#define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */ -#define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */ -#define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */ -#define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */ -#define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */ -#define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */ -#define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */ -#define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */ -#define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */ -#define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ -#define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */ - -/***************************************************************************** -********************************* ******************************** -********************************* RIO PCI ******************************** -********************************* ******************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_PCI_IDENT "ECDDPGJGJHJRGSK#" - -#define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ -#define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ -#define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ -#define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */ - -/* PCI Definitions... */ -#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */ -#define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */ -#define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */ -#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */ -#define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */ - -/***************************************************************************** -***************************** ****************************** -***************************** RIO (Jet) PCI ****************************** -***************************** ****************************** -*****************************************************************************/ - -/* Control Register Definitions... */ -#define RIO_PCI2_IDENT "JET HOST BY KEV#" - -#define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */ -#define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ - -/* PCI Definitions... */ -#define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */ - -#endif /*_rioboard_h */ - -/* End of RIOBOARD.H */ diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c deleted file mode 100644 index d956dd316005..000000000000 --- a/drivers/char/rio/rioboot.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioboot.c -** SID : 1.3 -** Last Modified : 11/6/98 10:33:36 -** Retrieved : 11/6/98 10:33:48 -** -** ident @(#)rioboot.c 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" - -static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP); - -static const unsigned char RIOAtVec2Ctrl[] = { - /* 0 */ INTERRUPT_DISABLE, - /* 1 */ INTERRUPT_DISABLE, - /* 2 */ INTERRUPT_DISABLE, - /* 3 */ INTERRUPT_DISABLE, - /* 4 */ INTERRUPT_DISABLE, - /* 5 */ INTERRUPT_DISABLE, - /* 6 */ INTERRUPT_DISABLE, - /* 7 */ INTERRUPT_DISABLE, - /* 8 */ INTERRUPT_DISABLE, - /* 9 */ IRQ_9 | INTERRUPT_ENABLE, - /* 10 */ INTERRUPT_DISABLE, - /* 11 */ IRQ_11 | INTERRUPT_ENABLE, - /* 12 */ IRQ_12 | INTERRUPT_ENABLE, - /* 13 */ INTERRUPT_DISABLE, - /* 14 */ INTERRUPT_DISABLE, - /* 15 */ IRQ_15 | INTERRUPT_ENABLE -}; - -/** - * RIOBootCodeRTA - Load RTA boot code - * @p: RIO to load - * @rbp: Download descriptor - * - * Called when the user process initiates booting of the card firmware. - * Lads the firmware - */ - -int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp) -{ - int offset; - - func_enter(); - - rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP); - - /* - ** Check that we have set asside enough memory for this - */ - if (rbp->Count > SIXTY_FOUR_K) { - rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); - p->RIOError.Error = HOST_FILE_TOO_LARGE; - func_exit(); - return -ENOMEM; - } - - if (p->RIOBooting) { - rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); - p->RIOError.Error = BOOT_IN_PROGRESS; - func_exit(); - return -EBUSY; - } - - /* - ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary, - ** so calculate how far we have to move the data up the buffer - ** to achieve this. - */ - offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE; - - /* - ** Be clean, and clear the 'unused' portion of the boot buffer, - ** because it will (eventually) be part of the Rta run time environment - ** and so should be zeroed. - */ - memset(p->RIOBootPackets, 0, offset); - - /* - ** Copy the data from user space into the array - */ - - if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) { - rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n"); - p->RIOError.Error = COPYIN_FAILED; - func_exit(); - return -EFAULT; - } - - /* - ** Make sure that our copy of the size includes that offset we discussed - ** earlier. - */ - p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE; - p->RIOBootCount = rbp->Count; - - func_exit(); - return 0; -} - -/** - * rio_start_card_running - host card start - * @HostP: The RIO to kick off - * - * Start a RIO processor unit running. Encapsulates the knowledge - * of the card type. - */ - -void rio_start_card_running(struct Host *HostP) -{ - switch (HostP->Type) { - case RIO_AT: - rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n"); - writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control); - break; - case RIO_PCI: - /* - ** PCI is much the same as MCA. Everything is once again memory - ** mapped, so we are writing to memory registers instead of io - ** ports. - */ - rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n"); - writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control); - break; - default: - rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); - break; - } - return; -} - -/* -** Load in the host boot code - load it directly onto all halted hosts -** of the correct type. -** -** Put your rubber pants on before messing with this code - even the magic -** numbers have trouble understanding what they are doing here. -*/ - -int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) -{ - struct Host *HostP; - u8 __iomem *Cad; - PARM_MAP __iomem *ParmMapP; - int RupN; - int PortN; - unsigned int host; - u8 __iomem *StartP; - u8 __iomem *DestP; - int wait_count; - u16 OldParmMap; - u16 offset; /* It is very important that this is a u16 */ - u8 *DownCode = NULL; - unsigned long flags; - - HostP = NULL; /* Assure the compiler we've initialized it */ - - - /* Walk the hosts */ - for (host = 0; host < p->RIONumHosts; host++) { - rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host); - HostP = &p->RIOHosts[host]; - - rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); - - /* Don't boot hosts already running */ - if ((HostP->Flags & RUN_STATE) != RC_WAITING) { - rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host); - continue; - } - - /* - ** Grab a pointer to the card (ioremapped) - */ - Cad = HostP->Caddr; - - /* - ** We are going to (try) and load in rbp->Count bytes. - ** The last byte will reside at p->RIOConf.HostLoadBase-1; - ** Therefore, we need to start copying at address - ** (caddr+p->RIOConf.HostLoadBase-rbp->Count) - */ - StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count]; - - rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad); - rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP); - rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); - rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); - - /* Make sure it fits */ - if (p->RIOConf.HostLoadBase < rbp->Count) { - rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n"); - p->RIOError.Error = HOST_FILE_TOO_LARGE; - func_exit(); - return -EFBIG; - } - /* - ** Ensure that the host really is stopped. - ** Disable it's external bus & twang its reset line. - */ - RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot); - - /* - ** Copy the data directly from user space to the SRAM. - ** This ain't going to be none too clever if the download - ** code is bigger than this segment. - */ - rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n"); - - /* Buffer to local memory as we want to use I/O space and - some cards only do 8 or 16 bit I/O */ - - DownCode = vmalloc(rbp->Count); - if (!DownCode) { - p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; - func_exit(); - return -ENOMEM; - } - if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) { - kfree(DownCode); - p->RIOError.Error = COPYIN_FAILED; - func_exit(); - return -EFAULT; - } - HostP->Copy(DownCode, StartP, rbp->Count); - vfree(DownCode); - - rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n"); - - /* - ** S T O P ! - ** - ** Upto this point the code has been fairly rational, and possibly - ** even straight forward. What follows is a pile of crud that will - ** magically turn into six bytes of transputer assembler. Normally - ** you would expect an array or something, but, being me, I have - ** chosen [been told] to use a technique whereby the startup code - ** will be correct if we change the loadbase for the code. Which - ** brings us onto another issue - the loadbase is the *end* of the - ** code, not the start. - ** - ** If I were you I wouldn't start from here. - */ - - /* - ** We now need to insert a short boot section into - ** the memory at the end of Sram2. This is normally (de)composed - ** of the last eight bytes of the download code. The - ** download has been assembled/compiled to expect to be - ** loaded from 0x7FFF downwards. We have loaded it - ** at some other address. The startup code goes into the small - ** ram window at Sram2, in the last 8 bytes, which are really - ** at addresses 0x7FF8-0x7FFF. - ** - ** If the loadbase is, say, 0x7C00, then we need to branch to - ** address 0x7BFE to run the host.bin startup code. We assemble - ** this jump manually. - ** - ** The two byte sequence 60 08 is loaded into memory at address - ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0, - ** which adds '0' to the .O register, complements .O, and then shifts - ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will - ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new - ** location. Now, the branch starts from the value of .PC (or .IP or - ** whatever the bloody register is called on this chip), and the .PC - ** will be pointing to the location AFTER the branch, in this case - ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8. - ** - ** A long branch is coded at 0x7FF8. This consists of loading a four - ** byte offset into .O using nfix (as above) and pfix operators. The - ** pfix operates in exactly the same way as the nfix operator, but - ** without the complement operation. The offset, of course, must be - ** relative to the address of the byte AFTER the branch instruction, - ** which will be (urm) 0x7FFC, so, our final destination of the branch - ** (loadbase-2), has to be reached from here. Imagine that the loadbase - ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which - ** is the first byte of the initial two byte short local branch of the - ** download code). - ** - ** To code a jump from 0x7FFC (which is where the branch will start - ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)= - ** 0x7BFE. - ** This will be coded as four bytes: - ** 60 2C 20 02 - ** being nfix .O+0 - ** pfix .O+C - ** pfix .O+0 - ** jump .O+2 - ** - ** The nfix operator is used, so that the startup code will be - ** compatible with the whole Tp family. (lies, damn lies, it'll never - ** work in a month of Sundays). - ** - ** The nfix nyble is the 1s complement of the nyble value you - ** want to load - in this case we wanted 'F' so we nfix loaded '0'. - */ - - - /* - ** Dest points to the top 8 bytes of Sram2. The Tp jumps - ** to 0x7FFE at reset time, and starts executing. This is - ** a short branch to 0x7FF8, where a long branch is coded. - */ - - DestP = &Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ - -#define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */ -#define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */ -#define JUMP(N) (0x00 | (N)) /* .PC = .PC + .O */ - - /* - ** 0x7FFC is the address of the location following the last byte of - ** the four byte jump instruction. - ** READ THE ABOVE COMMENTS - ** - ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about. - ** Memsize is 64K for this range of Tp, so offset is a short (unsigned, - ** cos I don't understand 2's complement). - */ - offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC; - - writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP); - writeb(PFIX((offset >> 8) & 0xF), DestP + 1); - writeb(PFIX((offset >> 4) & 0xF), DestP + 2); - writeb(JUMP(offset & 0xF), DestP + 3); - - writeb(NFIX(0), DestP + 6); - writeb(JUMP(8), DestP + 7); - - rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); - rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset); - - /* - ** Flag what is going on - */ - HostP->Flags &= ~RUN_STATE; - HostP->Flags |= RC_STARTUP; - - /* - ** Grab a copy of the current ParmMap pointer, so we - ** can tell when it has changed. - */ - OldParmMap = readw(&HostP->__ParmMapR); - - rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap); - - /* - ** And start it running (I hope). - ** As there is nothing dodgy or obscure about the - ** above code, this is guaranteed to work every time. - */ - rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); - - rio_start_card_running(HostP); - - rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n"); - - /* - ** Now, wait for upto five seconds for the Tp to setup the parmmap - ** pointer: - */ - for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) { - rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR)); - mdelay(100); - - } - - /* - ** If the parmmap pointer is unchanged, then the host code - ** has crashed & burned in a really spectacular way - */ - if (readw(&HostP->__ParmMapR) == OldParmMap) { - rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR)); - rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); - HostP->Flags &= ~RUN_STATE; - HostP->Flags |= RC_STUFFED; - RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); - continue; - } - - rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR)); - - /* - ** Well, the board thought it was OK, and setup its parmmap - ** pointer. For the time being, we will pretend that this - ** board is running, and check out what the error flag says. - */ - - /* - ** Grab a 32 bit pointer to the parmmap structure - */ - ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR)); - rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); - ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR)); - rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); - - /* - ** The links entry should be 0xFFFF; we set it up - ** with a mask to say how many PHBs to use, and - ** which links to use. - */ - if (readw(&ParmMapP->links) != 0xFFFF) { - rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); - rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links)); - HostP->Flags &= ~RUN_STATE; - HostP->Flags |= RC_STUFFED; - RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); - continue; - } - - writew(RIO_LINK_ENABLE, &ParmMapP->links); - - /* - ** now wait for the card to set all the parmmap->XXX stuff - ** this is a wait of upto two seconds.... - */ - rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime); - HostP->timeout_id = 0; - for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) { - rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n"); - mdelay(100); - } - rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n"); - - if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) { - rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); - rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); - HostP->Flags &= ~RUN_STATE; - HostP->Flags |= RC_STUFFED; - RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); - continue; - } - - rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n"); - - /* - ** It runs! It runs! - */ - rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum); - - /* - ** set the time period between interrupts. - */ - writew(p->RIOConf.Timer, &ParmMapP->timer); - - /* - ** Translate all the 16 bit pointers in the __ParmMapR into - ** 32 bit pointers for the driver in ioremap space. - */ - HostP->ParmMapP = ParmMapP; - HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); - HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups)); - HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); - HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); - - /* - ** point the UnixRups at the real Rups - */ - for (RupN = 0; RupN < MAX_RUP; RupN++) { - HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN]; - HostP->UnixRups[RupN].Id = RupN + 1; - HostP->UnixRups[RupN].BaseSysPort = NO_PORT; - spin_lock_init(&HostP->UnixRups[RupN].RupLock); - } - - for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) { - HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup; - HostP->UnixRups[RupN + MAX_RUP].Id = 0; - HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT; - spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock); - } - - /* - ** point the PortP->Phbs at the real Phbs - */ - for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) { - if (p->RIOPortp[PortN]->HostP == HostP) { - struct Port *PortP = p->RIOPortp[PortN]; - struct PHB __iomem *PhbP; - /* int oldspl; */ - - if (!PortP->Mapped) - continue; - - PhbP = &HostP->PhbP[PortP->HostPort]; - rio_spin_lock_irqsave(&PortP->portSem, flags); - - PortP->PhbP = PhbP; - - PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add)); - PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start)); - PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end)); - PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove)); - PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start)); - PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end)); - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - /* - ** point the UnixRup at the base SysPort - */ - if (!(PortN % PORTS_PER_RTA)) - HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN; - } - } - - rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n"); - /* - ** last thing - show the world that everything is in place - */ - HostP->Flags &= ~RUN_STATE; - HostP->Flags |= RC_RUNNING; - } - /* - ** MPX always uses a poller. This is actually patched into the system - ** configuration and called directly from each clock tick. - ** - */ - p->RIOPolling = 1; - - p->RIOSystemUp++; - - rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec); - func_exit(); - return 0; -} - - - -/** - * RIOBootRup - Boot an RTA - * @p: rio we are working with - * @Rup: Rup number - * @HostP: host object - * @PacketP: packet to use - * - * If we have successfully processed this boot, then - * return 1. If we havent, then return 0. - */ - -int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP) -{ - struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data; - struct PktCmd_M *PktReplyP; - struct CmdBlk *CmdBlkP; - unsigned int sequence; - - /* - ** If we haven't been told what to boot, we can't boot it. - */ - if (p->RIONumBootPkts == 0) { - rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n"); - return 0; - } - - /* - ** Special case of boot completed - if we get one of these then we - ** don't need a command block. For all other cases we do, so handle - ** this first and then get a command block, then handle every other - ** case, relinquishing the command block if disaster strikes! - */ - if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED)) - return RIOBootComplete(p, HostP, Rup, PktCmdP); - - /* - ** Try to allocate a command block. This is in kernel space - */ - if (!(CmdBlkP = RIOGetCmdBlk())) { - rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); - return 0; - } - - /* - ** Fill in the default info on the command block - */ - CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0; - CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.src_port = BOOT_RUP; - - CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; - PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data; - - /* - ** process COMMANDS on the boot rup! - */ - if (readb(&PacketP->len) & PKT_CMD_BIT) { - /* - ** We only expect one type of command - a BOOT_REQUEST! - */ - if (readb(&PktCmdP->Command) != BOOT_REQUEST) { - rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts); - RIOFreeCmdBlk(CmdBlkP); - return 1; - } - - /* - ** Build a Boot Sequence command block - ** - ** We no longer need to use "Boot Mode", we'll always allow - ** boot requests - the boot will not complete if the device - ** appears in the bindings table. - ** - ** We'll just (always) set the command field in packet reply - ** to allow an attempted boot sequence : - */ - PktReplyP->Command = BOOT_SEQUENCE; - - PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts; - PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase; - PktReplyP->BootSequence.CodeSize = p->RIOBootCount; - - CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT; - - memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4); - - rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase); - - /* - ** If this host is in slave mode, send the RTA an invalid boot - ** sequence command block to force it to kill the boot. We wait - ** for half a second before sending this packet to prevent the RTA - ** attempting to boot too often. The master host should then grab - ** the RTA and make it its own. - */ - p->RIOBooting++; - RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return 1; - } - - /* - ** It is a request for boot data. - */ - sequence = readw(&PktCmdP->Sequence); - - rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup); - - if (sequence >= p->RIONumBootPkts) { - rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts); - } - - PktReplyP->Sequence = sequence; - memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE); - CmdBlkP->Packet.len = PKT_MAX_DATA_LEN; - RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return 1; -} - -/** - * RIOBootComplete - RTA boot is done - * @p: RIO we are working with - * @HostP: Host structure - * @Rup: RUP being used - * @PktCmdP: Packet command that was used - * - * This function is called when an RTA been booted. - * If booted by a host, HostP->HostUniqueNum is the booting host. - * If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA. - * RtaUniq is the booted RTA. - */ - -static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP) -{ - struct Map *MapP = NULL; - struct Map *MapP2 = NULL; - int Flag; - int found; - int host, rta; - int EmptySlot = -1; - int entry, entry2; - char *MyType, *MyName; - unsigned int MyLink; - unsigned short RtaType; - u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); - - p->RIOBooting = 0; - - rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); - - /* - ** Determine type of unit (16/8 port RTA). - */ - - RtaType = GetUnitType(RtaUniq); - if (Rup >= (unsigned short) MAX_RUP) - rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); - else - rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); - - rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq); - - if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) { - rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); - return 1; - } - - /* - ** If this RTA has just booted an RTA which doesn't belong to this - ** system, or the system is in slave mode, do not attempt to create - ** a new table entry for it. - */ - - if (!RIOBootOk(p, HostP, RtaUniq)) { - MyLink = readb(&PktCmdP->LinkNum); - if (Rup < (unsigned short) MAX_RUP) { - /* - ** RtaUniq was clone booted (by this RTA). Instruct this RTA - ** to hold off further attempts to boot on this link for 30 - ** seconds. - */ - if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) { - rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink); - } - } else - /* - ** RtaUniq was booted by this host. Set the booting link - ** to hold off for 30 seconds to give another unit a - ** chance to boot it. - */ - writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot); - rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); - return 1; - } - - /* - ** Check for a SLOT_IN_USE entry for this RTA attached to the - ** current host card in the driver table. - ** - ** If it exists, make a note that we have booted it. Other parts of - ** the driver are interested in this information at a later date, - ** in particular when the booting RTA asks for an ID for this unit, - ** we must have set the BOOTED flag, and the NEWBOOT flag is used - ** to force an open on any ports that where previously open on this - ** unit. - */ - for (entry = 0; entry < MAX_RUP; entry++) { - unsigned int sysport; - - if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { - HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT; - if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) { - if (sysport < p->RIOFirstPortsBooted) - p->RIOFirstPortsBooted = sysport; - if (sysport > p->RIOLastPortsBooted) - p->RIOLastPortsBooted = sysport; - /* - ** For a 16 port RTA, check the second bank of 8 ports - */ - if (RtaType == TYPE_RTA16) { - entry2 = HostP->Mapping[entry].ID2 - 1; - HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT; - sysport = HostP->Mapping[entry2].SysPort; - if (sysport < p->RIOFirstPortsBooted) - p->RIOFirstPortsBooted = sysport; - if (sysport > p->RIOLastPortsBooted) - p->RIOLastPortsBooted = sysport; - } - } - if (RtaType == TYPE_RTA16) - rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1); - else - rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1); - return 1; - } - } - - rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n"); - - if (Rup >= (unsigned short) MAX_RUP) { - /* - ** It was a host that did the booting - */ - MyType = "Host"; - MyName = HostP->Name; - } else { - /* - ** It was an RTA that did the booting - */ - MyType = "RTA"; - MyName = HostP->Mapping[Rup].Name; - } - MyLink = readb(&PktCmdP->LinkNum); - - /* - ** There is no SLOT_IN_USE entry for this RTA attached to the current - ** host card in the driver table. - ** - ** Check for a SLOT_TENTATIVE entry for this RTA attached to the - ** current host card in the driver table. - ** - ** If we find one, then we re-use that slot. - */ - for (entry = 0; entry < MAX_RUP; entry++) { - if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { - if (RtaType == TYPE_RTA16) { - entry2 = HostP->Mapping[entry].ID2 - 1; - if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq)) - rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2); - else - continue; - } else - rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry); - if (!p->RIONoMessage) - printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); - return 1; - } - } - - /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another - ** host for this RTA in the driver table. - ** - ** For a SLOT_IN_USE entry on another host, we need to delete the RTA - ** entry from the other host and add it to this host (using some of - ** the functions from table.c which do this). - ** For a SLOT_TENTATIVE entry on another host, we must cope with the - ** following scenario: - ** - ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry - ** in table) - ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE - ** entries) - ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE) - ** + Unplug RTA and plug back into host A. - ** + Configure RTA on host A. We now have the same RTA configured - ** with different ports on two different hosts. - */ - rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq); - found = 0; - Flag = 0; /* Convince the compiler this variable is initialized */ - for (host = 0; !found && (host < p->RIONumHosts); host++) { - for (rta = 0; rta < MAX_RUP; rta++) { - if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) { - Flag = p->RIOHosts[host].Mapping[rta].Flags; - MapP = &p->RIOHosts[host].Mapping[rta]; - if (RtaType == TYPE_RTA16) { - MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1]; - rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name); - } else - rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name); - found = 1; - break; - } - } - } - - /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on - ** another host for this RTA in the driver table... - ** - ** Check for a SLOT_IN_USE entry for this RTA in the config table. - */ - if (!MapP) { - rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq); - for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) { - rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum); - - if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) { - MapP = &p->RIOSavedTable[rta]; - Flag = p->RIOSavedTable[rta].Flags; - if (RtaType == TYPE_RTA16) { - for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) { - if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq) - break; - } - MapP2 = &p->RIOSavedTable[entry2]; - rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2); - } else - rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta); - break; - } - } - } - - /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** We may have found a SLOT_IN_USE entry on another host for this - ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry - ** on another host for this RTA in the driver table. - ** - ** Check the driver table for room to fit this newly discovered RTA. - ** RIOFindFreeID() first looks for free slots and if it does not - ** find any free slots it will then attempt to oust any - ** tentative entry in the table. - */ - EmptySlot = 1; - if (RtaType == TYPE_RTA16) { - if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) { - RIODefaultName(p, HostP, entry); - rio_fill_host_slot(entry, entry2, RtaUniq, HostP); - EmptySlot = 0; - } - } else { - if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) { - RIODefaultName(p, HostP, entry); - rio_fill_host_slot(entry, 0, RtaUniq, HostP); - EmptySlot = 0; - } - } - - /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** If we found a SLOT_IN_USE entry on another host for this - ** RTA in the config or driver table, and there are enough free - ** slots in the driver table, then we need to move it over and - ** delete it from the other host. - ** If we found a SLOT_TENTATIVE entry on another host for this - ** RTA in the driver table, just delete the other host entry. - */ - if (EmptySlot == 0) { - if (MapP) { - if (Flag & SLOT_IN_USE) { - rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n"); - HostP->Mapping[entry].SysPort = MapP->SysPort; - memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN); - HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; - RIOReMapPorts(p, HostP, &HostP->Mapping[entry]); - if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted) - p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; - if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted) - p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort; - rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name); - } else { - rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n"); - HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; - } - if (RtaType == TYPE_RTA16) { - if (Flag & SLOT_IN_USE) { - HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; - HostP->Mapping[entry2].SysPort = MapP2->SysPort; - /* - ** Map second block of ttys for 16 port RTA - */ - RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]); - if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted) - p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort; - if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted) - p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort; - rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name); - } else - HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; - memset(MapP2, 0, sizeof(struct Map)); - } - memset(MapP, 0, sizeof(struct Map)); - if (!p->RIONoMessage) - printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A'); - } else if (!p->RIONoMessage) - printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); - RIOSetChange(p); - return 1; - } - - /* - ** There is no room in the driver table to make an entry for the - ** booted RTA. Keep a note of its Uniq Num in the overflow table, - ** so we can ignore it's ID requests. - */ - if (!p->RIONoMessage) - printk("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A'); - for (entry = 0; entry < HostP->NumExtraBooted; entry++) { - if (HostP->ExtraUnits[entry] == RtaUniq) { - /* - ** already got it! - */ - return 1; - } - } - /* - ** If there is room, add the unit to the list of extras - */ - if (HostP->NumExtraBooted < MAX_EXTRA_UNITS) - HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq; - return 1; -} - - -/* -** If the RTA or its host appears in the RIOBindTab[] structure then -** we mustn't boot the RTA and should return 0. -** This operation is slightly different from the other drivers for RIO -** in that this is designed to work with the new utilities -** not config.rio and is FAR SIMPLER. -** We no longer support the RIOBootMode variable. It is all done from the -** "boot/noboot" field in the rio.cf file. -*/ -int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq) -{ - int Entry; - unsigned int HostUniq = HostP->UniqueNum; - - /* - ** Search bindings table for RTA or its parent. - ** If it exists, return 0, else 1. - */ - for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) { - if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq)) - return 0; - } - return 1; -} - -/* -** Make an empty slot tentative. If this is a 16 port RTA, make both -** slots tentative, and the second one RTA_SECOND_SLOT as well. -*/ - -void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host) -{ - int link; - - rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq); - - host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); - host->Mapping[entry].SysPort = NO_PORT; - host->Mapping[entry].RtaUniqueNum = rta_uniq; - host->Mapping[entry].HostUniqueNum = host->UniqueNum; - host->Mapping[entry].ID = entry + 1; - host->Mapping[entry].ID2 = 0; - if (entry2) { - host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT); - host->Mapping[entry2].SysPort = NO_PORT; - host->Mapping[entry2].RtaUniqueNum = rta_uniq; - host->Mapping[entry2].HostUniqueNum = host->UniqueNum; - host->Mapping[entry2].Name[0] = '\0'; - host->Mapping[entry2].ID = entry2 + 1; - host->Mapping[entry2].ID2 = entry + 1; - host->Mapping[entry].ID2 = entry2 + 1; - } - /* - ** Must set these up, so that utilities show - ** topology of 16 port RTAs correctly - */ - for (link = 0; link < LINKS_PER_UNIT; link++) { - host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT; - host->Mapping[entry].Topology[link].Link = NO_LINK; - if (entry2) { - host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT; - host->Mapping[entry2].Topology[link].Link = NO_LINK; - } - } -} diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c deleted file mode 100644 index f121357e5af0..000000000000 --- a/drivers/char/rio/riocmd.c +++ /dev/null @@ -1,939 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** ported from the existing SCO driver source -** - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riocmd.c -** SID : 1.2 -** Last Modified : 11/6/98 10:33:41 -** Retrieved : 11/6/98 10:33:49 -** -** ident @(#)riocmd.c 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" - - -static struct IdentifyRta IdRta; -static struct KillNeighbour KillUnit; - -int RIOFoadRta(struct Host *HostP, struct Map *MapP) -{ - struct CmdBlk *CmdBlkP; - - rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n"); - - CmdBlkP = RIOGetCmdBlk(); - - if (!CmdBlkP) { - rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n"); - return -ENXIO; - } - - CmdBlkP->Packet.dest_unit = MapP->ID; - CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.src_port = BOOT_RUP; - CmdBlkP->Packet.len = 0x84; - CmdBlkP->Packet.data[0] = IFOAD; - CmdBlkP->Packet.data[1] = 0; - CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF; - CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF; - - if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n"); - return -EIO; - } - return 0; -} - -int RIOZombieRta(struct Host *HostP, struct Map *MapP) -{ - struct CmdBlk *CmdBlkP; - - rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n"); - - CmdBlkP = RIOGetCmdBlk(); - - if (!CmdBlkP) { - rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n"); - return -ENXIO; - } - - CmdBlkP->Packet.dest_unit = MapP->ID; - CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.src_port = BOOT_RUP; - CmdBlkP->Packet.len = 0x84; - CmdBlkP->Packet.data[0] = ZOMBIE; - CmdBlkP->Packet.data[1] = 0; - CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF; - CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF; - - if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n"); - return -EIO; - } - return 0; -} - -int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP)) -{ - unsigned int Host; - - rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func); - - if (!RtaUnique) - return (0); - - for (Host = 0; Host < p->RIONumHosts; Host++) { - unsigned int Rta; - struct Host *HostP = &p->RIOHosts[Host]; - - for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) { - struct Map *MapP = &HostP->Mapping[Rta]; - - if (MapP->RtaUniqueNum == RtaUnique) { - uint Link; - - /* - ** now, lets just check we have a route to it... - ** IF the routing stuff is working, then one of the - ** topology entries for this unit will have a legit - ** route *somewhere*. We care not where - if its got - ** any connections, we can get to it. - */ - for (Link = 0; Link < LINKS_PER_UNIT; Link++) { - if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) { - /* - ** Its worth trying the operation... - */ - return (*func) (HostP, MapP); - } - } - } - } - } - return -ENXIO; -} - - -int RIOIdentifyRta(struct rio_info *p, void __user * arg) -{ - unsigned int Host; - - if (copy_from_user(&IdRta, arg, sizeof(IdRta))) { - rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - - for (Host = 0; Host < p->RIONumHosts; Host++) { - unsigned int Rta; - struct Host *HostP = &p->RIOHosts[Host]; - - for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) { - struct Map *MapP = &HostP->Mapping[Rta]; - - if (MapP->RtaUniqueNum == IdRta.RtaUnique) { - uint Link; - /* - ** now, lets just check we have a route to it... - ** IF the routing stuff is working, then one of the - ** topology entries for this unit will have a legit - ** route *somewhere*. We care not where - if its got - ** any connections, we can get to it. - */ - for (Link = 0; Link < LINKS_PER_UNIT; Link++) { - if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) { - /* - ** Its worth trying the operation... - */ - struct CmdBlk *CmdBlkP; - - rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n"); - - CmdBlkP = RIOGetCmdBlk(); - - if (!CmdBlkP) { - rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n"); - return -ENXIO; - } - - CmdBlkP->Packet.dest_unit = MapP->ID; - CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.src_port = BOOT_RUP; - CmdBlkP->Packet.len = 0x84; - CmdBlkP->Packet.data[0] = IDENTIFY; - CmdBlkP->Packet.data[1] = 0; - CmdBlkP->Packet.data[2] = IdRta.ID; - - if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n"); - return -EIO; - } - return 0; - } - } - } - } - } - return -ENOENT; -} - - -int RIOKillNeighbour(struct rio_info *p, void __user * arg) -{ - uint Host; - uint ID; - struct Host *HostP; - struct CmdBlk *CmdBlkP; - - rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n"); - - if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) { - rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - - if (KillUnit.Link > 3) - return -ENXIO; - - CmdBlkP = RIOGetCmdBlk(); - - if (!CmdBlkP) { - rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n"); - return -ENXIO; - } - - CmdBlkP->Packet.dest_unit = 0; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_port = BOOT_RUP; - CmdBlkP->Packet.len = 0x84; - CmdBlkP->Packet.data[0] = UFOAD; - CmdBlkP->Packet.data[1] = KillUnit.Link; - CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF; - CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF; - - for (Host = 0; Host < p->RIONumHosts; Host++) { - ID = 0; - HostP = &p->RIOHosts[Host]; - - if (HostP->UniqueNum == KillUnit.UniqueNum) { - if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); - return -EIO; - } - return 0; - } - - for (ID = 0; ID < RTAS_PER_HOST; ID++) { - if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) { - CmdBlkP->Packet.dest_unit = ID + 1; - if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); - return -EIO; - } - return 0; - } - } - } - RIOFreeCmdBlk(CmdBlkP); - return -ENXIO; -} - -int RIOSuspendBootRta(struct Host *HostP, int ID, int Link) -{ - struct CmdBlk *CmdBlkP; - - rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link); - - CmdBlkP = RIOGetCmdBlk(); - - if (!CmdBlkP) { - rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n"); - return -ENXIO; - } - - CmdBlkP->Packet.dest_unit = ID; - CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.src_port = BOOT_RUP; - CmdBlkP->Packet.len = 0x84; - CmdBlkP->Packet.data[0] = IWAIT; - CmdBlkP->Packet.data[1] = Link; - CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF; - CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF; - - if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n"); - return -EIO; - } - return 0; -} - -int RIOFoadWakeup(struct rio_info *p) -{ - int port; - struct Port *PortP; - unsigned long flags; - - for (port = 0; port < RIO_PORTS; port++) { - PortP = p->RIOPortp[port]; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->Config = 0; - PortP->State = 0; - PortP->InUse = NOT_INUSE; - PortP->PortState = 0; - PortP->FlushCmdBodge = 0; - PortP->ModemLines = 0; - PortP->ModemState = 0; - PortP->CookMode = 0; - PortP->ParamSem = 0; - PortP->Mapped = 0; - PortP->WflushFlag = 0; - PortP->MagicFlags = 0; - PortP->RxDataStart = 0; - PortP->TxBufferIn = 0; - PortP->TxBufferOut = 0; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - } - return (0); -} - -/* -** Incoming command on the COMMAND_RUP to be processed. -*/ -static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP) -{ - struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data; - struct Port *PortP; - struct UnixRup *UnixRupP; - unsigned short SysPort; - unsigned short ReportedModemStatus; - unsigned short rup; - unsigned short subCommand; - unsigned long flags; - - func_enter(); - - /* - ** 16 port RTA note: - ** Command rup packets coming from the RTA will have pkt->data[1] (which - ** translates to PktCmdP->PhbNum) set to the host port number for the - ** particular unit. To access the correct BaseSysPort for a 16 port RTA, - ** we can use PhbNum to get the rup number for the appropriate 8 port - ** block (for the first block, this should be equal to 'Rup'). - */ - rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA; - UnixRupP = &HostP->UnixRups[rup]; - SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA); - rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); - - if (UnixRupP->BaseSysPort == NO_PORT) { - rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); - rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); - rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); - rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); - - if (Rup < (unsigned short) MAX_RUP) { - rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); - } else - rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); - - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port)); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port)); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len)); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control)); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum)); - rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command)); - return 1; - } - PortP = p->RIOPortp[SysPort]; - rio_spin_lock_irqsave(&PortP->portSem, flags); - switch (readb(&PktCmdP->Command)) { - case RIOC_BREAK_RECEIVED: - rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n"); - /* If the current line disc. is not multi-threading and - the current processor is not the default, reset rup_intr - and return 0 to ensure that the command packet is - not freed. */ - /* Call tmgr HANGUP HERE */ - /* Fix this later when every thing works !!!! RAMRAJ */ - gs_got_break(&PortP->gs); - break; - - case RIOC_COMPLETE: - rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts); - subCommand = 1; - switch (readb(&PktCmdP->SubCommand)) { - case RIOC_MEMDUMP: - rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr)); - break; - case RIOC_READ_REGISTER: - rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr)); - p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST); - break; - default: - subCommand = 0; - break; - } - if (subCommand) - break; - rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState); - if (PortP->PortState != readb(&PktCmdP->PortStatus)) { - rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n"); - PortP->PortState = readb(&PktCmdP->PortStatus); - /* What should we do here ... - wakeup( &PortP->PortState ); - */ - } else - rio_dprintk(RIO_DEBUG_CMD, "No change\n"); - - /* FALLTHROUGH */ - case RIOC_MODEM_STATUS: - /* - ** Knock out the tbusy and tstop bits, as these are not relevant - ** to the check for modem status change (they're just there because - ** it's a convenient place to put them!). - */ - ReportedModemStatus = readb(&PktCmdP->ModemStatus); - if ((PortP->ModemState & RIOC_MSVR1_HOST) == - (ReportedModemStatus & RIOC_MSVR1_HOST)) { - rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); - /* - ** Update ModemState just in case tbusy or tstop states have - ** changed. - */ - PortP->ModemState = ReportedModemStatus; - } else { - rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus); - PortP->ModemState = ReportedModemStatus; -#ifdef MODEM_SUPPORT - if (PortP->Mapped) { - /***********************************************************\ - ************************************************************* - *** *** - *** M O D E M S T A T E C H A N G E *** - *** *** - ************************************************************* - \***********************************************************/ - /* - ** If the device is a modem, then check the modem - ** carrier. - */ - if (PortP->gs.port.tty == NULL) - break; - if (PortP->gs.port.tty->termios == NULL) - break; - - if (!(PortP->gs.port.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) { - - rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n"); - /* - ** Is there a carrier? - */ - if (PortP->ModemState & RIOC_MSVR1_CD) { - /* - ** Has carrier just appeared? - */ - if (!(PortP->State & RIO_CARR_ON)) { - rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n"); - PortP->State |= RIO_CARR_ON; - /* - ** wakeup anyone in WOPEN - */ - if (PortP->State & (PORT_ISOPEN | RIO_WOPEN)) - wake_up_interruptible(&PortP->gs.port.open_wait); - } - } else { - /* - ** Has carrier just dropped? - */ - if (PortP->State & RIO_CARR_ON) { - if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN)) - tty_hangup(PortP->gs.port.tty); - PortP->State &= ~RIO_CARR_ON; - rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n"); - } - } - } - } -#endif - } - break; - - default: - rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts); - break; - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - - func_exit(); - - return 1; -} - -/* -** The command mechanism: -** Each rup has a chain of commands associated with it. -** This chain is maintained by routines in this file. -** Periodically we are called and we run a quick check of all the -** active chains to determine if there is a command to be executed, -** and if the rup is ready to accept it. -** -*/ - -/* -** Allocate an empty command block. -*/ -struct CmdBlk *RIOGetCmdBlk(void) -{ - struct CmdBlk *CmdBlkP; - - CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC); - return CmdBlkP; -} - -/* -** Return a block to the head of the free list. -*/ -void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP) -{ - kfree(CmdBlkP); -} - -/* -** attach a command block to the list of commands to be performed for -** a given rup. -*/ -int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) -{ - struct CmdBlk **Base; - struct UnixRup *UnixRupP; - unsigned long flags; - - if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) { - rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup); - RIOFreeCmdBlk(CmdBlkP); - return RIO_FAIL; - } - - UnixRupP = &HostP->UnixRups[Rup]; - - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - - /* - ** If the RUP is currently inactive, then put the request - ** straight on the RUP.... - */ - if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) - : 1)) { - rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]); - - /* - ** Whammy! blat that pack! - */ - HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); - - /* - ** place command packet on the pending position. - */ - UnixRupP->CmdPendingP = CmdBlkP; - - /* - ** set the command register - */ - writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); - - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - - return 0; - } - rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n"); - - if (UnixRupP->CmdsWaitingP != NULL) - rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n"); - if (UnixRupP->CmdPendingP != NULL) - rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n"); - if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE) - rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); - - Base = &UnixRupP->CmdsWaitingP; - - rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base); - - while (*Base) { - rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base); - Base = &((*Base)->NextP); - rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base); - } - - rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base); - - *Base = CmdBlkP; - - CmdBlkP->NextP = NULL; - - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - - return 0; -} - -/* -** Here we go - if there is an empty rup, fill it! -** must be called at splrio() or higher. -*/ -void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) -{ - struct CmdBlk *CmdBlkP; - struct UnixRup *UnixRupP; - struct PKT __iomem *PacketP; - unsigned short Rup; - unsigned long flags; - - - Rup = MAX_RUP + LINKS_PER_UNIT; - - do { /* do this loop for each RUP */ - /* - ** locate the rup we are processing & lock it - */ - UnixRupP = &HostP->UnixRups[--Rup]; - - spin_lock_irqsave(&UnixRupP->RupLock, flags); - - /* - ** First check for incoming commands: - */ - if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { - int FreeMe; - - PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); - - switch (readb(&PacketP->dest_port)) { - case BOOT_RUP: - rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0])); - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - FreeMe = RIOBootRup(p, Rup, HostP, PacketP); - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - break; - - case COMMAND_RUP: - /* - ** Free the RUP lock as loss of carrier causes a - ** ttyflush which will (eventually) call another - ** routine that uses the RUP lock. - */ - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - FreeMe = RIOCommandRup(p, Rup, HostP, PacketP); - if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) { - rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6]))); - rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32); - } - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - break; - - case ROUTE_RUP: - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - FreeMe = RIORouteRup(p, Rup, HostP, PacketP); - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - break; - - default: - rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port)); - FreeMe = 1; - break; - } - - if (FreeMe) { - rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n"); - put_free_end(HostP, PacketP); - - writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol); - - if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) { - rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup); - writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake); - } - } - } - - /* - ** IF a command was running on the port, - ** and it has completed, then tidy it up. - */ - if ((CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ - (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { - /* - ** we are idle. - ** there is a command in pending. - ** Therefore, this command has finished. - ** So, wakeup whoever is waiting for it (and tell them - ** what happened). - */ - if (CmdBlkP->Packet.dest_port == BOOT_RUP) - rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]); - - rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP); - - /* - ** Clear the Rup lock to prevent mutual exclusion. - */ - if (CmdBlkP->PostFuncP) { - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP); - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - } - - /* - ** ....clear the pending flag.... - */ - UnixRupP->CmdPendingP = NULL; - - /* - ** ....and return the command block to the freelist. - */ - RIOFreeCmdBlk(CmdBlkP); - } - - /* - ** If there is a command for this rup, and the rup - ** is idle, then process the command - */ - if ((CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ - (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { - /* - ** if the pre-function is non-zero, call it. - ** If it returns RIO_FAIL then don't - ** send this command yet! - */ - if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) { - rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP); - } else { - rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]); - /* - ** Whammy! blat that pack! - */ - HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); - - /* - ** remove the command from the rup command queue... - */ - UnixRupP->CmdsWaitingP = CmdBlkP->NextP; - - /* - ** ...and place it on the pending position. - */ - UnixRupP->CmdPendingP = CmdBlkP; - - /* - ** set the command register - */ - writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); - - /* - ** the command block will be freed - ** when the command has been processed. - */ - } - } - spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - } while (Rup); -} - -int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP) -{ - struct Port *PortP = (struct Port *) iPortP; - unsigned long flags; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->WflushFlag++; - PortP->MagicFlags |= MAGIC_FLUSH; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return RIOUnUse(iPortP, CmdBlkP); -} - -int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP) -{ - struct Port *PortP = (struct Port *) iPortP; - struct PKT __iomem *PacketP; - unsigned long flags; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - while (can_remove_receive(&PacketP, PortP)) { - remove_receive(PortP); - put_free_end(PortP->HostP, PacketP); - } - - if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) { - /* - ** MAGIC! (Basically, handshake the RX buffer, so that - ** the RTAs upstream can be re-enabled.) - */ - rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n"); - writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return RIOUnUse(iPortP, CmdBlkP); -} - -int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) -{ - struct Port *PortP = (struct Port *) iPortP; - unsigned long flags; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n"); - - if (PortP->InUse) { - if (--PortP->InUse != NOT_INUSE) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - } - } - /* - ** While PortP->InUse is set (i.e. a preemptive command has been sent to - ** the RTA and is awaiting completion), any transmit data is prevented from - ** being transferred from the write queue into the transmit packets - ** (add_transmit) and no furthur transmit interrupt will be sent for that - ** data. The next interrupt will occur up to 500ms later (RIOIntr is called - ** twice a second as a saftey measure). This was the case when kermit was - ** used to send data into a RIO port. After each packet was sent, TCFLSH - ** was called to flush the read queue preemptively. PortP->InUse was - ** incremented, thereby blocking the 6 byte acknowledgement packet - ** transmitted back. This acknowledgment hung around for 500ms before - ** being sent, thus reducing input performance substantially!. - ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data - ** hanging around in the transmit buffer is sent immediately. - */ - writew(1, &PortP->HostP->ParmMapP->tx_intr); - /* What to do here .. - wakeup( (caddr_t)&(PortP->InUse) ); - */ - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; -} - -/* -** -** How to use this file: -** -** To send a command down a rup, you need to allocate a command block, fill -** in the packet information, fill in the command number, fill in the pre- -** and post- functions and arguments, and then add the command block to the -** queue of command blocks for the port in question. When the port is idle, -** then the pre-function will be called. If this returns RIO_FAIL then the -** command will be re-queued and tried again at a later date (probably in one -** clock tick). If the pre-function returns NOT RIO_FAIL, then the command -** packet will be queued on the RUP, and the txcontrol field set to the -** command number. When the txcontrol field has changed from being the -** command number, then the post-function will be called, with the argument -** specified earlier, a pointer to the command block, and the value of -** txcontrol. -** -** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer -** to the command block structure allocated, or NULL if there aren't any. -** The block will have been zeroed for you. -** -** The structure has the following fields: -** -** struct CmdBlk -** { -** struct CmdBlk *NextP; ** Pointer to next command block ** -** struct PKT Packet; ** A packet, to copy to the rup ** -** int (*PreFuncP)(); ** The func to call to check if OK ** -** int PreArg; ** The arg for the func ** -** int (*PostFuncP)(); ** The func to call when completed ** -** int PostArg; ** The arg for the func ** -** }; -** -** You need to fill in ALL fields EXCEPT NextP, which is used to link the -** blocks together either on the free list or on the Rup list. -** -** Packet is an actual packet structure to be filled in with the packet -** information associated with the command. You need to fill in everything, -** as the command processor doesn't process the command packet in any way. -** -** The PreFuncP is called before the packet is enqueued on the host rup. -** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must -** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL -** if the packet is NOT to be queued. -** -** The PostFuncP is called when the command has completed. It is called -** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected -** to return a value. PostFuncP does NOT need to free the command block, -** as this happens automatically after PostFuncP returns. -** -** Once the command block has been filled in, it is attached to the correct -** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is -** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer -** to it!), and CmdBlkP is the pointer to the command block allocated using -** RIOGetCmdBlk(). -** -*/ diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c deleted file mode 100644 index 780506326a73..000000000000 --- a/drivers/char/rio/rioctrl.c +++ /dev/null @@ -1,1504 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioctrl.c -** SID : 1.3 -** Last Modified : 11/6/98 10:33:42 -** Retrieved : 11/6/98 10:33:49 -** -** ident @(#)rioctrl.c 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" - - -static struct LpbReq LpbReq; -static struct RupReq RupReq; -static struct PortReq PortReq; -static struct HostReq HostReq; /* oh really? global? and no locking? */ -static struct HostDpRam HostDpRam; -static struct DebugCtrl DebugCtrl; -static struct Map MapEnt; -static struct PortSetup PortSetup; -static struct DownLoad DownLoad; -static struct SendPack SendPack; -/* static struct StreamInfo StreamInfo; */ -/* static char modemtable[RIO_PORTS]; */ -static struct SpecialRupCmd SpecialRupCmd; -static struct PortParams PortParams; -static struct portStats portStats; - -static struct SubCmdStruct { - ushort Host; - ushort Rup; - ushort Port; - ushort Addr; -} SubCmd; - -struct PortTty { - uint port; - struct ttystatics Tty; -}; - -static struct PortTty PortTty; -typedef struct ttystatics TERMIO; - -/* -** This table is used when the config.rio downloads bin code to the -** driver. We index the table using the product code, 0-F, and call -** the function pointed to by the entry, passing the information -** about the boot. -** The RIOBootCodeUNKNOWN entry is there to politely tell the calling -** process to bog off. -*/ -static int - (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = { - /* 0 */ RIOBootCodeHOST, - /* Host Card */ - /* 1 */ RIOBootCodeRTA, - /* RTA */ -}; - -#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff)) - -static int copy_from_io(void __user *to, void __iomem *from, size_t size) -{ - void *buf = kmalloc(size, GFP_KERNEL); - int res = -ENOMEM; - if (buf) { - rio_memcpy_fromio(buf, from, size); - res = copy_to_user(to, buf, size); - kfree(buf); - } - return res; -} - -int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su) -{ - uint Host; /* leave me unsigned! */ - uint port; /* and me! */ - struct Host *HostP; - ushort loop; - int Entry; - struct Port *PortP; - struct PKT __iomem *PacketP; - int retval = 0; - unsigned long flags; - void __user *argp = (void __user *)arg; - - func_enter(); - - /* Confuse the compiler to think that we've initialized these */ - Host = 0; - PortP = NULL; - - rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp); - - switch (cmd) { - /* - ** RIO_SET_TIMER - ** - ** Change the value of the host card interrupt timer. - ** If the host card number is -1 then all host cards are changed - ** otherwise just the specified host card will be changed. - */ - case RIO_SET_TIMER: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg); - { - int host, value; - host = (arg >> 16) & 0x0000FFFF; - value = arg & 0x0000ffff; - if (host == -1) { - for (host = 0; host < p->RIONumHosts; host++) { - if (p->RIOHosts[host].Flags == RC_RUNNING) { - writew(value, &p->RIOHosts[host].ParmMapP->timer); - } - } - } else if (host >= p->RIONumHosts) { - return -EINVAL; - } else { - if (p->RIOHosts[host].Flags == RC_RUNNING) { - writew(value, &p->RIOHosts[host].ParmMapP->timer); - } - } - } - return 0; - - case RIO_FOAD_RTA: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); - return RIOCommandRta(p, arg, RIOFoadRta); - - case RIO_ZOMBIE_RTA: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); - return RIOCommandRta(p, arg, RIOZombieRta); - - case RIO_IDENTIFY_RTA: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); - return RIOIdentifyRta(p, argp); - - case RIO_KILL_NEIGHBOUR: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n"); - return RIOKillNeighbour(p, argp); - - case SPECIAL_RUP_CMD: - { - struct CmdBlk *CmdBlkP; - - rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); - if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) { - rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - CmdBlkP = RIOGetCmdBlk(); - if (!CmdBlkP) { - rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n"); - return -ENXIO; - } - CmdBlkP->Packet = SpecialRupCmd.Packet; - if (SpecialRupCmd.Host >= p->RIONumHosts) - SpecialRupCmd.Host = 0; - rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum); - if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) { - printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n"); - } - return 0; - } - - case RIO_DEBUG_MEM: - return -EPERM; - - case RIO_ALL_MODEM: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n"); - p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; - return -EINVAL; - - case RIO_GET_TABLE: - /* - ** Read the routing table from the device driver to user space - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n"); - - if ((retval = RIOApel(p)) != 0) - return retval; - - if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - - { - int entry; - rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n"); - for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { - if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0)) - continue; - - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link); - rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name); - } - rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n"); - } - p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */ - return 0; - - case RIO_PUT_TABLE: - /* - ** Write the routing table to the device driver from user space - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n"); - - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } -/* -*********************************** - { - int entry; - rio_dprint(RIO_DEBUG_CTRL, ("*****\nMAP ENTRIES\n") ); - for ( entry=0; entryRIOConnectTable[entry].HostUniqueNum ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) ); - } - rio_dprint(RIO_DEBUG_CTRL, ("*****\nEND MAP ENTRIES\n") ); - } -*********************************** -*/ - return RIONewTable(p); - - case RIO_GET_BINDINGS: - /* - ** Send bindings table, containing unique numbers of RTAs owned - ** by this system to user space - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n"); - - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return 0; - - case RIO_PUT_BINDINGS: - /* - ** Receive a bindings table, containing unique numbers of RTAs owned - ** by this system - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n"); - - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - return 0; - - case RIO_BIND_RTA: - { - int EmptySlot = -1; - /* - ** Bind this RTA to host, so that it will be booted by - ** host in 'boot owned RTAs' mode. - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n"); - - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) { - if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L)) - EmptySlot = Entry; - else if (p->RIOBindTab[Entry] == arg) { - /* - ** Already exists - delete - */ - p->RIOBindTab[Entry] = 0L; - rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg); - return 0; - } - } - /* - ** Dosen't exist - add - */ - if (EmptySlot != -1) { - p->RIOBindTab[EmptySlot] = arg; - rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg); - } else { - rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg); - return -ENOMEM; - } - return 0; - } - - case RIO_RESUME: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n"); - port = arg; - if ((port < 0) || (port > 511)) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - PortP = p->RIOPortp[port]; - if (!PortP->Mapped) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port); - p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; - return -EINVAL; - } - if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port); - return -EINVAL; - } - - rio_spin_lock_irqsave(&PortP->portSem, flags); - if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) == - RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EBUSY; - } else { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port); - PortP->State |= RIO_BUSY; - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_ASSIGN_RTA: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n"); - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { - rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - return RIOAssignRta(p, &MapEnt); - - case RIO_CHANGE_NAME: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n"); - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { - rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - return RIOChangeName(p, &MapEnt); - - case RIO_DELETE_RTA: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n"); - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { - rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - return RIODeleteRta(p, &MapEnt); - - case RIO_QUICK_CHECK: - if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return 0; - - case RIO_LAST_ERROR: - if (copy_to_user(argp, &p->RIOError, sizeof(struct Error))) - return -EFAULT; - return 0; - - case RIO_GET_LOG: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n"); - return -EINVAL; - - case RIO_GET_MODTYPE: - if (copy_from_user(&port, argp, sizeof(unsigned int))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port); - if (port < 0 || port > 511) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - PortP = (p->RIOPortp[port]); - if (!PortP->Mapped) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port); - p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; - return -EINVAL; - } - /* - ** Return module type of port - */ - port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes; - if (copy_to_user(argp, &port, sizeof(unsigned int))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return (0); - case RIO_BLOCK_OPENS: - rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n"); - for (Entry = 0; Entry < RIO_PORTS; Entry++) { - rio_spin_lock_irqsave(&PortP->portSem, flags); - p->RIOPortp[Entry]->WaitUntilBooted = 1; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - } - return 0; - - case RIO_SETUP_PORTS: - rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n"); - if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) { - p->RIOError.Error = COPYIN_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "EFAULT"); - return -EFAULT; - } - if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - rio_dprintk(RIO_DEBUG_CTRL, "ENXIO"); - return -ENXIO; - } - if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) { - p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE; - rio_dprintk(RIO_DEBUG_CTRL, "EINVAL"); - return -EINVAL; - } - if (!p->RIOPortp) { - printk(KERN_ERR "rio: No p->RIOPortp array!\n"); - rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n"); - return -EIO; - } - rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To); - for (loop = PortSetup.From; loop <= PortSetup.To; loop++) { - rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop); - } - rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop); - rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval); - return retval; - - case RIO_GET_PORT_SETUP: - rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n"); - if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (PortSetup.From >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - - port = PortSetup.To = PortSetup.From; - PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0; - PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0; - PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0; - PortSetup.Store = p->RIOPortp[port]->Store; - PortSetup.Lock = p->RIOPortp[port]->Lock; - PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps; - memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN); - memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN); - PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; - PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; - - if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_GET_PORT_PARAMS: - rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n"); - if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (PortParams.Port >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - PortP = (p->RIOPortp[PortParams.Port]); - PortParams.Config = PortP->Config; - PortParams.State = PortP->State; - rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); - - if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_GET_PORT_TTY: - rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n"); - if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (PortTty.port >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - - rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); - PortP = (p->RIOPortp[PortTty.port]); - if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_SET_PORT_TTY: - if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port); - if (PortTty.port >= (ushort) RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - PortP = (p->RIOPortp[PortTty.port]); - RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM, - OK_TO_SLEEP); - return retval; - - case RIO_SET_PORT_PARAMS: - rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n"); - if (copy_from_user(&PortParams, argp, sizeof(PortParams))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (PortParams.Port >= (ushort) RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - PortP = (p->RIOPortp[PortParams.Port]); - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->Config = PortParams.Config; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_GET_PORT_STATS: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n"); - if (copy_from_user(&portStats, argp, sizeof(struct portStats))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (portStats.port < 0 || portStats.port >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - PortP = (p->RIOPortp[portStats.port]); - portStats.gather = PortP->statsGather; - portStats.txchars = PortP->txchars; - portStats.rxchars = PortP->rxchars; - portStats.opens = PortP->opens; - portStats.closes = PortP->closes; - portStats.ioctls = PortP->ioctls; - if (copy_to_user(argp, &portStats, sizeof(struct portStats))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_RESET_PORT_STATS: - port = arg; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); - if (port >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - PortP = (p->RIOPortp[port]); - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->txchars = 0; - PortP->rxchars = 0; - PortP->opens = 0; - PortP->closes = 0; - PortP->ioctls = 0; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_GATHER_PORT_STATS: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n"); - if (copy_from_user(&portStats, argp, sizeof(struct portStats))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (portStats.port < 0 || portStats.port >= RIO_PORTS) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - PortP = (p->RIOPortp[portStats.port]); - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->statsGather = portStats.gather; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_READ_CONFIG: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); - if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_SET_CONFIG: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n"); - if (!su) { - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - /* - ** move a few value around - */ - for (Host = 0; Host < p->RIONumHosts; Host++) - if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING) - writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer); - return retval; - - case RIO_START_POLLER: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n"); - return -EINVAL; - - case RIO_STOP_POLLER: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n"); - if (!su) { - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - p->RIOPolling = NOT_POLLING; - return retval; - - case RIO_SETDEBUG: - case RIO_GETDEBUG: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n"); - if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (DebugCtrl.SysPort == NO_PORT) { - if (cmd == RIO_SETDEBUG) { - if (!su) { - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - p->rio_debug = DebugCtrl.Debug; - p->RIODebugWait = DebugCtrl.Wait; - rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait); - } else { - rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait); - DebugCtrl.Debug = p->rio_debug; - DebugCtrl.Wait = p->RIODebugWait; - if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - } - } else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } else if (cmd == RIO_SETDEBUG) { - if (!su) { - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug); - } else { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug); - DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug; - if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - } - return retval; - - case RIO_VERSID: - /* - ** Enquire about the release and version. - ** We return MAX_VERSION_LEN bytes, being a - ** textual null terminated string. - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n"); - if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_NUM_HOSTS: - /* - ** Enquire as to the number of hosts located - ** at init time. - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); - if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - case RIO_HOST_FOAD: - /* - ** Kill host. This may not be in the final version... - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg); - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - p->RIOHalted = 1; - p->RIOSystemUp = 0; - - for (Host = 0; Host < p->RIONumHosts; Host++) { - (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot); - memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags)); - p->RIOHosts[Host].Flags = RC_WAITING; - } - RIOFoadWakeup(p); - p->RIONumBootPkts = 0; - p->RIOBooting = 0; - printk("HEEEEELP!\n"); - - for (loop = 0; loop < RIO_PORTS; loop++) { - spin_lock_init(&p->RIOPortp[loop]->portSem); - p->RIOPortp[loop]->InUse = NOT_INUSE; - } - - p->RIOSystemUp = 0; - return retval; - - case RIO_DOWNLOAD: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n"); - if (!su) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n"); - p->RIOError.Error = NOT_SUPER_USER; - return -EPERM; - } - if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode); - - /* - ** It is important that the product code is an unsigned object! - */ - if (DownLoad.ProductCode >= MAX_PRODUCT) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode); - p->RIOError.Error = NO_SUCH_PRODUCT; - return -ENXIO; - } - /* - ** do something! - */ - retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad); - /* <-- Panic */ - p->RIOHalted = 0; - /* - ** and go back, content with a job well completed. - */ - return retval; - - case RIO_PARMS: - { - unsigned int host; - - if (copy_from_user(&host, argp, sizeof(host))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - /* - ** Fetch the parmmap - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n"); - if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) { - p->RIOError.Error = COPYOUT_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); - return -EFAULT; - } - } - return retval; - - case RIO_HOST_REQ: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); - if (copy_from_user(&HostReq, argp, sizeof(HostReq))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (HostReq.HostNum >= p->RIONumHosts) { - p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum); - return -ENXIO; - } - rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum); - - if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) { - p->RIOError.Error = COPYOUT_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n"); - return -EFAULT; - } - return retval; - - case RIO_HOST_DPRAM: - rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n"); - if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (HostDpRam.HostNum >= p->RIONumHosts) { - p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum); - return -ENXIO; - } - rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum); - - if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) { - int off; - /* It's hardware like this that really gets on my tits. */ - static unsigned char copy[sizeof(struct DpRam)]; - for (off = 0; off < sizeof(struct DpRam); off++) - copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off); - if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) { - p->RIOError.Error = COPYOUT_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); - return -EFAULT; - } - } else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) { - p->RIOError.Error = COPYOUT_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); - return -EFAULT; - } - return retval; - - case RIO_SET_BUSY: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); - if (arg > 511) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - p->RIOPortp[arg]->State |= RIO_BUSY; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_HOST_PORT: - /* - ** The daemon want port information - ** (probably for debug reasons) - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); - if (copy_from_user(&PortReq, argp, sizeof(PortReq))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - - if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort); - if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) { - p->RIOError.Error = COPYOUT_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n"); - return -EFAULT; - } - return retval; - - case RIO_HOST_RUP: - /* - ** The daemon want rup information - ** (probably for debug reasons) - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); - if (copy_from_user(&RupReq, argp, sizeof(RupReq))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum); - p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) { /* eek! */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum); - p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - HostP = &p->RIOHosts[RupReq.HostNum]; - - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum); - p->RIOError.Error = HOST_NOT_RUNNING; - return -EIO; - } - rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum); - - if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) { - p->RIOError.Error = COPYOUT_FAILED; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); - return -EFAULT; - } - return retval; - - case RIO_HOST_LPB: - /* - ** The daemon want lpb information - ** (probably for debug reasons) - */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); - if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host); - p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - if (LpbReq.Link >= LINKS_PER_UNIT) { /* eek! */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link); - p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - HostP = &p->RIOHosts[LpbReq.Host]; - - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host); - p->RIOError.Error = HOST_NOT_RUNNING; - return -EIO; - } - rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host); - - if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - - /* - ** Here 3 IOCTL's that allow us to change the way in which - ** rio logs errors. send them just to syslog or send them - ** to both syslog and console or send them to just the console. - ** - ** See RioStrBuf() in util.c for the other half. - */ - case RIO_SYSLOG_ONLY: - p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */ - return 0; - - case RIO_SYSLOG_CONS: - p->RIOPrintLogState = PRINT_TO_LOG_CONS; /* syslog and console */ - return 0; - - case RIO_CONS_ONLY: - p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */ - return 0; - - case RIO_SIGNALS_ON: - if (p->RIOSignalProcess) { - p->RIOError.Error = SIGNALS_ALREADY_SET; - return -EBUSY; - } - /* FIXME: PID tracking */ - p->RIOSignalProcess = current->pid; - p->RIOPrintDisabled = DONT_PRINT; - return retval; - - case RIO_SIGNALS_OFF: - if (p->RIOSignalProcess != current->pid) { - p->RIOError.Error = NOT_RECEIVING_PROCESS; - return -EPERM; - } - rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n"); - p->RIOSignalProcess = 0; - return retval; - - case RIO_SET_BYTE_MODE: - for (Host = 0; Host < p->RIONumHosts; Host++) - if (p->RIOHosts[Host].Type == RIO_AT) - p->RIOHosts[Host].Mode &= ~WORD_OPERATION; - return retval; - - case RIO_SET_WORD_MODE: - for (Host = 0; Host < p->RIONumHosts; Host++) - if (p->RIOHosts[Host].Type == RIO_AT) - p->RIOHosts[Host].Mode |= WORD_OPERATION; - return retval; - - case RIO_SET_FAST_BUS: - for (Host = 0; Host < p->RIONumHosts; Host++) - if (p->RIOHosts[Host].Type == RIO_AT) - p->RIOHosts[Host].Mode |= FAST_AT_BUS; - return retval; - - case RIO_SET_SLOW_BUS: - for (Host = 0; Host < p->RIONumHosts; Host++) - if (p->RIOHosts[Host].Type == RIO_AT) - p->RIOHosts[Host].Mode &= ~FAST_AT_BUS; - return retval; - - case RIO_MAP_B50_TO_50: - case RIO_MAP_B50_TO_57600: - case RIO_MAP_B110_TO_110: - case RIO_MAP_B110_TO_115200: - rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n"); - port = arg; - if (port < 0 || port > 511) { - rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - switch (cmd) { - case RIO_MAP_B50_TO_50: - p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50; - break; - case RIO_MAP_B50_TO_57600: - p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50; - break; - case RIO_MAP_B110_TO_110: - p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110; - break; - case RIO_MAP_B110_TO_115200: - p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110; - break; - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_STREAM_INFO: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n"); - return -EINVAL; - - case RIO_SEND_PACKET: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); - if (copy_from_user(&SendPack, argp, sizeof(SendPack))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - if (SendPack.PortNum >= 128) { - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -ENXIO; - } - - PortP = p->RIOPortp[SendPack.PortNum]; - rio_spin_lock_irqsave(&PortP->portSem, flags); - - if (!can_add_transmit(&PacketP, PortP)) { - p->RIOError.Error = UNIT_IS_IN_USE; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -ENOSPC; - } - - for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++) - writeb(SendPack.Data[loop], &PacketP->data[loop]); - - writeb(SendPack.Len, &PacketP->len); - - add_transmit(PortP); - /* - ** Count characters transmitted for port statistics reporting - */ - if (PortP->statsGather) - PortP->txchars += (SendPack.Len & 127); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - - case RIO_NO_MESG: - if (su) - p->RIONoMessage = 1; - return su ? 0 : -EPERM; - - case RIO_MESG: - if (su) - p->RIONoMessage = 0; - return su ? 0 : -EPERM; - - case RIO_WHAT_MESG: - if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return 0; - - case RIO_MEM_DUMP: - if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr); - - if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) { - p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - if (SubCmd.Host >= p->RIONumHosts) { - p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort; - - PortP = p->RIOPortp[port]; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EBUSY; - } else - PortP->State |= RIO_BUSY; - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return 0; - - case RIO_TICK: - if (arg >= p->RIONumHosts) - return -EINVAL; - rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg); - writeb(0xFF, &p->RIOHosts[arg].SetInt); - return 0; - - case RIO_TOCK: - if (arg >= p->RIONumHosts) - return -EINVAL; - rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg); - writeb(0xFF, &p->RIOHosts[arg].ResetInt); - return 0; - - case RIO_READ_CHECK: - /* Check reads for pkts with data[0] the same */ - p->RIOReadCheck = !p->RIOReadCheck; - if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return 0; - - case RIO_READ_REGISTER: - if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) { - p->RIOError.Error = COPYIN_FAILED; - return -EFAULT; - } - rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr); - - if (SubCmd.Port > 511) { - rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port); - p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) { - p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - if (SubCmd.Host >= p->RIONumHosts) { - p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port; - PortP = p->RIOPortp[port]; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) == - RIO_FAIL) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EBUSY; - } else - PortP->State |= RIO_BUSY; - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return 0; - /* - ** rio_make_dev: given port number (0-511) ORed with port type - ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t - ** value to pass to mknod to create the correct device node. - */ - case RIO_MAKE_DEV: - { - unsigned int port = arg & RIO_MODEM_MASK; - unsigned int ret; - - switch (arg & RIO_DEV_MASK) { - case RIO_DEV_DIRECT: - ret = drv_makedev(MAJOR(dev), port); - rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret); - return ret; - case RIO_DEV_MODEM: - ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT)); - rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret); - return ret; - case RIO_DEV_XPRINT: - ret = drv_makedev(MAJOR(dev), port); - rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret); - return ret; - } - rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n"); - return -EINVAL; - } - /* - ** rio_minor: given a dev_t from a stat() call, return - ** the port number (0-511) ORed with the port type - ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT ) - */ - case RIO_MINOR: - { - dev_t dv; - int mino; - unsigned long ret; - - dv = (dev_t) (arg); - mino = RIO_UNMODEM(dv); - - if (RIO_ISMODEM(dv)) { - rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino); - ret = mino | RIO_DEV_MODEM; - } else { - rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino); - ret = mino | RIO_DEV_DIRECT; - } - return ret; - } - } - rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd); - p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; - - func_exit(); - return -EINVAL; -} - -/* -** Pre-emptive commands go on RUPs and are only one byte long. -*/ -int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) -{ - struct CmdBlk *CmdBlkP; - struct PktCmd_M *PktCmdP; - int Ret; - ushort rup; - int port; - - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n"); - return RIO_FAIL; - } - - if ((PortP->InUse == (typeof(PortP->InUse))-1) || - !(CmdBlkP = RIOGetCmdBlk())) { - rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block " - "for command %d on port %d\n", Cmd, PortP->PortNum); - return RIO_FAIL; - } - - rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", - CmdBlkP, PortP->InUse); - - PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0]; - - CmdBlkP->Packet.src_unit = 0; - if (PortP->SecondBlock) - rup = PortP->ID2; - else - rup = PortP->RupNum; - CmdBlkP->Packet.dest_unit = rup; - CmdBlkP->Packet.src_port = COMMAND_RUP; - CmdBlkP->Packet.dest_port = COMMAND_RUP; - CmdBlkP->Packet.len = PKT_CMD_BIT | 2; - CmdBlkP->PostFuncP = RIOUnUse; - CmdBlkP->PostArg = (unsigned long) PortP; - PktCmdP->Command = Cmd; - port = PortP->HostPort % (ushort) PORTS_PER_RTA; - /* - ** Index ports 8-15 for 2nd block of 16 port RTA. - */ - if (PortP->SecondBlock) - port += (ushort) PORTS_PER_RTA; - PktCmdP->PhbNum = port; - - switch (Cmd) { - case RIOC_MEMDUMP: - rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p " - "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); - PktCmdP->SubCommand = RIOC_MEMDUMP; - PktCmdP->SubAddr = SubCmd.Addr; - break; - case RIOC_FCLOSE: - rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", - CmdBlkP); - break; - case RIOC_READ_REGISTER: - rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) " - "command blk %p\n", (int) SubCmd.Addr, CmdBlkP); - PktCmdP->SubCommand = RIOC_READ_REGISTER; - PktCmdP->SubAddr = SubCmd.Addr; - break; - case RIOC_RESUME: - rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", - CmdBlkP); - break; - case RIOC_RFLUSH: - rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", - CmdBlkP); - CmdBlkP->PostFuncP = RIORFlushEnable; - break; - case RIOC_SUSPEND: - rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", - CmdBlkP); - break; - - case RIOC_MGET: - rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", - CmdBlkP); - break; - - case RIOC_MSET: - case RIOC_MBIC: - case RIOC_MBIS: - CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; - rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command " - "blk %p\n", CmdBlkP); - break; - - case RIOC_WFLUSH: - /* - ** If we have queued up the maximum number of Write flushes - ** allowed then we should not bother sending any more to the - ** RTA. - */ - if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) { - rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, " - "WflushFlag about to wrap!"); - RIOFreeCmdBlk(CmdBlkP); - return (RIO_FAIL); - } else { - rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command " - "blk %p\n", CmdBlkP); - CmdBlkP->PostFuncP = RIOWFlushMark; - } - break; - } - - PortP->InUse++; - - Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP); - - return Ret; -} diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h deleted file mode 100644 index 0907e711b355..000000000000 --- a/drivers/char/rio/riodrvr.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riodrvr.h -** SID : 1.3 -** Last Modified : 11/6/98 09:22:46 -** Retrieved : 11/6/98 09:22:46 -** -** ident @(#)riodrvr.h 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __riodrvr_h -#define __riodrvr_h - -#include /* for HZ */ - -#define MEMDUMP_SIZE 32 -#define MOD_DISABLE (RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT) - - -struct rio_info { - int mode; /* Intr or polled, word/byte */ - spinlock_t RIOIntrSem; /* Interrupt thread sem */ - int current_chan; /* current channel */ - int RIOFailed; /* Not initialised ? */ - int RIOInstallAttempts; /* no. of rio-install() calls */ - int RIOLastPCISearch; /* status of last search */ - int RIONumHosts; /* Number of RIO Hosts */ - struct Host *RIOHosts; /* RIO Host values */ - struct Port **RIOPortp; /* RIO port values */ -/* -** 02.03.1999 ARG - ESIL 0820 fix -** We no longer use RIOBootMode -** - int RIOBootMode; * RIO boot mode * -** -*/ - int RIOPrintDisabled; /* RIO printing disabled ? */ - int RIOPrintLogState; /* RIO printing state ? */ - int RIOPolling; /* Polling ? */ -/* -** 09.12.1998 ARG - ESIL 0776 part fix -** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted. -** The fix for this ESIL introduces another member (RIORtaDisCons) here to be -** updated in RIOConCon() - to keep track of RTA connections/disconnections. -** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons. -*/ - int RIOHalted; /* halted ? */ - int RIORtaDisCons; /* RTA connections/disconnections */ - unsigned int RIOReadCheck; /* Rio read check */ - unsigned int RIONoMessage; /* To display message or not */ - unsigned int RIONumBootPkts; /* how many packets for an RTA */ - unsigned int RIOBootCount; /* size of RTA code */ - unsigned int RIOBooting; /* count of outstanding boots */ - unsigned int RIOSystemUp; /* Booted ?? */ - unsigned int RIOCounting; /* for counting interrupts */ - unsigned int RIOIntCount; /* # of intr since last check */ - unsigned int RIOTxCount; /* number of xmit intrs */ - unsigned int RIORxCount; /* number of rx intrs */ - unsigned int RIORupCount; /* number of rup intrs */ - int RIXTimer; - int RIOBufferSize; /* Buffersize */ - int RIOBufferMask; /* Buffersize */ - - int RIOFirstMajor; /* First host card's major no */ - - unsigned int RIOLastPortsMapped; /* highest port number known */ - unsigned int RIOFirstPortsMapped; /* lowest port number known */ - - unsigned int RIOLastPortsBooted; /* highest port number running */ - unsigned int RIOFirstPortsBooted; /* lowest port number running */ - - unsigned int RIOLastPortsOpened; /* highest port number running */ - unsigned int RIOFirstPortsOpened; /* lowest port number running */ - - /* Flag to say that the topology information has been changed. */ - unsigned int RIOQuickCheck; - unsigned int CdRegister; /* ??? */ - int RIOSignalProcess; /* Signalling process */ - int rio_debug; /* To debug ... */ - int RIODebugWait; /* For what ??? */ - int tpri; /* Thread prio */ - int tid; /* Thread id */ - unsigned int _RIO_Polled; /* Counter for polling */ - unsigned int _RIO_Interrupted; /* Counter for interrupt */ - int intr_tid; /* iointset return value */ - int TxEnSem; /* TxEnable Semaphore */ - - - struct Error RIOError; /* to Identify what went wrong */ - struct Conf RIOConf; /* Configuration ??? */ - struct ttystatics channel[RIO_PORTS]; /* channel information */ - char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)] - [RTA_BOOT_DATA_SIZE]; - struct Map RIOConnectTable[TOTAL_MAP_ENTRIES]; - struct Map RIOSavedTable[TOTAL_MAP_ENTRIES]; - - /* RTA to host binding table for master/slave operation */ - unsigned long RIOBindTab[MAX_RTA_BINDINGS]; - /* RTA memory dump variable */ - unsigned char RIOMemDump[MEMDUMP_SIZE]; - struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES]; - -}; - - -#ifdef linux -#define debug(x) printk x -#else -#define debug(x) kkprintf x -#endif - - - -#define RIO_RESET_INT 0x7d80 - -#endif /* __riodrvr.h */ diff --git a/drivers/char/rio/rioinfo.h b/drivers/char/rio/rioinfo.h deleted file mode 100644 index 42ff1e79d96f..000000000000 --- a/drivers/char/rio/rioinfo.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioinfo.h -** SID : 1.2 -** Last Modified : 11/6/98 14:07:49 -** Retrieved : 11/6/98 14:07:50 -** -** ident @(#)rioinfo.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rioinfo_h -#define __rioinfo_h - -/* -** Host card data structure -*/ -struct RioHostInfo { - long location; /* RIO Card Base I/O address */ - long vector; /* RIO Card IRQ vector */ - int bus; /* ISA/EISA/MCA/PCI */ - int mode; /* pointer to host mode - INTERRUPT / POLLED */ - struct old_sgttyb - *Sg; /* pointer to default term characteristics */ -}; - - -/* Mode in rio device info */ -#define INTERRUPTED_MODE 0x01 /* Interrupt is generated */ -#define POLLED_MODE 0x02 /* No interrupt */ -#define AUTO_MODE 0x03 /* Auto mode */ - -#define WORD_ACCESS_MODE 0x10 /* Word Access Mode */ -#define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */ - - -/* Bus type that RIO supports */ -#define ISA_BUS 0x01 /* The card is ISA */ -#define EISA_BUS 0x02 /* The card is EISA */ -#define MCA_BUS 0x04 /* The card is MCA */ -#define PCI_BUS 0x08 /* The card is PCI */ - -/* -** 11.11.1998 ARG - ESIL ???? part fix -** Moved definition for 'CHAN' here from rioinfo.c (it is now -** called 'DEF_TERM_CHARACTERISTICS'). -*/ - -#define DEF_TERM_CHARACTERISTICS \ -{ \ - B19200, B19200, /* input and output speed */ \ - 'H' - '@', /* erase char */ \ - -1, /* 2nd erase char */ \ - 'U' - '@', /* kill char */ \ - ECHO | CRMOD, /* mode */ \ - 'C' - '@', /* interrupt character */ \ - '\\' - '@', /* quit char */ \ - 'Q' - '@', /* start char */ \ - 'S' - '@', /* stop char */ \ - 'D' - '@', /* EOF */ \ - -1, /* brk */ \ - (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */ \ - 'Z' - '@', /* process stop */ \ - 'Y' - '@', /* delayed stop */ \ - 'R' - '@', /* reprint line */ \ - 'O' - '@', /* flush output */ \ - 'W' - '@', /* word erase */ \ - 'V' - '@' /* literal next char */ \ -} - -#endif /* __rioinfo_h */ diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c deleted file mode 100644 index 24a282bb89d4..000000000000 --- a/drivers/char/rio/rioinit.c +++ /dev/null @@ -1,421 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioinit.c -** SID : 1.3 -** Last Modified : 11/6/98 10:33:43 -** Retrieved : 11/6/98 10:33:49 -** -** ident @(#)rioinit.c 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - -#include "linux_compat.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" -#include "rio_linux.h" - -int RIOPCIinit(struct rio_info *p, int Mode); - -static int RIOScrub(int, u8 __iomem *, int); - - -/** -** RIOAssignAT : -** -** Fill out the fields in the p->RIOHosts structure now we know we know -** we have a board present. -** -** bits < 0 indicates 8 bit operation requested, -** bits > 0 indicates 16 bit operation. -*/ - -int RIOAssignAT(struct rio_info *p, int Base, void __iomem *virtAddr, int mode) -{ - int bits; - struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr; - - if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE)) - bits = BYTE_OPERATION; - else - bits = WORD_OPERATION; - - /* - ** Board has passed its scrub test. Fill in all the - ** transient stuff. - */ - p->RIOHosts[p->RIONumHosts].Caddr = virtAddr; - p->RIOHosts[p->RIONumHosts].CardP = virtAddr; - - /* - ** Revision 01 AT host cards don't support WORD operations, - */ - if (readb(&cardp->DpRevision) == 01) - bits = BYTE_OPERATION; - - p->RIOHosts[p->RIONumHosts].Type = RIO_AT; - p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card; - /* set this later */ - p->RIOHosts[p->RIONumHosts].Slot = -1; - p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits; - writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE , - &p->RIOHosts[p->RIONumHosts].Control); - writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); - writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE, - &p->RIOHosts[p->RIONumHosts].Control); - writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); - p->RIOHosts[p->RIONumHosts].UniqueNum = - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| - ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum); - - p->RIONumHosts++; - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base); - return(1); -} - -static u8 val[] = { -#ifdef VERY_LONG_TEST - 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, -#endif - 0xff, 0x00, 0x00 }; - -#define TEST_END sizeof(val) - -/* -** RAM test a board. -** Nothing too complicated, just enough to check it out. -*/ -int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot) -{ - struct DpRam __iomem *DpRam = caddr; - void __iomem *ram[4]; - int size[4]; - int op, bank; - int nbanks; - - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n", - type, DpRam, slot); - - RIOHostReset(type, DpRam, slot); - - /* - ** Scrub the memory. This comes in several banks: - ** DPsram1 - 7000h bytes - ** DPsram2 - 200h bytes - ** DPsram3 - 7000h bytes - ** scratch - 1000h bytes - */ - - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n"); - - size[0] = DP_SRAM1_SIZE; - size[1] = DP_SRAM2_SIZE; - size[2] = DP_SRAM3_SIZE; - size[3] = DP_SCRATCH_SIZE; - - ram[0] = DpRam->DpSram1; - ram[1] = DpRam->DpSram2; - ram[2] = DpRam->DpSram3; - nbanks = (type == RIO_PCI) ? 3 : 4; - if (nbanks == 4) - ram[3] = DpRam->DpScratch; - - - if (nbanks == 3) { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n", - ram[0], size[0], ram[1], size[1], ram[2], size[2]); - } else { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n", - ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]); - } - - /* - ** This scrub operation will test for crosstalk between - ** banks. TEST_END is a magic number, and relates to the offset - ** within the 'val' array used by Scrub. - */ - for (op=0; opMapping[UnitId].Name, "UNKNOWN RTA X-XX", 17); - HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts); - if ((UnitId+1) > 9) { - HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10); - HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10); - } - else { - HostP->Mapping[UnitId].Name[14]='1'+UnitId; - HostP->Mapping[UnitId].Name[15]=0; - } - return 0; -} - -#define RIO_RELEASE "Linux" -#define RELEASE_ID "1.0" - -static struct rioVersion stVersion; - -struct rioVersion *RIOVersid(void) -{ - strlcpy(stVersion.version, "RIO driver for linux V1.0", - sizeof(stVersion.version)); - strlcpy(stVersion.buildDate, __DATE__, - sizeof(stVersion.buildDate)); - - return &stVersion; -} - -void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot) -{ - /* - ** Reset the Tpu - */ - rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: type 0x%x", Type); - switch ( Type ) { - case RIO_AT: - rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); - writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION | - SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); - writeb(0xFF, &DpRamP->DpResetTpu); - udelay(3); - rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); - writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | - BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); - writeb(0xFF, &DpRamP->DpResetTpu); - udelay(3); - break; - case RIO_PCI: - rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); - writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl); - writeb(0xFF, &DpRamP->DpResetInt); - writeb(0xFF, &DpRamP->DpResetTpu); - udelay(100); - break; - default: - rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); - break; - } - return; -} diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c deleted file mode 100644 index 2e71aecae206..000000000000 --- a/drivers/char/rio/riointr.c +++ /dev/null @@ -1,645 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riointr.c -** SID : 1.2 -** Last Modified : 11/6/98 10:33:44 -** Retrieved : 11/6/98 10:33:49 -** -** ident @(#)riointr.c 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" - - -static void RIOReceive(struct rio_info *, struct Port *); - - -static char *firstchars(char *p, int nch) -{ - static char buf[2][128]; - static int t = 0; - t = !t; - memcpy(buf[t], p, nch); - buf[t][nch] = 0; - return buf[t]; -} - - -#define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask)) -/* Enable and start the transmission of packets */ -void RIOTxEnable(char *en) -{ - struct Port *PortP; - struct rio_info *p; - struct tty_struct *tty; - int c; - struct PKT __iomem *PacketP; - unsigned long flags; - - PortP = (struct Port *) en; - p = (struct rio_info *) PortP->p; - tty = PortP->gs.port.tty; - - - rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt); - - if (!PortP->gs.xmit_cnt) - return; - - - /* This routine is an order of magnitude simpler than the specialix - version. One of the disadvantages is that this version will send - an incomplete packet (usually 64 bytes instead of 72) once for - every 4k worth of data. Let's just say that this won't influence - performance significantly..... */ - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - while (can_add_transmit(&PacketP, PortP)) { - c = PortP->gs.xmit_cnt; - if (c > PKT_MAX_DATA_LEN) - c = PKT_MAX_DATA_LEN; - - /* Don't copy past the end of the source buffer */ - if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail) - c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail; - - { - int t; - t = (c > 10) ? 10 : c; - - rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t)); - } - /* If for one reason or another, we can't copy more data, - we're done! */ - if (c == 0) - break; - - rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c); - /* udelay (1); */ - - writeb(c, &(PacketP->len)); - if (!(PortP->State & RIO_DELETED)) { - add_transmit(PortP); - /* - ** Count chars tx'd for port statistics reporting - */ - if (PortP->statsGather) - PortP->txchars += c; - } - PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1); - PortP->gs.xmit_cnt -= c; - } - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - - if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) - tty_wakeup(PortP->gs.port.tty); - -} - - -/* -** RIO Host Service routine. Does all the work traditionally associated with an -** interrupt. -*/ -static int RupIntr; -static int RxIntr; -static int TxIntr; - -void RIOServiceHost(struct rio_info *p, struct Host *HostP) -{ - rio_spin_lock(&HostP->HostLock); - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { - static int t = 0; - rio_spin_unlock(&HostP->HostLock); - if ((t++ % 200) == 0) - rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags); - return; - } - rio_spin_unlock(&HostP->HostLock); - - if (readw(&HostP->ParmMapP->rup_intr)) { - writew(0, &HostP->ParmMapP->rup_intr); - p->RIORupCount++; - RupIntr++; - rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts); - RIOPollHostCommands(p, HostP); - } - - if (readw(&HostP->ParmMapP->rx_intr)) { - int port; - - writew(0, &HostP->ParmMapP->rx_intr); - p->RIORxCount++; - RxIntr++; - - rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts); - /* - ** Loop through every port. If the port is mapped into - ** the system ( i.e. has /dev/ttyXXXX associated ) then it is - ** worth checking. If the port isn't open, grab any packets - ** hanging on its receive queue and stuff them on the free - ** list; check for commands on the way. - */ - for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { - struct Port *PortP = p->RIOPortp[port]; - struct tty_struct *ttyP; - struct PKT __iomem *PacketP; - - /* - ** not mapped in - most of the RIOPortp[] information - ** has not been set up! - ** Optimise: ports come in bundles of eight. - */ - if (!PortP->Mapped) { - port += 7; - continue; /* with the next port */ - } - - /* - ** If the host board isn't THIS host board, check the next one. - ** optimise: ports come in bundles of eight. - */ - if (PortP->HostP != HostP) { - port += 7; - continue; - } - - /* - ** Let us see - is the port open? If not, then don't service it. - */ - if (!(PortP->PortState & PORT_ISOPEN)) { - continue; - } - - /* - ** find corresponding tty structure. The process of mapping - ** the ports puts these here. - */ - ttyP = PortP->gs.port.tty; - - /* - ** Lock the port before we begin working on it. - */ - rio_spin_lock(&PortP->portSem); - - /* - ** Process received data if there is any. - */ - if (can_remove_receive(&PacketP, PortP)) - RIOReceive(p, PortP); - - /* - ** If there is no data left to be read from the port, and - ** it's handshake bit is set, then we must clear the handshake, - ** so that that downstream RTA is re-enabled. - */ - if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) { - /* - ** MAGIC! ( Basically, handshake the RX buffer, so that - ** the RTAs upstream can be re-enabled. ) - */ - rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n"); - writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); - } - rio_spin_unlock(&PortP->portSem); - } - } - - if (readw(&HostP->ParmMapP->tx_intr)) { - int port; - - writew(0, &HostP->ParmMapP->tx_intr); - - p->RIOTxCount++; - TxIntr++; - rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts); - - /* - ** Loop through every port. - ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX - ** associated ) then it is worth checking. - */ - for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { - struct Port *PortP = p->RIOPortp[port]; - struct tty_struct *ttyP; - struct PKT __iomem *PacketP; - - /* - ** not mapped in - most of the RIOPortp[] information - ** has not been set up! - */ - if (!PortP->Mapped) { - port += 7; - continue; /* with the next port */ - } - - /* - ** If the host board isn't running, then its data structures - ** are no use to us - continue quietly. - */ - if (PortP->HostP != HostP) { - port += 7; - continue; /* with the next port */ - } - - /* - ** Let us see - is the port open? If not, then don't service it. - */ - if (!(PortP->PortState & PORT_ISOPEN)) { - continue; - } - - rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port); - /* - ** Lock the port before we begin working on it. - */ - rio_spin_lock(&PortP->portSem); - - /* - ** If we can't add anything to the transmit queue, then - ** we need do none of this processing. - */ - if (!can_add_transmit(&PacketP, PortP)) { - rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n"); - rio_spin_unlock(&PortP->portSem); - continue; - } - - /* - ** find corresponding tty structure. The process of mapping - ** the ports puts these here. - */ - ttyP = PortP->gs.port.tty; - /* If ttyP is NULL, the port is getting closed. Forget about it. */ - if (!ttyP) { - rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n"); - rio_spin_unlock(&PortP->portSem); - continue; - } - /* - ** If there is more room available we start up the transmit - ** data process again. This can be direct I/O, if the cookmode - ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the - ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch - ** characters via the line discipline. We must always call - ** the line discipline, - ** so that user input characters can be echoed correctly. - ** - ** ++++ Update +++++ - ** With the advent of double buffering, we now see if - ** TxBufferOut-In is non-zero. If so, then we copy a packet - ** to the output place, and set it going. If this empties - ** the buffer, then we must issue a wakeup( ) on OUT. - ** If it frees space in the buffer then we must issue - ** a wakeup( ) on IN. - ** - ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we - ** have to send a WFLUSH command down the PHB, to mark the - ** end point of a WFLUSH. We also need to clear out any - ** data from the double buffer! ( note that WflushFlag is a - ** *count* of the number of WFLUSH commands outstanding! ) - ** - ** ++++ And there's more! - ** If an RTA is powered off, then on again, and rebooted, - ** whilst it has ports open, then we need to re-open the ports. - ** ( reasonable enough ). We can't do this when we spot the - ** re-boot, in interrupt time, because the queue is probably - ** full. So, when we come in here, we need to test if any - ** ports are in this condition, and re-open the port before - ** we try to send any more data to it. Now, the re-booted - ** RTA will be discarding packets from the PHB until it - ** receives this open packet, but don't worry tooo much - ** about that. The one thing that is interesting is the - ** combination of this effect and the WFLUSH effect! - */ - /* For now don't handle RTA reboots. -- REW. - Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */ - if (PortP->MagicFlags) { - if (PortP->MagicFlags & MAGIC_REBOOT) { - /* - ** well, the RTA has been rebooted, and there is room - ** on its queue to add the open packet that is required. - ** - ** The messy part of this line is trying to decide if - ** we need to call the Param function as a tty or as - ** a modem. - ** DONT USE CLOCAL AS A TEST FOR THIS! - ** - ** If we can't param the port, then move on to the - ** next port. - */ - PortP->InUse = NOT_INUSE; - - rio_spin_unlock(&PortP->portSem); - if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) - continue; /* with next port */ - rio_spin_lock(&PortP->portSem); - PortP->MagicFlags &= ~MAGIC_REBOOT; - } - - /* - ** As mentioned above, this is a tacky hack to cope - ** with WFLUSH - */ - if (PortP->WflushFlag) { - rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n"); - - if (PortP->InUse) - rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n"); - } - - while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) { - int p; - struct PktCmd __iomem *PktCmdP; - - rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n"); - /* - ** make it look just like a WFLUSH command - */ - PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0]; - - writeb(RIOC_WFLUSH, &PktCmdP->Command); - - p = PortP->HostPort % (u16) PORTS_PER_RTA; - - /* - ** If second block of ports for 16 port RTA, add 8 - ** to index 8-15. - */ - if (PortP->SecondBlock) - p += PORTS_PER_RTA; - - writeb(p, &PktCmdP->PhbNum); - - /* - ** to make debuggery easier - */ - writeb('W', &PacketP->data[2]); - writeb('F', &PacketP->data[3]); - writeb('L', &PacketP->data[4]); - writeb('U', &PacketP->data[5]); - writeb('S', &PacketP->data[6]); - writeb('H', &PacketP->data[7]); - writeb(' ', &PacketP->data[8]); - writeb('0' + PortP->WflushFlag, &PacketP->data[9]); - writeb(' ', &PacketP->data[10]); - writeb(' ', &PacketP->data[11]); - writeb('\0', &PacketP->data[12]); - - /* - ** its two bytes long! - */ - writeb(PKT_CMD_BIT | 2, &PacketP->len); - - /* - ** queue it! - */ - if (!(PortP->State & RIO_DELETED)) { - add_transmit(PortP); - /* - ** Count chars tx'd for port statistics reporting - */ - if (PortP->statsGather) - PortP->txchars += 2; - } - - if (--(PortP->WflushFlag) == 0) { - PortP->MagicFlags &= ~MAGIC_FLUSH; - } - - rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag); - } - if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) { - if (PortP->MagicFlags & MAGIC_FLUSH) { - PortP->MagicFlags |= MORE_OUTPUT_EYGOR; - } else { - if (!can_add_transmit(&PacketP, PortP)) { - rio_spin_unlock(&PortP->portSem); - continue; - } - rio_spin_unlock(&PortP->portSem); - RIOTxEnable((char *) PortP); - rio_spin_lock(&PortP->portSem); - PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; - } - } - } - - - /* - ** If we can't add anything to the transmit queue, then - ** we need do none of the remaining processing. - */ - if (!can_add_transmit(&PacketP, PortP)) { - rio_spin_unlock(&PortP->portSem); - continue; - } - - rio_spin_unlock(&PortP->portSem); - RIOTxEnable((char *) PortP); - } - } -} - -/* -** Routine for handling received data for tty drivers -*/ -static void RIOReceive(struct rio_info *p, struct Port *PortP) -{ - struct tty_struct *TtyP; - unsigned short transCount; - struct PKT __iomem *PacketP; - register unsigned int DataCnt; - unsigned char __iomem *ptr; - unsigned char *buf; - int copied = 0; - - static int intCount, RxIntCnt; - - /* - ** The receive data process is to remove packets from the - ** PHB until there aren't any more or the current cblock - ** is full. When this occurs, there will be some left over - ** data in the packet, that we must do something with. - ** As we haven't unhooked the packet from the read list - ** yet, we can just leave the packet there, having first - ** made a note of how far we got. This means that we need - ** a pointer per port saying where we start taking the - ** data from - this will normally be zero, but when we - ** run out of space it will be set to the offset of the - ** next byte to copy from the packet data area. The packet - ** length field is decremented by the number of bytes that - ** we successfully removed from the packet. When this reaches - ** zero, we reset the offset pointer to be zero, and free - ** the packet from the front of the queue. - */ - - intCount++; - - TtyP = PortP->gs.port.tty; - if (!TtyP) { - rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n"); - return; - } - - if (PortP->State & RIO_THROTTLE_RX) { - rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n"); - return; - } - - if (PortP->State & RIO_DELETED) { - while (can_remove_receive(&PacketP, PortP)) { - remove_receive(PortP); - put_free_end(PortP->HostP, PacketP); - } - } else { - /* - ** loop, just so long as: - ** i ) there's some data ( i.e. can_remove_receive ) - ** ii ) we haven't been blocked - ** iii ) there's somewhere to put the data - ** iv ) we haven't outstayed our welcome - */ - transCount = 1; - while (can_remove_receive(&PacketP, PortP) - && transCount) { - RxIntCnt++; - - /* - ** check that it is not a command! - */ - if (readb(&PacketP->len) & PKT_CMD_BIT) { - rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n"); - /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */ - rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit)); - rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port)); - rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", readb(&PacketP->src_unit)); - rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", readb(&PacketP->src_port)); - rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", readb(&PacketP->len)); - rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", readb(&PacketP->control)); - rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", readw(&PacketP->csum)); - rio_dprintk(RIO_DEBUG_INTR, " data bytes: "); - for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++) - rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt])); - remove_receive(PortP); - put_free_end(PortP->HostP, PacketP); - continue; /* with next packet */ - } - - /* - ** How many characters can we move 'upstream' ? - ** - ** Determine the minimum of the amount of data - ** available and the amount of space in which to - ** put it. - ** - ** 1. Get the packet length by masking 'len' - ** for only the length bits. - ** 2. Available space is [buffer size] - [space used] - ** - ** Transfer count is the minimum of packet length - ** and available space. - */ - - transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK); - rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount); - /* - ** To use the following 'kkprintfs' for debugging - change the '#undef' - ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the - ** driver). - */ - ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart; - - tty_prepare_flip_string(TtyP, &buf, transCount); - rio_memcpy_fromio(buf, ptr, transCount); - PortP->RxDataStart += transCount; - writeb(readb(&PacketP->len)-transCount, &PacketP->len); - copied += transCount; - - - - if (readb(&PacketP->len) == 0) { - /* - ** If we have emptied the packet, then we can - ** free it, and reset the start pointer for - ** the next packet. - */ - remove_receive(PortP); - put_free_end(PortP->HostP, PacketP); - PortP->RxDataStart = 0; - } - } - } - if (copied) { - rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied); - tty_flip_buffer_push(TtyP); - } - - return; -} - diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h deleted file mode 100644 index e8af5b30519e..000000000000 --- a/drivers/char/rio/rioioctl.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioioctl.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:13 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)rioioctl.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rioioctl_h__ -#define __rioioctl_h__ - -/* -** RIO device driver - user ioctls and associated structures. -*/ - -struct portStats { - int port; - int gather; - unsigned long txchars; - unsigned long rxchars; - unsigned long opens; - unsigned long closes; - unsigned long ioctls; -}; - -#define RIOC ('R'<<8)|('i'<<16)|('o'<<24) - -#define RIO_QUICK_CHECK (RIOC | 105) -#define RIO_GATHER_PORT_STATS (RIOC | 193) -#define RIO_RESET_PORT_STATS (RIOC | 194) -#define RIO_GET_PORT_STATS (RIOC | 195) - -#endif /* __rioioctl_h__ */ diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c deleted file mode 100644 index 6415f3f32a72..000000000000 --- a/drivers/char/rio/rioparam.c +++ /dev/null @@ -1,663 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioparam.c -** SID : 1.3 -** Last Modified : 11/6/98 10:33:45 -** Retrieved : 11/6/98 10:33:50 -** -** ident @(#)rioparam.c 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" -#include "param.h" - - - -/* -** The Scam, based on email from jeremyr@bugs.specialix.co.uk.... -** -** To send a command on a particular port, you put a packet with the -** command bit set onto the port. The command bit is in the len field, -** and gets ORed in with the actual byte count. -** -** When you send a packet with the command bit set the first -** data byte (data[0]) is interpreted as the command to execute. -** It also governs what data structure overlay should accompany the packet. -** Commands are defined in cirrus/cirrus.h -** -** If you want the command to pre-emt data already on the queue for the -** port, set the pre-emptive bit in conjunction with the command bit. -** It is not defined what will happen if you set the preemptive bit -** on a packet that is NOT a command. -** -** Pre-emptive commands should be queued at the head of the queue using -** add_start(), whereas normal commands and data are enqueued using -** add_end(). -** -** Most commands do not use the remaining bytes in the data array. The -** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and -** OPEN are currently analogous). With these three commands the following -** 11 data bytes are all used to pass config information such as baud rate etc. -** The fields are also defined in cirrus.h. Some contain straightforward -** information such as the transmit XON character. Two contain the transmit and -** receive baud rates respectively. For most baud rates there is a direct -** mapping between the rates defined in and the byte in the -** packet. There are additional (non UNIX-standard) rates defined in -** /u/dos/rio/cirrus/h/brates.h. -** -** The rest of the data fields contain approximations to the Cirrus registers -** that are used to program number of bits etc. Each registers bit fields is -** defined in cirrus.h. -** -** NB. Only use those bits that are defined as being driver specific -** or common to the RTA and the driver. -** -** All commands going from RTA->Host will be dealt with by the Host code - you -** will never see them. As with the SI there will be three fields to look out -** for in each phb (not yet defined - needs defining a.s.a.p). -** -** modem_status - current state of handshake pins. -** -** port_status - current port status - equivalent to hi_stat for SI, indicates -** if port is IDLE_OPEN, IDLE_CLOSED etc. -** -** break_status - bit X set if break has been received. -** -** Happy hacking. -** -*/ - -/* -** RIOParam is used to open or configure a port. You pass it a PortP, -** which will have a tty struct attached to it. You also pass a command, -** either OPEN or CONFIG. The port's setup is taken from the t_ fields -** of the tty struct inside the PortP, and the port is either opened -** or re-configured. You must also tell RIOParam if the device is a modem -** device or not (i.e. top bit of minor number set or clear - take special -** care when deciding on this!). -** RIOParam neither flushes nor waits for drain, and is NOT preemptive. -** -** RIOParam assumes it will be called at splrio(), and also assumes -** that CookMode is set correctly in the port structure. -** -** NB. for MPX -** tty lock must NOT have been previously acquired. -*/ -int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) -{ - struct tty_struct *TtyP; - int retval; - struct phb_param __iomem *phb_param_ptr; - struct PKT __iomem *PacketP; - int res; - u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0; - u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0; - u8 LNext = 0, TxBaud = 0, RxBaud = 0; - int retries = 0xff; - unsigned long flags; - - func_enter(); - - TtyP = PortP->gs.port.tty; - - rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP); - - if (!TtyP) { - rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n"); - - func_exit(); - - return RIO_FAIL; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - - if (cmd == RIOC_OPEN) { - /* - ** If the port is set to store or lock the parameters, and it is - ** paramed with OPEN, we want to restore the saved port termio, but - ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot. - */ - } - - /* - ** wait for space - */ - while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) { - if (retries-- <= 0) { - break; - } - if (PortP->InUse != NOT_INUSE) { - rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n"); - } - - if (!res) { - rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n"); - } - - if (SleepFlag != OK_TO_SLEEP) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - - return RIO_FAIL; - } - - rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - retval = RIODelay(PortP, HUNDRED_MS); - rio_spin_lock_irqsave(&PortP->portSem, flags); - if (retval == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - return -EINTR; - } - if (PortP->State & RIO_DELETED) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - return 0; - } - } - - if (!res) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - - return RIO_FAIL; - } - - rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res); - rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP); - - phb_param_ptr = (struct phb_param __iomem *) PacketP->data; - - - switch (TtyP->termios->c_cflag & CSIZE) { - case CS5: - { - rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n"); - Cor1 |= RIOC_COR1_5BITS; - break; - } - case CS6: - { - rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n"); - Cor1 |= RIOC_COR1_6BITS; - break; - } - case CS7: - { - rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n"); - Cor1 |= RIOC_COR1_7BITS; - break; - } - case CS8: - { - rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n"); - Cor1 |= RIOC_COR1_8BITS; - break; - } - } - - if (TtyP->termios->c_cflag & CSTOPB) { - rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n"); - Cor1 |= RIOC_COR1_2STOP; - } else { - rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n"); - Cor1 |= RIOC_COR1_1STOP; - } - - if (TtyP->termios->c_cflag & PARENB) { - rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n"); - Cor1 |= RIOC_COR1_NORMAL; - } else { - rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n"); - Cor1 |= RIOC_COR1_NOP; - } - if (TtyP->termios->c_cflag & PARODD) { - rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n"); - Cor1 |= RIOC_COR1_ODD; - } else { - rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n"); - Cor1 |= RIOC_COR1_EVEN; - } - - /* - ** COR 2 - */ - if (TtyP->termios->c_iflag & IXON) { - rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n"); - Cor2 |= RIOC_COR2_IXON; - } else { - if (PortP->Config & RIO_IXON) { - rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n"); - Cor2 |= RIOC_COR2_IXON; - } else - rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n"); - } - - if (TtyP->termios->c_iflag & IXANY) { - if (PortP->Config & RIO_IXANY) { - rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n"); - Cor2 |= RIOC_COR2_IXANY; - } else - rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n"); - } - - if (TtyP->termios->c_iflag & IXOFF) { - rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n"); - Cor2 |= RIOC_COR2_IXOFF; - } - - if (TtyP->termios->c_cflag & HUPCL) { - rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n"); - Cor2 |= RIOC_COR2_HUPCL; - } - - if (C_CRTSCTS(TtyP)) { - rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n"); - Cor2 |= RIOC_COR2_CTSFLOW; - Cor2 |= RIOC_COR2_RTSFLOW; - } else { - rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n"); - Cor2 &= ~RIOC_COR2_CTSFLOW; - Cor2 &= ~RIOC_COR2_RTSFLOW; - } - - - if (TtyP->termios->c_cflag & CLOCAL) { - rio_dprintk(RIO_DEBUG_PARAM, "Local line\n"); - } else { - rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n"); - } - - /* - ** COR 4 (there is no COR 3) - */ - if (TtyP->termios->c_iflag & IGNBRK) { - rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n"); - Cor4 |= RIOC_COR4_IGNBRK; - } - if (!(TtyP->termios->c_iflag & BRKINT)) { - rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n"); - Cor4 |= RIOC_COR4_NBRKINT; - } else { - rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on break condition\n"); - } - - if (TtyP->termios->c_iflag & INLCR) { - rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n"); - Cor4 |= RIOC_COR4_INLCR; - } - - if (TtyP->termios->c_iflag & IGNCR) { - rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n"); - Cor4 |= RIOC_COR4_IGNCR; - } - - if (TtyP->termios->c_iflag & ICRNL) { - rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n"); - Cor4 |= RIOC_COR4_ICRNL; - } - if (TtyP->termios->c_iflag & IGNPAR) { - rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n"); - Cor4 |= RIOC_COR4_IGNPAR; - } - if (TtyP->termios->c_iflag & PARMRK) { - rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n"); - Cor4 |= RIOC_COR4_PARMRK; - } - - /* - ** Set the RAISEMOD flag to ensure that the modem lines are raised - ** on reception of a config packet. - ** The download code handles the zero baud condition. - */ - Cor4 |= RIOC_COR4_RAISEMOD; - - /* - ** COR 5 - */ - - Cor5 = RIOC_COR5_CMOE; - - /* - ** Set to monitor tbusy/tstop (or not). - */ - - if (PortP->MonitorTstate) - Cor5 |= RIOC_COR5_TSTATE_ON; - else - Cor5 |= RIOC_COR5_TSTATE_OFF; - - /* - ** Could set LNE here if you wanted LNext processing. SVR4 will use it. - */ - if (TtyP->termios->c_iflag & ISTRIP) { - rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n"); - if (!(PortP->State & RIO_TRIAD_MODE)) { - Cor5 |= RIOC_COR5_ISTRIP; - } - } - - if (TtyP->termios->c_oflag & ONLCR) { - rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n"); - if (PortP->CookMode == COOK_MEDIUM) - Cor5 |= RIOC_COR5_ONLCR; - } - if (TtyP->termios->c_oflag & OCRNL) { - rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n"); - if (PortP->CookMode == COOK_MEDIUM) - Cor5 |= RIOC_COR5_OCRNL; - } - if ((TtyP->termios->c_oflag & TABDLY) == TAB3) { - rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n"); - if (PortP->CookMode == COOK_MEDIUM) - Cor5 |= RIOC_COR5_TAB3; - } - - /* - ** Flow control bytes. - */ - TxXon = TtyP->termios->c_cc[VSTART]; - TxXoff = TtyP->termios->c_cc[VSTOP]; - RxXon = TtyP->termios->c_cc[VSTART]; - RxXoff = TtyP->termios->c_cc[VSTOP]; - /* - ** LNEXT byte - */ - LNext = 0; - - /* - ** Baud rate bytes - */ - rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD); - - switch (TtyP->termios->c_cflag & CBAUD) { -#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break - e(50); - e(75); - e(110); - e(134); - e(150); - e(200); - e(300); - e(600); - e(1200); - e(1800); - e(2400); - e(4800); - e(9600); - e(19200); - e(38400); - e(57600); - e(115200); /* e(230400);e(460800); e(921600); */ - } - - rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud); - - - /* - ** Leftovers - */ - if (TtyP->termios->c_cflag & CREAD) - rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n"); -#ifdef RCV1EN - if (TtyP->termios->c_cflag & RCV1EN) - rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n"); -#endif -#ifdef XMT1EN - if (TtyP->termios->c_cflag & XMT1EN) - rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n"); -#endif - if (TtyP->termios->c_lflag & ISIG) - rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n"); - if (TtyP->termios->c_lflag & ICANON) - rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n"); - if (TtyP->termios->c_lflag & XCASE) - rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n"); - if (TtyP->termios->c_lflag & ECHO) - rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n"); - if (TtyP->termios->c_lflag & ECHOE) - rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n"); - if (TtyP->termios->c_lflag & ECHOK) - rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n"); - if (TtyP->termios->c_lflag & ECHONL) - rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n"); - if (TtyP->termios->c_lflag & NOFLSH) - rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n"); -#ifdef TOSTOP - if (TtyP->termios->c_lflag & TOSTOP) - rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n"); -#endif -#ifdef XCLUDE - if (TtyP->termios->c_lflag & XCLUDE) - rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n"); -#endif - if (TtyP->termios->c_iflag & IUCLC) - rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n"); - if (TtyP->termios->c_oflag & OPOST) - rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n"); - if (TtyP->termios->c_oflag & OLCUC) - rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n"); - if (TtyP->termios->c_oflag & ONOCR) - rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n"); - if (TtyP->termios->c_oflag & ONLRET) - rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n"); - if (TtyP->termios->c_oflag & OFILL) - rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n"); - if (TtyP->termios->c_oflag & OFDEL) - rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n"); - if (TtyP->termios->c_oflag & NLDLY) - rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n"); - if (TtyP->termios->c_oflag & CRDLY) - rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n"); - if (TtyP->termios->c_oflag & TABDLY) - rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n"); - /* - ** These things are kind of useful in a later life! - */ - PortP->Cor2Copy = Cor2; - - if (PortP->State & RIO_DELETED) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - - return RIO_FAIL; - } - - /* - ** Actually write the info into the packet to be sent - */ - writeb(cmd, &phb_param_ptr->Cmd); - writeb(Cor1, &phb_param_ptr->Cor1); - writeb(Cor2, &phb_param_ptr->Cor2); - writeb(Cor4, &phb_param_ptr->Cor4); - writeb(Cor5, &phb_param_ptr->Cor5); - writeb(TxXon, &phb_param_ptr->TxXon); - writeb(RxXon, &phb_param_ptr->RxXon); - writeb(TxXoff, &phb_param_ptr->TxXoff); - writeb(RxXoff, &phb_param_ptr->RxXoff); - writeb(LNext, &phb_param_ptr->LNext); - writeb(TxBaud, &phb_param_ptr->TxBaud); - writeb(RxBaud, &phb_param_ptr->RxBaud); - - /* - ** Set the length/command field - */ - writeb(12 | PKT_CMD_BIT, &PacketP->len); - - /* - ** The packet is formed - now, whack it off - ** to its final destination: - */ - add_transmit(PortP); - /* - ** Count characters transmitted for port statistics reporting - */ - if (PortP->statsGather) - PortP->txchars += 12; - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - - rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n"); - /* - ** job done. - */ - func_exit(); - - return 0; -} - - -/* -** We can add another packet to a transmit queue if the packet pointer pointed -** to by the TxAdd pointer has PKT_IN_USE clear in its address. -*/ -int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP) -{ - struct PKT __iomem *tp; - - *PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); - - return !((unsigned long) tp & PKT_IN_USE); -} - -/* -** To add a packet to the queue, you set the PKT_IN_USE bit in the address, -** and then move the TxAdd pointer along one position to point to the next -** packet pointer. You must wrap the pointer from the end back to the start. -*/ -void add_transmit(struct Port *PortP) -{ - if (readw(PortP->TxAdd) & PKT_IN_USE) { - rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!"); - } - writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd); - PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1; - writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add); -} - -/**************************************** - * Put a packet onto the end of the - * free list - ****************************************/ -void put_free_end(struct Host *HostP, struct PKT __iomem *PktP) -{ - struct rio_free_list __iomem *tmp_pointer; - unsigned short old_end, new_end; - unsigned long flags; - - rio_spin_lock_irqsave(&HostP->HostLock, flags); - - /************************************************* - * Put a packet back onto the back of the free list - * - ************************************************/ - - rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP); - - if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) { - new_end = RIO_OFF(HostP->Caddr, PktP); - tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end); - writew(new_end, &tmp_pointer->next); - writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev); - writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next); - writew(new_end, &HostP->ParmMapP->free_list_end); - } else { /* First packet on the free list this should never happen! */ - rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n"); - writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end); - tmp_pointer = (struct rio_free_list __iomem *) PktP; - writew(TPNULL, &tmp_pointer->prev); - writew(TPNULL, &tmp_pointer->next); - } - rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock); - rio_spin_unlock_irqrestore(&HostP->HostLock, flags); -} - -/* -** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set -** for the next packet on the queue. It will also set PktP to point to the -** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, -** then can_remove_receive() returns 0. -*/ -int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP) -{ - if (readw(PortP->RxRemove) & PKT_IN_USE) { - *PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); - return 1; - } - return 0; -} - -/* -** To remove a packet from the receive queue you clear its PKT_IN_USE bit, -** and then bump the pointers. Once the pointers get to the end, they must -** be wrapped back to the start. -*/ -void remove_receive(struct Port *PortP) -{ - writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove); - PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1; - writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove); -} diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c deleted file mode 100644 index f9b936ac3394..000000000000 --- a/drivers/char/rio/rioroute.c +++ /dev/null @@ -1,1039 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : rioroute.c -** SID : 1.3 -** Last Modified : 11/6/98 10:33:46 -** Retrieved : 11/6/98 10:33:50 -** -** ident @(#)rioroute.c 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" -#include "param.h" - -static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int); -static int RIOIsolate(struct rio_info *, struct Host *, unsigned int); -static int RIOCheck(struct Host *, unsigned int); -static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int); - - -/* -** Incoming on the ROUTE_RUP -** I wrote this while I was tired. Forgive me. -*/ -int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP) -{ - struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data; - struct PktCmd_M *PktReplyP; - struct CmdBlk *CmdBlkP; - struct Port *PortP; - struct Map *MapP; - struct Top *TopP; - int ThisLink, ThisLinkMin, ThisLinkMax; - int port; - int Mod, Mod1, Mod2; - unsigned short RtaType; - unsigned int RtaUniq; - unsigned int ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */ - unsigned int OldUnit, NewUnit, OldLink, NewLink; - char *MyType, *MyName; - int Lies; - unsigned long flags; - - /* - ** Is this unit telling us it's current link topology? - */ - if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) { - MapP = HostP->Mapping; - - /* - ** The packet can be sent either by the host or by an RTA. - ** If it comes from the host, then we need to fill in the - ** Topology array in the host structure. If it came in - ** from an RTA then we need to fill in the Mapping structure's - ** Topology array for the unit. - */ - if (Rup >= (unsigned short) MAX_RUP) { - ThisUnit = HOST_ID; - TopP = HostP->Topology; - MyType = "Host"; - MyName = HostP->Name; - ThisLinkMin = ThisLinkMax = Rup - MAX_RUP; - } else { - ThisUnit = Rup + 1; - TopP = HostP->Mapping[Rup].Topology; - MyType = "RTA"; - MyName = HostP->Mapping[Rup].Name; - ThisLinkMin = 0; - ThisLinkMax = LINKS_PER_UNIT - 1; - } - - /* - ** Lies will not be tolerated. - ** If any pair of links claim to be connected to the same - ** place, then ignore this packet completely. - */ - Lies = 0; - for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) { - /* - ** it won't lie about network interconnect, total disconnects - ** and no-IDs. (or at least, it doesn't *matter* if it does) - */ - if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP) - continue; - - for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) { - if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) { - Lies++; - } - } - } - - if (Lies) { - rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies); - rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n", - readb(&PktCmdP->RouteTopology[0].Unit), - 'A' + readb(&PktCmdP->RouteTopology[0].Link), - readb(&PktCmdP->RouteTopology[1].Unit), - 'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link)); - return 1; - } - - /* - ** now, process each link. - */ - for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) { - /* - ** this is what it was connected to - */ - OldUnit = TopP[ThisLink].Unit; - OldLink = TopP[ThisLink].Link; - - /* - ** this is what it is now connected to - */ - NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit); - NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link); - - if (OldUnit != NewUnit || OldLink != NewLink) { - /* - ** something has changed! - */ - - if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) { - rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink); - } else { - /* - ** put the new values in - */ - TopP[ThisLink].Unit = NewUnit; - TopP[ThisLink].Link = NewLink; - - RIOSetChange(p); - - if (OldUnit <= MAX_RUP) { - /* - ** If something has become bust, then re-enable them messages - */ - if (!p->RIONoMessage) - RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT); - } - - if ((NewUnit <= MAX_RUP) && !p->RIONoMessage) - RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT); - - if (NewUnit == ROUTE_NO_ID) - rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink); - - if (NewUnit == ROUTE_INTERCONNECT) { - if (!p->RIONoMessage) - printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink); - } - - /* - ** perform an update for 'the other end', so that these messages - ** only appears once. Only disconnect the other end if it is pointing - ** at us! - */ - if (OldUnit == HOST_ID) { - if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) { - rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A'); - HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT; - HostP->Topology[OldLink].Link = NO_LINK; - } else { - rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A'); - } - } else if (OldUnit <= MAX_RUP) { - if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) { - rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A'); - HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT; - HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK; - } else { - rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A'); - } - } - if (NewUnit == HOST_ID) { - rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A'); - HostP->Topology[NewLink].Unit = ThisUnit; - HostP->Topology[NewLink].Link = ThisLink; - } else if (NewUnit <= MAX_RUP) { - rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A'); - HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit; - HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink; - } - } - RIOSetChange(p); - RIOCheckIsolated(p, HostP, OldUnit); - } - } - return 1; - } - - /* - ** The only other command we recognise is a route_request command - */ - if (readb(&PktCmdP->Command) != ROUTE_REQUEST) { - rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP); - return 1; - } - - RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); - - /* - ** Determine if 8 or 16 port RTA - */ - RtaType = GetUnitType(RtaUniq); - - rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq); - - Mod = readb(&PktCmdP->ModuleTypes); - Mod1 = LONYBLE(Mod); - if (RtaType == TYPE_RTA16) { - /* - ** Only one ident is set for a 16 port RTA. To make compatible - ** with 8 port, set 2nd ident in Mod2 to the same as Mod1. - */ - Mod2 = Mod1; - rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name); - } else { - Mod2 = HINYBLE(Mod); - rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name); - } - - /* - ** try to unhook a command block from the command free list. - */ - if (!(CmdBlkP = RIOGetCmdBlk())) { - rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n"); - return 0; - } - - /* - ** Fill in the default info on the command block - */ - CmdBlkP->Packet.dest_unit = Rup; - CmdBlkP->Packet.dest_port = ROUTE_RUP; - CmdBlkP->Packet.src_unit = HOST_ID; - CmdBlkP->Packet.src_port = ROUTE_RUP; - CmdBlkP->Packet.len = PKT_CMD_BIT | 1; - CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; - PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data; - - if (!RIOBootOk(p, HostP, RtaUniq)) { - rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq); - PktReplyP->Command = ROUTE_FOAD; - memcpy(PktReplyP->CommandText, "RT_FOAD", 7); - RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return 1; - } - - /* - ** Check to see if the RTA is configured for this host - */ - for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) { - rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n", - ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum); - - /* - ** We have an entry for it. - */ - if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) { - if (RtaType == TYPE_RTA16) { - ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1; - rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2); - } else - rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit); - /* - ** If we have no knowledge of booting it, then the host has - ** been re-booted, and so we must kill the RTA, so that it - ** will be booted again (potentially with new bins) - ** and it will then re-ask for an ID, which we will service. - */ - if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) { - if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) { - if (!p->RIONoMessage) - printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name); - HostP->Mapping[ThisUnit].Flags |= MSG_DONE; - } - PktReplyP->Command = ROUTE_FOAD; - memcpy(PktReplyP->CommandText, "RT_FOAD", 7); - RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return 1; - } - - /* - ** Send the ID (entry) to this RTA. The ID number is implicit as - ** the offset into the table. It is worth noting at this stage - ** that offset zero in the table contains the entries for the - ** RTA with ID 1!!!! - */ - PktReplyP->Command = ROUTE_ALLOCATE; - PktReplyP->IDNum = ThisUnit + 1; - if (RtaType == TYPE_RTA16) { - if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) - /* - ** Adjust the phb and tx pkt dest_units for 2nd block of 8 - ** only if the RTA has ports associated (SLOT_IN_USE) - */ - RIOFixPhbs(p, HostP, ThisUnit2); - PktReplyP->IDNum2 = ThisUnit2 + 1; - rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2); - } else { - PktReplyP->IDNum2 = ROUTE_NO_ID; - rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum); - } - memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10); - - RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - - /* - ** If this is a freshly booted RTA, then we need to re-open - ** the ports, if any where open, so that data may once more - ** flow around the system! - */ - if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) { - /* - ** look at the ports associated with this beast and - ** see if any where open. If they was, then re-open - ** them, using the info from the tty flags. - */ - for (port = 0; port < PORTS_PER_RTA; port++) { - PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]; - if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) { - rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n"); - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->MagicFlags |= MAGIC_REBOOT; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - } - } - if (RtaType == TYPE_RTA16) { - for (port = 0; port < PORTS_PER_RTA; port++) { - PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]; - if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) { - rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n"); - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->MagicFlags |= MAGIC_REBOOT; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - } - } - } - } - - /* - ** keep a copy of the module types! - */ - HostP->UnixRups[ThisUnit].ModTypes = Mod; - if (RtaType == TYPE_RTA16) - HostP->UnixRups[ThisUnit2].ModTypes = Mod; - - /* - ** If either of the modules on this unit is read-only or write-only - ** or none-xprint, then we need to transfer that info over to the - ** relevant ports. - */ - if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) { - for (port = 0; port < PORTS_PER_MODULE; port++) { - p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; - p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; - p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; - p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; - } - if (RtaType == TYPE_RTA16) { - for (port = 0; port < PORTS_PER_MODULE; port++) { - p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; - p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; - p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; - p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; - } - } - } - - /* - ** Job done, get on with the interrupts! - */ - return 1; - } - } - /* - ** There is no table entry for this RTA at all. - ** - ** Lets check to see if we actually booted this unit - if not, - ** then we reset it and it will go round the loop of being booted - ** we can then worry about trying to fit it into the table. - */ - for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++) - if (HostP->ExtraUnits[ThisUnit] == RtaUniq) - break; - if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) { - /* - ** if the unit wasn't in the table, and the table wasn't full, then - ** we reset the unit, because we didn't boot it. - ** However, if the table is full, it could be that we did boot - ** this unit, and so we won't reboot it, because it isn't really - ** all that disasterous to keep the old bins in most cases. This - ** is a rather tacky feature, but we are on the edge of reallity - ** here, because the implication is that someone has connected - ** 16+MAX_EXTRA_UNITS onto one host. - */ - static int UnknownMesgDone = 0; - - if (!UnknownMesgDone) { - if (!p->RIONoMessage) - printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n"); - UnknownMesgDone = 1; - } - - PktReplyP->Command = ROUTE_FOAD; - memcpy(PktReplyP->CommandText, "RT_FOAD", 7); - } else { - /* - ** we did boot it (as an extra), and there may now be a table - ** slot free (because of a delete), so we will try to make - ** a tentative entry for it, so that the configurator can see it - ** and fill in the details for us. - */ - if (RtaType == TYPE_RTA16) { - if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) { - RIODefaultName(p, HostP, ThisUnit); - rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP); - } - } else { - if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) { - RIODefaultName(p, HostP, ThisUnit); - rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP); - } - } - PktReplyP->Command = ROUTE_USED; - memcpy(PktReplyP->CommandText, "RT_USED", 7); - } - RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return 1; -} - - -void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit) -{ - unsigned short link, port; - struct Port *PortP; - unsigned long flags; - int PortN = HostP->Mapping[unit].SysPort; - - rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN); - - if (PortN != -1) { - unsigned short dest_unit = HostP->Mapping[unit].ID2; - - /* - ** Get the link number used for the 1st 8 phbs on this unit. - */ - PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort]; - - link = readw(&PortP->PhbP->link); - - for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { - unsigned short dest_port = port + 8; - u16 __iomem *TxPktP; - struct PKT __iomem *Pkt; - - PortP = p->RIOPortp[PortN]; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - /* - ** If RTA is not powered on, the tx packets will be - ** unset, so go no further. - */ - if (!PortP->TxStart) { - rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - break; - } - - /* - ** For the second slot of a 16 port RTA, the driver needs to - ** sort out the phb to port mappings. The dest_unit for this - ** group of 8 phbs is set to the dest_unit of the accompanying - ** 8 port block. The dest_port of the second unit is set to - ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port - ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6 - ** (being the second map ID) will be sent to dest_unit 5, port - ** 14. When this RTA is deleted, dest_unit for ID 6 will be - ** restored, and the dest_port will be reduced by 8. - ** Transmit packets also have a destination field which needs - ** adjusting in the same manner. - ** Note that the unit/port bytes in 'dest' are swapped. - ** We also need to adjust the phb and rup link numbers for the - ** second block of 8 ttys. - */ - for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { - /* - ** *TxPktP is the pointer to the transmit packet on the host - ** card. This needs to be translated into a 32 bit pointer - ** so it can be accessed from the driver. - */ - Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP)); - - /* - ** If the packet is used, reset it. - */ - Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE); - writeb(dest_unit, &Pkt->dest_unit); - writeb(dest_port, &Pkt->dest_port); - } - rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); - writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); - writew(link, &PortP->PhbP->link); - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - } - /* - ** Now make sure the range of ports to be serviced includes - ** the 2nd 8 on this 16 port RTA. - */ - if (link > 3) - return; - if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) { - rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7); - writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port); - } - } -} - -/* -** Check to see if the new disconnection has isolated this unit. -** If it has, then invalidate all its link information, and tell -** the world about it. This is done to ensure that the configurator -** only gets up-to-date information about what is going on. -*/ -static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId) -{ - unsigned long flags; - rio_spin_lock_irqsave(&HostP->HostLock, flags); - - if (RIOCheck(HostP, UnitId)) { - rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId); - rio_spin_unlock_irqrestore(&HostP->HostLock, flags); - return (0); - } - - RIOIsolate(p, HostP, UnitId); - RIOSetChange(p); - rio_spin_unlock_irqrestore(&HostP->HostLock, flags); - return 1; -} - -/* -** Invalidate all the link interconnectivity of this unit, and of -** all the units attached to it. This will mean that the entire -** subnet will re-introduce itself. -*/ -static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId) -{ - unsigned int link, unit; - - UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */ - - if (UnitId >= MAX_RUP) /* dontcha just lurv unsigned maths! */ - return (0); - - if (HostP->Mapping[UnitId].Flags & BEEN_HERE) - return (0); - - HostP->Mapping[UnitId].Flags |= BEEN_HERE; - - if (p->RIOPrintDisabled == DO_PRINT) - rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name); - - for (link = 0; link < LINKS_PER_UNIT; link++) { - unit = HostP->Mapping[UnitId].Topology[link].Unit; - HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT; - HostP->Mapping[UnitId].Topology[link].Link = NO_LINK; - RIOIsolate(p, HostP, unit); - } - HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; - return 1; -} - -static int RIOCheck(struct Host *HostP, unsigned int UnitId) -{ - unsigned char link; - -/* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */ - rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId); - - if (UnitId == HOST_ID) { - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */ - return 1; - } - - UnitId--; - - if (UnitId >= MAX_RUP) { - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */ - return 0; - } - - for (link = 0; link < LINKS_PER_UNIT; link++) { - if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) { - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", - UnitId, 'A'+link)); */ - return 1; - } - } - - if (HostP->Mapping[UnitId].Flags & BEEN_HERE) { - /* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */ - return 0; - } - - HostP->Mapping[UnitId].Flags |= BEEN_HERE; - - for (link = 0; link < LINKS_PER_UNIT; link++) { - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */ - if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) { - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */ - HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; - return 1; - } - } - - HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; - - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */ - - return 0; -} - -/* -** Returns the type of unit (host, 16/8 port RTA) -*/ - -unsigned int GetUnitType(unsigned int Uniq) -{ - switch ((Uniq >> 28) & 0xf) { - case RIO_AT: - case RIO_MCA: - case RIO_EISA: - case RIO_PCI: - rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n"); - return (TYPE_HOST); - case RIO_RTA_16: - rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n"); - return (TYPE_RTA16); - case RIO_RTA: - rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n"); - return (TYPE_RTA8); - default: - rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n"); - return (99); - } -} - -int RIOSetChange(struct rio_info *p) -{ - if (p->RIOQuickCheck != NOT_CHANGED) - return (0); - p->RIOQuickCheck = CHANGED; - if (p->RIOSignalProcess) { - rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP"); - /* - psignal( RIOSignalProcess, SIGHUP ); - */ - } - return (0); -} - -static void RIOConCon(struct rio_info *p, - struct Host *HostP, - unsigned int FromId, - unsigned int FromLink, - unsigned int ToId, - unsigned int ToLink, - int Change) -{ - char *FromName; - char *FromType; - char *ToName; - char *ToType; - unsigned int tp; - -/* -** 15.10.1998 ARG - ESIL 0759 -** (Part) fix for port being trashed when opened whilst RTA "disconnected" -** -** What's this doing in here anyway ? -** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected" -** -** 09.12.1998 ARG - ESIL 0776 - part fix -** Okay, We've found out what this was all about now ! -** Someone had botched this to use RIOHalted to indicated the number of RTAs -** 'disconnected'. The value in RIOHalted was then being used in the -** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA -** is 'disconnected'. The change was put in to satisfy a customer's needs. -** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for -** the customer. -** - if (Change == CONNECT) { - if (p->RIOHalted) p->RIOHalted --; - } - else { - p->RIOHalted ++; - } -** -** So - we need to implement it slightly differently - a new member of the -** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA -** connections and disconnections. -*/ - if (Change == CONNECT) { - if (p->RIORtaDisCons) - p->RIORtaDisCons--; - } else { - p->RIORtaDisCons++; - } - - if (p->RIOPrintDisabled == DONT_PRINT) - return; - - if (FromId > ToId) { - tp = FromId; - FromId = ToId; - ToId = tp; - tp = FromLink; - FromLink = ToLink; - ToLink = tp; - } - - FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name; - FromType = FromId ? "RTA" : "HOST"; - ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name; - ToType = ToId ? "RTA" : "HOST"; - - rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); - printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); -} - -/* -** RIORemoveFromSavedTable : -** -** Delete and RTA entry from the saved table given to us -** by the configuration program. -*/ -static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap) -{ - int entry; - - /* - ** We loop for all entries even after finding an entry and - ** zeroing it because we may have two entries to delete if - ** it's a 16 port RTA. - */ - for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { - if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) { - memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map)); - } - } - return 0; -} - - -/* -** RIOCheckDisconnected : -** -** Scan the unit links to and return zero if the unit is completely -** disconnected. -*/ -static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) -{ - int link; - - - rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit); - /* - ** If the slot is tentative and does not belong to the - ** second half of a 16 port RTA then scan to see if - ** is disconnected. - */ - for (link = 0; link < LINKS_PER_UNIT; link++) { - if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT) - break; - } - - /* - ** If not all links are disconnected then we can forget about it. - */ - if (link < LINKS_PER_UNIT) - return 1; - -#ifdef NEED_TO_FIX_THIS - /* Ok so all the links are disconnected. But we may have only just - ** made this slot tentative and not yet received a topology update. - ** Lets check how long ago we made it tentative. - */ - rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit); - if (drv_getparm(LBOLT, (ulong_t *) & current_time)) - rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n"); - - elapse_time = current_time - TentTime[unit]; - rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time)); - if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) { - rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time)); - return 1; - } -#endif - - /* - ** We have found an usable slot. - ** If it is half of a 16 port RTA then delete the other half. - */ - if (HostP->Mapping[unit].ID2 != 0) { - int nOther = (HostP->Mapping[unit].ID2) - 1; - - rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther); - memset(&HostP->Mapping[nOther], 0, sizeof(struct Map)); - } - RIORemoveFromSavedTable(p, &HostP->Mapping[unit]); - - return 0; -} - - -/* -** RIOFindFreeID : -** -** This function scans the given host table for either one -** or two free unit ID's. -*/ - -int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2) -{ - int unit, tempID; - - /* - ** Initialise the ID's to MAX_RUP. - ** We do this to make the loop for setting the ID's as simple as - ** possible. - */ - *pID1 = MAX_RUP; - if (pID2 != NULL) - *pID2 = MAX_RUP; - - /* - ** Scan all entries of the host mapping table for free slots. - ** We scan for free slots first and then if that is not successful - ** we start all over again looking for tentative slots we can re-use. - */ - for (unit = 0; unit < MAX_RUP; unit++) { - rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit); - /* - ** If the flags are zero then the slot is empty. - */ - if (HostP->Mapping[unit].Flags == 0) { - rio_dprintk(RIO_DEBUG_ROUTE, " This slot is empty.\n"); - /* - ** If we haven't allocated the first ID then do it now. - */ - if (*pID1 == MAX_RUP) { - rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit); - *pID1 = unit; - - /* - ** If the second ID is not needed then we can return - ** now. - */ - if (pID2 == NULL) - return 0; - } else { - /* - ** Allocate the second slot and return. - */ - rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit); - *pID2 = unit; - return 0; - } - } - } - - /* - ** If we manage to come out of the free slot loop then we - ** need to start all over again looking for tentative slots - ** that we can re-use. - */ - rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n"); - for (unit = 0; unit < MAX_RUP; unit++) { - if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) { - rio_dprintk(RIO_DEBUG_ROUTE, " Slot %d looks promising.\n", unit); - - if (unit == *pID1) { - rio_dprintk(RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n"); - continue; - } - - /* - ** Slot is Tentative or Empty, but not a tentative second - ** slot of a 16 porter. - ** Attempt to free up this slot (and its parnter if - ** it is a 16 port slot. The second slot will become - ** empty after a call to RIOFreeDisconnected so thats why - ** we look for empty slots above as well). - */ - if (HostP->Mapping[unit].Flags != 0) - if (RIOFreeDisconnected(p, HostP, unit) != 0) - continue; - /* - ** If we haven't allocated the first ID then do it now. - */ - if (*pID1 == MAX_RUP) { - rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit); - *pID1 = unit; - - /* - ** Clear out this slot now that we intend to use it. - */ - memset(&HostP->Mapping[unit], 0, sizeof(struct Map)); - - /* - ** If the second ID is not needed then we can return - ** now. - */ - if (pID2 == NULL) - return 0; - } else { - /* - ** Allocate the second slot and return. - */ - rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", unit); - *pID2 = unit; - - /* - ** Clear out this slot now that we intend to use it. - */ - memset(&HostP->Mapping[unit], 0, sizeof(struct Map)); - - /* At this point under the right(wrong?) conditions - ** we may have a first unit ID being higher than the - ** second unit ID. This is a bad idea if we are about - ** to fill the slots with a 16 port RTA. - ** Better check and swap them over. - */ - - if (*pID1 > *pID2) { - rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2); - tempID = *pID1; - *pID1 = *pID2; - *pID2 = tempID; - } - return 0; - } - } - } - - /* - ** If we manage to get to the end of the second loop then we - ** can give up and return a failure. - */ - return 1; -} - - -/* -** The link switch scenario. -** -** Rta Wun (A) is connected to Tuw (A). -** The tables are all up to date, and the system is OK. -** -** If Wun (A) is now moved to Wun (B) before Wun (A) can -** become disconnected, then the follow happens: -** -** Tuw (A) spots the change of unit:link at the other end -** of its link and Tuw sends a topology packet reflecting -** the change: Tuw (A) now disconnected from Wun (A), and -** this is closely followed by a packet indicating that -** Tuw (A) is now connected to Wun (B). -** -** Wun (B) will spot that it has now become connected, and -** Wun will send a topology packet, which indicates that -** both Wun (A) and Wun (B) is connected to Tuw (A). -** -** Eventually Wun (A) realises that it is now disconnected -** and Wun will send out a topology packet indicating that -** Wun (A) is now disconnected. -*/ diff --git a/drivers/char/rio/riospace.h b/drivers/char/rio/riospace.h deleted file mode 100644 index ffb31d4332b9..000000000000 --- a/drivers/char/rio/riospace.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riospace.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:13 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)riospace.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_riospace_h__ -#define __rio_riospace_h__ - -#define RIO_LOCATOR_LEN 16 -#define MAX_RIO_BOARDS 4 - -/* -** DONT change this file. At all. Unless you can rebuild the entire -** device driver, which you probably can't, then the rest of the -** driver won't see any changes you make here. So don't make any. -** In particular, it won't be able to see changes to RIO_SLOTS -*/ - -struct Conf { - char Locator[24]; - unsigned int StartupTime; - unsigned int SlowCook; - unsigned int IntrPollTime; - unsigned int BreakInterval; - unsigned int Timer; - unsigned int RtaLoadBase; - unsigned int HostLoadBase; - unsigned int XpHz; - unsigned int XpCps; - char *XpOn; - char *XpOff; - unsigned int MaxXpCps; - unsigned int MinXpCps; - unsigned int SpinCmds; - unsigned int FirstAddr; - unsigned int LastAddr; - unsigned int BufferSize; - unsigned int LowWater; - unsigned int LineLength; - unsigned int CmdTime; -}; - -/* -** Board types - these MUST correspond to product codes! -*/ -#define RIO_EMPTY 0x0 -#define RIO_EISA 0x3 -#define RIO_RTA_16 0x9 -#define RIO_AT 0xA -#define RIO_MCA 0xB -#define RIO_PCI 0xD -#define RIO_RTA 0xE - -/* -** Board data structure. This is used for configuration info -*/ -struct Brd { - unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */ - unsigned char Ivec; /* POLLED or ivec number */ - unsigned char Mode; /* Control stuff, see below */ -}; - -struct Board { - char Locator[RIO_LOCATOR_LEN]; - int NumSlots; - struct Brd Boards[MAX_RIO_BOARDS]; -}; - -#define BOOT_FROM_LINK 0x00 -#define BOOT_FROM_RAM 0x01 -#define EXTERNAL_BUS_OFF 0x00 -#define EXTERNAL_BUS_ON 0x02 -#define INTERRUPT_DISABLE 0x00 -#define INTERRUPT_ENABLE 0x04 -#define BYTE_OPERATION 0x00 -#define WORD_OPERATION 0x08 -#define POLLED INTERRUPT_DISABLE -#define IRQ_15 (0x00 | INTERRUPT_ENABLE) -#define IRQ_12 (0x10 | INTERRUPT_ENABLE) -#define IRQ_11 (0x20 | INTERRUPT_ENABLE) -#define IRQ_9 (0x30 | INTERRUPT_ENABLE) -#define SLOW_LINKS 0x00 -#define FAST_LINKS 0x40 -#define SLOW_AT_BUS 0x00 -#define FAST_AT_BUS 0x80 -#define SLOW_PCI_TP 0x00 -#define FAST_PCI_TP 0x80 -/* -** Debug levels -*/ -#define DBG_NONE 0x00000000 - -#define DBG_INIT 0x00000001 -#define DBG_OPEN 0x00000002 -#define DBG_CLOSE 0x00000004 -#define DBG_IOCTL 0x00000008 - -#define DBG_READ 0x00000010 -#define DBG_WRITE 0x00000020 -#define DBG_INTR 0x00000040 -#define DBG_PROC 0x00000080 - -#define DBG_PARAM 0x00000100 -#define DBG_CMD 0x00000200 -#define DBG_XPRINT 0x00000400 -#define DBG_POLL 0x00000800 - -#define DBG_DAEMON 0x00001000 -#define DBG_FAIL 0x00002000 -#define DBG_MODEM 0x00004000 -#define DBG_LIST 0x00008000 - -#define DBG_ROUTE 0x00010000 -#define DBG_UTIL 0x00020000 -#define DBG_BOOT 0x00040000 -#define DBG_BUFFER 0x00080000 - -#define DBG_MON 0x00100000 -#define DBG_SPECIAL 0x00200000 -#define DBG_VPIX 0x00400000 -#define DBG_FLUSH 0x00800000 - -#define DBG_QENABLE 0x01000000 - -#define DBG_ALWAYS 0x80000000 - -#endif /* __rio_riospace_h__ */ diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c deleted file mode 100644 index 3d15802dc0f3..000000000000 --- a/drivers/char/rio/riotable.c +++ /dev/null @@ -1,941 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riotable.c -** SID : 1.2 -** Last Modified : 11/6/98 10:33:47 -** Retrieved : 11/6/98 10:33:50 -** -** ident @(#)riotable.c 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include - - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" -#include "param.h" -#include "protsts.h" - -/* -** A configuration table has been loaded. It is now up to us -** to sort it out and use the information contained therein. -*/ -int RIONewTable(struct rio_info *p) -{ - int Host, Host1, Host2, NameIsUnique, Entry, SubEnt; - struct Map *MapP; - struct Map *HostMapP; - struct Host *HostP; - - char *cptr; - - /* - ** We have been sent a new table to install. We need to break - ** it down into little bits and spread it around a bit to see - ** what we have got. - */ - /* - ** Things to check: - ** (things marked 'xx' aren't checked any more!) - ** (1) That there are no booted Hosts/RTAs out there. - ** (2) That the names are properly formed - ** (3) That blank entries really are. - ** xx (4) That hosts mentioned in the table actually exist. xx - ** (5) That the IDs are unique (per host). - ** (6) That host IDs are zero - ** (7) That port numbers are valid - ** (8) That port numbers aren't duplicated - ** (9) That names aren't duplicated - ** xx (10) That hosts that actually exist are mentioned in the table. xx - */ - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n"); - if (p->RIOSystemUp) { /* (1) */ - p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED; - return -EBUSY; - } - - p->RIOError.Error = NOTHING_WRONG_AT_ALL; - p->RIOError.Entry = -1; - p->RIOError.Other = -1; - - for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) { - MapP = &p->RIOConnectTable[Entry]; - if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) { - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n"); - cptr = MapP->Name; /* (2) */ - cptr[MAX_NAME_LEN - 1] = '\0'; - if (cptr[0] == '\0') { - memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA NN" : "HOST NN", 8); - MapP->Name[5] = '0' + Entry / 10; - MapP->Name[6] = '0' + Entry % 10; - } - while (*cptr) { - if (*cptr < ' ' || *cptr > '~') { - p->RIOError.Error = BAD_CHARACTER_IN_NAME; - p->RIOError.Entry = Entry; - return -ENXIO; - } - cptr++; - } - } - - /* - ** If the entry saved was a tentative entry then just forget - ** about it. - */ - if (MapP->Flags & SLOT_TENTATIVE) { - MapP->HostUniqueNum = 0; - MapP->RtaUniqueNum = 0; - continue; - } - - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n"); - if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) { /* (3) */ - if (MapP->ID || MapP->SysPort || MapP->Flags) { - rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name); - p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL; - p->RIOError.Entry = Entry; - return -ENXIO; - } - rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n"); - continue; - } - - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n"); - for (Host = 0; Host < p->RIONumHosts; Host++) { /* (4) */ - if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) { - HostP = &p->RIOHosts[Host]; - /* - ** having done the lookup, we don't really want to do - ** it again, so hang the host number in a safe place - */ - MapP->Topology[0].Unit = Host; - break; - } - } - - if (Host >= p->RIONumHosts) { - rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum); - MapP->HostUniqueNum = 0; - /* MapP->RtaUniqueNum = 0; */ - /* MapP->ID = 0; */ - /* MapP->Flags = 0; */ - /* MapP->SysPort = 0; */ - /* MapP->Name[0] = 0; */ - continue; - } - - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n"); - if (MapP->RtaUniqueNum) { /* (5) */ - if (!MapP->ID) { - rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name); - p->RIOError.Error = ZERO_RTA_ID; - p->RIOError.Entry = Entry; - return -ENXIO; - } - if (MapP->ID > MAX_RUP) { - rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID); - p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; - p->RIOError.Entry = Entry; - return -ENXIO; - } - for (SubEnt = 0; SubEnt < Entry; SubEnt++) { - if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) { - rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name); - p->RIOError.Error = DUPLICATED_RTA_ID; - p->RIOError.Entry = Entry; - p->RIOError.Other = SubEnt; - return -ENXIO; - } - /* - ** If the RtaUniqueNum is the same, it may be looking at both - ** entries for a 16 port RTA, so check the ids - */ - if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum) - && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) { - rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name); - rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name); - p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER; - p->RIOError.Entry = Entry; - p->RIOError.Other = SubEnt; - return -ENXIO; - } - } - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n"); - /* (7a) */ - if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) { - rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA); - p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; - p->RIOError.Entry = Entry; - return -ENXIO; - } - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n"); - /* (7b) */ - if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) { - rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name); - p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; - p->RIOError.Entry = Entry; - return -ENXIO; - } - for (SubEnt = 0; SubEnt < Entry; SubEnt++) { - if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT) - continue; - if (p->RIOConnectTable[SubEnt].RtaUniqueNum) { - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n"); - /* (8) */ - if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) { - rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort); - p->RIOError.Error = TTY_NUMBER_IN_USE; - p->RIOError.Entry = Entry; - p->RIOError.Other = SubEnt; - return -ENXIO; - } - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n"); - if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */ - rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name); - p->RIOError.Error = NAME_USED_TWICE; - p->RIOError.Entry = Entry; - p->RIOError.Other = SubEnt; - return -ENXIO; - } - } - } - } else { /* (6) */ - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n"); - if (MapP->ID) { - rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name); - p->RIOError.Error = HOST_ID_NOT_ZERO; - p->RIOError.Entry = Entry; - return -ENXIO; - } - if (MapP->SysPort != NO_PORT) { - rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name); - p->RIOError.Error = HOST_SYSPORT_BAD; - p->RIOError.Entry = Entry; - return -ENXIO; - } - } - } - - /* - ** wow! if we get here then it's a goody! - */ - - /* - ** Zero the (old) entries for each host... - */ - for (Host = 0; Host < RIO_HOSTS; Host++) { - for (Entry = 0; Entry < MAX_RUP; Entry++) { - memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map)); - } - memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name)); - } - - /* - ** Copy in the new table entries - */ - for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) { - rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry); - MapP = &p->RIOConnectTable[Entry]; - - /* - ** Now, if it is an empty slot ignore it! - */ - if (MapP->HostUniqueNum == 0) - continue; - - /* - ** we saved the host number earlier, so grab it back - */ - HostP = &p->RIOHosts[MapP->Topology[0].Unit]; - - /* - ** If it is a host, then we only need to fill in the name field. - */ - if (MapP->ID == 0) { - rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name); - memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN); - continue; - } - - /* - ** Its an RTA entry, so fill in the host mapping entries for it - ** and the port mapping entries. Notice that entry zero is for - ** ID one. - */ - HostMapP = &HostP->Mapping[MapP->ID - 1]; - - if (MapP->Flags & SLOT_IN_USE) { - rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name); - /* - ** structure assign, then sort out the bits we shouldn't have done - */ - *HostMapP = *MapP; - - HostMapP->Flags = SLOT_IN_USE; - if (MapP->Flags & RTA16_SECOND_SLOT) - HostMapP->Flags |= RTA16_SECOND_SLOT; - - RIOReMapPorts(p, HostP, HostMapP); - } else { - rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name); - } - } - - for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) { - p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry]; - } - - for (Host = 0; Host < p->RIONumHosts; Host++) { - for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) { - p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT; - p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK; - } - for (Entry = 0; Entry < MAX_RUP; Entry++) { - for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) { - p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT; - p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK; - } - } - if (!p->RIOHosts[Host].Name[0]) { - memcpy(p->RIOHosts[Host].Name, "HOST 1", 7); - p->RIOHosts[Host].Name[5] += Host; - } - /* - ** Check that default name assigned is unique. - */ - Host1 = Host; - NameIsUnique = 0; - while (!NameIsUnique) { - NameIsUnique = 1; - for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) { - if (Host2 == Host) - continue; - if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name) - == 0) { - NameIsUnique = 0; - Host1++; - if (Host1 >= p->RIONumHosts) - Host1 = 0; - p->RIOHosts[Host].Name[5] = '1' + Host1; - } - } - } - /* - ** Rename host if name already used. - */ - if (Host1 != Host) { - rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name); - memcpy(p->RIOHosts[Host].Name, "HOST 1", 7); - p->RIOHosts[Host].Name[5] += Host1; - } - rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name); - } - return 0; -} - -/* -** User process needs the config table - build it from first -** principles. -** -* FIXME: SMP locking -*/ -int RIOApel(struct rio_info *p) -{ - int Host; - int link; - int Rup; - int Next = 0; - struct Map *MapP; - struct Host *HostP; - unsigned long flags; - - rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n"); - - memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES); - - for (Host = 0; Host < RIO_HOSTS; Host++) { - rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host); - HostP = &p->RIOHosts[Host]; - rio_spin_lock_irqsave(&HostP->HostLock, flags); - - MapP = &p->RIOConnectTable[Next++]; - MapP->HostUniqueNum = HostP->UniqueNum; - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { - rio_spin_unlock_irqrestore(&HostP->HostLock, flags); - continue; - } - MapP->RtaUniqueNum = 0; - MapP->ID = 0; - MapP->Flags = SLOT_IN_USE; - MapP->SysPort = NO_PORT; - for (link = 0; link < LINKS_PER_UNIT; link++) - MapP->Topology[link] = HostP->Topology[link]; - memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN); - for (Rup = 0; Rup < MAX_RUP; Rup++) { - if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) { - p->RIOConnectTable[Next] = HostP->Mapping[Rup]; - if (HostP->Mapping[Rup].Flags & SLOT_IN_USE) - p->RIOConnectTable[Next].Flags |= SLOT_IN_USE; - if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE) - p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE; - if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT) - p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT; - Next++; - } - } - rio_spin_unlock_irqrestore(&HostP->HostLock, flags); - } - return 0; -} - -/* -** config.rio has taken a dislike to one of the gross maps entries. -** if the entry is suitably inactive, then we can gob on it and remove -** it from the table. -*/ -int RIODeleteRta(struct rio_info *p, struct Map *MapP) -{ - int host, entry, port, link; - int SysPort; - struct Host *HostP; - struct Map *HostMapP; - struct Port *PortP; - int work_done = 0; - unsigned long lock_flags, sem_flags; - - rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum); - - for (host = 0; host < p->RIONumHosts; host++) { - HostP = &p->RIOHosts[host]; - - rio_spin_lock_irqsave(&HostP->HostLock, lock_flags); - - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { - rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); - continue; - } - - for (entry = 0; entry < MAX_RUP; entry++) { - if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) { - HostMapP = &HostP->Mapping[entry]; - rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name); - - /* - ** Check all four links of the unit are disconnected - */ - for (link = 0; link < LINKS_PER_UNIT; link++) { - if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) { - rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n"); - p->RIOError.Error = UNIT_IS_IN_USE; - rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); - return -EBUSY; - } - } - /* - ** Slot has been allocated, BUT not booted/routed/ - ** connected/selected or anything else-ed - */ - SysPort = HostMapP->SysPort; - - if (SysPort != NO_PORT) { - for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) { - PortP = p->RIOPortp[port]; - rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n"); - - rio_spin_lock_irqsave(&PortP->portSem, sem_flags); - - PortP->Mapped = 0; - - if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) { - - rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n"); - PortP->TxBufferIn = PortP->TxBufferOut = 0; - /* What should I do - wakeup( &PortP->TxBufferIn ); - wakeup( &PortP->TxBufferOut); - */ - PortP->InUse = NOT_INUSE; - /* What should I do - wakeup( &PortP->InUse ); - signal(PortP->TtyP->t_pgrp,SIGKILL); - ttyflush(PortP->TtyP,(FREAD|FWRITE)); - */ - PortP->State |= RIO_CLOSING | RIO_DELETED; - } - - /* - ** For the second slot of a 16 port RTA, the - ** driver needs to reset the changes made to - ** the phb to port mappings in RIORouteRup. - */ - if (PortP->SecondBlock) { - u16 dest_unit = HostMapP->ID; - u16 dest_port = port - SysPort; - u16 __iomem *TxPktP; - struct PKT __iomem *Pkt; - - for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { - /* - ** *TxPktP is the pointer to the - ** transmit packet on the host card. - ** This needs to be translated into - ** a 32 bit pointer so it can be - ** accessed from the driver. - */ - Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); - rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port); - writew(dest_unit, &Pkt->dest_unit); - writew(dest_port, &Pkt->dest_port); - } - rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); - writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); - } - rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags); - } - } - rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n"); - memset(HostMapP, 0, sizeof(struct Map)); - work_done++; - } - } - rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); - } - - /* XXXXX lock me up */ - for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { - if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) { - memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map)); - work_done++; - } - if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) { - memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map)); - work_done++; - } - } - if (work_done) - return 0; - - rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n"); - p->RIOError.Error = COULDNT_FIND_ENTRY; - return -ENXIO; -} - -int RIOAssignRta(struct rio_info *p, struct Map *MapP) -{ - int host; - struct Map *HostMapP; - char *sptr; - int link; - - - rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort); - - if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) { - rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); - p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - if (MapP->RtaUniqueNum == 0) { - rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n"); - p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO; - return -EINVAL; - } - if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) { - rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA); - p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) { - rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort); - p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - /* - ** Copy the name across to the map entry. - */ - MapP->Name[MAX_NAME_LEN - 1] = '\0'; - sptr = MapP->Name; - while (*sptr) { - if (*sptr < ' ' || *sptr > '~') { - rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); - p->RIOError.Error = BAD_CHARACTER_IN_NAME; - return -EINVAL; - } - sptr++; - } - - for (host = 0; host < p->RIONumHosts; host++) { - if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) { - if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) { - p->RIOError.Error = HOST_NOT_RUNNING; - return -ENXIO; - } - - /* - ** Now we have a host we need to allocate an ID - ** if the entry does not already have one. - */ - if (MapP->ID == (u16) - 1) { - int nNewID; - - rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name); - /* - ** The idea here is to allow RTA's to be assigned - ** before they actually appear on the network. - ** This allows the addition of RTA's without having - ** to plug them in. - ** What we do is: - ** - Find a free ID and allocate it to the RTA. - ** - If this map entry is the second half of a - ** 16 port entry then find the other half and - ** make sure the 2 cross reference each other. - */ - if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) { - p->RIOError.Error = COULDNT_FIND_ENTRY; - return -EBUSY; - } - MapP->ID = (u16) nNewID + 1; - rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID); - HostMapP = &p->RIOHosts[host].Mapping[nNewID]; - HostMapP->RtaUniqueNum = MapP->RtaUniqueNum; - HostMapP->HostUniqueNum = MapP->HostUniqueNum; - HostMapP->ID = MapP->ID; - for (link = 0; link < LINKS_PER_UNIT; link++) { - HostMapP->Topology[link].Unit = ROUTE_DISCONNECT; - HostMapP->Topology[link].Link = NO_LINK; - } - if (MapP->Flags & RTA16_SECOND_SLOT) { - int unit; - - for (unit = 0; unit < MAX_RUP; unit++) - if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum) - break; - if (unit == MAX_RUP) { - p->RIOError.Error = COULDNT_FIND_ENTRY; - return -EBUSY; - } - HostMapP->Flags |= RTA16_SECOND_SLOT; - HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID; - p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID; - rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID); - } - } - - HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1]; - - if (HostMapP->Flags & SLOT_IN_USE) { - rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID); - p->RIOError.Error = ID_ALREADY_IN_USE; - return -EBUSY; - } - - /* - ** Assign the sys ports and the name, and mark the slot as - ** being in use. - */ - HostMapP->SysPort = MapP->SysPort; - if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) - memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN); - HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]); -#endif - if (MapP->Flags & RTA16_SECOND_SLOT) - HostMapP->Flags |= RTA16_SECOND_SLOT; - - RIOReMapPorts(p, &p->RIOHosts[host], HostMapP); - /* - ** Adjust 2nd block of 8 phbs - */ - if (MapP->Flags & RTA16_SECOND_SLOT) - RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1); - - if (HostMapP->SysPort != NO_PORT) { - if (HostMapP->SysPort < p->RIOFirstPortsBooted) - p->RIOFirstPortsBooted = HostMapP->SysPort; - if (HostMapP->SysPort > p->RIOLastPortsBooted) - p->RIOLastPortsBooted = HostMapP->SysPort; - } - if (MapP->Flags & RTA16_SECOND_SLOT) - rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name); - else - rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name); - return 0; - } - } - p->RIOError.Error = UNKNOWN_HOST_NUMBER; - rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); - return -ENXIO; -} - - -int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP) -{ - struct Port *PortP; - unsigned int SubEnt; - unsigned int HostPort; - unsigned int SysPort; - u16 RtaType; - unsigned long flags; - - rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID); - - /* - ** We need to tell the UnixRups which sysport the rup corresponds to - */ - HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort; - - if (HostMapP->SysPort == NO_PORT) - return (0); - - RtaType = GetUnitType(HostMapP->RtaUniqueNum); - rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1); - - /* - ** now map each of its eight ports - */ - for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) { - rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort); - SysPort = HostMapP->SysPort + SubEnt; /* portnumber within system */ - /* portnumber on host */ - - HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt; - - rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp); - PortP = p->RIOPortp[SysPort]; - rio_dprintk(RIO_DEBUG_TABLE, "Map port\n"); - - /* - ** Point at all the real neat data structures - */ - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->HostP = HostP; - PortP->Caddr = HostP->Caddr; - - /* - ** The PhbP cannot be filled in yet - ** unless the host has been booted - */ - if ((HostP->Flags & RUN_STATE) == RC_RUNNING) { - struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; - PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add)); - PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start)); - PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end)); - PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove)); - PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start)); - PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end)); - } else - PortP->PhbP = NULL; - - /* - ** port related flags - */ - PortP->HostPort = HostPort; - /* - ** For each part of a 16 port RTA, RupNum is ID - 1. - */ - PortP->RupNum = HostMapP->ID - 1; - if (HostMapP->Flags & RTA16_SECOND_SLOT) { - PortP->ID2 = HostMapP->ID2 - 1; - PortP->SecondBlock = 1; - } else { - PortP->ID2 = 0; - PortP->SecondBlock = 0; - } - PortP->RtaUniqueNum = HostMapP->RtaUniqueNum; - - /* - ** If the port was already mapped then thats all we need to do. - */ - if (PortP->Mapped) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - continue; - } else - HostMapP->Flags &= ~RTA_NEWBOOT; - - PortP->State = 0; - PortP->Config = 0; - /* - ** Check out the module type - if it is special (read only etc.) - ** then we need to set flags in the PortP->Config. - ** Note: For 16 port RTA, all ports are of the same type. - */ - if (RtaType == TYPE_RTA16) { - PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE]; - } else { - if (SubEnt < PORTS_PER_MODULE) - PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; - else - PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; - } - - /* - ** more port related flags - */ - PortP->PortState = 0; - PortP->ModemLines = 0; - PortP->ModemState = 0; - PortP->CookMode = COOK_WELL; - PortP->ParamSem = 0; - PortP->FlushCmdBodge = 0; - PortP->WflushFlag = 0; - PortP->MagicFlags = 0; - PortP->Lock = 0; - PortP->Store = 0; - PortP->FirstOpen = 1; - - /* - ** Buffers 'n things - */ - PortP->RxDataStart = 0; - PortP->Cor2Copy = 0; - PortP->Name = &HostMapP->Name[0]; - PortP->statsGather = 0; - PortP->txchars = 0; - PortP->rxchars = 0; - PortP->opens = 0; - PortP->closes = 0; - PortP->ioctls = 0; - if (PortP->TxRingBuffer) - memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); - else if (p->RIOBufferSize) { - PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL); - } - PortP->TxBufferOut = 0; - PortP->TxBufferIn = 0; - PortP->Debug = 0; - /* - ** LastRxTgl stores the state of the rx toggle bit for this - ** port, to be compared with the state of the next pkt received. - ** If the same, we have received the same rx pkt from the RTA - ** twice. Initialise to a value not equal to PHB_RX_TGL or 0. - */ - PortP->LastRxTgl = ~(u8) PHB_RX_TGL; - - /* - ** and mark the port as usable - */ - PortP->Mapped = 1; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - } - if (HostMapP->SysPort < p->RIOFirstPortsMapped) - p->RIOFirstPortsMapped = HostMapP->SysPort; - if (HostMapP->SysPort > p->RIOLastPortsMapped) - p->RIOLastPortsMapped = HostMapP->SysPort; - - return 0; -} - -int RIOChangeName(struct rio_info *p, struct Map *MapP) -{ - int host; - struct Map *HostMapP; - char *sptr; - - rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort); - - if (MapP->ID > MAX_RUP) { - rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); - p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; - return -EINVAL; - } - - MapP->Name[MAX_NAME_LEN - 1] = '\0'; - sptr = MapP->Name; - - while (*sptr) { - if (*sptr < ' ' || *sptr > '~') { - rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); - p->RIOError.Error = BAD_CHARACTER_IN_NAME; - return -EINVAL; - } - sptr++; - } - - for (host = 0; host < p->RIONumHosts; host++) { - if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) { - if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) { - p->RIOError.Error = HOST_NOT_RUNNING; - return -ENXIO; - } - if (MapP->ID == 0) { - memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN); - return 0; - } - - HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1]; - - if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) { - p->RIOError.Error = RTA_NUMBER_WRONG; - return -ENXIO; - } - memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN); - return 0; - } - } - p->RIOError.Error = UNKNOWN_HOST_NUMBER; - rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); - return -ENXIO; -} diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c deleted file mode 100644 index 8a90393faf3c..000000000000 --- a/drivers/char/rio/riotty.c +++ /dev/null @@ -1,654 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riotty.c -** SID : 1.3 -** Last Modified : 11/6/98 10:33:47 -** Retrieved : 11/6/98 10:33:50 -** -** ident @(#)riotty.c 1.3 -** -** ----------------------------------------------------------------------------- -*/ - -#define __EXPLICIT_DEF_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - - -#include "linux_compat.h" -#include "rio_linux.h" -#include "pkt.h" -#include "daemon.h" -#include "rio.h" -#include "riospace.h" -#include "cmdpkt.h" -#include "map.h" -#include "rup.h" -#include "port.h" -#include "riodrvr.h" -#include "rioinfo.h" -#include "func.h" -#include "errors.h" -#include "pci.h" - -#include "parmmap.h" -#include "unixrup.h" -#include "board.h" -#include "host.h" -#include "phb.h" -#include "link.h" -#include "cmdblk.h" -#include "route.h" -#include "cirrus.h" -#include "rioioctl.h" -#include "param.h" - -static void RIOClearUp(struct Port *PortP); - -/* Below belongs in func.h */ -int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); - - -extern struct rio_info *p; - - -int riotopen(struct tty_struct *tty, struct file *filp) -{ - unsigned int SysPort; - int repeat_this = 250; - struct Port *PortP; /* pointer to the port structure */ - unsigned long flags; - int retval = 0; - - func_enter(); - - /* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close - is going to oops. - */ - tty->driver_data = NULL; - - SysPort = rio_minor(tty); - - if (p->RIOFailed) { - rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n"); - func_exit(); - return -ENXIO; - } - - rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped); - - /* - ** Validate that we have received a legitimate request. - ** Currently, just check that we are opening a port on - ** a host card that actually exists, and that the port - ** has been mapped onto a host. - */ - if (SysPort >= RIO_PORTS) { /* out of range ? */ - rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort); - func_exit(); - return -ENXIO; - } - - /* - ** Grab pointer to the port stucture - */ - PortP = p->RIOPortp[SysPort]; /* Get control struc */ - rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP); - if (!PortP->Mapped) { /* we aren't mapped yet! */ - /* - ** The system doesn't know which RTA this port - ** corresponds to. - */ - rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n"); - func_exit(); - return -ENXIO; - } - - tty->driver_data = PortP; - - PortP->gs.port.tty = tty; - PortP->gs.port.count++; - - rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt); - - retval = gs_init_port(&PortP->gs); - if (retval) { - PortP->gs.port.count--; - return -ENXIO; - } - /* - ** If the host hasn't been booted yet, then - ** fail - */ - if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) { - rio_dprintk(RIO_DEBUG_TTY, "Host not running\n"); - func_exit(); - return -ENXIO; - } - - /* - ** If the RTA has not booted yet and the user has choosen to block - ** until the RTA is present then we must spin here waiting for - ** the RTA to boot. - */ - /* I find the above code a bit hairy. I find the below code - easier to read and shorter. Now, if it works too that would - be great... -- REW - */ - rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n"); - while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { - if (!PortP->WaitUntilBooted) { - rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n"); - func_exit(); - return -ENXIO; - } - - /* Under Linux you'd normally use a wait instead of this - busy-waiting. I'll stick with the old implementation for - now. --REW - */ - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n"); - func_exit(); - return -EINTR; - } - if (repeat_this-- <= 0) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); - func_exit(); - return -EIO; - } - } - rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n"); - rio_spin_lock_irqsave(&PortP->portSem, flags); - if (p->RIOHalted) { - goto bombout; - } - - /* - ** If the port is in the final throws of being closed, - ** we should wait here (politely), waiting - ** for it to finish, so that it doesn't close us! - */ - while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n"); - if (repeat_this-- <= 0) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - retval = -EINTR; - goto bombout; - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_spin_lock_irqsave(&PortP->portSem, flags); - retval = -EINTR; - goto bombout; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - - if (!PortP->Mapped) { - rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - retval = -ENXIO; - func_exit(); - return retval; - } - - if (p->RIOHalted) { - goto bombout; - } - -/* -** 15.10.1998 ARG - ESIL 0761 part fix -** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure, -** we need to make sure that the flags are clear when the port is opened. -*/ - /* Uh? Suppose I turn these on and then another process opens - the port again? The flags get cleared! Not good. -- REW */ - if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) { - PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW); - } - - if (!(PortP->firstOpen)) { /* First time ? */ - rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n"); - - - PortP->firstOpen++; - PortP->CookMode = 0; /* XXX RIOCookMode(tp); */ - PortP->InUse = NOT_INUSE; - - /* Tentative fix for bug PR27. Didn't work. */ - /* PortP->gs.xmit_cnt = 0; */ - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - - /* Someone explain to me why this delay/config is - here. If I read the docs correctly the "open" - command piggybacks the parameters immediately. - -- REW */ - RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */ - rio_spin_lock_irqsave(&PortP->portSem, flags); - - /* - ** wait for the port to be not closed. - */ - while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n"); - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - func_exit(); - return -EINTR; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - - if (p->RIOHalted) { - retval = -EIO; - bombout: - /* RIOClearUp( PortP ); */ - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return retval; - } - rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n"); - } - rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n"); - /* - ** ACTION - ** insert test for carrier here. -- ??? - ** I already see that test here. What's the deal? -- REW - */ - if ((PortP->gs.port.tty->termios->c_cflag & CLOCAL) || - (PortP->ModemState & RIOC_MSVR1_CD)) { - rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort); - /* - tp->tm.c_state |= CARR_ON; - wakeup((caddr_t) &tp->tm.c_canq); - */ - PortP->State |= RIO_CARR_ON; - wake_up_interruptible(&PortP->gs.port.open_wait); - } else { /* no carrier - wait for DCD */ - /* - while (!(PortP->gs.port.tty->termios->c_state & CARR_ON) && - !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) - */ - while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) { - rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort); - /* - PortP->gs.port.tty->termios->c_state |= WOPEN; - */ - PortP->State |= RIO_WOPEN; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_spin_lock_irqsave(&PortP->portSem, flags); - /* - ** ACTION: verify that this is a good thing - ** to do here. -- ??? - ** I think it's OK. -- REW - */ - rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort); - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - /* - tp->tm.c_state &= ~WOPEN; - */ - PortP->State &= ~RIO_WOPEN; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - return -EINTR; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - PortP->State &= ~RIO_WOPEN; - } - if (p->RIOHalted) - goto bombout; - rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); - PortP->State |= RIO_MOPEN; - - if (p->RIOHalted) - goto bombout; - - rio_dprintk(RIO_DEBUG_TTY, "high level open done\n"); - - /* - ** Count opens for port statistics reporting - */ - if (PortP->statsGather) - PortP->opens++; - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n"); - func_exit(); - return 0; -} - -/* -** RIOClose the port. -** The operating system thinks that this is last close for the device. -** As there are two interfaces to the port (Modem and tty), we need to -** check that both are closed before we close the device. -*/ -int riotclose(void *ptr) -{ - struct Port *PortP = ptr; /* pointer to the port structure */ - int deleted = 0; - int try = -1; /* Disable the timeouts by setting them to -1 */ - int repeat_this = -1; /* Congrats to those having 15 years of - uptime! (You get to break the driver.) */ - unsigned long end_time; - struct tty_struct *tty; - unsigned long flags; - int rv = 0; - - rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum); - - /* PortP = p->RIOPortp[SysPort]; */ - rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP); - /* tp = PortP->TtyP; *//* Get tty */ - tty = PortP->gs.port.tty; - rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty); - - if (PortP->gs.closing_wait) - end_time = jiffies + PortP->gs.closing_wait; - else - end_time = jiffies + MAX_SCHEDULE_TIMEOUT; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - /* - ** Setting this flag will make any process trying to open - ** this port block until we are complete closing it. - */ - PortP->State |= RIO_CLOSING; - - if ((PortP->State & RIO_DELETED)) { - rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n"); - deleted = 1; - } - - if (p->RIOHalted) { - RIOClearUp(PortP); - rv = -EIO; - goto close_end; - } - - rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n"); - /* - ** clear the open bits for this device - */ - PortP->State &= ~RIO_MOPEN; - PortP->State &= ~RIO_CARR_ON; - PortP->ModemState &= ~RIOC_MSVR1_CD; - /* - ** If the device was open as both a Modem and a tty line - ** then we need to wimp out here, as the port has not really - ** been finally closed (gee, whizz!) The test here uses the - ** bit for the OTHER mode of operation, to see if THAT is - ** still active! - */ - if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) { - /* - ** The port is still open for the other task - - ** return, pretending that we are still active. - */ - rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum); - PortP->State &= ~RIO_CLOSING; - if (PortP->firstOpen) - PortP->firstOpen--; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EIO; - } - - rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n"); - - PortP->State &= ~RIO_DYNOROD; - - /* - ** This is where we wait for the port - ** to drain down before closing. Bye-bye.... - ** (We never meant to do this) - */ - rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n"); - - if (!deleted) - while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) { - if (repeat_this-- <= 0) { - rv = -EINTR; - rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - goto close_end; - } - rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n"); - rv = -EINTR; - rio_spin_lock_irqsave(&PortP->portSem, flags); - goto close_end; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - - PortP->TxBufferIn = PortP->TxBufferOut = 0; - repeat_this = 0xff; - - PortP->InUse = 0; - if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) { - /* - ** The port has been re-opened for the other task - - ** return, pretending that we are still active. - */ - rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum); - PortP->State &= ~RIO_CLOSING; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (PortP->firstOpen) - PortP->firstOpen--; - return -EIO; - } - - if (p->RIOHalted) { - RIOClearUp(PortP); - goto close_end; - } - - /* Can't call RIOShortCommand with the port locked. */ - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - - if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) { - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - rio_spin_lock_irqsave(&PortP->portSem, flags); - goto close_end; - } - - if (!deleted) - while (try && (PortP->PortState & PORT_ISOPEN)) { - try--; - if (time_after(jiffies, end_time)) { - rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n"); - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - break; - } - rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN); - - if (p->RIOHalted) { - RIOClearUp(PortP); - rio_spin_lock_irqsave(&PortP->portSem, flags); - goto close_end; - } - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n"); - RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); - break; - } - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try); - - /* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */ - -/* -** 15.10.1998 ARG - ESIL 0761 part fix -** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened. -*/ - PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW); - - /* - ** Count opens for port statistics reporting - */ - if (PortP->statsGather) - PortP->closes++; - -close_end: - /* XXX: Why would a "DELETED" flag be reset here? I'd have - thought that a "deleted" flag means that the port was - permanently gone, but here we can make it reappear by it - being in close during the "deletion". - */ - PortP->State &= ~(RIO_CLOSING | RIO_DELETED); - if (PortP->firstOpen) - PortP->firstOpen--; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprintk(RIO_DEBUG_TTY, "Return from close\n"); - return rv; -} - - - -static void RIOClearUp(struct Port *PortP) -{ - rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n"); - PortP->Config = 0; /* Direct semaphore */ - PortP->PortState = 0; - PortP->firstOpen = 0; - PortP->FlushCmdBodge = 0; - PortP->ModemState = PortP->CookMode = 0; - PortP->Mapped = 0; - PortP->WflushFlag = 0; - PortP->MagicFlags = 0; - PortP->RxDataStart = 0; - PortP->TxBufferIn = 0; - PortP->TxBufferOut = 0; -} - -/* -** Put a command onto a port. -** The PortPointer, command, length and arg are passed. -** The len is the length *inclusive* of the command byte, -** and so for a command that takes no data, len==1. -** The arg is a single byte, and is only used if len==2. -** Other values of len aren't allowed, and will cause -** a panic. -*/ -int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg) -{ - struct PKT __iomem *PacketP; - int retries = 20; /* at 10 per second -> 2 seconds */ - unsigned long flags; - - rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n"); - - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); - return RIO_FAIL; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - - /* - ** If the port is in use for pre-emptive command, then wait for it to - ** be free again. - */ - while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (retries-- <= 0) { - return RIO_FAIL; - } - if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) { - return RIO_FAIL; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return RIO_FAIL; - } - - while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (retries-- <= 0) { - rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n"); - return RIO_FAIL; - } - if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) { - return RIO_FAIL; - } - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - - if (p->RIOHalted) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return RIO_FAIL; - } - - /* - ** set the command byte and the argument byte - */ - writeb(command, &PacketP->data[0]); - - if (len == 2) - writeb(arg, &PacketP->data[1]); - - /* - ** set the length of the packet and set the command bit. - */ - writeb(PKT_CMD_BIT | len, &PacketP->len); - - add_transmit(PortP); - /* - ** Count characters transmitted for port statistics reporting - */ - if (PortP->statsGather) - PortP->txchars += len; - - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL; -} - - diff --git a/drivers/char/rio/route.h b/drivers/char/rio/route.h deleted file mode 100644 index 46e963771c30..000000000000 --- a/drivers/char/rio/route.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* R O U T E H E A D E R - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _route_h -#define _route_h - -#define MAX_LINKS 4 -#define MAX_NODES 17 /* Maximum nodes in a subnet */ -#define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for - 1 bit per node */ -#define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete - info about cost etc. */ -#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE) - /* Number of nodes we can squeeze - into one packet */ -#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1) -/************************************************ - * Define the types of command for the ROUTE RUP. - ************************************************/ -#define ROUTE_REQUEST 0 /* Request an ID */ -#define ROUTE_FOAD 1 /* Kill the RTA */ -#define ROUTE_ALREADY 2 /* ID given already */ -#define ROUTE_USED 3 /* All ID's used */ -#define ROUTE_ALLOCATE 4 /* Here it is */ -#define ROUTE_REQ_TOP 5 /* I bet you didn't expect.... - the Topological Inquisition */ -#define ROUTE_TOPOLOGY 6 /* Topology request answered FD */ -/******************************************************************* - * Define the Route Map Structure - * - * The route map gives a pointer to a Link Structure to use. - * This allows Disconnected Links to be checked quickly - ******************************************************************/ -typedef struct COST_ROUTE COST_ROUTE; -struct COST_ROUTE { - unsigned char cost; /* Cost down this link */ - unsigned char route[NODE_BYTES]; /* Nodes through this route */ -}; - -typedef struct ROUTE_STR ROUTE_STR; -struct ROUTE_STR { - COST_ROUTE cost_route[MAX_LINKS]; - /* cost / route for this link */ - ushort favoured; /* favoured link */ -}; - - -#define NO_LINK (short) 5 /* Link unattached */ -#define ROUTE_NO_ID (short) 100 /* No Id */ -#define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */ -#define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */ - - -#define SYNC_RUP (ushort) 255 -#define COMMAND_RUP (ushort) 254 -#define ERROR_RUP (ushort) 253 -#define POLL_RUP (ushort) 252 -#define BOOT_RUP (ushort) 251 -#define ROUTE_RUP (ushort) 250 -#define STATUS_RUP (ushort) 249 -#define POWER_RUP (ushort) 248 - -#define HIGHEST_RUP (ushort) 255 /* Set to Top one */ -#define LOWEST_RUP (ushort) 248 /* Set to bottom one */ - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h deleted file mode 100644 index 4ae90cb207a9..000000000000 --- a/drivers/char/rio/rup.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* R U P S T R U C T U R E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _rup_h -#define _rup_h 1 - -#define MAX_RUP ((short) 16) -#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ - -/************************************************* - * Define all the packet request stuff - ************************************************/ -#define TX_RUP_INACTIVE 0 /* Nothing to transmit */ -#define TX_PACKET_READY 1 /* Transmit packet ready */ -#define TX_LOCK_RUP 2 /* Transmit side locked */ - -#define RX_RUP_INACTIVE 0 /* Nothing received */ -#define RX_PACKET_READY 1 /* Packet received */ - -#define RUP_NO_OWNER 0xff /* RUP not owned by any process */ - -struct RUP { - u16 txpkt; /* Outgoing packet */ - u16 rxpkt; /* Incoming packet */ - u16 link; /* Which link to send down? */ - u8 rup_dest_unit[2]; /* Destination unit */ - u16 handshake; /* For handshaking */ - u16 timeout; /* Timeout */ - u16 status; /* Status */ - u16 txcontrol; /* Transmit control */ - u16 rxcontrol; /* Receive control */ -}; - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h deleted file mode 100644 index 7abf0cba0f2c..000000000000 --- a/drivers/char/rio/unixrup.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : unixrup.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:20 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)unixrup.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_unixrup_h__ -#define __rio_unixrup_h__ - -/* -** UnixRup data structure. This contains pointers to actual RUPs on the -** host card, and all the command/boot control stuff. -*/ -struct UnixRup { - struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */ - struct CmdBlk *CmdPendingP; /* The command currently being sent */ - struct RUP __iomem *RupP; /* the Rup to send it to */ - unsigned int Id; /* Id number */ - unsigned int BaseSysPort; /* SysPort of first tty on this RTA */ - unsigned int ModTypes; /* Modules on this RTA */ - spinlock_t RupLock; /* Lock structure for MPX */ - /* struct lockb RupLock; *//* Lock structure for MPX */ -}; - -#endif /* __rio_unixrup_h__ */ diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c deleted file mode 100644 index 3f47c2ead8e5..000000000000 --- a/drivers/char/ser_a2232.c +++ /dev/null @@ -1,831 +0,0 @@ -/* drivers/char/ser_a2232.c */ - -/* $Id: ser_a2232.c,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */ - -/* Linux serial driver for the Amiga A2232 board */ - -/* This driver is MAINTAINED. Before applying any changes, please contact - * the author. - */ - -/* Copyright (c) 2000-2001 Enver Haase - * alias The A2232 driver project - * All rights reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -/***************************** Documentation ************************/ -/* - * This driver is in EXPERIMENTAL state. That means I could not find - * someone with five A2232 boards with 35 ports running at 19200 bps - * at the same time and test the machine's behaviour. - * However, I know that you can performance-tweak this driver (see - * the source code). - * One thing to consider is the time this driver consumes during the - * Amiga's vertical blank interrupt. Everything that is to be done - * _IS DONE_ when entering the vertical blank interrupt handler of - * this driver. - * However, it would be more sane to only do the job for only ONE card - * instead of ALL cards at a time; or, more generally, to handle only - * SOME ports instead of ALL ports at a time. - * However, as long as no-one runs into problems I guess I shouldn't - * change the driver as it runs fine for me :) . - * - * Version history of this file: - * 0.4 Resolved licensing issues. - * 0.3 Inclusion in the Linux/m68k tree, small fixes. - * 0.2 Added documentation, minor typo fixes. - * 0.1 Initial release. - * - * TO DO: - * - Handle incoming BREAK events. I guess "Stevens: Advanced - * Programming in the UNIX(R) Environment" is a good reference - * on what is to be done. - * - When installing as a module, don't simply 'printk' text, but - * send it to the TTY used by the user. - * - * THANKS TO: - * - Jukka Marin (65EC02 code). - * - The other NetBSD developers on whose A2232 driver I had a - * pretty close look. However, I didn't copy any code so it - * is okay to put my code under the GPL and include it into - * Linux. - */ -/***************************** End of Documentation *****************/ - -/***************************** Defines ******************************/ -/* - * Enables experimental 115200 (normal) 230400 (turbo) baud rate. - * The A2232 specification states it can only operate at speeds up to - * 19200 bits per second, and I was not able to send a file via - * "sz"/"rz" and a null-modem cable from one A2232 port to another - * at 115200 bits per second. - * However, this might work for you. - */ -#undef A2232_SPEEDHACK -/* - * Default is not to use RTS/CTS so you could be talked to death. - */ -#define A2232_SUPPRESS_RTSCTS_WARNING -/************************* End of Defines ***************************/ - -/***************************** Includes *****************************/ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "ser_a2232.h" -#include "ser_a2232fw.h" -/************************* End of Includes **************************/ - -/***************************** Prototypes ***************************/ -/* The interrupt service routine */ -static irqreturn_t a2232_vbl_inter(int irq, void *data); -/* Initialize the port structures */ -static void a2232_init_portstructs(void); -/* Initialize and register TTY drivers. */ -/* returns 0 IFF successful */ -static int a2232_init_drivers(void); - -/* BEGIN GENERIC_SERIAL PROTOTYPES */ -static void a2232_disable_tx_interrupts(void *ptr); -static void a2232_enable_tx_interrupts(void *ptr); -static void a2232_disable_rx_interrupts(void *ptr); -static void a2232_enable_rx_interrupts(void *ptr); -static int a2232_carrier_raised(struct tty_port *port); -static void a2232_shutdown_port(void *ptr); -static int a2232_set_real_termios(void *ptr); -static int a2232_chars_in_buffer(void *ptr); -static void a2232_close(void *ptr); -static void a2232_hungup(void *ptr); -/* static void a2232_getserial (void *ptr, struct serial_struct *sp); */ -/* END GENERIC_SERIAL PROTOTYPES */ - -/* Functions that the TTY driver struct expects */ -static int a2232_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg); -static void a2232_throttle(struct tty_struct *tty); -static void a2232_unthrottle(struct tty_struct *tty); -static int a2232_open(struct tty_struct * tty, struct file * filp); -/************************* End of Prototypes ************************/ - -/***************************** Global variables *********************/ -/*--------------------------------------------------------------------------- - * Interface from generic_serial.c back here - *--------------------------------------------------------------------------*/ -static struct real_driver a2232_real_driver = { - a2232_disable_tx_interrupts, - a2232_enable_tx_interrupts, - a2232_disable_rx_interrupts, - a2232_enable_rx_interrupts, - a2232_shutdown_port, - a2232_set_real_termios, - a2232_chars_in_buffer, - a2232_close, - a2232_hungup, - NULL /* a2232_getserial */ -}; - -static void *a2232_driver_ID = &a2232_driver_ID; // Some memory address WE own. - -/* Ports structs */ -static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES]; - -/* TTY driver structs */ -static struct tty_driver *a2232_driver; - -/* nr of cards completely (all ports) and correctly configured */ -static int nr_a2232; - -/* zorro_dev structs for the A2232's */ -static struct zorro_dev *zd_a2232[MAX_A2232_BOARDS]; -/***************************** End of Global variables **************/ - -/* Helper functions */ - -static inline volatile struct a2232memory *a2232mem(unsigned int board) -{ - return (volatile struct a2232memory *)ZTWO_VADDR(zd_a2232[board]->resource.start); -} - -static inline volatile struct a2232status *a2232stat(unsigned int board, - unsigned int portonboard) -{ - volatile struct a2232memory *mem = a2232mem(board); - return &(mem->Status[portonboard]); -} - -static inline void a2232_receive_char(struct a2232_port *port, int ch, int err) -{ -/* Mostly stolen from other drivers. - Maybe one could implement a more efficient version by not only - transferring one character at a time. -*/ - struct tty_struct *tty = port->gs.port.tty; - -#if 0 - switch(err) { - case TTY_BREAK: - break; - case TTY_PARITY: - break; - case TTY_OVERRUN: - break; - case TTY_FRAME: - break; - } -#endif - - tty_insert_flip_char(tty, ch, err); - tty_flip_buffer_push(tty); -} - -/***************************** Functions ****************************/ -/*** BEGIN OF REAL_DRIVER FUNCTIONS ***/ - -static void a2232_disable_tx_interrupts(void *ptr) -{ - struct a2232_port *port; - volatile struct a2232status *stat; - unsigned long flags; - - port = ptr; - stat = a2232stat(port->which_a2232, port->which_port_on_a2232); - stat->OutDisable = -1; - - /* Does this here really have to be? */ - local_irq_save(flags); - port->gs.port.flags &= ~GS_TX_INTEN; - local_irq_restore(flags); -} - -static void a2232_enable_tx_interrupts(void *ptr) -{ - struct a2232_port *port; - volatile struct a2232status *stat; - unsigned long flags; - - port = ptr; - stat = a2232stat(port->which_a2232, port->which_port_on_a2232); - stat->OutDisable = 0; - - /* Does this here really have to be? */ - local_irq_save(flags); - port->gs.port.flags |= GS_TX_INTEN; - local_irq_restore(flags); -} - -static void a2232_disable_rx_interrupts(void *ptr) -{ - struct a2232_port *port; - port = ptr; - port->disable_rx = -1; -} - -static void a2232_enable_rx_interrupts(void *ptr) -{ - struct a2232_port *port; - port = ptr; - port->disable_rx = 0; -} - -static int a2232_carrier_raised(struct tty_port *port) -{ - struct a2232_port *ap = container_of(port, struct a2232_port, gs.port); - return ap->cd_status; -} - -static void a2232_shutdown_port(void *ptr) -{ - struct a2232_port *port; - volatile struct a2232status *stat; - unsigned long flags; - - port = ptr; - stat = a2232stat(port->which_a2232, port->which_port_on_a2232); - - local_irq_save(flags); - - port->gs.port.flags &= ~GS_ACTIVE; - - if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { - /* Set DTR and RTS to Low, flush output. - The NetBSD driver "msc.c" does it this way. */ - stat->Command = ( (stat->Command & ~A2232CMD_CMask) | - A2232CMD_Close ); - stat->OutFlush = -1; - stat->Setup = -1; - } - - local_irq_restore(flags); - - /* After analyzing control flow, I think a2232_shutdown_port - is actually the last call from the system when at application - level someone issues a "echo Hello >>/dev/ttyY0". - Therefore I think the MOD_DEC_USE_COUNT should be here and - not in "a2232_close()". See the comment in "sx.c", too. - If you run into problems, compile this driver into the - kernel instead of compiling it as a module. */ -} - -static int a2232_set_real_termios(void *ptr) -{ - unsigned int cflag, baud, chsize, stopb, parity, softflow; - int rate; - int a2232_param, a2232_cmd; - unsigned long flags; - unsigned int i; - struct a2232_port *port = ptr; - volatile struct a2232status *status; - volatile struct a2232memory *mem; - - if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; - - status = a2232stat(port->which_a2232, port->which_port_on_a2232); - mem = a2232mem(port->which_a2232); - - a2232_param = a2232_cmd = 0; - - // get baud rate - baud = port->gs.baud; - if (baud == 0) { - /* speed == 0 -> drop DTR, do nothing else */ - local_irq_save(flags); - // Clear DTR (and RTS... mhhh). - status->Command = ( (status->Command & ~A2232CMD_CMask) | - A2232CMD_Close ); - status->OutFlush = -1; - status->Setup = -1; - - local_irq_restore(flags); - return 0; - } - - rate = A2232_BAUD_TABLE_NOAVAIL; - for (i=0; i < A2232_BAUD_TABLE_NUM_RATES * 3; i += 3){ - if (a2232_baud_table[i] == baud){ - if (mem->Common.Crystal == A2232_TURBO) rate = a2232_baud_table[i+2]; - else rate = a2232_baud_table[i+1]; - } - } - if (rate == A2232_BAUD_TABLE_NOAVAIL){ - printk("a2232: Board %d Port %d unsupported baud rate: %d baud. Using another.\n",port->which_a2232,port->which_port_on_a2232,baud); - // This is useful for both (turbo or normal) Crystal versions. - rate = A2232PARAM_B9600; - } - a2232_param |= rate; - - cflag = port->gs.port.tty->termios->c_cflag; - - // get character size - chsize = cflag & CSIZE; - switch (chsize){ - case CS8: a2232_param |= A2232PARAM_8Bit; break; - case CS7: a2232_param |= A2232PARAM_7Bit; break; - case CS6: a2232_param |= A2232PARAM_6Bit; break; - case CS5: a2232_param |= A2232PARAM_5Bit; break; - default: printk("a2232: Board %d Port %d unsupported character size: %d. Using 8 data bits.\n", - port->which_a2232,port->which_port_on_a2232,chsize); - a2232_param |= A2232PARAM_8Bit; break; - } - - // get number of stop bits - stopb = cflag & CSTOPB; - if (stopb){ // two stop bits instead of one - printk("a2232: Board %d Port %d 2 stop bits unsupported. Using 1 stop bit.\n", - port->which_a2232,port->which_port_on_a2232); - } - - // Warn if RTS/CTS not wanted - if (!(cflag & CRTSCTS)){ -#ifndef A2232_SUPPRESS_RTSCTS_WARNING - printk("a2232: Board %d Port %d cannot switch off firmware-implemented RTS/CTS hardware flow control.\n", - port->which_a2232,port->which_port_on_a2232); -#endif - } - - /* I think this is correct. - However, IXOFF means _input_ flow control and I wonder - if one should care about IXON _output_ flow control, - too. If this makes problems, one should turn the A2232 - firmware XON/XOFF "SoftFlow" flow control off and use - the conventional way of inserting START/STOP characters - by hand in throttle()/unthrottle(). - */ - softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF ); - - // get Parity (Enabled/Disabled? If Enabled, Odd or Even?) - parity = cflag & (PARENB | PARODD); - if (parity & PARENB){ - if (parity & PARODD){ - a2232_cmd |= A2232CMD_OddParity; - } - else{ - a2232_cmd |= A2232CMD_EvenParity; - } - } - else a2232_cmd |= A2232CMD_NoParity; - - - /* Hmm. Maybe an own a2232_port structure - member would be cleaner? */ - if (cflag & CLOCAL) - port->gs.port.flags &= ~ASYNC_CHECK_CD; - else - port->gs.port.flags |= ASYNC_CHECK_CD; - - - /* Now we have all parameters and can go to set them: */ - local_irq_save(flags); - - status->Param = a2232_param | A2232PARAM_RcvBaud; - status->Command = a2232_cmd | A2232CMD_Open | A2232CMD_Enable; - status->SoftFlow = softflow; - status->OutDisable = 0; - status->Setup = -1; - - local_irq_restore(flags); - return 0; -} - -static int a2232_chars_in_buffer(void *ptr) -{ - struct a2232_port *port; - volatile struct a2232status *status; - unsigned char ret; /* we need modulo-256 arithmetics */ - port = ptr; - status = a2232stat(port->which_a2232, port->which_port_on_a2232); -#if A2232_IOBUFLEN != 256 -#error "Re-Implement a2232_chars_in_buffer()!" -#endif - ret = (status->OutHead - status->OutTail); - return ret; -} - -static void a2232_close(void *ptr) -{ - a2232_disable_tx_interrupts(ptr); - a2232_disable_rx_interrupts(ptr); - /* see the comment in a2232_shutdown_port above. */ -} - -static void a2232_hungup(void *ptr) -{ - a2232_close(ptr); -} -/*** END OF REAL_DRIVER FUNCTIONS ***/ - -/*** BEGIN FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/ -static int a2232_ioctl( struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; -} - -static void a2232_throttle(struct tty_struct *tty) -{ -/* Throttle: System cannot take another chars: Drop RTS or - send the STOP char or whatever. - The A2232 firmware does RTS/CTS anyway, and XON/XOFF - if switched on. So the only thing we can do at this - layer here is not taking any characters out of the - A2232 buffer any more. */ - struct a2232_port *port = tty->driver_data; - port->throttle_input = -1; -} - -static void a2232_unthrottle(struct tty_struct *tty) -{ -/* Unthrottle: dual to "throttle()" above. */ - struct a2232_port *port = tty->driver_data; - port->throttle_input = 0; -} - -static int a2232_open(struct tty_struct * tty, struct file * filp) -{ -/* More or less stolen from other drivers. */ - int line; - int retval; - struct a2232_port *port; - - line = tty->index; - port = &a2232_ports[line]; - - tty->driver_data = port; - port->gs.port.tty = tty; - port->gs.port.count++; - retval = gs_init_port(&port->gs); - if (retval) { - port->gs.port.count--; - return retval; - } - port->gs.port.flags |= GS_ACTIVE; - retval = gs_block_til_ready(port, filp); - - if (retval) { - port->gs.port.count--; - return retval; - } - - a2232_enable_rx_interrupts(port); - - return 0; -} -/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/ - -static irqreturn_t a2232_vbl_inter(int irq, void *data) -{ -#if A2232_IOBUFLEN != 256 -#error "Re-Implement a2232_vbl_inter()!" -#endif - -struct a2232_port *port; -volatile struct a2232memory *mem; -volatile struct a2232status *status; -unsigned char newhead; -unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */ -unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */ -volatile u_char *ibuf, *cbuf, *obuf; -int ch, err, n, p; - for (n = 0; n < nr_a2232; n++){ /* for every completely initialized A2232 board */ - mem = a2232mem(n); - for (p = 0; p < NUMLINES; p++){ /* for every port on this board */ - err = 0; - port = &a2232_ports[n*NUMLINES+p]; - if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */ - - status = a2232stat(n,p); - - if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */ - newhead = status->InHead; /* 65EC02 write pointer */ - bufpos = status->InTail; - - /* check for input for this port */ - if (newhead != bufpos) { - /* buffer for input chars/events */ - ibuf = mem->InBuf[p]; - - /* data types of bytes in ibuf */ - cbuf = mem->InCtl[p]; - - /* do for all chars */ - while (bufpos != newhead) { - /* which type of input data? */ - switch (cbuf[bufpos]) { - /* switch on input event (CD, BREAK, etc.) */ - case A2232INCTL_EVENT: - switch (ibuf[bufpos++]) { - case A2232EVENT_Break: - /* TODO: Handle BREAK signal */ - break; - /* A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are - handled in a separate queue and should not occur here. */ - case A2232EVENT_Sync: - printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring."); - break; - default: - printk("A2232: 65EC02 software broken, unknown event type %d occurred.\n",ibuf[bufpos-1]); - } /* event type switch */ - break; - case A2232INCTL_CHAR: - /* Receive incoming char */ - a2232_receive_char(port, ibuf[bufpos], err); - bufpos++; - break; - default: - printk("A2232: 65EC02 software broken, unknown data type %d occurred.\n",cbuf[bufpos]); - bufpos++; - } /* switch on input data type */ - } /* while there's something in the buffer */ - - status->InTail = bufpos; /* tell 65EC02 what we've read */ - - } /* if there was something in the buffer */ - } /* If input is not disabled */ - - /* Now check if there's something to output */ - obuf = mem->OutBuf[p]; - bufpos = status->OutHead; - while ( (port->gs.xmit_cnt > 0) && - (!port->gs.port.tty->stopped) && - (!port->gs.port.tty->hw_stopped) ){ /* While there are chars to transmit */ - if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */ - ch = port->gs.xmit_buf[port->gs.xmit_tail]; /* get the next char to transmit */ - port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */ - obuf[bufpos++] = ch; /* put it into the A2232 buffer */ - port->gs.xmit_cnt--; - } - else{ /* If A2232 the buffer is full */ - break; /* simply stop filling it. */ - } - } - status->OutHead = bufpos; - - /* WakeUp if output buffer runs low */ - if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { - tty_wakeup(port->gs.port.tty); - } - } // if the port is used - } // for every port on the board - - /* Now check the CD message queue */ - newhead = mem->Common.CDHead; - bufpos = mem->Common.CDTail; - if (newhead != bufpos){ /* There are CD events in queue */ - ocd = mem->Common.CDStatus; /* get old status bits */ - while (newhead != bufpos){ /* read all events */ - ncd = mem->CDBuf[bufpos++]; /* get one event */ - ccd = ncd ^ ocd; /* mask of changed lines */ - ocd = ncd; /* save new status bits */ - for(p=0; p < NUMLINES; p++){ /* for all ports */ - if (ccd & 1){ /* this one changed */ - - struct a2232_port *port = &a2232_ports[n*7+p]; - port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */ - - if (!(port->gs.port.flags & ASYNC_CHECK_CD)) - ; /* Don't report DCD changes */ - else if (port->cd_status) { // if DCD on: DCD went UP! - - /* Are we blocking in open?*/ - wake_up_interruptible(&port->gs.port.open_wait); - } - else { // if DCD off: DCD went DOWN! - if (port->gs.port.tty) - tty_hangup (port->gs.port.tty); - } - - } // if CD changed for this port - ccd >>= 1; - ncd >>= 1; /* Shift bits for next line */ - } // for every port - } // while CD events in queue - mem->Common.CDStatus = ocd; /* save new status */ - mem->Common.CDTail = bufpos; /* remove events */ - } // if events in CD queue - - } // for every completely initialized A2232 board - return IRQ_HANDLED; -} - -static const struct tty_port_operations a2232_port_ops = { - .carrier_raised = a2232_carrier_raised, -}; - -static void a2232_init_portstructs(void) -{ - struct a2232_port *port; - int i; - - for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) { - port = a2232_ports + i; - tty_port_init(&port->gs.port); - port->gs.port.ops = &a2232_port_ops; - port->which_a2232 = i/NUMLINES; - port->which_port_on_a2232 = i%NUMLINES; - port->disable_rx = port->throttle_input = port->cd_status = 0; - port->gs.magic = A2232_MAGIC; - port->gs.close_delay = HZ/2; - port->gs.closing_wait = 30 * HZ; - port->gs.rd = &a2232_real_driver; - } -} - -static const struct tty_operations a2232_ops = { - .open = a2232_open, - .close = gs_close, - .write = gs_write, - .put_char = gs_put_char, - .flush_chars = gs_flush_chars, - .write_room = gs_write_room, - .chars_in_buffer = gs_chars_in_buffer, - .flush_buffer = gs_flush_buffer, - .ioctl = a2232_ioctl, - .throttle = a2232_throttle, - .unthrottle = a2232_unthrottle, - .set_termios = gs_set_termios, - .stop = gs_stop, - .start = gs_start, - .hangup = gs_hangup, -}; - -static int a2232_init_drivers(void) -{ - int error; - - a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232); - if (!a2232_driver) - return -ENOMEM; - a2232_driver->owner = THIS_MODULE; - a2232_driver->driver_name = "commodore_a2232"; - a2232_driver->name = "ttyY"; - a2232_driver->major = A2232_NORMAL_MAJOR; - a2232_driver->type = TTY_DRIVER_TYPE_SERIAL; - a2232_driver->subtype = SERIAL_TYPE_NORMAL; - a2232_driver->init_termios = tty_std_termios; - a2232_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - a2232_driver->init_termios.c_ispeed = 9600; - a2232_driver->init_termios.c_ospeed = 9600; - a2232_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(a2232_driver, &a2232_ops); - if ((error = tty_register_driver(a2232_driver))) { - printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n", - error); - put_tty_driver(a2232_driver); - return 1; - } - return 0; -} - -static int __init a2232board_init(void) -{ - struct zorro_dev *z; - - unsigned int boardaddr; - int bcount; - short start; - u_char *from; - volatile u_char *to; - volatile struct a2232memory *mem; - int error, i; - -#ifdef CONFIG_SMP - return -ENODEV; /* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */ -#endif - - if (!MACH_IS_AMIGA){ - return -ENODEV; - } - - printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */ - - z = NULL; - nr_a2232 = 0; - while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){ - if ( (z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && - (z->id != ZORRO_PROD_CBM_A2232) ){ - continue; // The board found was no A2232 - } - if (!zorro_request_device(z,"A2232 driver")) - continue; - - printk("Commodore A2232 found (#%d).\n",nr_a2232); - - zd_a2232[nr_a2232] = z; - - boardaddr = ZTWO_VADDR( z->resource.start ); - printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start))); - - mem = (volatile struct a2232memory *) boardaddr; - - (void) mem->Enable6502Reset; /* copy the code across to the board */ - to = (u_char *)mem; from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2; - start = *(short *)from; - from += sizeof(start); - to += start; - while(bcount--) *to++ = *from++; - printk("65EC02 software uploaded to the A2232 memory.\n"); - - mem->Common.Crystal = A2232_UNKNOWN; /* use automatic speed check */ - - /* start 6502 running */ - (void) mem->ResetBoard; - printk("A2232's 65EC02 CPU up and running.\n"); - - /* wait until speed detector has finished */ - for (bcount = 0; bcount < 2000; bcount++) { - udelay(1000); - if (mem->Common.Crystal) - break; - } - printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: ")); - switch (mem->Common.Crystal){ - case A2232_UNKNOWN: - printk("Unknown crystal.\n"); - break; - case A2232_NORMAL: - printk ("Normal crystal.\n"); - break; - case A2232_TURBO: - printk ("Turbo crystal.\n"); - break; - default: - printk ("0x%x. Huh?\n",mem->Common.Crystal); - } - - nr_a2232++; - - } - - printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */ - - a2232_init_portstructs(); - - /* - a2232_init_drivers also registers the drivers. Must be here because all boards - have to be detected first. - */ - if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx? - - error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0, - "A2232 serial VBL", a2232_driver_ID); - if (error) { - for (i = 0; i < nr_a2232; i++) - zorro_release_device(zd_a2232[i]); - tty_unregister_driver(a2232_driver); - put_tty_driver(a2232_driver); - } - return error; -} - -static void __exit a2232board_exit(void) -{ - int i; - - for (i = 0; i < nr_a2232; i++) { - zorro_release_device(zd_a2232[i]); - } - - tty_unregister_driver(a2232_driver); - put_tty_driver(a2232_driver); - free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID); -} - -module_init(a2232board_init); -module_exit(a2232board_exit); - -MODULE_AUTHOR("Enver Haase"); -MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/ser_a2232.h b/drivers/char/ser_a2232.h deleted file mode 100644 index bc09eb9e118b..000000000000 --- a/drivers/char/ser_a2232.h +++ /dev/null @@ -1,202 +0,0 @@ -/* drivers/char/ser_a2232.h */ - -/* $Id: ser_a2232.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */ - -/* Linux serial driver for the Amiga A2232 board */ - -/* This driver is MAINTAINED. Before applying any changes, please contact - * the author. - */ - -/* Copyright (c) 2000-2001 Enver Haase - * alias The A2232 driver project - * All rights reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _SER_A2232_H_ -#define _SER_A2232_H_ - -/* - How many boards are to be supported at maximum; - "up to five A2232 Multiport Serial Cards may be installed in a - single Amiga 2000" states the A2232 User's Guide. If you have - more slots available, you might want to change the value below. -*/ -#define MAX_A2232_BOARDS 5 - -#ifndef A2232_NORMAL_MAJOR -/* This allows overriding on the compiler commandline, or in a "major.h" - include or something like that */ -#define A2232_NORMAL_MAJOR 224 /* /dev/ttyY* */ -#define A2232_CALLOUT_MAJOR 225 /* /dev/cuy* */ -#endif - -/* Some magic is always good - Who knows :) */ -#define A2232_MAGIC 0x000a2232 - -/* A2232 port structure to keep track of the - status of every single line used */ -struct a2232_port{ - struct gs_port gs; - unsigned int which_a2232; - unsigned int which_port_on_a2232; - short disable_rx; - short throttle_input; - short cd_status; -}; - -#define NUMLINES 7 /* number of lines per board */ -#define A2232_IOBUFLEN 256 /* number of bytes per buffer */ -#define A2232_IOBUFLENMASK 0xff /* mask for maximum number of bytes */ - - -#define A2232_UNKNOWN 0 /* crystal not known */ -#define A2232_NORMAL 1 /* normal A2232 (1.8432 MHz oscillator) */ -#define A2232_TURBO 2 /* turbo A2232 (3.6864 MHz oscillator) */ - - -struct a2232common { - char Crystal; /* normal (1) or turbo (2) board? */ - u_char Pad_a; - u_char TimerH; /* timer value after speed check */ - u_char TimerL; - u_char CDHead; /* head pointer for CD message queue */ - u_char CDTail; /* tail pointer for CD message queue */ - u_char CDStatus; - u_char Pad_b; -}; - -struct a2232status { - u_char InHead; /* input queue head */ - u_char InTail; /* input queue tail */ - u_char OutDisable; /* disables output */ - u_char OutHead; /* output queue head */ - u_char OutTail; /* output queue tail */ - u_char OutCtrl; /* soft flow control character to send */ - u_char OutFlush; /* flushes output buffer */ - u_char Setup; /* causes reconfiguration */ - u_char Param; /* parameter byte - see A2232PARAM */ - u_char Command; /* command byte - see A2232CMD */ - u_char SoftFlow; /* enables xon/xoff flow control */ - /* private 65EC02 fields: */ - u_char XonOff; /* stores XON/XOFF enable/disable */ -}; - -#define A2232_MEMPAD1 \ - (0x0200 - NUMLINES * sizeof(struct a2232status) - \ - sizeof(struct a2232common)) -#define A2232_MEMPAD2 (0x2000 - NUMLINES * A2232_IOBUFLEN - A2232_IOBUFLEN) - -struct a2232memory { - struct a2232status Status[NUMLINES]; /* 0x0000-0x006f status areas */ - struct a2232common Common; /* 0x0070-0x0077 common flags */ - u_char Dummy1[A2232_MEMPAD1]; /* 0x00XX-0x01ff */ - u_char OutBuf[NUMLINES][A2232_IOBUFLEN];/* 0x0200-0x08ff output bufs */ - u_char InBuf[NUMLINES][A2232_IOBUFLEN]; /* 0x0900-0x0fff input bufs */ - u_char InCtl[NUMLINES][A2232_IOBUFLEN]; /* 0x1000-0x16ff control data */ - u_char CDBuf[A2232_IOBUFLEN]; /* 0x1700-0x17ff CD event buffer */ - u_char Dummy2[A2232_MEMPAD2]; /* 0x1800-0x2fff */ - u_char Code[0x1000]; /* 0x3000-0x3fff code area */ - u_short InterruptAck; /* 0x4000 intr ack */ - u_char Dummy3[0x3ffe]; /* 0x4002-0x7fff */ - u_short Enable6502Reset; /* 0x8000 Stop board, */ - /* 6502 RESET line held low */ - u_char Dummy4[0x3ffe]; /* 0x8002-0xbfff */ - u_short ResetBoard; /* 0xc000 reset board & run, */ - /* 6502 RESET line held high */ -}; - -#undef A2232_MEMPAD1 -#undef A2232_MEMPAD2 - -#define A2232INCTL_CHAR 0 /* corresponding byte in InBuf is a character */ -#define A2232INCTL_EVENT 1 /* corresponding byte in InBuf is an event */ - -#define A2232EVENT_Break 1 /* break set */ -#define A2232EVENT_CarrierOn 2 /* carrier raised */ -#define A2232EVENT_CarrierOff 3 /* carrier dropped */ -#define A2232EVENT_Sync 4 /* don't know, defined in 2232.ax */ - -#define A2232CMD_Enable 0x1 /* enable/DTR bit */ -#define A2232CMD_Close 0x2 /* close the device */ -#define A2232CMD_Open 0xb /* open the device */ -#define A2232CMD_CMask 0xf /* command mask */ -#define A2232CMD_RTSOff 0x0 /* turn off RTS */ -#define A2232CMD_RTSOn 0x8 /* turn on RTS */ -#define A2232CMD_Break 0xd /* transmit a break */ -#define A2232CMD_RTSMask 0xc /* mask for RTS stuff */ -#define A2232CMD_NoParity 0x00 /* don't use parity */ -#define A2232CMD_OddParity 0x20 /* odd parity */ -#define A2232CMD_EvenParity 0x60 /* even parity */ -#define A2232CMD_ParityMask 0xe0 /* parity mask */ - -#define A2232PARAM_B115200 0x0 /* baud rates */ -#define A2232PARAM_B50 0x1 -#define A2232PARAM_B75 0x2 -#define A2232PARAM_B110 0x3 -#define A2232PARAM_B134 0x4 -#define A2232PARAM_B150 0x5 -#define A2232PARAM_B300 0x6 -#define A2232PARAM_B600 0x7 -#define A2232PARAM_B1200 0x8 -#define A2232PARAM_B1800 0x9 -#define A2232PARAM_B2400 0xa -#define A2232PARAM_B3600 0xb -#define A2232PARAM_B4800 0xc -#define A2232PARAM_B7200 0xd -#define A2232PARAM_B9600 0xe -#define A2232PARAM_B19200 0xf -#define A2232PARAM_BaudMask 0xf /* baud rate mask */ -#define A2232PARAM_RcvBaud 0x10 /* enable receive baud rate */ -#define A2232PARAM_8Bit 0x00 /* numbers of bits */ -#define A2232PARAM_7Bit 0x20 -#define A2232PARAM_6Bit 0x40 -#define A2232PARAM_5Bit 0x60 -#define A2232PARAM_BitMask 0x60 /* numbers of bits mask */ - - -/* Standard speeds tables, -1 means unavailable, -2 means 0 baud: switch off line */ -#define A2232_BAUD_TABLE_NOAVAIL -1 -#define A2232_BAUD_TABLE_NUM_RATES (18) -static int a2232_baud_table[A2232_BAUD_TABLE_NUM_RATES*3] = { - //Baud //Normal //Turbo - 50, A2232PARAM_B50, A2232_BAUD_TABLE_NOAVAIL, - 75, A2232PARAM_B75, A2232_BAUD_TABLE_NOAVAIL, - 110, A2232PARAM_B110, A2232_BAUD_TABLE_NOAVAIL, - 134, A2232PARAM_B134, A2232_BAUD_TABLE_NOAVAIL, - 150, A2232PARAM_B150, A2232PARAM_B75, - 200, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL, - 300, A2232PARAM_B300, A2232PARAM_B150, - 600, A2232PARAM_B600, A2232PARAM_B300, - 1200, A2232PARAM_B1200, A2232PARAM_B600, - 1800, A2232PARAM_B1800, A2232_BAUD_TABLE_NOAVAIL, - 2400, A2232PARAM_B2400, A2232PARAM_B1200, - 4800, A2232PARAM_B4800, A2232PARAM_B2400, - 9600, A2232PARAM_B9600, A2232PARAM_B4800, - 19200, A2232PARAM_B19200, A2232PARAM_B9600, - 38400, A2232_BAUD_TABLE_NOAVAIL, A2232PARAM_B19200, - 57600, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL, -#ifdef A2232_SPEEDHACK - 115200, A2232PARAM_B115200, A2232_BAUD_TABLE_NOAVAIL, - 230400, A2232_BAUD_TABLE_NOAVAIL, A2232PARAM_B115200 -#else - 115200, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL, - 230400, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL -#endif -}; -#endif diff --git a/drivers/char/ser_a2232fw.ax b/drivers/char/ser_a2232fw.ax deleted file mode 100644 index 736438032768..000000000000 --- a/drivers/char/ser_a2232fw.ax +++ /dev/null @@ -1,529 +0,0 @@ -;.lib "axm" -; -;begin -;title "A2232 serial board driver" -; -;set modules "2232" -;set executable "2232.bin" -; -;;;;set nolink -; -;set temporary directory "t:" -; -;set assembly options "-m6502 -l60:t:list" -;set link options "bin"; loadadr" -;;;bin2c 2232.bin msc6502.h msc6502code -;end -; -; -; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ### -; -; - Created 950501 by JM - -; -; -; Serial board driver software. -; -; -% Copyright (c) 1995 Jukka Marin . -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions -% are met: -% 1. Redistributions of source code must retain the above copyright -% notice, and the entire permission notice in its entirety, -% including the disclaimer of warranties. -% 2. Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% 3. The name of the author may not be used to endorse or promote -% products derived from this software without specific prior -% written permission. -% -% ALTERNATIVELY, this product may be distributed under the terms of -% the GNU General Public License, in which case the provisions of the -% GPL are required INSTEAD OF the above restrictions. (This clause is -% necessary due to a potential bad interaction between the GPL and -% the restrictions contained in a BSD-style copyright.) -% -% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED -% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -% DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, -% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -% OF THE POSSIBILITY OF SUCH DAMAGE. -; -; -; Bugs: -; -; - Can't send a break yet -; -; -; -; Edited: -; -; - 950501 by JM -> v0.1 - Created this file. -; - 951029 by JM -> v1.3 - Carrier Detect events now queued in a separate -; queue. -; -; - - -CODE equ $3800 ; start address for program code - - -CTL_CHAR equ $00 ; byte in ibuf is a character -CTL_EVENT equ $01 ; byte in ibuf is an event - -EVENT_BREAK equ $01 -EVENT_CDON equ $02 -EVENT_CDOFF equ $03 -EVENT_SYNC equ $04 - -XON equ $11 -XOFF equ $13 - - -VARBASE macro *starting_address ; was VARINIT -_varbase set \1 - endm - -VARDEF macro *name space_needs -\1 equ _varbase -_varbase set _varbase+\2 - endm - - -stz macro * address - db $64,\1 - endm - -stzax macro * address - db $9e,<\1,>\1 - endm - - -biti macro * immediate value - db $89,\1 - endm - -smb0 macro * address - db $87,\1 - endm -smb1 macro * address - db $97,\1 - endm -smb2 macro * address - db $a7,\1 - endm -smb3 macro * address - db $b7,\1 - endm -smb4 macro * address - db $c7,\1 - endm -smb5 macro * address - db $d7,\1 - endm -smb6 macro * address - db $e7,\1 - endm -smb7 macro * address - db $f7,\1 - endm - - - -;-----------------------------------------------------------------------; -; ; -; stuff common for all ports, non-critical (run once / loop) ; -; ; -DO_SLOW macro * port_number ; - .local ; ; - lda CIA+C_PA ; check all CD inputs ; - cmp CommonCDo ; changed from previous accptd? ; - beq =over ; nope, do nothing else here ; - ; ; - cmp CommonCDb ; bouncing? ; - beq =nobounce ; nope -> ; - ; ; - sta CommonCDb ; save current state ; - lda #64 ; reinitialize counter ; - sta CommonCDc ; ; - jmp =over ; skip CD save ; - ; ; -=nobounce dec CommonCDc ; no, decrement bounce counter ; - bpl =over ; not done yet, so skip CD save ; - ; ; -=saveCD ldx CDHead ; get write index ; - sta cdbuf,x ; save status in buffer ; - inx ; ; - cpx CDTail ; buffer full? ; - .if ne ; no: preserve status: ; - stx CDHead ; update index in RAM ; - sta CommonCDo ; save state for the next check ; - .end ; ; -=over .end local ; - endm ; - ; -;-----------------------------------------------------------------------; - - -; port specific stuff (no data transfer) - -DO_PORT macro * port_number - .local ; ; - lda SetUp\1 ; reconfiguration request? ; - .if ne ; yes: ; - lda SoftFlow\1 ; get XON/XOFF flag ; - sta XonOff\1 ; save it ; - lda Param\1 ; get parameter ; - ora #%00010000 ; use baud generator for Rx ; - sta ACIA\1+A_CTRL ; store in control register ; - stz OutDisable\1 ; enable transmit output ; - stz SetUp\1 ; no reconfiguration no more ; - .end ; ; - ; ; - lda InHead\1 ; get write index ; - sbc InTail\1 ; buffer full soon? ; - cmp #200 ; 200 chars or more in buffer? ; - lda Command\1 ; get Command reg value ; - and #%11110011 ; turn RTS OFF by default ; - .if cc ; still room in buffer: ; - ora #%00001000 ; turn RTS ON ; - .end ; ; - sta ACIA\1+A_CMD ; set/clear RTS ; - ; ; - lda OutFlush\1 ; request to flush output buffer; - .if ne ; yessh! ; - lda OutHead\1 ; get head ; - sta OutTail\1 ; save as tail ; - stz OutDisable\1 ; enable transmit output ; - stz OutFlush\1 ; clear request ; - .end - .end local - endm - - -DO_DATA macro * port number - .local - lda ACIA\1+A_SR ; read ACIA status register ; - biti [1<<3] ; something received? ; - .if ne ; yes: ; - biti [1<<1] ; framing error? ; - .if ne ; yes: ; - lda ACIA\1+A_DATA ; read received character ; - bne =SEND ; not break -> ignore it ; - ldx InHead\1 ; get write pointer ; - lda #CTL_EVENT ; get type of byte ; - sta ictl\1,x ; save it in InCtl buffer ; - lda #EVENT_BREAK ; event code ; - sta ibuf\1,x ; save it as well ; - inx ; ; - cpx InTail\1 ; still room in buffer? ; - .if ne ; absolutely: ; - stx InHead\1 ; update index in memory ; - .end ; ; - jmp =SEND ; go check if anything to send ; - .end ; ; - ; normal char received: ; - ldx InHead\1 ; get write index ; - lda ACIA\1+A_DATA ; read received character ; - sta ibuf\1,x ; save char in buffer ; - stzax ictl\1 ; set type to CTL_CHAR ; - inx ; ; - cpx InTail\1 ; buffer full? ; - .if ne ; no: preserve character: ; - stx InHead\1 ; update index in RAM ; - .end ; ; - and #$7f ; mask off parity if any ; - cmp #XOFF ; XOFF from remote host? ; - .if eq ; yes: ; - lda XonOff\1 ; if XON/XOFF handshaking.. ; - sta OutDisable\1 ; ..disable transmitter ; - .end ; ; - .end ; ; - ; ; - ; BUFFER FULL CHECK WAS HERE ; - ; ; -=SEND lda ACIA\1+A_SR ; transmit register empty? ; - and #[1<<4] ; ; - .if ne ; yes: ; - ldx OutCtrl\1 ; sending out XON/XOFF? ; - .if ne ; yes: ; - lda CIA+C_PB ; check CTS signal ; - and #[1<<\1] ; (for this port only) ; - bne =DONE ; not allowed to send -> done ; - stx ACIA\1+A_DATA ; transmit control char ; - stz OutCtrl\1 ; clear flag ; - jmp =DONE ; and we're done ; - .end ; ; - ; ; - ldx OutTail\1 ; anything to transmit? ; - cpx OutHead\1 ; ; - .if ne ; yes: ; - lda OutDisable\1 ; allowed to transmit? ; - .if eq ; yes: ; - lda CIA+C_PB ; check CTS signal ; - and #[1<<\1] ; (for this port only) ; - bne =DONE ; not allowed to send -> done ; - lda obuf\1,x ; get a char from buffer ; - sta ACIA\1+A_DATA ; send it away ; - inc OutTail\1 ; update read index ; - .end ; ; - .end ; ; - .end ; ; -=DONE .end local - endm - - - -PORTVAR macro * port number - VARDEF InHead\1 1 - VARDEF InTail\1 1 - VARDEF OutDisable\1 1 - VARDEF OutHead\1 1 - VARDEF OutTail\1 1 - VARDEF OutCtrl\1 1 - VARDEF OutFlush\1 1 - VARDEF SetUp\1 1 - VARDEF Param\1 1 - VARDEF Command\1 1 - VARDEF SoftFlow\1 1 - ; private: - VARDEF XonOff\1 1 - endm - - - VARBASE 0 ; start variables at address $0000 - PORTVAR 0 ; define variables for port 0 - PORTVAR 1 ; define variables for port 1 - PORTVAR 2 ; define variables for port 2 - PORTVAR 3 ; define variables for port 3 - PORTVAR 4 ; define variables for port 4 - PORTVAR 5 ; define variables for port 5 - PORTVAR 6 ; define variables for port 6 - - - - VARDEF Crystal 1 ; 0 = unknown, 1 = normal, 2 = turbo - VARDEF Pad_a 1 - VARDEF TimerH 1 - VARDEF TimerL 1 - VARDEF CDHead 1 - VARDEF CDTail 1 - VARDEF CDStatus 1 - VARDEF Pad_b 1 - - VARDEF CommonCDo 1 ; for carrier detect optimization - VARDEF CommonCDc 1 ; for carrier detect debouncing - VARDEF CommonCDb 1 ; for carrier detect debouncing - - - VARBASE $0200 - VARDEF obuf0 256 ; output data (characters only) - VARDEF obuf1 256 - VARDEF obuf2 256 - VARDEF obuf3 256 - VARDEF obuf4 256 - VARDEF obuf5 256 - VARDEF obuf6 256 - - VARDEF ibuf0 256 ; input data (characters, events etc - see ictl) - VARDEF ibuf1 256 - VARDEF ibuf2 256 - VARDEF ibuf3 256 - VARDEF ibuf4 256 - VARDEF ibuf5 256 - VARDEF ibuf6 256 - - VARDEF ictl0 256 ; input control information (type of data in ibuf) - VARDEF ictl1 256 - VARDEF ictl2 256 - VARDEF ictl3 256 - VARDEF ictl4 256 - VARDEF ictl5 256 - VARDEF ictl6 256 - - VARDEF cdbuf 256 ; CD event queue - - -ACIA0 equ $4400 -ACIA1 equ $4c00 -ACIA2 equ $5400 -ACIA3 equ $5c00 -ACIA4 equ $6400 -ACIA5 equ $6c00 -ACIA6 equ $7400 - -A_DATA equ $00 -A_SR equ $02 -A_CMD equ $04 -A_CTRL equ $06 -; 00 write transmit data read received data -; 02 reset ACIA read status register -; 04 write command register read command register -; 06 write control register read control register - -CIA equ $7c00 ; 8520 CIA -C_PA equ $00 ; port A data register -C_PB equ $02 ; port B data register -C_DDRA equ $04 ; data direction register for port A -C_DDRB equ $06 ; data direction register for port B -C_TAL equ $08 ; timer A -C_TAH equ $0a -C_TBL equ $0c ; timer B -C_TBH equ $0e -C_TODL equ $10 ; TOD LSB -C_TODM equ $12 ; TOD middle byte -C_TODH equ $14 ; TOD MSB -C_DATA equ $18 ; serial data register -C_INTCTRL equ $1a ; interrupt control register -C_CTRLA equ $1c ; control register A -C_CTRLB equ $1e ; control register B - - - - - - section main,code,CODE-2 - - db >CODE,. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* This is the 65EC02 code by Jukka Marin that is executed by - the A2232's 65EC02 processor (base address: 0x3800) - Source file: ser_a2232fw.ax - Version: 1.3 (951029) - Known Bugs: Cannot send a break yet -*/ -static unsigned char a2232_65EC02code[] = { - 0x38, 0x00, 0xA2, 0xFF, 0x9A, 0xD8, 0xA2, 0x00, - 0xA9, 0x00, 0xA0, 0x54, 0x95, 0x00, 0xE8, 0x88, - 0xD0, 0xFA, 0x64, 0x5C, 0x64, 0x5E, 0x64, 0x58, - 0x64, 0x59, 0xA9, 0x00, 0x85, 0x55, 0xA9, 0xAA, - 0xC9, 0x64, 0x90, 0x02, 0xE6, 0x55, 0xA5, 0x54, - 0xF0, 0x03, 0x4C, 0x92, 0x38, 0xA9, 0x98, 0x8D, - 0x06, 0x44, 0xA9, 0x0B, 0x8D, 0x04, 0x44, 0xAD, - 0x02, 0x44, 0xA9, 0x80, 0x8D, 0x1A, 0x7C, 0xA9, - 0xFF, 0x8D, 0x08, 0x7C, 0x8D, 0x0A, 0x7C, 0xA2, - 0x00, 0x8E, 0x00, 0x44, 0xEA, 0xEA, 0xAD, 0x02, - 0x44, 0xEA, 0xEA, 0x8E, 0x00, 0x44, 0xAD, 0x02, - 0x44, 0x29, 0x10, 0xF0, 0xF9, 0xA9, 0x11, 0x8E, - 0x00, 0x44, 0x8D, 0x1C, 0x7C, 0xAD, 0x02, 0x44, - 0x29, 0x10, 0xF0, 0xF9, 0x8E, 0x1C, 0x7C, 0xAD, - 0x08, 0x7C, 0x85, 0x57, 0xAD, 0x0A, 0x7C, 0x85, - 0x56, 0xC9, 0xD0, 0x90, 0x05, 0xA9, 0x02, 0x4C, - 0x82, 0x38, 0xA9, 0x01, 0x85, 0x54, 0xA9, 0x00, - 0x8D, 0x02, 0x44, 0x8D, 0x06, 0x44, 0x8D, 0x04, - 0x44, 0x4C, 0x92, 0x38, 0xAD, 0x00, 0x7C, 0xC5, - 0x5C, 0xF0, 0x1F, 0xC5, 0x5E, 0xF0, 0x09, 0x85, - 0x5E, 0xA9, 0x40, 0x85, 0x5D, 0x4C, 0xB8, 0x38, - 0xC6, 0x5D, 0x10, 0x0E, 0xA6, 0x58, 0x9D, 0x00, - 0x17, 0xE8, 0xE4, 0x59, 0xF0, 0x04, 0x86, 0x58, - 0x85, 0x5C, 0x20, 0x23, 0x3A, 0xA5, 0x07, 0xF0, - 0x0F, 0xA5, 0x0A, 0x85, 0x0B, 0xA5, 0x08, 0x09, - 0x10, 0x8D, 0x06, 0x44, 0x64, 0x02, 0x64, 0x07, - 0xA5, 0x00, 0xE5, 0x01, 0xC9, 0xC8, 0xA5, 0x09, - 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, - 0x44, 0xA5, 0x06, 0xF0, 0x08, 0xA5, 0x03, 0x85, - 0x04, 0x64, 0x02, 0x64, 0x06, 0x20, 0x23, 0x3A, - 0xA5, 0x13, 0xF0, 0x0F, 0xA5, 0x16, 0x85, 0x17, - 0xA5, 0x14, 0x09, 0x10, 0x8D, 0x06, 0x4C, 0x64, - 0x0E, 0x64, 0x13, 0xA5, 0x0C, 0xE5, 0x0D, 0xC9, - 0xC8, 0xA5, 0x15, 0x29, 0xF3, 0xB0, 0x02, 0x09, - 0x08, 0x8D, 0x04, 0x4C, 0xA5, 0x12, 0xF0, 0x08, - 0xA5, 0x0F, 0x85, 0x10, 0x64, 0x0E, 0x64, 0x12, - 0x20, 0x23, 0x3A, 0xA5, 0x1F, 0xF0, 0x0F, 0xA5, - 0x22, 0x85, 0x23, 0xA5, 0x20, 0x09, 0x10, 0x8D, - 0x06, 0x54, 0x64, 0x1A, 0x64, 0x1F, 0xA5, 0x18, - 0xE5, 0x19, 0xC9, 0xC8, 0xA5, 0x21, 0x29, 0xF3, - 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x54, 0xA5, - 0x1E, 0xF0, 0x08, 0xA5, 0x1B, 0x85, 0x1C, 0x64, - 0x1A, 0x64, 0x1E, 0x20, 0x23, 0x3A, 0xA5, 0x2B, - 0xF0, 0x0F, 0xA5, 0x2E, 0x85, 0x2F, 0xA5, 0x2C, - 0x09, 0x10, 0x8D, 0x06, 0x5C, 0x64, 0x26, 0x64, - 0x2B, 0xA5, 0x24, 0xE5, 0x25, 0xC9, 0xC8, 0xA5, - 0x2D, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, - 0x04, 0x5C, 0xA5, 0x2A, 0xF0, 0x08, 0xA5, 0x27, - 0x85, 0x28, 0x64, 0x26, 0x64, 0x2A, 0x20, 0x23, - 0x3A, 0xA5, 0x37, 0xF0, 0x0F, 0xA5, 0x3A, 0x85, - 0x3B, 0xA5, 0x38, 0x09, 0x10, 0x8D, 0x06, 0x64, - 0x64, 0x32, 0x64, 0x37, 0xA5, 0x30, 0xE5, 0x31, - 0xC9, 0xC8, 0xA5, 0x39, 0x29, 0xF3, 0xB0, 0x02, - 0x09, 0x08, 0x8D, 0x04, 0x64, 0xA5, 0x36, 0xF0, - 0x08, 0xA5, 0x33, 0x85, 0x34, 0x64, 0x32, 0x64, - 0x36, 0x20, 0x23, 0x3A, 0xA5, 0x43, 0xF0, 0x0F, - 0xA5, 0x46, 0x85, 0x47, 0xA5, 0x44, 0x09, 0x10, - 0x8D, 0x06, 0x6C, 0x64, 0x3E, 0x64, 0x43, 0xA5, - 0x3C, 0xE5, 0x3D, 0xC9, 0xC8, 0xA5, 0x45, 0x29, - 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x6C, - 0xA5, 0x42, 0xF0, 0x08, 0xA5, 0x3F, 0x85, 0x40, - 0x64, 0x3E, 0x64, 0x42, 0x20, 0x23, 0x3A, 0xA5, - 0x4F, 0xF0, 0x0F, 0xA5, 0x52, 0x85, 0x53, 0xA5, - 0x50, 0x09, 0x10, 0x8D, 0x06, 0x74, 0x64, 0x4A, - 0x64, 0x4F, 0xA5, 0x48, 0xE5, 0x49, 0xC9, 0xC8, - 0xA5, 0x51, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, - 0x8D, 0x04, 0x74, 0xA5, 0x4E, 0xF0, 0x08, 0xA5, - 0x4B, 0x85, 0x4C, 0x64, 0x4A, 0x64, 0x4E, 0x20, - 0x23, 0x3A, 0x4C, 0x92, 0x38, 0xAD, 0x02, 0x44, - 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, - 0xAD, 0x00, 0x44, 0xD0, 0x32, 0xA6, 0x00, 0xA9, - 0x01, 0x9D, 0x00, 0x10, 0xA9, 0x01, 0x9D, 0x00, - 0x09, 0xE8, 0xE4, 0x01, 0xF0, 0x02, 0x86, 0x00, - 0x4C, 0x65, 0x3A, 0xA6, 0x00, 0xAD, 0x00, 0x44, - 0x9D, 0x00, 0x09, 0x9E, 0x00, 0x10, 0xE8, 0xE4, - 0x01, 0xF0, 0x02, 0x86, 0x00, 0x29, 0x7F, 0xC9, - 0x13, 0xD0, 0x04, 0xA5, 0x0B, 0x85, 0x02, 0xAD, - 0x02, 0x44, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x05, - 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 0xD0, - 0x21, 0x8E, 0x00, 0x44, 0x64, 0x05, 0x4C, 0x98, - 0x3A, 0xA6, 0x04, 0xE4, 0x03, 0xF0, 0x13, 0xA5, - 0x02, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, - 0xD0, 0x08, 0xBD, 0x00, 0x02, 0x8D, 0x00, 0x44, - 0xE6, 0x04, 0xAD, 0x02, 0x4C, 0x89, 0x08, 0xF0, - 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x4C, - 0xD0, 0x32, 0xA6, 0x0C, 0xA9, 0x01, 0x9D, 0x00, - 0x11, 0xA9, 0x01, 0x9D, 0x00, 0x0A, 0xE8, 0xE4, - 0x0D, 0xF0, 0x02, 0x86, 0x0C, 0x4C, 0xDA, 0x3A, - 0xA6, 0x0C, 0xAD, 0x00, 0x4C, 0x9D, 0x00, 0x0A, - 0x9E, 0x00, 0x11, 0xE8, 0xE4, 0x0D, 0xF0, 0x02, - 0x86, 0x0C, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, - 0xA5, 0x17, 0x85, 0x0E, 0xAD, 0x02, 0x4C, 0x29, - 0x10, 0xF0, 0x2C, 0xA6, 0x11, 0xF0, 0x0F, 0xAD, - 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x21, 0x8E, 0x00, - 0x4C, 0x64, 0x11, 0x4C, 0x0D, 0x3B, 0xA6, 0x10, - 0xE4, 0x0F, 0xF0, 0x13, 0xA5, 0x0E, 0xD0, 0x0F, - 0xAD, 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x08, 0xBD, - 0x00, 0x03, 0x8D, 0x00, 0x4C, 0xE6, 0x10, 0xAD, - 0x02, 0x54, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, - 0xF0, 0x1B, 0xAD, 0x00, 0x54, 0xD0, 0x32, 0xA6, - 0x18, 0xA9, 0x01, 0x9D, 0x00, 0x12, 0xA9, 0x01, - 0x9D, 0x00, 0x0B, 0xE8, 0xE4, 0x19, 0xF0, 0x02, - 0x86, 0x18, 0x4C, 0x4F, 0x3B, 0xA6, 0x18, 0xAD, - 0x00, 0x54, 0x9D, 0x00, 0x0B, 0x9E, 0x00, 0x12, - 0xE8, 0xE4, 0x19, 0xF0, 0x02, 0x86, 0x18, 0x29, - 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x23, 0x85, - 0x1A, 0xAD, 0x02, 0x54, 0x29, 0x10, 0xF0, 0x2C, - 0xA6, 0x1D, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, - 0x04, 0xD0, 0x21, 0x8E, 0x00, 0x54, 0x64, 0x1D, - 0x4C, 0x82, 0x3B, 0xA6, 0x1C, 0xE4, 0x1B, 0xF0, - 0x13, 0xA5, 0x1A, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, - 0x29, 0x04, 0xD0, 0x08, 0xBD, 0x00, 0x04, 0x8D, - 0x00, 0x54, 0xE6, 0x1C, 0xAD, 0x02, 0x5C, 0x89, - 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, - 0x00, 0x5C, 0xD0, 0x32, 0xA6, 0x24, 0xA9, 0x01, - 0x9D, 0x00, 0x13, 0xA9, 0x01, 0x9D, 0x00, 0x0C, - 0xE8, 0xE4, 0x25, 0xF0, 0x02, 0x86, 0x24, 0x4C, - 0xC4, 0x3B, 0xA6, 0x24, 0xAD, 0x00, 0x5C, 0x9D, - 0x00, 0x0C, 0x9E, 0x00, 0x13, 0xE8, 0xE4, 0x25, - 0xF0, 0x02, 0x86, 0x24, 0x29, 0x7F, 0xC9, 0x13, - 0xD0, 0x04, 0xA5, 0x2F, 0x85, 0x26, 0xAD, 0x02, - 0x5C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x29, 0xF0, - 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 0x21, - 0x8E, 0x00, 0x5C, 0x64, 0x29, 0x4C, 0xF7, 0x3B, - 0xA6, 0x28, 0xE4, 0x27, 0xF0, 0x13, 0xA5, 0x26, - 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, - 0x08, 0xBD, 0x00, 0x05, 0x8D, 0x00, 0x5C, 0xE6, - 0x28, 0xAD, 0x02, 0x64, 0x89, 0x08, 0xF0, 0x3B, - 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x64, 0xD0, - 0x32, 0xA6, 0x30, 0xA9, 0x01, 0x9D, 0x00, 0x14, - 0xA9, 0x01, 0x9D, 0x00, 0x0D, 0xE8, 0xE4, 0x31, - 0xF0, 0x02, 0x86, 0x30, 0x4C, 0x39, 0x3C, 0xA6, - 0x30, 0xAD, 0x00, 0x64, 0x9D, 0x00, 0x0D, 0x9E, - 0x00, 0x14, 0xE8, 0xE4, 0x31, 0xF0, 0x02, 0x86, - 0x30, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, - 0x3B, 0x85, 0x32, 0xAD, 0x02, 0x64, 0x29, 0x10, - 0xF0, 0x2C, 0xA6, 0x35, 0xF0, 0x0F, 0xAD, 0x02, - 0x7C, 0x29, 0x10, 0xD0, 0x21, 0x8E, 0x00, 0x64, - 0x64, 0x35, 0x4C, 0x6C, 0x3C, 0xA6, 0x34, 0xE4, - 0x33, 0xF0, 0x13, 0xA5, 0x32, 0xD0, 0x0F, 0xAD, - 0x02, 0x7C, 0x29, 0x10, 0xD0, 0x08, 0xBD, 0x00, - 0x06, 0x8D, 0x00, 0x64, 0xE6, 0x34, 0xAD, 0x02, - 0x6C, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, - 0x1B, 0xAD, 0x00, 0x6C, 0xD0, 0x32, 0xA6, 0x3C, - 0xA9, 0x01, 0x9D, 0x00, 0x15, 0xA9, 0x01, 0x9D, - 0x00, 0x0E, 0xE8, 0xE4, 0x3D, 0xF0, 0x02, 0x86, - 0x3C, 0x4C, 0xAE, 0x3C, 0xA6, 0x3C, 0xAD, 0x00, - 0x6C, 0x9D, 0x00, 0x0E, 0x9E, 0x00, 0x15, 0xE8, - 0xE4, 0x3D, 0xF0, 0x02, 0x86, 0x3C, 0x29, 0x7F, - 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x47, 0x85, 0x3E, - 0xAD, 0x02, 0x6C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, - 0x41, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x20, - 0xD0, 0x21, 0x8E, 0x00, 0x6C, 0x64, 0x41, 0x4C, - 0xE1, 0x3C, 0xA6, 0x40, 0xE4, 0x3F, 0xF0, 0x13, - 0xA5, 0x3E, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, - 0x20, 0xD0, 0x08, 0xBD, 0x00, 0x07, 0x8D, 0x00, - 0x6C, 0xE6, 0x40, 0xAD, 0x02, 0x74, 0x89, 0x08, - 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, - 0x74, 0xD0, 0x32, 0xA6, 0x48, 0xA9, 0x01, 0x9D, - 0x00, 0x16, 0xA9, 0x01, 0x9D, 0x00, 0x0F, 0xE8, - 0xE4, 0x49, 0xF0, 0x02, 0x86, 0x48, 0x4C, 0x23, - 0x3D, 0xA6, 0x48, 0xAD, 0x00, 0x74, 0x9D, 0x00, - 0x0F, 0x9E, 0x00, 0x16, 0xE8, 0xE4, 0x49, 0xF0, - 0x02, 0x86, 0x48, 0x29, 0x7F, 0xC9, 0x13, 0xD0, - 0x04, 0xA5, 0x53, 0x85, 0x4A, 0xAD, 0x02, 0x74, - 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x4D, 0xF0, 0x0F, - 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x21, 0x8E, - 0x00, 0x74, 0x64, 0x4D, 0x4C, 0x56, 0x3D, 0xA6, - 0x4C, 0xE4, 0x4B, 0xF0, 0x13, 0xA5, 0x4A, 0xD0, - 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x08, - 0xBD, 0x00, 0x08, 0x8D, 0x00, 0x74, 0xE6, 0x4C, - 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xD0, 0x00, 0x38, - 0xCE, 0xC0, -}; diff --git a/drivers/char/sx.c b/drivers/char/sx.c deleted file mode 100644 index 1291462bcddb..000000000000 --- a/drivers/char/sx.c +++ /dev/null @@ -1,2894 +0,0 @@ -/* sx.c -- driver for the Specialix SX series cards. - * - * This driver will also support the older SI, and XIO cards. - * - * - * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl - * - * Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous - * version of this driver. Some fragments may have been copied. (none - * yet :-) - * - * Specialix pays for the development and support of this driver. - * Please DO contact support@specialix.co.uk if you require - * support. But please read the documentation (sx.txt) first. - * - * - * - * 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., 675 Mass Ave, Cambridge, MA 02139, - * USA. - * - * Revision history: - * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff - * - Fixed module and port counting - * - Fixed signal handling - * - Fixed an Ooops - * - * Revision 1.32 2000/03/07 09:00:00 wolff,pvdl - * - Fixed some sx_dprintk typos - * - added detection for an invalid board/module configuration - * - * Revision 1.31 2000/03/06 12:00:00 wolff,pvdl - * - Added support for EISA - * - * Revision 1.30 2000/01/21 17:43:06 wolff - * - Added support for SX+ - * - * Revision 1.26 1999/08/05 15:22:14 wolff - * - Port to 2.3.x - * - Reformatted to Linus' liking. - * - * Revision 1.25 1999/07/30 14:24:08 wolff - * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0). - * - * Revision 1.24 1999/07/28 09:41:52 wolff - * - I noticed the remark about use-count straying in sx.txt. I checked - * sx_open, and found a few places where that could happen. I hope it's - * fixed now. - * - * Revision 1.23 1999/07/28 08:56:06 wolff - * - Fixed crash when sx_firmware run twice. - * - Added sx_slowpoll as a module parameter (I guess nobody really wanted - * to change it from the default... ) - * - Fixed a stupid editing problem I introduced in 1.22. - * - Fixed dropping characters on a termios change. - * - * Revision 1.22 1999/07/26 21:01:43 wolff - * Russell Brown noticed that I had overlooked 4 out of six modem control - * signals in sx_getsignals. Ooops. - * - * Revision 1.21 1999/07/23 09:11:33 wolff - * I forgot to free dynamically allocated memory when the driver is unloaded. - * - * Revision 1.20 1999/07/20 06:25:26 wolff - * The "closing wait" wasn't honoured. Thanks to James Griffiths for - * reporting this. - * - * Revision 1.19 1999/07/11 08:59:59 wolff - * Fixed an oops in close, when an open was pending. Changed the memtest - * a bit. Should also test the board in word-mode, however my card fails the - * memtest then. I still have to figure out what is wrong... - * - * Revision 1.18 1999/06/10 09:38:42 wolff - * Changed the format of the firmware revision from %04x to %x.%02x . - * - * Revision 1.17 1999/06/04 09:44:35 wolff - * fixed problem: reference to pci stuff when config_pci was off... - * Thanks to Jorge Novo for noticing this. - * - * Revision 1.16 1999/06/02 08:30:15 wolff - * added/removed the workaround for the DCD bug in the Firmware. - * A bit more debugging code to locate that... - * - * Revision 1.15 1999/06/01 11:35:30 wolff - * when DCD is left low (floating?), on TA's the firmware first tells us - * that DCD is high, but after a short while suddenly comes to the - * conclusion that it is low. All this would be fine, if it weren't that - * Unix requires us to send a "hangup" signal in that case. This usually - * all happens BEFORE the program has had a chance to ioctl the device - * into clocal mode.. - * - * Revision 1.14 1999/05/25 11:18:59 wolff - * Added PCI-fix. - * Added checks for return code of sx_sendcommand. - * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...) - * - * Revision 1.13 1999/04/29 15:18:01 wolff - * Fixed an "oops" that showed on SuSE 6.0 systems. - * Activate DTR again after stty 0. - * - * Revision 1.12 1999/04/29 07:49:52 wolff - * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming - * the connection would be dropped anyway. That is not always the case, - * and confuses people). - * Told the card to always monitor the modem signals. - * Added support for dynamic gs_debug adjustments. - * Now tells the rest of the system the number of ports. - * - * Revision 1.11 1999/04/24 11:11:30 wolff - * Fixed two stupid typos in the memory test. - * - * Revision 1.10 1999/04/24 10:53:39 wolff - * Added some of Christian's suggestions. - * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the - * card to send the signal to the process.....) - * - * Revision 1.9 1999/04/23 07:26:38 wolff - * Included Christian Lademann's 2.0 compile-warning fixes and interrupt - * assignment redesign. - * Cleanup of some other stuff. - * - * Revision 1.8 1999/04/16 13:05:30 wolff - * fixed a DCD change unnoticed bug. - * - * Revision 1.7 1999/04/14 22:19:51 wolff - * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!) - * - * Revision 1.6 1999/04/13 18:40:20 wolff - * changed misc-minor to 161, as assigned by HPA. - * - * Revision 1.5 1999/04/13 15:12:25 wolff - * Fixed use-count leak when "hangup" occurred. - * Added workaround for a stupid-PCIBIOS bug. - * - * - * Revision 1.4 1999/04/01 22:47:40 wolff - * Fixed < 1M linux-2.0 problem. - * (vremap isn't compatible with ioremap in that case) - * - * Revision 1.3 1999/03/31 13:45:45 wolff - * Firmware loading is now done through a separate IOCTL. - * - * Revision 1.2 1999/03/28 12:22:29 wolff - * rcs cleanup - * - * Revision 1.1 1999/03/28 12:10:34 wolff - * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). - * - * Revision 0.12 1999/03/28 09:20:10 wolff - * Fixed problem in 0.11, continueing cleanup. - * - * Revision 0.11 1999/03/28 08:46:44 wolff - * cleanup. Not good. - * - * Revision 0.10 1999/03/28 08:09:43 wolff - * Fixed loosing characters on close. - * - * Revision 0.9 1999/03/21 22:52:01 wolff - * Ported back to 2.2.... (minor things) - * - * Revision 0.8 1999/03/21 22:40:33 wolff - * Port to 2.0 - * - * Revision 0.7 1999/03/21 19:06:34 wolff - * Fixed hangup processing. - * - * Revision 0.6 1999/02/05 08:45:14 wolff - * fixed real_raw problems. Inclusion into kernel imminent. - * - * Revision 0.5 1998/12/21 23:51:06 wolff - * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it - * shouldn't have. THATs why I want to have transmit interrupts even when - * the buffer is empty. - * - * Revision 0.4 1998/12/17 09:34:46 wolff - * PPP works. ioctl works. Basically works! - * - * Revision 0.3 1998/12/15 13:05:18 wolff - * It works! Wow! Gotta start implementing IOCTL and stuff.... - * - * Revision 0.2 1998/12/01 08:33:53 wolff - * moved over to 2.1.130 - * - * Revision 0.1 1998/11/03 21:23:51 wolff - * Initial revision. Detects SX card. - * - * */ - -#define SX_VERSION 1.33 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */ -#define BYTE u8 -#define WORD u16 - -/* .... but the 3.0.4 version uses _u8 and _u16. */ -#define _u8 u8 -#define _u16 u16 - -#include "sxboards.h" -#include "sxwindow.h" - -#include -#include "sx.h" - -/* I don't think that this driver can handle more than 256 ports on - one machine. You'll have to increase the number of boards in sx.h - if you want more than 4 boards. */ - -#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 -#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 -#endif - -/* Configurable options: - (Don't be too sure that it'll work if you toggle them) */ - -/* Am I paranoid or not ? ;-) */ -#undef SX_PARANOIA_CHECK - -/* 20 -> 2000 per second. The card should rate-limit interrupts at 100 - Hz, but it is user configurable. I don't recommend going above 1000 - Hz. The interrupt ratelimit might trigger if the interrupt is - shared with a very active other device. */ -#define IRQ_RATE_LIMIT 20 - -/* Sharing interrupts is possible now. If the other device wants more - than 2000 interrupts per second, we'd gracefully decline further - interrupts. That's not what we want. On the other hand, if the - other device interrupts 2000 times a second, don't use the SX - interrupt. Use polling. */ -#undef IRQ_RATE_LIMIT - -#if 0 -/* Not implemented */ -/* - * The following defines are mostly for testing purposes. But if you need - * some nice reporting in your syslog, you can define them also. - */ -#define SX_REPORT_FIFO -#define SX_REPORT_OVERRUN -#endif - -/* Function prototypes */ -static void sx_disable_tx_interrupts(void *ptr); -static void sx_enable_tx_interrupts(void *ptr); -static void sx_disable_rx_interrupts(void *ptr); -static void sx_enable_rx_interrupts(void *ptr); -static int sx_carrier_raised(struct tty_port *port); -static void sx_shutdown_port(void *ptr); -static int sx_set_real_termios(void *ptr); -static void sx_close(void *ptr); -static int sx_chars_in_buffer(void *ptr); -static int sx_init_board(struct sx_board *board); -static int sx_init_portstructs(int nboards, int nports); -static long sx_fw_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); -static int sx_init_drivers(void); - -static struct tty_driver *sx_driver; - -static DEFINE_MUTEX(sx_boards_lock); -static struct sx_board boards[SX_NBOARDS]; -static struct sx_port *sx_ports; -static int sx_initialized; -static int sx_nports; -static int sx_debug; - -/* You can have the driver poll your card. - - Set sx_poll to 1 to poll every timer tick (10ms on Intel). - This is used when the card cannot use an interrupt for some reason. - - - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If - the driver misses an interrupt (report this if it DOES happen to you!) - everything will continue to work.... - */ -static int sx_poll = 1; -static int sx_slowpoll; - -/* The card limits the number of interrupts per second. - At 115k2 "100" should be sufficient. - If you're using higher baudrates, you can increase this... - */ - -static int sx_maxints = 100; - -#ifdef CONFIG_ISA - -/* These are the only open spaces in my computer. Yours may have more - or less.... -- REW - duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl -*/ -static int sx_probe_addrs[] = { - 0xc0000, 0xd0000, 0xe0000, - 0xc8000, 0xd8000, 0xe8000 -}; -static int si_probe_addrs[] = { - 0xc0000, 0xd0000, 0xe0000, - 0xc8000, 0xd8000, 0xe8000, 0xa0000 -}; -static int si1_probe_addrs[] = { - 0xd0000 -}; - -#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs) -#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs) -#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs) - -module_param_array(sx_probe_addrs, int, NULL, 0); -module_param_array(si_probe_addrs, int, NULL, 0); -#endif - -/* Set the mask to all-ones. This alas, only supports 32 interrupts. - Some architectures may need more. */ -static int sx_irqmask = -1; - -module_param(sx_poll, int, 0); -module_param(sx_slowpoll, int, 0); -module_param(sx_maxints, int, 0); -module_param(sx_debug, int, 0); -module_param(sx_irqmask, int, 0); - -MODULE_LICENSE("GPL"); - -static struct real_driver sx_real_driver = { - sx_disable_tx_interrupts, - sx_enable_tx_interrupts, - sx_disable_rx_interrupts, - sx_enable_rx_interrupts, - sx_shutdown_port, - sx_set_real_termios, - sx_chars_in_buffer, - sx_close, -}; - -/* - This driver can spew a whole lot of debugging output at you. If you - need maximum performance, you should disable the DEBUG define. To - aid in debugging in the field, I'm leaving the compile-time debug - features enabled, and disable them "runtime". That allows me to - instruct people with problems to enable debugging without requiring - them to recompile... -*/ -#define DEBUG - -#ifdef DEBUG -#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) -#else -#define sx_dprintk(f, str...) /* nothing */ -#endif - -#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__) -#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__) - -#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ - __func__, port->line) - -/* - * Firmware loader driver specific routines - * - */ - -static const struct file_operations sx_fw_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = sx_fw_ioctl, - .llseek = noop_llseek, -}; - -static struct miscdevice sx_fw_device = { - SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops -}; - -#ifdef SX_PARANOIA_CHECK - -/* This doesn't work. Who's paranoid around here? Not me! */ - -static inline int sx_paranoia_check(struct sx_port const *port, - char *name, const char *routine) -{ - static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic " - "number for device %s in %s\n"; - static const char *badinfo = KERN_ERR "sx: Warning: null sx port for " - "device %s in %s\n"; - - if (!port) { - printk(badinfo, name, routine); - return 1; - } - if (port->magic != SX_MAGIC) { - printk(badmagic, name, routine); - return 1; - } - - return 0; -} -#else -#define sx_paranoia_check(a,b,c) 0 -#endif - -/* The timeouts. First try 30 times as fast as possible. Then give - the card some time to breathe between accesses. (Otherwise the - processor on the card might not be able to access its OWN bus... */ - -#define TIMEOUT_1 30 -#define TIMEOUT_2 1000000 - -#ifdef DEBUG -static void my_hd_io(void __iomem *p, int len) -{ - int i, j, ch; - unsigned char __iomem *addr = p; - - for (i = 0; i < len; i += 16) { - printk("%p ", addr + i); - for (j = 0; j < 16; j++) { - printk("%02x %s", readb(addr + j + i), - (j == 7) ? " " : ""); - } - for (j = 0; j < 16; j++) { - ch = readb(addr + j + i); - printk("%c", (ch < 0x20) ? '.' : - ((ch > 0x7f) ? '.' : ch)); - } - printk("\n"); - } -} -static void my_hd(void *p, int len) -{ - int i, j, ch; - unsigned char *addr = p; - - for (i = 0; i < len; i += 16) { - printk("%p ", addr + i); - for (j = 0; j < 16; j++) { - printk("%02x %s", addr[j + i], (j == 7) ? " " : ""); - } - for (j = 0; j < 16; j++) { - ch = addr[j + i]; - printk("%c", (ch < 0x20) ? '.' : - ((ch > 0x7f) ? '.' : ch)); - } - printk("\n"); - } -} -#endif - -/* This needs redoing for Alpha -- REW -- Done. */ - -static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte) -{ - writeb(byte, board->base + offset); -} - -static inline u8 read_sx_byte(struct sx_board *board, int offset) -{ - return readb(board->base + offset); -} - -static inline void write_sx_word(struct sx_board *board, int offset, u16 word) -{ - writew(word, board->base + offset); -} - -static inline u16 read_sx_word(struct sx_board *board, int offset) -{ - return readw(board->base + offset); -} - -static int sx_busy_wait_eq(struct sx_board *board, - int offset, int mask, int correctval) -{ - int i; - - func_enter(); - - for (i = 0; i < TIMEOUT_1; i++) - if ((read_sx_byte(board, offset) & mask) == correctval) { - func_exit(); - return 1; - } - - for (i = 0; i < TIMEOUT_2; i++) { - if ((read_sx_byte(board, offset) & mask) == correctval) { - func_exit(); - return 1; - } - udelay(1); - } - - func_exit(); - return 0; -} - -static int sx_busy_wait_neq(struct sx_board *board, - int offset, int mask, int badval) -{ - int i; - - func_enter(); - - for (i = 0; i < TIMEOUT_1; i++) - if ((read_sx_byte(board, offset) & mask) != badval) { - func_exit(); - return 1; - } - - for (i = 0; i < TIMEOUT_2; i++) { - if ((read_sx_byte(board, offset) & mask) != badval) { - func_exit(); - return 1; - } - udelay(1); - } - - func_exit(); - return 0; -} - -/* 5.6.4 of 6210028 r2.3 */ -static int sx_reset(struct sx_board *board) -{ - func_enter(); - - if (IS_SX_BOARD(board)) { - - write_sx_byte(board, SX_CONFIG, 0); - write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */ - - if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) { - printk(KERN_INFO "sx: Card doesn't respond to " - "reset...\n"); - return 0; - } - } else if (IS_EISA_BOARD(board)) { - outb(board->irq << 4, board->eisa_base + 0xc02); - } else if (IS_SI1_BOARD(board)) { - write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/ - } else { - /* Gory details of the SI/ISA board */ - write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET); - write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); - write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); - write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); - write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); - write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); - } - - func_exit(); - return 1; -} - -/* This doesn't work on machines where "NULL" isn't 0 */ -/* If you have one of those, someone will need to write - the equivalent of this, which will amount to about 3 lines. I don't - want to complicate this right now. -- REW - (See, I do write comments every now and then :-) */ -#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) - -#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) -#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) -#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) - -#define sx_write_channel_byte(port, elem, val) \ - write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) - -#define sx_read_channel_byte(port, elem) \ - read_sx_byte (port->board, CHAN_OFFSET (port, elem)) - -#define sx_write_channel_word(port, elem, val) \ - write_sx_word (port->board, CHAN_OFFSET (port, elem), val) - -#define sx_read_channel_word(port, elem) \ - read_sx_word (port->board, CHAN_OFFSET (port, elem)) - -#define sx_write_module_byte(board, addr, elem, val) \ - write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) - -#define sx_read_module_byte(board, addr, elem) \ - read_sx_byte (board, MODU_OFFSET (board, addr, elem)) - -#define sx_write_module_word(board, addr, elem, val) \ - write_sx_word (board, MODU_OFFSET (board, addr, elem), val) - -#define sx_read_module_word(board, addr, elem) \ - read_sx_word (board, MODU_OFFSET (board, addr, elem)) - -#define sx_write_board_byte(board, elem, val) \ - write_sx_byte (board, BRD_OFFSET (board, elem), val) - -#define sx_read_board_byte(board, elem) \ - read_sx_byte (board, BRD_OFFSET (board, elem)) - -#define sx_write_board_word(board, elem, val) \ - write_sx_word (board, BRD_OFFSET (board, elem), val) - -#define sx_read_board_word(board, elem) \ - read_sx_word (board, BRD_OFFSET (board, elem)) - -static int sx_start_board(struct sx_board *board) -{ - if (IS_SX_BOARD(board)) { - write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN); - } else if (IS_EISA_BOARD(board)) { - write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL); - outb((board->irq << 4) | 4, board->eisa_base + 0xc02); - } else if (IS_SI1_BOARD(board)) { - write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0); - write_sx_byte(board, SI1_ISA_INTCL, 0); - } else { - /* Don't bug me about the clear_set. - I haven't the foggiest idea what it's about -- REW */ - write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); - write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); - } - return 1; -} - -#define SX_IRQ_REG_VAL(board) \ - ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0) - -/* Note. The SX register is write-only. Therefore, we have to enable the - bus too. This is a no-op, if you don't mess with this driver... */ -static int sx_start_interrupts(struct sx_board *board) -{ - - /* Don't call this with board->irq == 0 */ - - if (IS_SX_BOARD(board)) { - write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) | - SX_CONF_BUSEN | SX_CONF_HOSTIRQ); - } else if (IS_EISA_BOARD(board)) { - inb(board->eisa_base + 0xc03); - } else if (IS_SI1_BOARD(board)) { - write_sx_byte(board, SI1_ISA_INTCL, 0); - write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0); - } else { - switch (board->irq) { - case 11: - write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET); - break; - case 12: - write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET); - break; - case 15: - write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET); - break; - default: - printk(KERN_INFO "sx: SI/XIO card doesn't support " - "interrupt %d.\n", board->irq); - return 0; - } - write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); - } - - return 1; -} - -static int sx_send_command(struct sx_port *port, - int command, int mask, int newstat) -{ - func_enter2(); - write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command); - func_exit(); - return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask, - newstat); -} - -static char *mod_type_s(int module_type) -{ - switch (module_type) { - case TA4: - return "TA4"; - case TA8: - return "TA8"; - case TA4_ASIC: - return "TA4_ASIC"; - case TA8_ASIC: - return "TA8_ASIC"; - case MTA_CD1400: - return "MTA_CD1400"; - case SXDC: - return "SXDC"; - default: - return "Unknown/invalid"; - } -} - -static char *pan_type_s(int pan_type) -{ - switch (pan_type) { - case MOD_RS232DB25: - return "MOD_RS232DB25"; - case MOD_RS232RJ45: - return "MOD_RS232RJ45"; - case MOD_RS422DB25: - return "MOD_RS422DB25"; - case MOD_PARALLEL: - return "MOD_PARALLEL"; - case MOD_2_RS232DB25: - return "MOD_2_RS232DB25"; - case MOD_2_RS232RJ45: - return "MOD_2_RS232RJ45"; - case MOD_2_RS422DB25: - return "MOD_2_RS422DB25"; - case MOD_RS232DB25MALE: - return "MOD_RS232DB25MALE"; - case MOD_2_PARALLEL: - return "MOD_2_PARALLEL"; - case MOD_BLANK: - return "empty"; - default: - return "invalid"; - } -} - -static int mod_compat_type(int module_type) -{ - return module_type >> 4; -} - -static void sx_reconfigure_port(struct sx_port *port) -{ - if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) { - if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { - printk(KERN_WARNING "sx: Sent reconfigure command, but " - "card didn't react.\n"); - } - } else { - sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: " - "port isn't open (%02x).\n", - sx_read_channel_byte(port, hi_hstat)); - } -} - -static void sx_setsignals(struct sx_port *port, int dtr, int rts) -{ - int t; - func_enter2(); - - t = sx_read_channel_byte(port, hi_op); - if (dtr >= 0) - t = dtr ? (t | OP_DTR) : (t & ~OP_DTR); - if (rts >= 0) - t = rts ? (t | OP_RTS) : (t & ~OP_RTS); - sx_write_channel_byte(port, hi_op, t); - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); - - func_exit(); -} - -static int sx_getsignals(struct sx_port *port) -{ - int i_stat, o_stat; - - o_stat = sx_read_channel_byte(port, hi_op); - i_stat = sx_read_channel_byte(port, hi_ip); - - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " - "%02x/%02x\n", - (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, - port->c_dcd, tty_port_carrier_raised(&port->gs.port), - sx_read_channel_byte(port, hi_ip), - sx_read_channel_byte(port, hi_state)); - - return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) | - ((o_stat & OP_RTS) ? TIOCM_RTS : 0) | - ((i_stat & IP_CTS) ? TIOCM_CTS : 0) | - ((i_stat & IP_DCD) ? TIOCM_CAR : 0) | - ((i_stat & IP_DSR) ? TIOCM_DSR : 0) | - ((i_stat & IP_RI) ? TIOCM_RNG : 0)); -} - -static void sx_set_baud(struct sx_port *port) -{ - int t; - - if (port->board->ta_type == MOD_SXDC) { - switch (port->gs.baud) { - /* Save some typing work... */ -#define e(x) case x: t = BAUD_ ## x; break - e(50); - e(75); - e(110); - e(150); - e(200); - e(300); - e(600); - e(1200); - e(1800); - e(2000); - e(2400); - e(4800); - e(7200); - e(9600); - e(14400); - e(19200); - e(28800); - e(38400); - e(56000); - e(57600); - e(64000); - e(76800); - e(115200); - e(128000); - e(150000); - e(230400); - e(256000); - e(460800); - e(921600); - case 134: - t = BAUD_134_5; - break; - case 0: - t = -1; - break; - default: - /* Can I return "invalid"? */ - t = BAUD_9600; - printk(KERN_INFO "sx: unsupported baud rate: %d.\n", - port->gs.baud); - break; - } -#undef e - if (t > 0) { -/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ - sx_setsignals(port, 1, -1); - /* XXX This is not TA & MTA compatible */ - sx_write_channel_byte(port, hi_csr, 0xff); - - sx_write_channel_byte(port, hi_txbaud, t); - sx_write_channel_byte(port, hi_rxbaud, t); - } else { - sx_setsignals(port, 0, -1); - } - } else { - switch (port->gs.baud) { -#define e(x) case x: t = CSR_ ## x; break - e(75); - e(150); - e(300); - e(600); - e(1200); - e(2400); - e(4800); - e(1800); - e(9600); - e(19200); - e(57600); - e(38400); -/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ - case 110: - if (port->board->ta_type == MOD_TA) { - t = CSR_110; - break; - } else { - t = CSR_9600; - printk(KERN_INFO "sx: Unsupported baud rate: " - "%d.\n", port->gs.baud); - break; - } - case 115200: - if (port->board->ta_type == MOD_TA) { - t = CSR_9600; - printk(KERN_INFO "sx: Unsupported baud rate: " - "%d.\n", port->gs.baud); - break; - } else { - t = CSR_110; - break; - } - case 0: - t = -1; - break; - default: - t = CSR_9600; - printk(KERN_INFO "sx: Unsupported baud rate: %d.\n", - port->gs.baud); - break; - } -#undef e - if (t >= 0) { - sx_setsignals(port, 1, -1); - sx_write_channel_byte(port, hi_csr, t * 0x11); - } else { - sx_setsignals(port, 0, -1); - } - } -} - -/* Simon Allen's version of this routine was 225 lines long. 85 is a lot - better. -- REW */ - -static int sx_set_real_termios(void *ptr) -{ - struct sx_port *port = ptr; - - func_enter2(); - - if (!port->gs.port.tty) - return 0; - - /* What is this doing here? -- REW - Ha! figured it out. It is to allow you to get DTR active again - if you've dropped it with stty 0. Moved to set_baud, where it - belongs (next to the drop dtr if baud == 0) -- REW */ - /* sx_setsignals (port, 1, -1); */ - - sx_set_baud(port); - -#define CFLAG port->gs.port.tty->termios->c_cflag - sx_write_channel_byte(port, hi_mr1, - (C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) | - (C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) | - (C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) | - (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) | - (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) | - (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) | - (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0)); - - sx_write_channel_byte(port, hi_mr2, - (C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) | - (C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP : - MR2_1_STOP)); - - switch (CFLAG & CSIZE) { - case CS8: - sx_write_channel_byte(port, hi_mask, 0xff); - break; - case CS7: - sx_write_channel_byte(port, hi_mask, 0x7f); - break; - case CS6: - sx_write_channel_byte(port, hi_mask, 0x3f); - break; - case CS5: - sx_write_channel_byte(port, hi_mask, 0x1f); - break; - default: - printk(KERN_INFO "sx: Invalid wordsize: %u\n", - (unsigned int)CFLAG & CSIZE); - break; - } - - sx_write_channel_byte(port, hi_prtcl, - (I_IXON(port->gs.port.tty) ? SP_TXEN : 0) | - (I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) | - (I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN); - - sx_write_channel_byte(port, hi_break, - (I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 | - I_BRKINT(port->gs.port.tty) ? BR_INT : 0)); - - sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty)); - sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty)); - sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty)); - sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty)); - - sx_reconfigure_port(port); - - /* Tell line discipline whether we will do input cooking */ - if (I_OTHER(port->gs.port.tty)) { - clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags); - } else { - set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags); - } - sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ", - (unsigned int)port->gs.port.tty->termios->c_iflag, - I_OTHER(port->gs.port.tty)); - -/* Tell line discipline whether we will do output cooking. - * If OPOST is set and no other output flags are set then we can do output - * processing. Even if only *one* other flag in the O_OTHER group is set - * we do cooking in software. - */ - if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) { - set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags); - } else { - clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags); - } - sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", - (unsigned int)port->gs.port.tty->termios->c_oflag, - O_OTHER(port->gs.port.tty)); - /* port->c_dcd = sx_get_CD (port); */ - func_exit(); - return 0; -} - -/* ********************************************************************** * - * the interrupt related routines * - * ********************************************************************** */ - -/* Note: - Other drivers use the macro "MIN" to calculate how much to copy. - This has the disadvantage that it will evaluate parts twice. That's - expensive when it's IO (and the compiler cannot optimize those away!). - Moreover, I'm not sure that you're race-free. - - I assign a value, and then only allow the value to decrease. This - is always safe. This makes the code a few lines longer, and you - know I'm dead against that, but I think it is required in this - case. */ - -static void sx_transmit_chars(struct sx_port *port) -{ - int c; - int tx_ip; - int txroom; - - func_enter2(); - sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", - port, port->gs.xmit_cnt); - - if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) { - return; - } - - while (1) { - c = port->gs.xmit_cnt; - - sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c); - tx_ip = sx_read_channel_byte(port, hi_txipos); - - /* Took me 5 minutes to deduce this formula. - Luckily it is literally in the manual in section 6.5.4.3.5 */ - txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) & - 0xff; - - /* Don't copy more bytes than there is room for in the buffer */ - if (c > txroom) - c = txroom; - sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom); - - /* Don't copy past the end of the hardware transmit buffer */ - if (c > 0x100 - tx_ip) - c = 0x100 - tx_ip; - - sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip); - - /* Don't copy pas the end of the source buffer */ - if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) - c = SERIAL_XMIT_SIZE - port->gs.xmit_tail; - - sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n", - c, SERIAL_XMIT_SIZE - port->gs.xmit_tail); - - /* If for one reason or another, we can't copy more data, we're - done! */ - if (c == 0) - break; - - memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) + - tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c); - - /* Update the pointer in the card */ - sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff); - - /* Update the kernel buffer end */ - port->gs.xmit_tail = (port->gs.xmit_tail + c) & - (SERIAL_XMIT_SIZE - 1); - - /* This one last. (this is essential) - It would allow others to start putting more data into the - buffer! */ - port->gs.xmit_cnt -= c; - } - - if (port->gs.xmit_cnt == 0) { - sx_disable_tx_interrupts(port); - } - - if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { - tty_wakeup(port->gs.port.tty); - sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", - port->gs.wakeup_chars); - } - - clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks); - func_exit(); -} - -/* Note the symmetry between receiving chars and transmitting them! - Note: The kernel should have implemented both a receive buffer and - a transmit buffer. */ - -/* Inlined: Called only once. Remove the inline when you add another call */ -static inline void sx_receive_chars(struct sx_port *port) -{ - int c; - int rx_op; - struct tty_struct *tty; - int copied = 0; - unsigned char *rp; - - func_enter2(); - tty = port->gs.port.tty; - while (1) { - rx_op = sx_read_channel_byte(port, hi_rxopos); - c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff; - - sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); - - /* Don't copy past the end of the hardware receive buffer */ - if (rx_op + c > 0x100) - c = 0x100 - rx_op; - - sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); - - /* Don't copy more bytes than there is room for in the buffer */ - - c = tty_prepare_flip_string(tty, &rp, c); - - sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); - - /* If for one reason or another, we can't copy more data, we're done! */ - if (c == 0) - break; - - sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is " - "%d at %lx\n", c, read_sx_byte(port->board, - CHAN_OFFSET(port, hi_rxbuf) + rx_op), - CHAN_OFFSET(port, hi_rxbuf)); - memcpy_fromio(rp, port->board->base + - CHAN_OFFSET(port, hi_rxbuf) + rx_op, c); - - /* This one last. ( Not essential.) - It allows the card to start putting more data into the - buffer! - Update the pointer in the card */ - sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff); - - copied += c; - } - if (copied) { - struct timeval tv; - - do_gettimeofday(&tv); - sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d " - "chars): %d.%06d (%d/%d)\n", port->line, - copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec, - tty->raw, tty->real_raw); - - /* Tell the rest of the system the news. Great news. New - characters! */ - tty_flip_buffer_push(tty); - /* tty_schedule_flip (tty); */ - } - - func_exit(); -} - -/* Inlined: it is called only once. Remove the inline if you add another - call */ -static inline void sx_check_modem_signals(struct sx_port *port) -{ - int hi_state; - int c_dcd; - - hi_state = sx_read_channel_byte(port, hi_state); - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", - port->c_dcd, tty_port_carrier_raised(&port->gs.port)); - - if (hi_state & ST_BREAK) { - hi_state &= ~ST_BREAK; - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n"); - sx_write_channel_byte(port, hi_state, hi_state); - gs_got_break(&port->gs); - } - if (hi_state & ST_DCD) { - hi_state &= ~ST_DCD; - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); - sx_write_channel_byte(port, hi_state, hi_state); - c_dcd = tty_port_carrier_raised(&port->gs.port); - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); - if (c_dcd != port->c_dcd) { - port->c_dcd = c_dcd; - if (tty_port_carrier_raised(&port->gs.port)) { - /* DCD went UP */ - if ((sx_read_channel_byte(port, hi_hstat) != - HS_IDLE_CLOSED) && - !(port->gs.port.tty->termios-> - c_cflag & CLOCAL)) { - /* Are we blocking in open? */ - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " - "active, unblocking open\n"); - wake_up_interruptible(&port->gs.port. - open_wait); - } else { - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " - "raised. Ignoring.\n"); - } - } else { - /* DCD went down! */ - if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){ - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " - "dropped. hanging up....\n"); - tty_hangup(port->gs.port.tty); - } else { - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " - "dropped. ignoring.\n"); - } - } - } else { - sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us " - "DCD changed, but it didn't.\n"); - } - } -} - -/* This is what an interrupt routine should look like. - * Small, elegant, clear. - */ - -static irqreturn_t sx_interrupt(int irq, void *ptr) -{ - struct sx_board *board = ptr; - struct sx_port *port; - int i; - - func_enter(); - sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, - board->irq); - - /* AAargh! The order in which to do these things is essential and - not trivial. - - - Rate limit goes before "recursive". Otherwise a series of - recursive calls will hang the machine in the interrupt routine. - - - hardware twiddling goes before "recursive". Otherwise when we - poll the card, and a recursive interrupt happens, we won't - ack the card, so it might keep on interrupting us. (especially - level sensitive interrupt systems like PCI). - - - Rate limit goes before hardware twiddling. Otherwise we won't - catch a card that has gone bonkers. - - - The "initialized" test goes after the hardware twiddling. Otherwise - the card will stick us in the interrupt routine again. - - - The initialized test goes before recursive. - */ - -#ifdef IRQ_RATE_LIMIT - /* Aaargh! I'm ashamed. This costs more lines-of-code than the - actual interrupt routine!. (Well, used to when I wrote that - comment) */ - { - static int lastjif; - static int nintr = 0; - - if (lastjif == jiffies) { - if (++nintr > IRQ_RATE_LIMIT) { - free_irq(board->irq, board); - printk(KERN_ERR "sx: Too many interrupts. " - "Turning off interrupt %d.\n", - board->irq); - } - } else { - lastjif = jiffies; - nintr = 0; - } - } -#endif - - if (board->irq == irq) { - /* Tell the card we've noticed the interrupt. */ - - sx_write_board_word(board, cc_int_pending, 0); - if (IS_SX_BOARD(board)) { - write_sx_byte(board, SX_RESET_IRQ, 1); - } else if (IS_EISA_BOARD(board)) { - inb(board->eisa_base + 0xc03); - write_sx_word(board, 8, 0); - } else { - write_sx_byte(board, SI2_ISA_INTCLEAR, - SI2_ISA_INTCLEAR_CLEAR); - write_sx_byte(board, SI2_ISA_INTCLEAR, - SI2_ISA_INTCLEAR_SET); - } - } - - if (!sx_initialized) - return IRQ_HANDLED; - if (!(board->flags & SX_BOARD_INITIALIZED)) - return IRQ_HANDLED; - - if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) { - printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq); - return IRQ_HANDLED; - } - - for (i = 0; i < board->nports; i++) { - port = &board->ports[i]; - if (port->gs.port.flags & GS_ACTIVE) { - if (sx_read_channel_byte(port, hi_state)) { - sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: " - "modem signal change?... \n",i); - sx_check_modem_signals(port); - } - if (port->gs.xmit_cnt) { - sx_transmit_chars(port); - } - if (!(port->gs.port.flags & SX_RX_THROTTLE)) { - sx_receive_chars(port); - } - } - } - - clear_bit(SX_BOARD_INTR_LOCK, &board->locks); - - sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, - board->irq); - func_exit(); - return IRQ_HANDLED; -} - -static void sx_pollfunc(unsigned long data) -{ - struct sx_board *board = (struct sx_board *)data; - - func_enter(); - - sx_interrupt(0, board); - - mod_timer(&board->timer, jiffies + sx_poll); - func_exit(); -} - -/* ********************************************************************** * - * Here are the routines that actually * - * interface with the generic_serial driver * - * ********************************************************************** */ - -/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */ -/* Hmm. Ok I figured it out. You don't. */ - -static void sx_disable_tx_interrupts(void *ptr) -{ - struct sx_port *port = ptr; - func_enter2(); - - port->gs.port.flags &= ~GS_TX_INTEN; - - func_exit(); -} - -static void sx_enable_tx_interrupts(void *ptr) -{ - struct sx_port *port = ptr; - int data_in_buffer; - func_enter2(); - - /* First transmit the characters that we're supposed to */ - sx_transmit_chars(port); - - /* The sx card will never interrupt us if we don't fill the buffer - past 25%. So we keep considering interrupts off if that's the case. */ - data_in_buffer = (sx_read_channel_byte(port, hi_txipos) - - sx_read_channel_byte(port, hi_txopos)) & 0xff; - - /* XXX Must be "HIGH_WATER" for SI card according to doc. */ - if (data_in_buffer < LOW_WATER) - port->gs.port.flags &= ~GS_TX_INTEN; - - func_exit(); -} - -static void sx_disable_rx_interrupts(void *ptr) -{ - /* struct sx_port *port = ptr; */ - func_enter(); - - func_exit(); -} - -static void sx_enable_rx_interrupts(void *ptr) -{ - /* struct sx_port *port = ptr; */ - func_enter(); - - func_exit(); -} - -/* Jeez. Isn't this simple? */ -static int sx_carrier_raised(struct tty_port *port) -{ - struct sx_port *sp = container_of(port, struct sx_port, gs.port); - return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0); -} - -/* Jeez. Isn't this simple? */ -static int sx_chars_in_buffer(void *ptr) -{ - struct sx_port *port = ptr; - func_enter2(); - - func_exit(); - return ((sx_read_channel_byte(port, hi_txipos) - - sx_read_channel_byte(port, hi_txopos)) & 0xff); -} - -static void sx_shutdown_port(void *ptr) -{ - struct sx_port *port = ptr; - - func_enter(); - - port->gs.port.flags &= ~GS_ACTIVE; - if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) { - sx_setsignals(port, 0, 0); - sx_reconfigure_port(port); - } - - func_exit(); -} - -/* ********************************************************************** * - * Here are the routines that actually * - * interface with the rest of the system * - * ********************************************************************** */ - -static int sx_open(struct tty_struct *tty, struct file *filp) -{ - struct sx_port *port; - int retval, line; - unsigned long flags; - - func_enter(); - - if (!sx_initialized) { - return -EIO; - } - - line = tty->index; - sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, " - "np=%d)\n", task_pid_nr(current), line, tty, - current->signal->tty, sx_nports); - - if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports)) - return -ENODEV; - - port = &sx_ports[line]; - port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a - 1 -> 0 transition. */ - - sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); - - spin_lock_irqsave(&port->gs.driver_lock, flags); - - tty->driver_data = port; - port->gs.port.tty = tty; - port->gs.port.count++; - spin_unlock_irqrestore(&port->gs.driver_lock, flags); - - sx_dprintk(SX_DEBUG_OPEN, "starting port\n"); - - /* - * Start up serial port - */ - retval = gs_init_port(&port->gs); - sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n"); - if (retval) { - port->gs.port.count--; - return retval; - } - - port->gs.port.flags |= GS_ACTIVE; - if (port->gs.port.count <= 1) - sx_setsignals(port, 1, 1); - -#if 0 - if (sx_debug & SX_DEBUG_OPEN) - my_hd(port, sizeof(*port)); -#else - if (sx_debug & SX_DEBUG_OPEN) - my_hd_io(port->board->base + port->ch_base, sizeof(*port)); -#endif - - if (port->gs.port.count <= 1) { - if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { - printk(KERN_ERR "sx: Card didn't respond to LOPEN " - "command.\n"); - spin_lock_irqsave(&port->gs.driver_lock, flags); - port->gs.port.count--; - spin_unlock_irqrestore(&port->gs.driver_lock, flags); - return -EIO; - } - } - - retval = gs_block_til_ready(port, filp); - sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", - retval, port->gs.port.count); - - if (retval) { -/* - * Don't lower gs.port.count here because sx_close() will be called later - */ - - return retval; - } - /* tty->low_latency = 1; */ - - port->c_dcd = sx_carrier_raised(&port->gs.port); - sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); - - func_exit(); - return 0; - -} - -static void sx_close(void *ptr) -{ - struct sx_port *port = ptr; - /* Give the port 5 seconds to close down. */ - int to = 5 * HZ; - - func_enter(); - - sx_setsignals(port, 0, 0); - sx_reconfigure_port(port); - sx_send_command(port, HS_CLOSE, 0, 0); - - while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) - if (msleep_interruptible(10)) - break; - if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) { - if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) - != 1) { - printk(KERN_ERR "sx: sent the force_close command, but " - "card didn't react\n"); - } else - sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close " - "command.\n"); - } - - sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", - 5 * HZ - to - 1, port->gs.port.count); - - if (port->gs.port.count) { - sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", - port->gs.port.count); - /*printk("%s SETTING port count to zero: %p count: %d\n", - __func__, port, port->gs.port.count); - port->gs.port.count = 0;*/ - } - - func_exit(); -} - -/* This is relatively thorough. But then again it is only 20 lines. */ -#define MARCHUP for (i = min; i < max; i++) -#define MARCHDOWN for (i = max - 1; i >= min; i--) -#define W0 write_sx_byte(board, i, 0x55) -#define W1 write_sx_byte(board, i, 0xaa) -#define R0 if (read_sx_byte(board, i) != 0x55) return 1 -#define R1 if (read_sx_byte(board, i) != 0xaa) return 1 - -/* This memtest takes a human-noticable time. You normally only do it - once a boot, so I guess that it is worth it. */ -static int do_memtest(struct sx_board *board, int min, int max) -{ - int i; - - /* This is a marchb. Theoretically, marchb catches much more than - simpler tests. In practise, the longer test just catches more - intermittent errors. -- REW - (For the theory behind memory testing see: - Testing Semiconductor Memories by A.J. van de Goor.) */ - MARCHUP { - W0; - } - MARCHUP { - R0; - W1; - R1; - W0; - R0; - W1; - } - MARCHUP { - R1; - W0; - W1; - } - MARCHDOWN { - R1; - W0; - W1; - W0; - } - MARCHDOWN { - R0; - W1; - W0; - } - - return 0; -} - -#undef MARCHUP -#undef MARCHDOWN -#undef W0 -#undef W1 -#undef R0 -#undef R1 - -#define MARCHUP for (i = min; i < max; i += 2) -#define MARCHDOWN for (i = max - 1; i >= min; i -= 2) -#define W0 write_sx_word(board, i, 0x55aa) -#define W1 write_sx_word(board, i, 0xaa55) -#define R0 if (read_sx_word(board, i) != 0x55aa) return 1 -#define R1 if (read_sx_word(board, i) != 0xaa55) return 1 - -#if 0 -/* This memtest takes a human-noticable time. You normally only do it - once a boot, so I guess that it is worth it. */ -static int do_memtest_w(struct sx_board *board, int min, int max) -{ - int i; - - MARCHUP { - W0; - } - MARCHUP { - R0; - W1; - R1; - W0; - R0; - W1; - } - MARCHUP { - R1; - W0; - W1; - } - MARCHDOWN { - R1; - W0; - W1; - W0; - } - MARCHDOWN { - R0; - W1; - W0; - } - - return 0; -} -#endif - -static long sx_fw_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - long rc = 0; - int __user *descr = (int __user *)arg; - int i; - static struct sx_board *board = NULL; - int nbytes, offset; - unsigned long data; - char *tmp; - - func_enter(); - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - - tty_lock(); - - sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); - - if (!board) - board = &boards[0]; - if (board->flags & SX_BOARD_PRESENT) { - sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n", - board->flags); - } else { - sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", - board->flags); - for (i = 0; i < SX_NBOARDS; i++) - sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); - sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); - rc = -EIO; - goto out; - } - - switch (cmd) { - case SXIO_SET_BOARD: - sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); - rc = -EIO; - if (arg >= SX_NBOARDS) - break; - sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); - if (!(boards[arg].flags & SX_BOARD_PRESENT)) - break; - sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); - board = &boards[arg]; - rc = 0; - /* FIXME: And this does ... nothing?? */ - break; - case SXIO_GET_TYPE: - rc = -ENOENT; /* If we manage to miss one, return error. */ - if (IS_SX_BOARD(board)) - rc = SX_TYPE_SX; - if (IS_CF_BOARD(board)) - rc = SX_TYPE_CF; - if (IS_SI_BOARD(board)) - rc = SX_TYPE_SI; - if (IS_SI1_BOARD(board)) - rc = SX_TYPE_SI; - if (IS_EISA_BOARD(board)) - rc = SX_TYPE_SI; - sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); - break; - case SXIO_DO_RAMTEST: - if (sx_initialized) { /* Already initialized: better not ramtest the board. */ - rc = -EPERM; - break; - } - if (IS_SX_BOARD(board)) { - rc = do_memtest(board, 0, 0x7000); - if (!rc) - rc = do_memtest(board, 0, 0x7000); - /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */ - } else { - rc = do_memtest(board, 0, 0x7ff8); - /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ - } - sx_dprintk(SX_DEBUG_FIRMWARE, - "returning memtest result= %ld\n", rc); - break; - case SXIO_DOWNLOAD: - if (sx_initialized) {/* Already initialized */ - rc = -EEXIST; - break; - } - if (!sx_reset(board)) { - rc = -EIO; - break; - } - sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); - - tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); - if (!tmp) { - rc = -ENOMEM; - break; - } - /* FIXME: check returns */ - get_user(nbytes, descr++); - get_user(offset, descr++); - get_user(data, descr++); - while (nbytes && data) { - for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) { - if (copy_from_user(tmp, (char __user *)data + i, - (i + SX_CHUNK_SIZE > nbytes) ? - nbytes - i : SX_CHUNK_SIZE)) { - kfree(tmp); - rc = -EFAULT; - goto out; - } - memcpy_toio(board->base2 + offset + i, tmp, - (i + SX_CHUNK_SIZE > nbytes) ? - nbytes - i : SX_CHUNK_SIZE); - } - - get_user(nbytes, descr++); - get_user(offset, descr++); - get_user(data, descr++); - } - kfree(tmp); - sx_nports += sx_init_board(board); - rc = sx_nports; - break; - case SXIO_INIT: - if (sx_initialized) { /* Already initialized */ - rc = -EEXIST; - break; - } - /* This is not allowed until all boards are initialized... */ - for (i = 0; i < SX_NBOARDS; i++) { - if ((boards[i].flags & SX_BOARD_PRESENT) && - !(boards[i].flags & SX_BOARD_INITIALIZED)) { - rc = -EIO; - break; - } - } - for (i = 0; i < SX_NBOARDS; i++) - if (!(boards[i].flags & SX_BOARD_PRESENT)) - break; - - sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, " - "%d channels, first board: %d ports\n", - i, sx_nports, boards[0].nports); - rc = sx_init_portstructs(i, sx_nports); - sx_init_drivers(); - if (rc >= 0) - sx_initialized++; - break; - case SXIO_SETDEBUG: - sx_debug = arg; - break; - case SXIO_GETDEBUG: - rc = sx_debug; - break; - case SXIO_GETGSDEBUG: - case SXIO_SETGSDEBUG: - rc = -EINVAL; - break; - case SXIO_GETNPORTS: - rc = sx_nports; - break; - default: - rc = -ENOTTY; - break; - } -out: - tty_unlock(); - func_exit(); - return rc; -} - -static int sx_break(struct tty_struct *tty, int flag) -{ - struct sx_port *port = tty->driver_data; - int rv; - - func_enter(); - tty_lock(); - - if (flag) - rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); - else - rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN); - if (rv != 1) - printk(KERN_ERR "sx: couldn't send break (%x).\n", - read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); - tty_unlock(); - func_exit(); - return 0; -} - -static int sx_tiocmget(struct tty_struct *tty) -{ - struct sx_port *port = tty->driver_data; - return sx_getsignals(port); -} - -static int sx_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct sx_port *port = tty->driver_data; - int rts = -1, dtr = -1; - - if (set & TIOCM_RTS) - rts = 1; - if (set & TIOCM_DTR) - dtr = 1; - if (clear & TIOCM_RTS) - rts = 0; - if (clear & TIOCM_DTR) - dtr = 0; - - sx_setsignals(port, dtr, rts); - sx_reconfigure_port(port); - return 0; -} - -static int sx_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - int rc; - struct sx_port *port = tty->driver_data; - void __user *argp = (void __user *)arg; - - /* func_enter2(); */ - - rc = 0; - tty_lock(); - switch (cmd) { - case TIOCGSERIAL: - rc = gs_getserial(&port->gs, argp); - break; - case TIOCSSERIAL: - rc = gs_setserial(&port->gs, argp); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - tty_unlock(); - - /* func_exit(); */ - return rc; -} - -/* The throttle/unthrottle scheme for the Specialix card is different - * from other drivers and deserves some explanation. - * The Specialix hardware takes care of XON/XOFF - * and CTS/RTS flow control itself. This means that all we have to - * do when signalled by the upper tty layer to throttle/unthrottle is - * to make a note of it here. When we come to read characters from the - * rx buffers on the card (sx_receive_chars()) we look to see if the - * upper layer can accept more (as noted here in sx_rx_throt[]). - * If it can't we simply don't remove chars from the cards buffer. - * When the tty layer can accept chars, we again note that here and when - * sx_receive_chars() is called it will remove them from the cards buffer. - * The card will notice that a ports buffer has drained below some low - * water mark and will unflow control the line itself, using whatever - * flow control scheme is in use for that port. -- Simon Allen - */ - -static void sx_throttle(struct tty_struct *tty) -{ - struct sx_port *port = tty->driver_data; - - func_enter2(); - /* If the port is using any type of input flow - * control then throttle the port. - */ - if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) { - port->gs.port.flags |= SX_RX_THROTTLE; - } - func_exit(); -} - -static void sx_unthrottle(struct tty_struct *tty) -{ - struct sx_port *port = tty->driver_data; - - func_enter2(); - /* Always unthrottle even if flow control is not enabled on - * this port in case we disabled flow control while the port - * was throttled - */ - port->gs.port.flags &= ~SX_RX_THROTTLE; - func_exit(); - return; -} - -/* ********************************************************************** * - * Here are the initialization routines. * - * ********************************************************************** */ - -static int sx_init_board(struct sx_board *board) -{ - int addr; - int chans; - int type; - - func_enter(); - - /* This is preceded by downloading the download code. */ - - board->flags |= SX_BOARD_INITIALIZED; - - if (read_sx_byte(board, 0)) - /* CF boards may need this. */ - write_sx_byte(board, 0, 0); - - /* This resets the processor again, to make sure it didn't do any - foolish things while we were downloading the image */ - if (!sx_reset(board)) - return 0; - - sx_start_board(board); - udelay(10); - if (!sx_busy_wait_neq(board, 0, 0xff, 0)) { - printk(KERN_ERR "sx: Ooops. Board won't initialize.\n"); - return 0; - } - - /* Ok. So now the processor on the card is running. It gathered - some info for us... */ - sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n"); - if (sx_debug & SX_DEBUG_INIT) - my_hd_io(board->base, 0x10); - sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n"); - if (sx_debug & SX_DEBUG_INIT) - my_hd_io(board->base + 0x80, 0x30); - - sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware " - "V%x.%02x,\n", - read_sx_byte(board, 0), read_sx_byte(board, 1), - read_sx_byte(board, 5), read_sx_byte(board, 4)); - - if (read_sx_byte(board, 0) == 0xff) { - printk(KERN_INFO "sx: No modules found. Sorry.\n"); - board->nports = 0; - return 0; - } - - chans = 0; - - if (IS_SX_BOARD(board)) { - sx_write_board_word(board, cc_int_count, sx_maxints); - } else { - if (sx_maxints) - sx_write_board_word(board, cc_int_count, - SI_PROCESSOR_CLOCK / 8 / sx_maxints); - } - - /* grab the first module type... */ - /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ - board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80, - mc_chip)); - - /* XXX byteorder */ - for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){ - type = sx_read_module_byte(board, addr, mc_chip); - sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n", - addr, read_sx_byte(board, addr + 2)); - - chans += sx_read_module_byte(board, addr, mc_type); - - sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s " - "panels\n", - mod_type_s(type), - pan_type_s(sx_read_module_byte(board, addr, - mc_mods) & 0xf), - pan_type_s(sx_read_module_byte(board, addr, - mc_mods) >> 4)); - - sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC " - "version: %x\n", - sx_read_module_byte(board, addr, mc_rev1), - sx_read_module_byte(board, addr, mc_rev2), - sx_read_module_byte(board, addr, mc_mtaasic_rev)); - - /* The following combinations are illegal: It should theoretically - work, but timing problems make the bus HANG. */ - - if (mod_compat_type(type) != board->ta_type) { - printk(KERN_ERR "sx: This is an invalid " - "configuration.\nDon't mix TA/MTA/SXDC on the " - "same hostadapter.\n"); - chans = 0; - break; - } - if ((IS_EISA_BOARD(board) || - IS_SI_BOARD(board)) && - (mod_compat_type(type) == 4)) { - printk(KERN_ERR "sx: This is an invalid " - "configuration.\nDon't use SXDCs on an SI/XIO " - "adapter.\n"); - chans = 0; - break; - } -#if 0 /* Problem fixed: firmware 3.05 */ - if (IS_SX_BOARD(board) && (type == TA8)) { - /* There are some issues with the firmware and the DCD/RTS - lines. It might work if you tie them together or something. - It might also work if you get a newer sx_firmware. Therefore - this is just a warning. */ - printk(KERN_WARNING - "sx: The SX host doesn't work too well " - "with the TA8 adapters.\nSpecialix is working on it.\n"); - } -#endif - } - - if (chans) { - if (board->irq > 0) { - /* fixed irq, probably PCI */ - if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ - if (request_irq(board->irq, sx_interrupt, - IRQF_SHARED | IRQF_DISABLED, - "sx", board)) { - printk(KERN_ERR "sx: Cannot allocate " - "irq %d.\n", board->irq); - board->irq = 0; - } - } else - board->irq = 0; - } else if (board->irq < 0 && sx_irqmask) { - /* auto-allocate irq */ - int irqnr; - int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? - SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); - for (irqnr = 15; irqnr > 0; irqnr--) - if (irqmask & (1 << irqnr)) - if (!request_irq(irqnr, sx_interrupt, - IRQF_SHARED | IRQF_DISABLED, - "sx", board)) - break; - if (!irqnr) - printk(KERN_ERR "sx: Cannot allocate IRQ.\n"); - board->irq = irqnr; - } else - board->irq = 0; - - if (board->irq) { - /* Found a valid interrupt, start up interrupts! */ - sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n", - board->irq); - sx_start_interrupts(board); - board->poll = sx_slowpoll; - board->flags |= SX_IRQ_ALLOCATED; - } else { - /* no irq: setup board for polled operation */ - board->poll = sx_poll; - sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n", - board->poll); - } - - /* The timer should be initialized anyway: That way we can - safely del_timer it when the module is unloaded. */ - setup_timer(&board->timer, sx_pollfunc, (unsigned long)board); - - if (board->poll) - mod_timer(&board->timer, jiffies + board->poll); - } else { - board->irq = 0; - } - - board->nports = chans; - sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports); - - func_exit(); - return chans; -} - -static void __devinit printheader(void) -{ - static int header_printed; - - if (!header_printed) { - printk(KERN_INFO "Specialix SX driver " - "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n"); - printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n"); - header_printed = 1; - } -} - -static int __devinit probe_sx(struct sx_board *board) -{ - struct vpd_prom vpdp; - char *p; - int i; - - func_enter(); - - if (!IS_CF_BOARD(board)) { - sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", - board->base + SX_VPD_ROM); - - if (sx_debug & SX_DEBUG_PROBE) - my_hd_io(board->base + SX_VPD_ROM, 0x40); - - p = (char *)&vpdp; - for (i = 0; i < sizeof(struct vpd_prom); i++) - *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2); - - if (sx_debug & SX_DEBUG_PROBE) - my_hd(&vpdp, 0x20); - - sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n"); - - if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { - sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: " - "'%s'\n", vpdp.identifier); - return 0; - } - } - - printheader(); - - if (!IS_CF_BOARD(board)) { - printk(KERN_DEBUG "sx: Found an SX board at %lx\n", - board->hw_base); - printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, " - "uniq ID:%08x, ", - vpdp.hwrev, vpdp.hwass, vpdp.uniqid); - printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek); - - if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != - SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) & - SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { - /* This might be a bit harsh. This was the primary - reason the SX/ISA card didn't work at first... */ - printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA " - "card. Sorry: giving up.\n"); - return (0); - } - - if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == - SX_ISA_UNIQUEID1) { - if (((unsigned long)board->hw_base) & 0x8000) { - printk(KERN_WARNING "sx: Warning: There may be " - "hardware problems with the card at " - "%lx.\n", board->hw_base); - printk(KERN_WARNING "sx: Read sx.txt for more " - "info.\n"); - } - } - } - - board->nports = -1; - - /* This resets the processor, and keeps it off the bus. */ - if (!sx_reset(board)) - return 0; - sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); - - func_exit(); - return 1; -} - -#if defined(CONFIG_ISA) || defined(CONFIG_EISA) - -/* Specialix probes for this card at 32k increments from 640k to 16M. - I consider machines with less than 16M unlikely nowadays, so I'm - not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA - card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves - 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */ - -static int __devinit probe_si(struct sx_board *board) -{ - int i; - - func_enter(); - sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at " - "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE); - - if (sx_debug & SX_DEBUG_PROBE) - my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8); - - if (!IS_EISA_BOARD(board)) { - if (IS_SI1_BOARD(board)) { - for (i = 0; i < 8; i++) { - write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i); - } - } - for (i = 0; i < 8; i++) { - if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7) - != i) { - func_exit(); - return 0; - } - } - } - - /* Now we're pretty much convinced that there is an SI board here, - but to prevent trouble, we'd better double check that we don't - have an SI1 board when we're probing for an SI2 board.... */ - - write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); - if (IS_SI1_BOARD(board)) { - /* This should be an SI1 board, which has this - location writable... */ - if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { - func_exit(); - return 0; - } - } else { - /* This should be an SI2 board, which has the bottom - 3 bits non-writable... */ - if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { - func_exit(); - return 0; - } - } - - /* Now we're pretty much convinced that there is an SI board here, - but to prevent trouble, we'd better double check that we don't - have an SI1 board when we're probing for an SI2 board.... */ - - write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); - if (IS_SI1_BOARD(board)) { - /* This should be an SI1 board, which has this - location writable... */ - if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { - func_exit(); - return 0; - } - } else { - /* This should be an SI2 board, which has the bottom - 3 bits non-writable... */ - if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { - func_exit(); - return 0; - } - } - - printheader(); - - printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); - /* Compared to the SX boards, it is a complete guess as to what - this card is up to... */ - - board->nports = -1; - - /* This resets the processor, and keeps it off the bus. */ - if (!sx_reset(board)) - return 0; - sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); - - func_exit(); - return 1; -} -#endif - -static const struct tty_operations sx_ops = { - .break_ctl = sx_break, - .open = sx_open, - .close = gs_close, - .write = gs_write, - .put_char = gs_put_char, - .flush_chars = gs_flush_chars, - .write_room = gs_write_room, - .chars_in_buffer = gs_chars_in_buffer, - .flush_buffer = gs_flush_buffer, - .ioctl = sx_ioctl, - .throttle = sx_throttle, - .unthrottle = sx_unthrottle, - .set_termios = gs_set_termios, - .stop = gs_stop, - .start = gs_start, - .hangup = gs_hangup, - .tiocmget = sx_tiocmget, - .tiocmset = sx_tiocmset, -}; - -static const struct tty_port_operations sx_port_ops = { - .carrier_raised = sx_carrier_raised, -}; - -static int sx_init_drivers(void) -{ - int error; - - func_enter(); - - sx_driver = alloc_tty_driver(sx_nports); - if (!sx_driver) - return 1; - sx_driver->owner = THIS_MODULE; - sx_driver->driver_name = "specialix_sx"; - sx_driver->name = "ttyX"; - sx_driver->major = SX_NORMAL_MAJOR; - sx_driver->type = TTY_DRIVER_TYPE_SERIAL; - sx_driver->subtype = SERIAL_TYPE_NORMAL; - sx_driver->init_termios = tty_std_termios; - sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - sx_driver->init_termios.c_ispeed = 9600; - sx_driver->init_termios.c_ospeed = 9600; - sx_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(sx_driver, &sx_ops); - - if ((error = tty_register_driver(sx_driver))) { - put_tty_driver(sx_driver); - printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n", - error); - return 1; - } - func_exit(); - return 0; -} - -static int sx_init_portstructs(int nboards, int nports) -{ - struct sx_board *board; - struct sx_port *port; - int i, j; - int addr, chans; - int portno; - - func_enter(); - - /* Many drivers statically allocate the maximum number of ports - There is no reason not to allocate them dynamically. - Is there? -- REW */ - sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL); - if (!sx_ports) - return -ENOMEM; - - port = sx_ports; - for (i = 0; i < nboards; i++) { - board = &boards[i]; - board->ports = port; - for (j = 0; j < boards[i].nports; j++) { - sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); - tty_port_init(&port->gs.port); - port->gs.port.ops = &sx_port_ops; - port->gs.magic = SX_MAGIC; - port->gs.close_delay = HZ / 2; - port->gs.closing_wait = 30 * HZ; - port->board = board; - port->gs.rd = &sx_real_driver; -#ifdef NEW_WRITE_LOCKING - port->gs.port_write_mutex = MUTEX; -#endif - spin_lock_init(&port->gs.driver_lock); - /* - * Initializing wait queue - */ - port++; - } - } - - port = sx_ports; - portno = 0; - for (i = 0; i < nboards; i++) { - board = &boards[i]; - board->port_base = portno; - /* Possibly the configuration was rejected. */ - sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n", - board->nports); - if (board->nports <= 0) - continue; - /* XXX byteorder ?? */ - for (addr = 0x80; addr != 0; - addr = read_sx_word(board, addr) & 0x7fff) { - chans = sx_read_module_byte(board, addr, mc_type); - sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d " - "channels\n", addr, chans); - sx_dprintk(SX_DEBUG_PROBE, "Port at"); - for (j = 0; j < chans; j++) { - /* The "sx-way" is the way it SHOULD be done. - That way in the future, the firmware may for - example pack the structures a bit more - efficient. Neil tells me it isn't going to - happen anytime soon though. */ - if (IS_SX_BOARD(board)) - port->ch_base = sx_read_module_word( - board, addr + j * 2, - mc_chan_pointer); - else - port->ch_base = addr + 0x100 + 0x300 *j; - - sx_dprintk(SX_DEBUG_PROBE, " %x", - port->ch_base); - port->line = portno++; - port++; - } - sx_dprintk(SX_DEBUG_PROBE, "\n"); - } - /* This has to be done earlier. */ - /* board->flags |= SX_BOARD_INITIALIZED; */ - } - - func_exit(); - return 0; -} - -static unsigned int sx_find_free_board(void) -{ - unsigned int i; - - for (i = 0; i < SX_NBOARDS; i++) - if (!(boards[i].flags & SX_BOARD_PRESENT)) - break; - - return i; -} - -static void __exit sx_release_drivers(void) -{ - func_enter(); - tty_unregister_driver(sx_driver); - put_tty_driver(sx_driver); - func_exit(); -} - -static void __devexit sx_remove_card(struct sx_board *board, - struct pci_dev *pdev) -{ - if (board->flags & SX_BOARD_INITIALIZED) { - /* The board should stop messing with us. (actually I mean the - interrupt) */ - sx_reset(board); - if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) - free_irq(board->irq, board); - - /* It is safe/allowed to del_timer a non-active timer */ - del_timer(&board->timer); - if (pdev) { -#ifdef CONFIG_PCI - iounmap(board->base2); - pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); -#endif - } else { - iounmap(board->base); - release_region(board->hw_base, board->hw_len); - } - - board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT); - } -} - -#ifdef CONFIG_EISA - -static int __devinit sx_eisa_probe(struct device *dev) -{ - struct eisa_device *edev = to_eisa_device(dev); - struct sx_board *board; - unsigned long eisa_slot = edev->base_addr; - unsigned int i; - int retval = -EIO; - - mutex_lock(&sx_boards_lock); - i = sx_find_free_board(); - if (i == SX_NBOARDS) { - mutex_unlock(&sx_boards_lock); - goto err; - } - board = &boards[i]; - board->flags |= SX_BOARD_PRESENT; - mutex_unlock(&sx_boards_lock); - - dev_info(dev, "XIO : Signature found in EISA slot %lu, " - "Product %d Rev %d (REPORT THIS TO LKLM)\n", - eisa_slot >> 12, - inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), - inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); - - board->eisa_base = eisa_slot; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_EISA_BOARD; - - board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + - inb(eisa_slot + 0xc00)) << 16; - board->hw_len = SI2_EISA_WINDOW_LEN; - if (!request_region(board->hw_base, board->hw_len, "sx")) { - dev_err(dev, "can't request region\n"); - goto err_flag; - } - board->base2 = - board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN); - if (!board->base) { - dev_err(dev, "can't remap memory\n"); - goto err_reg; - } - - sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); - sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); - board->irq = inb(eisa_slot + 0xc02) >> 4; - sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); - - if (!probe_si(board)) - goto err_unmap; - - dev_set_drvdata(dev, board); - - return 0; -err_unmap: - iounmap(board->base); -err_reg: - release_region(board->hw_base, board->hw_len); -err_flag: - board->flags &= ~SX_BOARD_PRESENT; -err: - return retval; -} - -static int __devexit sx_eisa_remove(struct device *dev) -{ - struct sx_board *board = dev_get_drvdata(dev); - - sx_remove_card(board, NULL); - - return 0; -} - -static struct eisa_device_id sx_eisa_tbl[] = { - { "SLX" }, - { "" } -}; - -MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl); - -static struct eisa_driver sx_eisadriver = { - .id_table = sx_eisa_tbl, - .driver = { - .name = "sx", - .probe = sx_eisa_probe, - .remove = __devexit_p(sx_eisa_remove), - } -}; - -#endif - -#ifdef CONFIG_PCI - /******************************************************** - * Setting bit 17 in the CNTRL register of the PLX 9050 * - * chip forces a retry on writes while a read is pending.* - * This is to prevent the card locking up on Intel Xeon * - * multiprocessor systems with the NX chipset. -- NV * - ********************************************************/ - -/* Newer cards are produced with this bit set from the configuration - EEprom. As the bit is read/write for the CPU, we can fix it here, - if we detect that it isn't set correctly. -- REW */ - -static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board) -{ - unsigned int hwbase; - void __iomem *rebase; - unsigned int t; - -#define CNTRL_REG_OFFSET 0x50 -#define CNTRL_REG_GOODVALUE 0x18260000 - - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); - hwbase &= PCI_BASE_ADDRESS_MEM_MASK; - rebase = ioremap_nocache(hwbase, 0x80); - t = readl(rebase + CNTRL_REG_OFFSET); - if (t != CNTRL_REG_GOODVALUE) { - printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> " - "%08x\n", t, CNTRL_REG_GOODVALUE); - writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); - } - iounmap(rebase); -} -#endif - -static int __devinit sx_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ -#ifdef CONFIG_PCI - struct sx_board *board; - unsigned int i, reg; - int retval = -EIO; - - mutex_lock(&sx_boards_lock); - i = sx_find_free_board(); - if (i == SX_NBOARDS) { - mutex_unlock(&sx_boards_lock); - goto err; - } - board = &boards[i]; - board->flags |= SX_BOARD_PRESENT; - mutex_unlock(&sx_boards_lock); - - retval = pci_enable_device(pdev); - if (retval) - goto err_flag; - - board->flags &= ~SX_BOARD_TYPE; - board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : - SX_CFPCI_BOARD; - - /* CF boards use base address 3.... */ - reg = IS_CF_BOARD(board) ? 3 : 2; - retval = pci_request_region(pdev, reg, "sx"); - if (retval) { - dev_err(&pdev->dev, "can't request region\n"); - goto err_flag; - } - board->hw_base = pci_resource_start(pdev, reg); - board->base2 = - board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board)); - if (!board->base) { - dev_err(&pdev->dev, "ioremap failed\n"); - goto err_reg; - } - - /* Most of the stuff on the CF board is offset by 0x18000 .... */ - if (IS_CF_BOARD(board)) - board->base += 0x18000; - - board->irq = pdev->irq; - - dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base, - board->irq, board->flags); - - if (!probe_sx(board)) { - retval = -EIO; - goto err_unmap; - } - - fix_sx_pci(pdev, board); - - pci_set_drvdata(pdev, board); - - return 0; -err_unmap: - iounmap(board->base2); -err_reg: - pci_release_region(pdev, reg); -err_flag: - board->flags &= ~SX_BOARD_PRESENT; -err: - return retval; -#else - return -ENODEV; -#endif -} - -static void __devexit sx_pci_remove(struct pci_dev *pdev) -{ - struct sx_board *board = pci_get_drvdata(pdev); - - sx_remove_card(board, pdev); -} - -/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say - its because the standard requires it. So check for SUBVENDOR_ID. */ -static struct pci_device_id sx_pci_tbl[] = { - { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, - .subvendor = PCI_ANY_ID, .subdevice = 0x0200 }, - { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, - .subvendor = PCI_ANY_ID, .subdevice = 0x0300 }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, sx_pci_tbl); - -static struct pci_driver sx_pcidriver = { - .name = "sx", - .id_table = sx_pci_tbl, - .probe = sx_pci_probe, - .remove = __devexit_p(sx_pci_remove) -}; - -static int __init sx_init(void) -{ -#ifdef CONFIG_EISA - int retval1; -#endif -#ifdef CONFIG_ISA - struct sx_board *board; - unsigned int i; -#endif - unsigned int found = 0; - int retval; - - func_enter(); - sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", - sx_debug); - if (abs((long)(&sx_debug) - sx_debug) < 0x10000) { - printk(KERN_WARNING "sx: sx_debug is an address, instead of a " - "value. Assuming -1.\n(%p)\n", &sx_debug); - sx_debug = -1; - } - - if (misc_register(&sx_fw_device) < 0) { - printk(KERN_ERR "SX: Unable to register firmware loader " - "driver.\n"); - return -EIO; - } -#ifdef CONFIG_ISA - for (i = 0; i < NR_SX_ADDRS; i++) { - board = &boards[found]; - board->hw_base = sx_probe_addrs[i]; - board->hw_len = SX_WINDOW_LEN; - if (!request_region(board->hw_base, board->hw_len, "sx")) - continue; - board->base2 = - board->base = ioremap_nocache(board->hw_base, board->hw_len); - if (!board->base) - goto err_sx_reg; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SX_ISA_BOARD; - board->irq = sx_irqmask ? -1 : 0; - - if (probe_sx(board)) { - board->flags |= SX_BOARD_PRESENT; - found++; - } else { - iounmap(board->base); -err_sx_reg: - release_region(board->hw_base, board->hw_len); - } - } - - for (i = 0; i < NR_SI_ADDRS; i++) { - board = &boards[found]; - board->hw_base = si_probe_addrs[i]; - board->hw_len = SI2_ISA_WINDOW_LEN; - if (!request_region(board->hw_base, board->hw_len, "sx")) - continue; - board->base2 = - board->base = ioremap_nocache(board->hw_base, board->hw_len); - if (!board->base) - goto err_si_reg; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_ISA_BOARD; - board->irq = sx_irqmask ? -1 : 0; - - if (probe_si(board)) { - board->flags |= SX_BOARD_PRESENT; - found++; - } else { - iounmap(board->base); -err_si_reg: - release_region(board->hw_base, board->hw_len); - } - } - for (i = 0; i < NR_SI1_ADDRS; i++) { - board = &boards[found]; - board->hw_base = si1_probe_addrs[i]; - board->hw_len = SI1_ISA_WINDOW_LEN; - if (!request_region(board->hw_base, board->hw_len, "sx")) - continue; - board->base2 = - board->base = ioremap_nocache(board->hw_base, board->hw_len); - if (!board->base) - goto err_si1_reg; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI1_ISA_BOARD; - board->irq = sx_irqmask ? -1 : 0; - - if (probe_si(board)) { - board->flags |= SX_BOARD_PRESENT; - found++; - } else { - iounmap(board->base); -err_si1_reg: - release_region(board->hw_base, board->hw_len); - } - } -#endif -#ifdef CONFIG_EISA - retval1 = eisa_driver_register(&sx_eisadriver); -#endif - retval = pci_register_driver(&sx_pcidriver); - - if (found) { - printk(KERN_INFO "sx: total of %d boards detected.\n", found); - retval = 0; - } else if (retval) { -#ifdef CONFIG_EISA - retval = retval1; - if (retval1) -#endif - misc_deregister(&sx_fw_device); - } - - func_exit(); - return retval; -} - -static void __exit sx_exit(void) -{ - int i; - - func_enter(); -#ifdef CONFIG_EISA - eisa_driver_unregister(&sx_eisadriver); -#endif - pci_unregister_driver(&sx_pcidriver); - - for (i = 0; i < SX_NBOARDS; i++) - sx_remove_card(&boards[i], NULL); - - if (misc_deregister(&sx_fw_device) < 0) { - printk(KERN_INFO "sx: couldn't deregister firmware loader " - "device\n"); - } - sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", - sx_initialized); - if (sx_initialized) - sx_release_drivers(); - - kfree(sx_ports); - func_exit(); -} - -module_init(sx_init); -module_exit(sx_exit); diff --git a/drivers/char/sx.h b/drivers/char/sx.h deleted file mode 100644 index 87c2defdead7..000000000000 --- a/drivers/char/sx.h +++ /dev/null @@ -1,201 +0,0 @@ - -/* - * sx.h - * - * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl - * - * SX serial driver. - * -- Supports SI, XIO and SX host cards. - * -- Supports TAs, MTAs and SXDCs. - * - * Version 1.3 -- March, 1999. - * - */ - -#define SX_NBOARDS 4 -#define SX_PORTSPERBOARD 32 -#define SX_NPORTS (SX_NBOARDS * SX_PORTSPERBOARD) - -#ifdef __KERNEL__ - -#define SX_MAGIC 0x12345678 - -struct sx_port { - struct gs_port gs; - struct wait_queue *shutdown_wait; - int ch_base; - int c_dcd; - struct sx_board *board; - int line; - unsigned long locks; -}; - -struct sx_board { - int magic; - void __iomem *base; - void __iomem *base2; - unsigned long hw_base; - resource_size_t hw_len; - int eisa_base; - int port_base; /* Number of the first port */ - struct sx_port *ports; - int nports; - int flags; - int irq; - int poll; - int ta_type; - struct timer_list timer; - unsigned long locks; -}; - -struct vpd_prom { - unsigned short id; - char hwrev; - char hwass; - int uniqid; - char myear; - char mweek; - char hw_feature[5]; - char oem_id; - char identifier[16]; -}; - -#ifndef MOD_RS232DB25MALE -#define MOD_RS232DB25MALE 0x0a -#endif - -#define SI_ISA_BOARD 0x00000001 -#define SX_ISA_BOARD 0x00000002 -#define SX_PCI_BOARD 0x00000004 -#define SX_CFPCI_BOARD 0x00000008 -#define SX_CFISA_BOARD 0x00000010 -#define SI_EISA_BOARD 0x00000020 -#define SI1_ISA_BOARD 0x00000040 - -#define SX_BOARD_PRESENT 0x00001000 -#define SX_BOARD_INITIALIZED 0x00002000 -#define SX_IRQ_ALLOCATED 0x00004000 - -#define SX_BOARD_TYPE 0x000000ff - -#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \ - SX_ISA_BOARD | SX_CFISA_BOARD)) - -#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD) -#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD) - -#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD) - -#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD)) - -/* The SI processor clock is required to calculate the cc_int_count register - value for the SI cards. */ -#define SI_PROCESSOR_CLOCK 25000000 - - -/* port flags */ -/* Make sure these don't clash with gs flags or async flags */ -#define SX_RX_THROTTLE 0x0000001 - - - -#define SX_PORT_TRANSMIT_LOCK 0 -#define SX_BOARD_INTR_LOCK 0 - - - -/* Debug flags. Add these together to get more debug info. */ - -#define SX_DEBUG_OPEN 0x00000001 -#define SX_DEBUG_SETTING 0x00000002 -#define SX_DEBUG_FLOW 0x00000004 -#define SX_DEBUG_MODEMSIGNALS 0x00000008 -#define SX_DEBUG_TERMIOS 0x00000010 -#define SX_DEBUG_TRANSMIT 0x00000020 -#define SX_DEBUG_RECEIVE 0x00000040 -#define SX_DEBUG_INTERRUPTS 0x00000080 -#define SX_DEBUG_PROBE 0x00000100 -#define SX_DEBUG_INIT 0x00000200 -#define SX_DEBUG_CLEANUP 0x00000400 -#define SX_DEBUG_CLOSE 0x00000800 -#define SX_DEBUG_FIRMWARE 0x00001000 -#define SX_DEBUG_MEMTEST 0x00002000 - -#define SX_DEBUG_ALL 0xffffffff - - -#define O_OTHER(tty) \ - ((O_OLCUC(tty)) ||\ - (O_ONLCR(tty)) ||\ - (O_OCRNL(tty)) ||\ - (O_ONOCR(tty)) ||\ - (O_ONLRET(tty)) ||\ - (O_OFILL(tty)) ||\ - (O_OFDEL(tty)) ||\ - (O_NLDLY(tty)) ||\ - (O_CRDLY(tty)) ||\ - (O_TABDLY(tty)) ||\ - (O_BSDLY(tty)) ||\ - (O_VTDLY(tty)) ||\ - (O_FFDLY(tty))) - -/* Same for input. */ -#define I_OTHER(tty) \ - ((I_INLCR(tty)) ||\ - (I_IGNCR(tty)) ||\ - (I_ICRNL(tty)) ||\ - (I_IUCLC(tty)) ||\ - (L_ISIG(tty))) - -#define MOD_TA ( TA>>4) -#define MOD_MTA (MTA_CD1400>>4) -#define MOD_SXDC ( SXDC>>4) - - -/* We copy the download code over to the card in chunks of ... bytes */ -#define SX_CHUNK_SIZE 128 - -#endif /* __KERNEL__ */ - - - -/* Specialix document 6210046-11 page 3 */ -#define SPX(X) (('S'<<24) | ('P' << 16) | (X)) - -/* Specialix-Linux specific IOCTLS. */ -#define SPXL(X) (SPX(('L' << 8) | (X))) - - -#define SXIO_SET_BOARD SPXL(0x01) -#define SXIO_GET_TYPE SPXL(0x02) -#define SXIO_DOWNLOAD SPXL(0x03) -#define SXIO_INIT SPXL(0x04) -#define SXIO_SETDEBUG SPXL(0x05) -#define SXIO_GETDEBUG SPXL(0x06) -#define SXIO_DO_RAMTEST SPXL(0x07) -#define SXIO_SETGSDEBUG SPXL(0x08) -#define SXIO_GETGSDEBUG SPXL(0x09) -#define SXIO_GETNPORTS SPXL(0x0a) - - -#ifndef SXCTL_MISC_MINOR -/* Allow others to gather this into "major.h" or something like that */ -#define SXCTL_MISC_MINOR 167 -#endif - -#ifndef SX_NORMAL_MAJOR -/* This allows overriding on the compiler commandline, or in a "major.h" - include or something like that */ -#define SX_NORMAL_MAJOR 32 -#define SX_CALLOUT_MAJOR 33 -#endif - - -#define SX_TYPE_SX 0x01 -#define SX_TYPE_SI 0x02 -#define SX_TYPE_CF 0x03 - - -#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN) -/* Need a #define for ^^^^^^^ !!! */ - diff --git a/drivers/char/sxboards.h b/drivers/char/sxboards.h deleted file mode 100644 index 427927dc7dbf..000000000000 --- a/drivers/char/sxboards.h +++ /dev/null @@ -1,206 +0,0 @@ -/************************************************************************/ -/* */ -/* Title : SX/SI/XIO Board Hardware Definitions */ -/* */ -/* Author : N.P.Vassallo */ -/* */ -/* Creation : 16th March 1998 */ -/* */ -/* Version : 3.0.0 */ -/* */ -/* Copyright : (c) Specialix International Ltd. 1998 */ -/* */ -/* Description : Prototypes, structures and definitions */ -/* describing the SX/SI/XIO board hardware */ -/* */ -/************************************************************************/ - -/* History... - -3.0.0 16/03/98 NPV Creation. - -*/ - -#ifndef _sxboards_h /* If SXBOARDS.H not already defined */ -#define _sxboards_h 1 - -/***************************************************************************** -******************************* ****************************** -******************************* Board Types ****************************** -******************************* ****************************** -*****************************************************************************/ - -/* BUS types... */ -#define BUS_ISA 0 -#define BUS_MCA 1 -#define BUS_EISA 2 -#define BUS_PCI 3 - -/* Board phases... */ -#define SI1_Z280 1 -#define SI2_Z280 2 -#define SI3_T225 3 - -/* Board types... */ -#define CARD_TYPE(bus,phase) (bus<<4|phase) -#define CARD_BUS(type) ((type>>4)&0xF) -#define CARD_PHASE(type) (type&0xF) - -#define TYPE_SI1_ISA CARD_TYPE(BUS_ISA,SI1_Z280) -#define TYPE_SI2_ISA CARD_TYPE(BUS_ISA,SI2_Z280) -#define TYPE_SI2_EISA CARD_TYPE(BUS_EISA,SI2_Z280) -#define TYPE_SI2_PCI CARD_TYPE(BUS_PCI,SI2_Z280) - -#define TYPE_SX_ISA CARD_TYPE(BUS_ISA,SI3_T225) -#define TYPE_SX_PCI CARD_TYPE(BUS_PCI,SI3_T225) -/***************************************************************************** -****************************** ****************************** -****************************** Phase 1 Z280 ****************************** -****************************** ****************************** -*****************************************************************************/ - -/* ISA board details... */ -#define SI1_ISA_WINDOW_LEN 0x10000 /* 64 Kbyte shared memory window */ -//#define SI1_ISA_MEMORY_LEN 0x8000 /* Usable memory - unused define*/ -//#define SI1_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ -//#define SI1_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ -//#define SI2_ISA_ADDR_STEP SI2_ISA_WINDOW_LEN/* ISA board address step */ -//#define SI2_ISA_IRQ_MASK 0x9800 /* IRQs 15,12,11 */ - -/* ISA board, register definitions... */ -//#define SI2_ISA_ID_BASE 0x7FF8 /* READ: Board ID string */ -#define SI1_ISA_RESET 0x8000 /* WRITE: Host Reset */ -#define SI1_ISA_RESET_CLEAR 0xc000 /* WRITE: Host Reset clear*/ -#define SI1_ISA_WAIT 0x9000 /* WRITE: Host wait */ -#define SI1_ISA_WAIT_CLEAR 0xd000 /* WRITE: Host wait clear */ -#define SI1_ISA_INTCL 0xa000 /* WRITE: Host Reset */ -#define SI1_ISA_INTCL_CLEAR 0xe000 /* WRITE: Host Reset */ - - -/***************************************************************************** -****************************** ****************************** -****************************** Phase 2 Z280 ****************************** -****************************** ****************************** -*****************************************************************************/ - -/* ISA board details... */ -#define SI2_ISA_WINDOW_LEN 0x8000 /* 32 Kbyte shared memory window */ -#define SI2_ISA_MEMORY_LEN 0x7FF8 /* Usable memory */ -#define SI2_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ -#define SI2_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ -#define SI2_ISA_ADDR_STEP SI2_ISA_WINDOW_LEN/* ISA board address step */ -#define SI2_ISA_IRQ_MASK 0x9800 /* IRQs 15,12,11 */ - -/* ISA board, register definitions... */ -#define SI2_ISA_ID_BASE 0x7FF8 /* READ: Board ID string */ -#define SI2_ISA_RESET SI2_ISA_ID_BASE /* WRITE: Host Reset */ -#define SI2_ISA_IRQ11 (SI2_ISA_ID_BASE+1) /* WRITE: Set IRQ11 */ -#define SI2_ISA_IRQ12 (SI2_ISA_ID_BASE+2) /* WRITE: Set IRQ12 */ -#define SI2_ISA_IRQ15 (SI2_ISA_ID_BASE+3) /* WRITE: Set IRQ15 */ -#define SI2_ISA_IRQSET (SI2_ISA_ID_BASE+4) /* WRITE: Set Host Interrupt */ -#define SI2_ISA_INTCLEAR (SI2_ISA_ID_BASE+5) /* WRITE: Enable Host Interrupt */ - -#define SI2_ISA_IRQ11_SET 0x10 -#define SI2_ISA_IRQ11_CLEAR 0x00 -#define SI2_ISA_IRQ12_SET 0x10 -#define SI2_ISA_IRQ12_CLEAR 0x00 -#define SI2_ISA_IRQ15_SET 0x10 -#define SI2_ISA_IRQ15_CLEAR 0x00 -#define SI2_ISA_INTCLEAR_SET 0x10 -#define SI2_ISA_INTCLEAR_CLEAR 0x00 -#define SI2_ISA_IRQSET_CLEAR 0x10 -#define SI2_ISA_IRQSET_SET 0x00 -#define SI2_ISA_RESET_SET 0x00 -#define SI2_ISA_RESET_CLEAR 0x10 - -/* PCI board details... */ -#define SI2_PCI_WINDOW_LEN 0x100000 /* 1 Mbyte memory window */ - -/* PCI board register definitions... */ -#define SI2_PCI_SET_IRQ 0x40001 /* Set Host Interrupt */ -#define SI2_PCI_RESET 0xC0001 /* Host Reset */ - -/***************************************************************************** -****************************** ****************************** -****************************** Phase 3 T225 ****************************** -****************************** ****************************** -*****************************************************************************/ - -/* General board details... */ -#define SX_WINDOW_LEN 64*1024 /* 64 Kbyte memory window */ - -/* ISA board details... */ -#define SX_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ -#define SX_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ -#define SX_ISA_ADDR_STEP SX_WINDOW_LEN /* ISA board address step */ -#define SX_ISA_IRQ_MASK 0x9E00 /* IRQs 15,12,11,10,9 */ - -/* Hardware register definitions... */ -#define SX_EVENT_STATUS 0x7800 /* READ: T225 Event Status */ -#define SX_EVENT_STROBE 0x7800 /* WRITE: T225 Event Strobe */ -#define SX_EVENT_ENABLE 0x7880 /* WRITE: T225 Event Enable */ -#define SX_VPD_ROM 0x7C00 /* READ: Vital Product Data ROM */ -#define SX_CONFIG 0x7C00 /* WRITE: Host Configuration Register */ -#define SX_IRQ_STATUS 0x7C80 /* READ: Host Interrupt Status */ -#define SX_SET_IRQ 0x7C80 /* WRITE: Set Host Interrupt */ -#define SX_RESET_STATUS 0x7D00 /* READ: Host Reset Status */ -#define SX_RESET 0x7D00 /* WRITE: Host Reset */ -#define SX_RESET_IRQ 0x7D80 /* WRITE: Reset Host Interrupt */ - -/* SX_VPD_ROM definitions... */ -#define SX_VPD_SLX_ID1 0x00 -#define SX_VPD_SLX_ID2 0x01 -#define SX_VPD_HW_REV 0x02 -#define SX_VPD_HW_ASSEM 0x03 -#define SX_VPD_UNIQUEID4 0x04 -#define SX_VPD_UNIQUEID3 0x05 -#define SX_VPD_UNIQUEID2 0x06 -#define SX_VPD_UNIQUEID1 0x07 -#define SX_VPD_MANU_YEAR 0x08 -#define SX_VPD_MANU_WEEK 0x09 -#define SX_VPD_IDENT 0x10 -#define SX_VPD_IDENT_STRING "JET HOST BY KEV#" - -/* SX unique identifiers... */ -#define SX_UNIQUEID_MASK 0xF0 -#define SX_ISA_UNIQUEID1 0x20 -#define SX_PCI_UNIQUEID1 0x50 - -/* SX_CONFIG definitions... */ -#define SX_CONF_BUSEN 0x02 /* Enable T225 memory and I/O */ -#define SX_CONF_HOSTIRQ 0x04 /* Enable board to host interrupt */ - -/* SX bootstrap... */ -#define SX_BOOTSTRAP "\x28\x20\x21\x02\x60\x0a" -#define SX_BOOTSTRAP_SIZE 6 -#define SX_BOOTSTRAP_ADDR (0x8000-SX_BOOTSTRAP_SIZE) - -/***************************************************************************** -********************************** ********************************** -********************************** EISA ********************************** -********************************** ********************************** -*****************************************************************************/ - -#define SI2_EISA_OFF 0x42 -#define SI2_EISA_VAL 0x01 -#define SI2_EISA_WINDOW_LEN 0x10000 - -/***************************************************************************** -*********************************** ********************************** -*********************************** PCI ********************************** -*********************************** ********************************** -*****************************************************************************/ - -/* General definitions... */ - -#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */ -#define SPX_DEVICE_ID 0x4000 /* SI/XIO boards */ -#define SPX_PLXDEVICE_ID 0x2000 /* SX boards */ - -#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */ -#define SI2_SUB_SYS_ID 0x400 /* Phase 2 (Z280) board */ -#define SX_SUB_SYS_ID 0x200 /* Phase 3 (t225) board */ - -#endif /*_sxboards_h */ - -/* End of SXBOARDS.H */ diff --git a/drivers/char/sxwindow.h b/drivers/char/sxwindow.h deleted file mode 100644 index cf01b662aefc..000000000000 --- a/drivers/char/sxwindow.h +++ /dev/null @@ -1,393 +0,0 @@ -/************************************************************************/ -/* */ -/* Title : SX Shared Memory Window Structure */ -/* */ -/* Author : N.P.Vassallo */ -/* */ -/* Creation : 16th March 1998 */ -/* */ -/* Version : 3.0.0 */ -/* */ -/* Copyright : (c) Specialix International Ltd. 1998 */ -/* */ -/* Description : Prototypes, structures and definitions */ -/* describing the SX/SI/XIO cards shared */ -/* memory window structure: */ -/* SXCARD */ -/* SXMODULE */ -/* SXCHANNEL */ -/* */ -/************************************************************************/ - -/* History... - -3.0.0 16/03/98 NPV Creation. (based on STRUCT.H) - -*/ - -#ifndef _sxwindow_h /* If SXWINDOW.H not already defined */ -#define _sxwindow_h 1 - -/***************************************************************************** -*************************** *************************** -*************************** Common Definitions *************************** -*************************** *************************** -*****************************************************************************/ - -typedef struct _SXCARD *PSXCARD; /* SXCARD structure pointer */ -typedef struct _SXMODULE *PMOD; /* SXMODULE structure pointer */ -typedef struct _SXCHANNEL *PCHAN; /* SXCHANNEL structure pointer */ - -/***************************************************************************** -********************************* ********************************* -********************************* SXCARD ********************************* -********************************* ********************************* -*****************************************************************************/ - -typedef struct _SXCARD -{ - BYTE cc_init_status; /* 0x00 Initialisation status */ - BYTE cc_mem_size; /* 0x01 Size of memory on card */ - WORD cc_int_count; /* 0x02 Interrupt count */ - WORD cc_revision; /* 0x04 Download code revision */ - BYTE cc_isr_count; /* 0x06 Count when ISR is run */ - BYTE cc_main_count; /* 0x07 Count when main loop is run */ - WORD cc_int_pending; /* 0x08 Interrupt pending */ - WORD cc_poll_count; /* 0x0A Count when poll is run */ - BYTE cc_int_set_count; /* 0x0C Count when host interrupt is set */ - BYTE cc_rfu[0x80 - 0x0D]; /* 0x0D Pad structure to 128 bytes (0x80) */ - -} SXCARD; - -/* SXCARD.cc_init_status definitions... */ -#define ADAPTERS_FOUND (BYTE)0x01 -#define NO_ADAPTERS_FOUND (BYTE)0xFF - -/* SXCARD.cc_mem_size definitions... */ -#define SX_MEMORY_SIZE (BYTE)0x40 - -/* SXCARD.cc_int_count definitions... */ -#define INT_COUNT_DEFAULT 100 /* Hz */ - -/***************************************************************************** -******************************** ******************************** -******************************** SXMODULE ******************************** -******************************** ******************************** -*****************************************************************************/ - -#define TOP_POINTER(a) ((a)|0x8000) /* Sets top bit of word */ -#define UNTOP_POINTER(a) ((a)&~0x8000) /* Clears top bit of word */ - -typedef struct _SXMODULE -{ - WORD mc_next; /* 0x00 Next module "pointer" (ORed with 0x8000) */ - BYTE mc_type; /* 0x02 Type of TA in terms of number of channels */ - BYTE mc_mod_no; /* 0x03 Module number on SI bus cable (0 closest to card) */ - BYTE mc_dtr; /* 0x04 Private DTR copy (TA only) */ - BYTE mc_rfu1; /* 0x05 Reserved */ - WORD mc_uart; /* 0x06 UART base address for this module */ - BYTE mc_chip; /* 0x08 Chip type / number of ports */ - BYTE mc_current_uart; /* 0x09 Current uart selected for this module */ -#ifdef DOWNLOAD - PCHAN mc_chan_pointer[8]; /* 0x0A Pointer to each channel structure */ -#else - WORD mc_chan_pointer[8]; /* 0x0A Define as WORD if not compiling into download */ -#endif - WORD mc_rfu2; /* 0x1A Reserved */ - BYTE mc_opens1; /* 0x1C Number of open ports on first four ports on MTA/SXDC */ - BYTE mc_opens2; /* 0x1D Number of open ports on second four ports on MTA/SXDC */ - BYTE mc_mods; /* 0x1E Types of connector module attached to MTA/SXDC */ - BYTE mc_rev1; /* 0x1F Revision of first CD1400 on MTA/SXDC */ - BYTE mc_rev2; /* 0x20 Revision of second CD1400 on MTA/SXDC */ - BYTE mc_mtaasic_rev; /* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */ - BYTE mc_rfu3[0x100 - 0x22]; /* 0x22 Pad structure to 256 bytes (0x100) */ - -} SXMODULE; - -/* SXMODULE.mc_type definitions... */ -#define FOUR_PORTS (BYTE)4 -#define EIGHT_PORTS (BYTE)8 - -/* SXMODULE.mc_chip definitions... */ -#define CHIP_MASK 0xF0 -#define TA (BYTE)0 -#define TA4 (TA | FOUR_PORTS) -#define TA8 (TA | EIGHT_PORTS) -#define TA4_ASIC (BYTE)0x0A -#define TA8_ASIC (BYTE)0x0B -#define MTA_CD1400 (BYTE)0x28 -#define SXDC (BYTE)0x48 - -/* SXMODULE.mc_mods definitions... */ -#define MOD_RS232DB25 0x00 /* RS232 DB25 (socket/plug) */ -#define MOD_RS232RJ45 0x01 /* RS232 RJ45 (shielded/opto-isolated) */ -#define MOD_RESERVED_2 0x02 /* Reserved (RS485) */ -#define MOD_RS422DB25 0x03 /* RS422 DB25 Socket */ -#define MOD_RESERVED_4 0x04 /* Reserved */ -#define MOD_PARALLEL 0x05 /* Parallel */ -#define MOD_RESERVED_6 0x06 /* Reserved (RS423) */ -#define MOD_RESERVED_7 0x07 /* Reserved */ -#define MOD_2_RS232DB25 0x08 /* Rev 2.0 RS232 DB25 (socket/plug) */ -#define MOD_2_RS232RJ45 0x09 /* Rev 2.0 RS232 RJ45 */ -#define MOD_RESERVED_A 0x0A /* Rev 2.0 Reserved */ -#define MOD_2_RS422DB25 0x0B /* Rev 2.0 RS422 DB25 */ -#define MOD_RESERVED_C 0x0C /* Rev 2.0 Reserved */ -#define MOD_2_PARALLEL 0x0D /* Rev 2.0 Parallel */ -#define MOD_RESERVED_E 0x0E /* Rev 2.0 Reserved */ -#define MOD_BLANK 0x0F /* Blank Panel */ - -/***************************************************************************** -******************************** ******************************* -******************************** SXCHANNEL ******************************* -******************************** ******************************* -*****************************************************************************/ - -#define TX_BUFF_OFFSET 0x60 /* Transmit buffer offset in channel structure */ -#define BUFF_POINTER(a) (((a)+TX_BUFF_OFFSET)|0x8000) -#define UNBUFF_POINTER(a) (jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) -#define BUFFER_SIZE 256 -#define HIGH_WATER ((BUFFER_SIZE / 4) * 3) -#define LOW_WATER (BUFFER_SIZE / 4) - -typedef struct _SXCHANNEL -{ - WORD next_item; /* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */ - WORD addr_uart; /* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */ - WORD module; /* 0x04 Offset from window base of parent SXMODULE structure */ - BYTE type; /* 0x06 Chip type / number of ports (copy of mc_chip) */ - BYTE chan_number; /* 0x07 Channel number on the TA/MTA/SXDC */ - WORD xc_status; /* 0x08 Flow control and I/O status */ - BYTE hi_rxipos; /* 0x0A Receive buffer input index */ - BYTE hi_rxopos; /* 0x0B Receive buffer output index */ - BYTE hi_txopos; /* 0x0C Transmit buffer output index */ - BYTE hi_txipos; /* 0x0D Transmit buffer input index */ - BYTE hi_hstat; /* 0x0E Command register */ - BYTE dtr_bit; /* 0x0F INTERNAL DTR control byte (TA only) */ - BYTE txon; /* 0x10 INTERNAL copy of hi_txon */ - BYTE txoff; /* 0x11 INTERNAL copy of hi_txoff */ - BYTE rxon; /* 0x12 INTERNAL copy of hi_rxon */ - BYTE rxoff; /* 0x13 INTERNAL copy of hi_rxoff */ - BYTE hi_mr1; /* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/ - BYTE hi_mr2; /* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/ - BYTE hi_csr; /* 0x16 Clock Select Register (baud rate) */ - BYTE hi_op; /* 0x17 Modem Output Signal */ - BYTE hi_ip; /* 0x18 Modem Input Signal */ - BYTE hi_state; /* 0x19 Channel status */ - BYTE hi_prtcl; /* 0x1A Channel protocol (flow control) */ - BYTE hi_txon; /* 0x1B Transmit XON character */ - BYTE hi_txoff; /* 0x1C Transmit XOFF character */ - BYTE hi_rxon; /* 0x1D Receive XON character */ - BYTE hi_rxoff; /* 0x1E Receive XOFF character */ - BYTE close_prev; /* 0x1F INTERNAL channel previously closed flag */ - BYTE hi_break; /* 0x20 Break and error control */ - BYTE break_state; /* 0x21 INTERNAL copy of hi_break */ - BYTE hi_mask; /* 0x22 Mask for received data */ - BYTE mask; /* 0x23 INTERNAL copy of hi_mask */ - BYTE mod_type; /* 0x24 MTA/SXDC hardware module type */ - BYTE ccr_state; /* 0x25 INTERNAL MTA/SXDC state of CCR register */ - BYTE ip_mask; /* 0x26 Input handshake mask */ - BYTE hi_parallel; /* 0x27 Parallel port flag */ - BYTE par_error; /* 0x28 Error code for parallel loopback test */ - BYTE any_sent; /* 0x29 INTERNAL data sent flag */ - BYTE asic_txfifo_size; /* 0x2A INTERNAL SXDC transmit FIFO size */ - BYTE rfu1[2]; /* 0x2B Reserved */ - BYTE csr; /* 0x2D INTERNAL copy of hi_csr */ -#ifdef DOWNLOAD - PCHAN nextp; /* 0x2E Offset from window base of next channel structure */ -#else - WORD nextp; /* 0x2E Define as WORD if not compiling into download */ -#endif - BYTE prtcl; /* 0x30 INTERNAL copy of hi_prtcl */ - BYTE mr1; /* 0x31 INTERNAL copy of hi_mr1 */ - BYTE mr2; /* 0x32 INTERNAL copy of hi_mr2 */ - BYTE hi_txbaud; /* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */ - BYTE hi_rxbaud; /* 0x34 Extended receive baud rate (SXDC only if((hi_csr&0xF0)==0xF0) */ - BYTE txbreak_state; /* 0x35 INTERNAL MTA/SXDC transmit break state */ - BYTE txbaud; /* 0x36 INTERNAL copy of hi_txbaud */ - BYTE rxbaud; /* 0x37 INTERNAL copy of hi_rxbaud */ - WORD err_framing; /* 0x38 Count of receive framing errors */ - WORD err_parity; /* 0x3A Count of receive parity errors */ - WORD err_overrun; /* 0x3C Count of receive overrun errors */ - WORD err_overflow; /* 0x3E Count of receive buffer overflow errors */ - BYTE rfu2[TX_BUFF_OFFSET - 0x40]; /* 0x40 Reserved until hi_txbuf */ - BYTE hi_txbuf[BUFFER_SIZE]; /* 0x060 Transmit buffer */ - BYTE hi_rxbuf[BUFFER_SIZE]; /* 0x160 Receive buffer */ - BYTE rfu3[0x300 - 0x260]; /* 0x260 Reserved until 768 bytes (0x300) */ - -} SXCHANNEL; - -/* SXCHANNEL.addr_uart definitions... */ -#define FASTPATH 0x1000 /* Set to indicate fast rx/tx processing (TA only) */ - -/* SXCHANNEL.xc_status definitions... */ -#define X_TANY 0x0001 /* XON is any character (TA only) */ -#define X_TION 0x0001 /* Tx interrupts on (MTA only) */ -#define X_TXEN 0x0002 /* Tx XON/XOFF enabled (TA only) */ -#define X_RTSEN 0x0002 /* RTS FLOW enabled (MTA only) */ -#define X_TXRC 0x0004 /* XOFF received (TA only) */ -#define X_RTSLOW 0x0004 /* RTS dropped (MTA only) */ -#define X_RXEN 0x0008 /* Rx XON/XOFF enabled */ -#define X_ANYXO 0x0010 /* XOFF pending/sent or RTS dropped */ -#define X_RXSE 0x0020 /* Rx XOFF sent */ -#define X_NPEND 0x0040 /* Rx XON pending or XOFF pending */ -#define X_FPEND 0x0080 /* Rx XOFF pending */ -#define C_CRSE 0x0100 /* Carriage return sent (TA only) */ -#define C_TEMR 0x0100 /* Tx empty requested (MTA only) */ -#define C_TEMA 0x0200 /* Tx empty acked (MTA only) */ -#define C_ANYP 0x0200 /* Any protocol bar tx XON/XOFF (TA only) */ -#define C_EN 0x0400 /* Cooking enabled (on MTA means port is also || */ -#define C_HIGH 0x0800 /* Buffer previously hit high water */ -#define C_CTSEN 0x1000 /* CTS automatic flow-control enabled */ -#define C_DCDEN 0x2000 /* DCD/DTR checking enabled */ -#define C_BREAK 0x4000 /* Break detected */ -#define C_RTSEN 0x8000 /* RTS automatic flow control enabled (MTA only) */ -#define C_PARITY 0x8000 /* Parity checking enabled (TA only) */ - -/* SXCHANNEL.hi_hstat definitions... */ -#define HS_IDLE_OPEN 0x00 /* Channel open state */ -#define HS_LOPEN 0x02 /* Local open command (no modem monitoring) */ -#define HS_MOPEN 0x04 /* Modem open command (wait for DCD signal) */ -#define HS_IDLE_MPEND 0x06 /* Waiting for DCD signal state */ -#define HS_CONFIG 0x08 /* Configuration command */ -#define HS_CLOSE 0x0A /* Close command */ -#define HS_START 0x0C /* Start transmit break command */ -#define HS_STOP 0x0E /* Stop transmit break command */ -#define HS_IDLE_CLOSED 0x10 /* Closed channel state */ -#define HS_IDLE_BREAK 0x12 /* Transmit break state */ -#define HS_FORCE_CLOSED 0x14 /* Force close command */ -#define HS_RESUME 0x16 /* Clear pending XOFF command */ -#define HS_WFLUSH 0x18 /* Flush transmit buffer command */ -#define HS_RFLUSH 0x1A /* Flush receive buffer command */ -#define HS_SUSPEND 0x1C /* Suspend output command (like XOFF received) */ -#define PARALLEL 0x1E /* Parallel port loopback test command (Diagnostics Only) */ -#define ENABLE_RX_INTS 0x20 /* Enable receive interrupts command (Diagnostics Only) */ -#define ENABLE_TX_INTS 0x22 /* Enable transmit interrupts command (Diagnostics Only) */ -#define ENABLE_MDM_INTS 0x24 /* Enable modem interrupts command (Diagnostics Only) */ -#define DISABLE_INTS 0x26 /* Disable interrupts command (Diagnostics Only) */ - -/* SXCHANNEL.hi_mr1 definitions... */ -#define MR1_BITS 0x03 /* Data bits mask */ -#define MR1_5_BITS 0x00 /* 5 data bits */ -#define MR1_6_BITS 0x01 /* 6 data bits */ -#define MR1_7_BITS 0x02 /* 7 data bits */ -#define MR1_8_BITS 0x03 /* 8 data bits */ -#define MR1_PARITY 0x1C /* Parity mask */ -#define MR1_ODD 0x04 /* Odd parity */ -#define MR1_EVEN 0x00 /* Even parity */ -#define MR1_WITH 0x00 /* Parity enabled */ -#define MR1_FORCE 0x08 /* Force parity */ -#define MR1_NONE 0x10 /* No parity */ -#define MR1_NOPARITY MR1_NONE /* No parity */ -#define MR1_ODDPARITY (MR1_WITH|MR1_ODD) /* Odd parity */ -#define MR1_EVENPARITY (MR1_WITH|MR1_EVEN) /* Even parity */ -#define MR1_MARKPARITY (MR1_FORCE|MR1_ODD) /* Mark parity */ -#define MR1_SPACEPARITY (MR1_FORCE|MR1_EVEN) /* Space parity */ -#define MR1_RTS_RXFLOW 0x80 /* RTS receive flow control */ - -/* SXCHANNEL.hi_mr2 definitions... */ -#define MR2_STOP 0x0F /* Stop bits mask */ -#define MR2_1_STOP 0x07 /* 1 stop bit */ -#define MR2_2_STOP 0x0F /* 2 stop bits */ -#define MR2_CTS_TXFLOW 0x10 /* CTS transmit flow control */ -#define MR2_RTS_TOGGLE 0x20 /* RTS toggle on transmit */ -#define MR2_NORMAL 0x00 /* Normal mode */ -#define MR2_AUTO 0x40 /* Auto-echo mode (TA only) */ -#define MR2_LOCAL 0x80 /* Local echo mode */ -#define MR2_REMOTE 0xC0 /* Remote echo mode (TA only) */ - -/* SXCHANNEL.hi_csr definitions... */ -#define CSR_75 0x0 /* 75 baud */ -#define CSR_110 0x1 /* 110 baud (TA), 115200 (MTA/SXDC) */ -#define CSR_38400 0x2 /* 38400 baud */ -#define CSR_150 0x3 /* 150 baud */ -#define CSR_300 0x4 /* 300 baud */ -#define CSR_600 0x5 /* 600 baud */ -#define CSR_1200 0x6 /* 1200 baud */ -#define CSR_2000 0x7 /* 2000 baud */ -#define CSR_2400 0x8 /* 2400 baud */ -#define CSR_4800 0x9 /* 4800 baud */ -#define CSR_1800 0xA /* 1800 baud */ -#define CSR_9600 0xB /* 9600 baud */ -#define CSR_19200 0xC /* 19200 baud */ -#define CSR_57600 0xD /* 57600 baud */ -#define CSR_EXTBAUD 0xF /* Extended baud rate (hi_txbaud/hi_rxbaud) */ - -/* SXCHANNEL.hi_op definitions... */ -#define OP_RTS 0x01 /* RTS modem output signal */ -#define OP_DTR 0x02 /* DTR modem output signal */ - -/* SXCHANNEL.hi_ip definitions... */ -#define IP_CTS 0x02 /* CTS modem input signal */ -#define IP_DCD 0x04 /* DCD modem input signal */ -#define IP_DSR 0x20 /* DTR modem input signal */ -#define IP_RI 0x40 /* RI modem input signal */ - -/* SXCHANNEL.hi_state definitions... */ -#define ST_BREAK 0x01 /* Break received (clear with config) */ -#define ST_DCD 0x02 /* DCD signal changed state */ - -/* SXCHANNEL.hi_prtcl definitions... */ -#define SP_TANY 0x01 /* Transmit XON/XANY (if SP_TXEN enabled) */ -#define SP_TXEN 0x02 /* Transmit XON/XOFF flow control */ -#define SP_CEN 0x04 /* Cooking enabled */ -#define SP_RXEN 0x08 /* Rx XON/XOFF enabled */ -#define SP_DCEN 0x20 /* DCD / DTR check */ -#define SP_DTR_RXFLOW 0x40 /* DTR receive flow control */ -#define SP_PAEN 0x80 /* Parity checking enabled */ - -/* SXCHANNEL.hi_break definitions... */ -#define BR_IGN 0x01 /* Ignore any received breaks */ -#define BR_INT 0x02 /* Interrupt on received break */ -#define BR_PARMRK 0x04 /* Enable parmrk parity error processing */ -#define BR_PARIGN 0x08 /* Ignore chars with parity errors */ -#define BR_ERRINT 0x80 /* Treat parity/framing/overrun errors as exceptions */ - -/* SXCHANNEL.par_error definitions.. */ -#define DIAG_IRQ_RX 0x01 /* Indicate serial receive interrupt (diags only) */ -#define DIAG_IRQ_TX 0x02 /* Indicate serial transmit interrupt (diags only) */ -#define DIAG_IRQ_MD 0x04 /* Indicate serial modem interrupt (diags only) */ - -/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */ -#define BAUD_75 0x00 /* 75 baud */ -#define BAUD_115200 0x01 /* 115200 baud */ -#define BAUD_38400 0x02 /* 38400 baud */ -#define BAUD_150 0x03 /* 150 baud */ -#define BAUD_300 0x04 /* 300 baud */ -#define BAUD_600 0x05 /* 600 baud */ -#define BAUD_1200 0x06 /* 1200 baud */ -#define BAUD_2000 0x07 /* 2000 baud */ -#define BAUD_2400 0x08 /* 2400 baud */ -#define BAUD_4800 0x09 /* 4800 baud */ -#define BAUD_1800 0x0A /* 1800 baud */ -#define BAUD_9600 0x0B /* 9600 baud */ -#define BAUD_19200 0x0C /* 19200 baud */ -#define BAUD_57600 0x0D /* 57600 baud */ -#define BAUD_230400 0x0E /* 230400 baud */ -#define BAUD_460800 0x0F /* 460800 baud */ -#define BAUD_921600 0x10 /* 921600 baud */ -#define BAUD_50 0x11 /* 50 baud */ -#define BAUD_110 0x12 /* 110 baud */ -#define BAUD_134_5 0x13 /* 134.5 baud */ -#define BAUD_200 0x14 /* 200 baud */ -#define BAUD_7200 0x15 /* 7200 baud */ -#define BAUD_56000 0x16 /* 56000 baud */ -#define BAUD_64000 0x17 /* 64000 baud */ -#define BAUD_76800 0x18 /* 76800 baud */ -#define BAUD_128000 0x19 /* 128000 baud */ -#define BAUD_150000 0x1A /* 150000 baud */ -#define BAUD_14400 0x1B /* 14400 baud */ -#define BAUD_256000 0x1C /* 256000 baud */ -#define BAUD_28800 0x1D /* 28800 baud */ - -/* SXCHANNEL.txbreak_state definiions... */ -#define TXBREAK_OFF 0 /* Not sending break */ -#define TXBREAK_START 1 /* Begin sending break */ -#define TXBREAK_START1 2 /* Begin sending break, part 1 */ -#define TXBREAK_ON 3 /* Sending break */ -#define TXBREAK_STOP 4 /* Stop sending break */ -#define TXBREAK_STOP1 5 /* Stop sending break, part 1 */ - -#endif /* _sxwindow_h */ - -/* End of SXWINDOW.H */ - diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c deleted file mode 100644 index 96838640f575..000000000000 --- a/drivers/char/vme_scc.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports - * implementation. - * Copyright 1999 Richard Hirst - * - * Based on atari_SCC.c which was - * Copyright 1994-95 Roman Hodek - * Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_MVME147_SCC -#include -#endif -#ifdef CONFIG_MVME162_SCC -#include -#endif -#ifdef CONFIG_BVME6000_SCC -#include -#endif - -#include -#include "scc.h" - - -#define CHANNEL_A 0 -#define CHANNEL_B 1 - -#define SCC_MINOR_BASE 64 - -/* Shadows for all SCC write registers */ -static unsigned char scc_shadow[2][16]; - -/* Location to access for SCC register access delay */ -static volatile unsigned char *scc_del = NULL; - -/* To keep track of STATUS_REG state for detection of Ext/Status int source */ -static unsigned char scc_last_status_reg[2]; - -/***************************** Prototypes *****************************/ - -/* Function prototypes */ -static void scc_disable_tx_interrupts(void * ptr); -static void scc_enable_tx_interrupts(void * ptr); -static void scc_disable_rx_interrupts(void * ptr); -static void scc_enable_rx_interrupts(void * ptr); -static int scc_carrier_raised(struct tty_port *port); -static void scc_shutdown_port(void * ptr); -static int scc_set_real_termios(void *ptr); -static void scc_hungup(void *ptr); -static void scc_close(void *ptr); -static int scc_chars_in_buffer(void * ptr); -static int scc_open(struct tty_struct * tty, struct file * filp); -static int scc_ioctl(struct tty_struct * tty, - unsigned int cmd, unsigned long arg); -static void scc_throttle(struct tty_struct *tty); -static void scc_unthrottle(struct tty_struct *tty); -static irqreturn_t scc_tx_int(int irq, void *data); -static irqreturn_t scc_rx_int(int irq, void *data); -static irqreturn_t scc_stat_int(int irq, void *data); -static irqreturn_t scc_spcond_int(int irq, void *data); -static void scc_setsignals(struct scc_port *port, int dtr, int rts); -static int scc_break_ctl(struct tty_struct *tty, int break_state); - -static struct tty_driver *scc_driver; - -static struct scc_port scc_ports[2]; - -/*--------------------------------------------------------------------------- - * Interface from generic_serial.c back here - *--------------------------------------------------------------------------*/ - -static struct real_driver scc_real_driver = { - scc_disable_tx_interrupts, - scc_enable_tx_interrupts, - scc_disable_rx_interrupts, - scc_enable_rx_interrupts, - scc_shutdown_port, - scc_set_real_termios, - scc_chars_in_buffer, - scc_close, - scc_hungup, - NULL -}; - - -static const struct tty_operations scc_ops = { - .open = scc_open, - .close = gs_close, - .write = gs_write, - .put_char = gs_put_char, - .flush_chars = gs_flush_chars, - .write_room = gs_write_room, - .chars_in_buffer = gs_chars_in_buffer, - .flush_buffer = gs_flush_buffer, - .ioctl = scc_ioctl, - .throttle = scc_throttle, - .unthrottle = scc_unthrottle, - .set_termios = gs_set_termios, - .stop = gs_stop, - .start = gs_start, - .hangup = gs_hangup, - .break_ctl = scc_break_ctl, -}; - -static const struct tty_port_operations scc_port_ops = { - .carrier_raised = scc_carrier_raised, -}; - -/*---------------------------------------------------------------------------- - * vme_scc_init() and support functions - *---------------------------------------------------------------------------*/ - -static int __init scc_init_drivers(void) -{ - int error; - - scc_driver = alloc_tty_driver(2); - if (!scc_driver) - return -ENOMEM; - scc_driver->owner = THIS_MODULE; - scc_driver->driver_name = "scc"; - scc_driver->name = "ttyS"; - scc_driver->major = TTY_MAJOR; - scc_driver->minor_start = SCC_MINOR_BASE; - scc_driver->type = TTY_DRIVER_TYPE_SERIAL; - scc_driver->subtype = SERIAL_TYPE_NORMAL; - scc_driver->init_termios = tty_std_termios; - scc_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - scc_driver->init_termios.c_ispeed = 9600; - scc_driver->init_termios.c_ospeed = 9600; - scc_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(scc_driver, &scc_ops); - - if ((error = tty_register_driver(scc_driver))) { - printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n", - error); - put_tty_driver(scc_driver); - return 1; - } - - return 0; -} - - -/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1). - */ - -static void __init scc_init_portstructs(void) -{ - struct scc_port *port; - int i; - - for (i = 0; i < 2; i++) { - port = scc_ports + i; - tty_port_init(&port->gs.port); - port->gs.port.ops = &scc_port_ops; - port->gs.magic = SCC_MAGIC; - port->gs.close_delay = HZ/2; - port->gs.closing_wait = 30 * HZ; - port->gs.rd = &scc_real_driver; -#ifdef NEW_WRITE_LOCKING - port->gs.port_write_mutex = MUTEX; -#endif - init_waitqueue_head(&port->gs.port.open_wait); - init_waitqueue_head(&port->gs.port.close_wait); - } -} - - -#ifdef CONFIG_MVME147_SCC -static int __init mvme147_scc_init(void) -{ - struct scc_port *port; - int error; - - printk(KERN_INFO "SCC: MVME147 Serial Driver\n"); - /* Init channel A */ - port = &scc_ports[0]; - port->channel = CHANNEL_A; - port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR; - port->datap = port->ctrlp + 1; - port->port_a = &scc_ports[0]; - port->port_b = &scc_ports[1]; - error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED, - "SCC-A TX", port); - if (error) - goto fail; - error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED, - "SCC-A status", port); - if (error) - goto fail_free_a_tx; - error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED, - "SCC-A RX", port); - if (error) - goto fail_free_a_stat; - error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, - IRQF_DISABLED, "SCC-A special cond", port); - if (error) - goto fail_free_a_rx; - - { - SCC_ACCESS_INIT(port); - - /* disable interrupts for this channel */ - SCCwrite(INT_AND_DMA_REG, 0); - /* Set the interrupt vector */ - SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE); - /* Interrupt parameters: vector includes status, status low */ - SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); - SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); - } - - /* Init channel B */ - port = &scc_ports[1]; - port->channel = CHANNEL_B; - port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR; - port->datap = port->ctrlp + 1; - port->port_a = &scc_ports[0]; - port->port_b = &scc_ports[1]; - error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED, - "SCC-B TX", port); - if (error) - goto fail_free_a_spcond; - error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED, - "SCC-B status", port); - if (error) - goto fail_free_b_tx; - error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED, - "SCC-B RX", port); - if (error) - goto fail_free_b_stat; - error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, - IRQF_DISABLED, "SCC-B special cond", port); - if (error) - goto fail_free_b_rx; - - { - SCC_ACCESS_INIT(port); - - /* disable interrupts for this channel */ - SCCwrite(INT_AND_DMA_REG, 0); - } - - /* Ensure interrupts are enabled in the PCC chip */ - m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB; - - /* Initialise the tty driver structures and register */ - scc_init_portstructs(); - scc_init_drivers(); - - return 0; - -fail_free_b_rx: - free_irq(MVME147_IRQ_SCCB_RX, port); -fail_free_b_stat: - free_irq(MVME147_IRQ_SCCB_STAT, port); -fail_free_b_tx: - free_irq(MVME147_IRQ_SCCB_TX, port); -fail_free_a_spcond: - free_irq(MVME147_IRQ_SCCA_SPCOND, port); -fail_free_a_rx: - free_irq(MVME147_IRQ_SCCA_RX, port); -fail_free_a_stat: - free_irq(MVME147_IRQ_SCCA_STAT, port); -fail_free_a_tx: - free_irq(MVME147_IRQ_SCCA_TX, port); -fail: - return error; -} -#endif - - -#ifdef CONFIG_MVME162_SCC -static int __init mvme162_scc_init(void) -{ - struct scc_port *port; - int error; - - if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA)) - return (-ENODEV); - - printk(KERN_INFO "SCC: MVME162 Serial Driver\n"); - /* Init channel A */ - port = &scc_ports[0]; - port->channel = CHANNEL_A; - port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR; - port->datap = port->ctrlp + 2; - port->port_a = &scc_ports[0]; - port->port_b = &scc_ports[1]; - error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED, - "SCC-A TX", port); - if (error) - goto fail; - error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED, - "SCC-A status", port); - if (error) - goto fail_free_a_tx; - error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED, - "SCC-A RX", port); - if (error) - goto fail_free_a_stat; - error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, - IRQF_DISABLED, "SCC-A special cond", port); - if (error) - goto fail_free_a_rx; - - { - SCC_ACCESS_INIT(port); - - /* disable interrupts for this channel */ - SCCwrite(INT_AND_DMA_REG, 0); - /* Set the interrupt vector */ - SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE); - /* Interrupt parameters: vector includes status, status low */ - SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); - SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); - } - - /* Init channel B */ - port = &scc_ports[1]; - port->channel = CHANNEL_B; - port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR; - port->datap = port->ctrlp + 2; - port->port_a = &scc_ports[0]; - port->port_b = &scc_ports[1]; - error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED, - "SCC-B TX", port); - if (error) - goto fail_free_a_spcond; - error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED, - "SCC-B status", port); - if (error) - goto fail_free_b_tx; - error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED, - "SCC-B RX", port); - if (error) - goto fail_free_b_stat; - error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, - IRQF_DISABLED, "SCC-B special cond", port); - if (error) - goto fail_free_b_rx; - - { - SCC_ACCESS_INIT(port); /* Either channel will do */ - - /* disable interrupts for this channel */ - SCCwrite(INT_AND_DMA_REG, 0); - } - - /* Ensure interrupts are enabled in the MC2 chip */ - *(volatile char *)0xfff4201d = 0x14; - - /* Initialise the tty driver structures and register */ - scc_init_portstructs(); - scc_init_drivers(); - - return 0; - -fail_free_b_rx: - free_irq(MVME162_IRQ_SCCB_RX, port); -fail_free_b_stat: - free_irq(MVME162_IRQ_SCCB_STAT, port); -fail_free_b_tx: - free_irq(MVME162_IRQ_SCCB_TX, port); -fail_free_a_spcond: - free_irq(MVME162_IRQ_SCCA_SPCOND, port); -fail_free_a_rx: - free_irq(MVME162_IRQ_SCCA_RX, port); -fail_free_a_stat: - free_irq(MVME162_IRQ_SCCA_STAT, port); -fail_free_a_tx: - free_irq(MVME162_IRQ_SCCA_TX, port); -fail: - return error; -} -#endif - - -#ifdef CONFIG_BVME6000_SCC -static int __init bvme6000_scc_init(void) -{ - struct scc_port *port; - int error; - - printk(KERN_INFO "SCC: BVME6000 Serial Driver\n"); - /* Init channel A */ - port = &scc_ports[0]; - port->channel = CHANNEL_A; - port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR; - port->datap = port->ctrlp + 4; - port->port_a = &scc_ports[0]; - port->port_b = &scc_ports[1]; - error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED, - "SCC-A TX", port); - if (error) - goto fail; - error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED, - "SCC-A status", port); - if (error) - goto fail_free_a_tx; - error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED, - "SCC-A RX", port); - if (error) - goto fail_free_a_stat; - error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, - IRQF_DISABLED, "SCC-A special cond", port); - if (error) - goto fail_free_a_rx; - - { - SCC_ACCESS_INIT(port); - - /* disable interrupts for this channel */ - SCCwrite(INT_AND_DMA_REG, 0); - /* Set the interrupt vector */ - SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE); - /* Interrupt parameters: vector includes status, status low */ - SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); - SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); - } - - /* Init channel B */ - port = &scc_ports[1]; - port->channel = CHANNEL_B; - port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR; - port->datap = port->ctrlp + 4; - port->port_a = &scc_ports[0]; - port->port_b = &scc_ports[1]; - error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED, - "SCC-B TX", port); - if (error) - goto fail_free_a_spcond; - error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED, - "SCC-B status", port); - if (error) - goto fail_free_b_tx; - error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED, - "SCC-B RX", port); - if (error) - goto fail_free_b_stat; - error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, - IRQF_DISABLED, "SCC-B special cond", port); - if (error) - goto fail_free_b_rx; - - { - SCC_ACCESS_INIT(port); /* Either channel will do */ - - /* disable interrupts for this channel */ - SCCwrite(INT_AND_DMA_REG, 0); - } - - /* Initialise the tty driver structures and register */ - scc_init_portstructs(); - scc_init_drivers(); - - return 0; - -fail: - free_irq(BVME_IRQ_SCCA_STAT, port); -fail_free_a_tx: - free_irq(BVME_IRQ_SCCA_RX, port); -fail_free_a_stat: - free_irq(BVME_IRQ_SCCA_SPCOND, port); -fail_free_a_rx: - free_irq(BVME_IRQ_SCCB_TX, port); -fail_free_a_spcond: - free_irq(BVME_IRQ_SCCB_STAT, port); -fail_free_b_tx: - free_irq(BVME_IRQ_SCCB_RX, port); -fail_free_b_stat: - free_irq(BVME_IRQ_SCCB_SPCOND, port); -fail_free_b_rx: - return error; -} -#endif - - -static int __init vme_scc_init(void) -{ - int res = -ENODEV; - -#ifdef CONFIG_MVME147_SCC - if (MACH_IS_MVME147) - res = mvme147_scc_init(); -#endif -#ifdef CONFIG_MVME162_SCC - if (MACH_IS_MVME16x) - res = mvme162_scc_init(); -#endif -#ifdef CONFIG_BVME6000_SCC - if (MACH_IS_BVME6000) - res = bvme6000_scc_init(); -#endif - return res; -} - -module_init(vme_scc_init); - - -/*--------------------------------------------------------------------------- - * Interrupt handlers - *--------------------------------------------------------------------------*/ - -static irqreturn_t scc_rx_int(int irq, void *data) -{ - unsigned char ch; - struct scc_port *port = data; - struct tty_struct *tty = port->gs.port.tty; - SCC_ACCESS_INIT(port); - - ch = SCCread_NB(RX_DATA_REG); - if (!tty) { - printk(KERN_WARNING "scc_rx_int with NULL tty!\n"); - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - return IRQ_HANDLED; - } - tty_insert_flip_char(tty, ch, 0); - - /* Check if another character is already ready; in that case, the - * spcond_int() function must be used, because this character may have an - * error condition that isn't signalled by the interrupt vector used! - */ - if (SCCread(INT_PENDING_REG) & - (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) { - scc_spcond_int (irq, data); - return IRQ_HANDLED; - } - - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - - tty_flip_buffer_push(tty); - return IRQ_HANDLED; -} - - -static irqreturn_t scc_spcond_int(int irq, void *data) -{ - struct scc_port *port = data; - struct tty_struct *tty = port->gs.port.tty; - unsigned char stat, ch, err; - int int_pending_mask = port->channel == CHANNEL_A ? - IPR_A_RX : IPR_B_RX; - SCC_ACCESS_INIT(port); - - if (!tty) { - printk(KERN_WARNING "scc_spcond_int with NULL tty!\n"); - SCCwrite(COMMAND_REG, CR_ERROR_RESET); - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - return IRQ_HANDLED; - } - do { - stat = SCCread(SPCOND_STATUS_REG); - ch = SCCread_NB(RX_DATA_REG); - - if (stat & SCSR_RX_OVERRUN) - err = TTY_OVERRUN; - else if (stat & SCSR_PARITY_ERR) - err = TTY_PARITY; - else if (stat & SCSR_CRC_FRAME_ERR) - err = TTY_FRAME; - else - err = 0; - - tty_insert_flip_char(tty, ch, err); - - /* ++TeSche: *All* errors have to be cleared manually, - * else the condition persists for the next chars - */ - if (err) - SCCwrite(COMMAND_REG, CR_ERROR_RESET); - - } while(SCCread(INT_PENDING_REG) & int_pending_mask); - - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - - tty_flip_buffer_push(tty); - return IRQ_HANDLED; -} - - -static irqreturn_t scc_tx_int(int irq, void *data) -{ - struct scc_port *port = data; - SCC_ACCESS_INIT(port); - - if (!port->gs.port.tty) { - printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); - SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); - SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - return IRQ_HANDLED; - } - while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) { - if (port->x_char) { - SCCwrite(TX_DATA_REG, port->x_char); - port->x_char = 0; - } - else if ((port->gs.xmit_cnt <= 0) || - port->gs.port.tty->stopped || - port->gs.port.tty->hw_stopped) - break; - else { - SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]); - port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1); - if (--port->gs.xmit_cnt <= 0) - break; - } - } - if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped || - port->gs.port.tty->hw_stopped) { - /* disable tx interrupts */ - SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); - SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ - port->gs.port.flags &= ~GS_TX_INTEN; - } - if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) - tty_wakeup(port->gs.port.tty); - - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - return IRQ_HANDLED; -} - - -static irqreturn_t scc_stat_int(int irq, void *data) -{ - struct scc_port *port = data; - unsigned channel = port->channel; - unsigned char last_sr, sr, changed; - SCC_ACCESS_INIT(port); - - last_sr = scc_last_status_reg[channel]; - sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG); - changed = last_sr ^ sr; - - if (changed & SR_DCD) { - port->c_dcd = !!(sr & SR_DCD); - if (!(port->gs.port.flags & ASYNC_CHECK_CD)) - ; /* Don't report DCD changes */ - else if (port->c_dcd) { - wake_up_interruptible(&port->gs.port.open_wait); - } - else { - if (port->gs.port.tty) - tty_hangup (port->gs.port.tty); - } - } - SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); - SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); - return IRQ_HANDLED; -} - - -/*--------------------------------------------------------------------------- - * generic_serial.c callback funtions - *--------------------------------------------------------------------------*/ - -static void scc_disable_tx_interrupts(void *ptr) -{ - struct scc_port *port = ptr; - unsigned long flags; - SCC_ACCESS_INIT(port); - - local_irq_save(flags); - SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); - port->gs.port.flags &= ~GS_TX_INTEN; - local_irq_restore(flags); -} - - -static void scc_enable_tx_interrupts(void *ptr) -{ - struct scc_port *port = ptr; - unsigned long flags; - SCC_ACCESS_INIT(port); - - local_irq_save(flags); - SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB); - /* restart the transmitter */ - scc_tx_int (0, port); - local_irq_restore(flags); -} - - -static void scc_disable_rx_interrupts(void *ptr) -{ - struct scc_port *port = ptr; - unsigned long flags; - SCC_ACCESS_INIT(port); - - local_irq_save(flags); - SCCmod(INT_AND_DMA_REG, - ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0); - local_irq_restore(flags); -} - - -static void scc_enable_rx_interrupts(void *ptr) -{ - struct scc_port *port = ptr; - unsigned long flags; - SCC_ACCESS_INIT(port); - - local_irq_save(flags); - SCCmod(INT_AND_DMA_REG, 0xff, - IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL); - local_irq_restore(flags); -} - - -static int scc_carrier_raised(struct tty_port *port) -{ - struct scc_port *sc = container_of(port, struct scc_port, gs.port); - unsigned channel = sc->channel; - - return !!(scc_last_status_reg[channel] & SR_DCD); -} - - -static void scc_shutdown_port(void *ptr) -{ - struct scc_port *port = ptr; - - port->gs.port.flags &= ~ GS_ACTIVE; - if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) { - scc_setsignals (port, 0, 0); - } -} - - -static int scc_set_real_termios (void *ptr) -{ - /* the SCC has char sizes 5,7,6,8 in that order! */ - static int chsize_map[4] = { 0, 2, 1, 3 }; - unsigned cflag, baud, chsize, channel, brgval = 0; - unsigned long flags; - struct scc_port *port = ptr; - SCC_ACCESS_INIT(port); - - if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; - - channel = port->channel; - - if (channel == CHANNEL_A) - return 0; /* Settings controlled by boot PROM */ - - cflag = port->gs.port.tty->termios->c_cflag; - baud = port->gs.baud; - chsize = (cflag & CSIZE) >> 4; - - if (baud == 0) { - /* speed == 0 -> drop DTR */ - local_irq_save(flags); - SCCmod(TX_CTRL_REG, ~TCR_DTR, 0); - local_irq_restore(flags); - return 0; - } - else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) || - (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) || - (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) { - printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud); - return 0; - } - - if (cflag & CLOCAL) - port->gs.port.flags &= ~ASYNC_CHECK_CD; - else - port->gs.port.flags |= ASYNC_CHECK_CD; - -#ifdef CONFIG_MVME147_SCC - if (MACH_IS_MVME147) - brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; -#endif -#ifdef CONFIG_MVME162_SCC - if (MACH_IS_MVME16x) - brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; -#endif -#ifdef CONFIG_BVME6000_SCC - if (MACH_IS_BVME6000) - brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2; -#endif - /* Now we have all parameters and can go to set them: */ - local_irq_save(flags); - - /* receiver's character size and auto-enables */ - SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE), - (chsize_map[chsize] << 6) | - ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0)); - /* parity and stop bits (both, Tx and Rx), clock mode never changes */ - SCCmod (AUX1_CTRL_REG, - ~(A1CR_PARITY_MASK | A1CR_MODE_MASK), - ((cflag & PARENB - ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN) - : A1CR_PARITY_NONE) - | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1))); - /* sender's character size, set DTR for valid baud rate */ - SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR); - /* clock sources never change */ - /* disable BRG before changing the value */ - SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0); - /* BRG value */ - SCCwrite(TIMER_LOW_REG, brgval & 0xff); - SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff); - /* BRG enable, and clock source never changes */ - SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB); - - local_irq_restore(flags); - - return 0; -} - - -static int scc_chars_in_buffer (void *ptr) -{ - struct scc_port *port = ptr; - SCC_ACCESS_INIT(port); - - return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1; -} - - -/* Comment taken from sx.c (2.4.0): - I haven't the foggiest why the decrement use count has to happen - here. The whole linux serial drivers stuff needs to be redesigned. - My guess is that this is a hack to minimize the impact of a bug - elsewhere. Thinking about it some more. (try it sometime) Try - running minicom on a serial port that is driven by a modularized - driver. Have the modem hangup. Then remove the driver module. Then - exit minicom. I expect an "oops". -- REW */ - -static void scc_hungup(void *ptr) -{ - scc_disable_tx_interrupts(ptr); - scc_disable_rx_interrupts(ptr); -} - - -static void scc_close(void *ptr) -{ - scc_disable_tx_interrupts(ptr); - scc_disable_rx_interrupts(ptr); -} - - -/*--------------------------------------------------------------------------- - * Internal support functions - *--------------------------------------------------------------------------*/ - -static void scc_setsignals(struct scc_port *port, int dtr, int rts) -{ - unsigned long flags; - unsigned char t; - SCC_ACCESS_INIT(port); - - local_irq_save(flags); - t = SCCread(TX_CTRL_REG); - if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR); - if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS); - SCCwrite(TX_CTRL_REG, t); - local_irq_restore(flags); -} - - -static void scc_send_xchar(struct tty_struct *tty, char ch) -{ - struct scc_port *port = tty->driver_data; - - port->x_char = ch; - if (ch) - scc_enable_tx_interrupts(port); -} - - -/*--------------------------------------------------------------------------- - * Driver entrypoints referenced from above - *--------------------------------------------------------------------------*/ - -static int scc_open (struct tty_struct * tty, struct file * filp) -{ - int line = tty->index; - int retval; - struct scc_port *port = &scc_ports[line]; - int i, channel = port->channel; - unsigned long flags; - SCC_ACCESS_INIT(port); -#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC) - static const struct { - unsigned reg, val; - } mvme_init_tab[] = { - /* Values for MVME162 and MVME147 */ - /* no parity, 1 stop bit, async, 1:16 */ - { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 }, - /* parity error is special cond, ints disabled, no DMA */ - { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB }, - /* Rx 8 bits/char, no auto enable, Rx off */ - { RX_CTRL_REG, RCR_CHSIZE_8 }, - /* DTR off, Tx 8 bits/char, RTS off, Tx off */ - { TX_CTRL_REG, TCR_CHSIZE_8 }, - /* special features off */ - { AUX2_CTRL_REG, 0 }, - { CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG }, - { DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK }, - /* Start Rx */ - { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 }, - /* Start Tx */ - { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 }, - /* Ext/Stat ints: DCD only */ - { INT_CTRL_REG, ICR_ENAB_DCD_INT }, - /* Reset Ext/Stat ints */ - { COMMAND_REG, CR_EXTSTAT_RESET }, - /* ...again */ - { COMMAND_REG, CR_EXTSTAT_RESET }, - }; -#endif -#if defined(CONFIG_BVME6000_SCC) - static const struct { - unsigned reg, val; - } bvme_init_tab[] = { - /* Values for BVME6000 */ - /* no parity, 1 stop bit, async, 1:16 */ - { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 }, - /* parity error is special cond, ints disabled, no DMA */ - { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB }, - /* Rx 8 bits/char, no auto enable, Rx off */ - { RX_CTRL_REG, RCR_CHSIZE_8 }, - /* DTR off, Tx 8 bits/char, RTS off, Tx off */ - { TX_CTRL_REG, TCR_CHSIZE_8 }, - /* special features off */ - { AUX2_CTRL_REG, 0 }, - { CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG }, - { DPLL_CTRL_REG, DCR_BRG_ENAB }, - /* Start Rx */ - { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 }, - /* Start Tx */ - { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 }, - /* Ext/Stat ints: DCD only */ - { INT_CTRL_REG, ICR_ENAB_DCD_INT }, - /* Reset Ext/Stat ints */ - { COMMAND_REG, CR_EXTSTAT_RESET }, - /* ...again */ - { COMMAND_REG, CR_EXTSTAT_RESET }, - }; -#endif - if (!(port->gs.port.flags & ASYNC_INITIALIZED)) { - local_irq_save(flags); -#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) - if (MACH_IS_MVME147 || MACH_IS_MVME16x) { - for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i) - SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val); - } -#endif -#if defined(CONFIG_BVME6000_SCC) - if (MACH_IS_BVME6000) { - for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i) - SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val); - } -#endif - - /* remember status register for detection of DCD and CTS changes */ - scc_last_status_reg[channel] = SCCread(STATUS_REG); - - port->c_dcd = 0; /* Prevent initial 1->0 interrupt */ - scc_setsignals (port, 1,1); - local_irq_restore(flags); - } - - tty->driver_data = port; - port->gs.port.tty = tty; - port->gs.port.count++; - retval = gs_init_port(&port->gs); - if (retval) { - port->gs.port.count--; - return retval; - } - port->gs.port.flags |= GS_ACTIVE; - retval = gs_block_til_ready(port, filp); - - if (retval) { - port->gs.port.count--; - return retval; - } - - port->c_dcd = tty_port_carrier_raised(&port->gs.port); - - scc_enable_rx_interrupts(port); - - return 0; -} - - -static void scc_throttle (struct tty_struct * tty) -{ - struct scc_port *port = tty->driver_data; - unsigned long flags; - SCC_ACCESS_INIT(port); - - if (tty->termios->c_cflag & CRTSCTS) { - local_irq_save(flags); - SCCmod(TX_CTRL_REG, ~TCR_RTS, 0); - local_irq_restore(flags); - } - if (I_IXOFF(tty)) - scc_send_xchar(tty, STOP_CHAR(tty)); -} - - -static void scc_unthrottle (struct tty_struct * tty) -{ - struct scc_port *port = tty->driver_data; - unsigned long flags; - SCC_ACCESS_INIT(port); - - if (tty->termios->c_cflag & CRTSCTS) { - local_irq_save(flags); - SCCmod(TX_CTRL_REG, 0xff, TCR_RTS); - local_irq_restore(flags); - } - if (I_IXOFF(tty)) - scc_send_xchar(tty, START_CHAR(tty)); -} - - -static int scc_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; -} - - -static int scc_break_ctl(struct tty_struct *tty, int break_state) -{ - struct scc_port *port = tty->driver_data; - unsigned long flags; - SCC_ACCESS_INIT(port); - - local_irq_save(flags); - SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, - break_state ? TCR_SEND_BREAK : 0); - local_irq_restore(flags); - return 0; -} - - -/*--------------------------------------------------------------------------- - * Serial console stuff... - *--------------------------------------------------------------------------*/ - -#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0) - -static void scc_ch_write (char ch) -{ - volatile char *p = NULL; - -#ifdef CONFIG_MVME147_SCC - if (MACH_IS_MVME147) - p = (volatile char *)M147_SCC_A_ADDR; -#endif -#ifdef CONFIG_MVME162_SCC - if (MACH_IS_MVME16x) - p = (volatile char *)MVME_SCC_A_ADDR; -#endif -#ifdef CONFIG_BVME6000_SCC - if (MACH_IS_BVME6000) - p = (volatile char *)BVME_SCC_A_ADDR; -#endif - - do { - scc_delay(); - } - while (!(*p & 4)); - scc_delay(); - *p = 8; - scc_delay(); - *p = ch; -} - -/* The console must be locked when we get here. */ - -static void scc_console_write (struct console *co, const char *str, unsigned count) -{ - unsigned long flags; - - local_irq_save(flags); - - while (count--) - { - if (*str == '\n') - scc_ch_write ('\r'); - scc_ch_write (*str++); - } - local_irq_restore(flags); -} - -static struct tty_driver *scc_console_device(struct console *c, int *index) -{ - *index = c->index; - return scc_driver; -} - -static struct console sercons = { - .name = "ttyS", - .write = scc_console_write, - .device = scc_console_device, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - - -static int __init vme_scc_console_init(void) -{ - if (vme_brdtype == VME_TYPE_MVME147 || - vme_brdtype == VME_TYPE_MVME162 || - vme_brdtype == VME_TYPE_MVME172 || - vme_brdtype == VME_TYPE_BVME4000 || - vme_brdtype == VME_TYPE_BVME6000) - register_console(&sercons); - return 0; -} -console_initcall(vme_scc_console_init); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index fb1fc4e5a8cb..58e4a8e15a0e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -43,6 +43,8 @@ if !STAGING_EXCLUDE_BUILD source "drivers/staging/tty/Kconfig" +source "drivers/staging/generic_serial/Kconfig" + source "drivers/staging/et131x/Kconfig" source "drivers/staging/slicoss/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index f498e345a01d..ff7372d25c91 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_STAGING) += staging.o obj-y += tty/ +obj-y += generic_serial/ obj-$(CONFIG_ET131X) += et131x/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ diff --git a/drivers/staging/generic_serial/Kconfig b/drivers/staging/generic_serial/Kconfig new file mode 100644 index 000000000000..795daea37750 --- /dev/null +++ b/drivers/staging/generic_serial/Kconfig @@ -0,0 +1,45 @@ +config A2232 + tristate "Commodore A2232 serial support (EXPERIMENTAL)" + depends on EXPERIMENTAL && ZORRO && BROKEN + ---help--- + This option supports the 2232 7-port serial card shipped with the + Amiga 2000 and other Zorro-bus machines, dating from 1989. At + a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip + each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The + ports were connected with 8 pin DIN connectors on the card bracket, + for which 8 pin to DB25 adapters were supplied. The card also had + jumpers internally to toggle various pinning configurations. + + This driver can be built as a module; but then "generic_serial" + will also be built as a module. This has to be loaded before + "ser_a2232". If you want to do this, answer M here. + +config SX + tristate "Specialix SX (and SI) card support" + depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN + help + This is a driver for the SX and SI multiport serial cards. + Please read the file for details. + + This driver can only be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called sx. If you want to do that, say M here. + +config RIO + tristate "Specialix RIO system support" + depends on SERIAL_NONSTANDARD && BROKEN + help + This is a driver for the Specialix RIO, a smart serial card which + drives an outboard box that can support up to 128 ports. Product + information is at . + There are both ISA and PCI versions. + +config RIO_OLDPCI + bool "Support really old RIO/PCI cards" + depends on RIO + help + Older RIO PCI cards need some initialization-time configuration to + determine the IRQ and some control addresses. If you have a RIO and + this doesn't seem to work, try setting this to Y. + + diff --git a/drivers/staging/generic_serial/Makefile b/drivers/staging/generic_serial/Makefile new file mode 100644 index 000000000000..ffc90c8b013c --- /dev/null +++ b/drivers/staging/generic_serial/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o +obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o +obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o +obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o +obj-$(CONFIG_SX) += sx.o generic_serial.o +obj-$(CONFIG_RIO) += rio/ generic_serial.o diff --git a/drivers/staging/generic_serial/TODO b/drivers/staging/generic_serial/TODO new file mode 100644 index 000000000000..88756453ac6c --- /dev/null +++ b/drivers/staging/generic_serial/TODO @@ -0,0 +1,6 @@ +These are a few tty/serial drivers that either do not build, +or work if they do build, or if they seem to work, are for obsolete +hardware, or are full of unfixable races and no one uses them anymore. + +If no one steps up to adopt any of these drivers, they will be removed +in the 2.6.41 release. diff --git a/drivers/staging/generic_serial/generic_serial.c b/drivers/staging/generic_serial/generic_serial.c new file mode 100644 index 000000000000..5954ee1dc953 --- /dev/null +++ b/drivers/staging/generic_serial/generic_serial.c @@ -0,0 +1,844 @@ +/* + * generic_serial.c + * + * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl + * + * written for the SX serial driver. + * Contains the code that should be shared over all the serial drivers. + * + * Credit for the idea to do it this way might go to Alan Cox. + * + * + * Version 0.1 -- December, 1998. Initial version. + * Version 0.2 -- March, 1999. Some more routines. Bugfixes. Etc. + * Version 0.5 -- August, 1999. Some more fixes. Reformat for Linus. + * + * BitWizard is actively maintaining this file. We sometimes find + * that someone submitted changes to this file. We really appreciate + * your help, but please submit changes through us. We're doing our + * best to be responsive. -- REW + * */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +static int gs_debug; + +#ifdef DEBUG +#define gs_dprintk(f, str...) if (gs_debug & f) printk (str) +#else +#define gs_dprintk(f, str...) /* nothing */ +#endif + +#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__) +#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __func__) + +#define RS_EVENT_WRITE_WAKEUP 1 + +module_param(gs_debug, int, 0644); + + +int gs_put_char(struct tty_struct * tty, unsigned char ch) +{ + struct gs_port *port; + + func_enter (); + + port = tty->driver_data; + + if (!port) return 0; + + if (! (port->port.flags & ASYNC_INITIALIZED)) return 0; + + /* Take a lock on the serial tranmit buffer! */ + mutex_lock(& port->port_write_mutex); + + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ + mutex_unlock(&port->port_write_mutex); + return 0; + } + + port->xmit_buf[port->xmit_head++] = ch; + port->xmit_head &= SERIAL_XMIT_SIZE - 1; + port->xmit_cnt++; /* Characters in buffer */ + + mutex_unlock(&port->port_write_mutex); + func_exit (); + return 1; +} + + +/* +> Problems to take into account are: +> -1- Interrupts that empty part of the buffer. +> -2- page faults on the access to userspace. +> -3- Other processes that are also trying to do a "write". +*/ + +int gs_write(struct tty_struct * tty, + const unsigned char *buf, int count) +{ + struct gs_port *port; + int c, total = 0; + int t; + + func_enter (); + + port = tty->driver_data; + + if (!port) return 0; + + if (! (port->port.flags & ASYNC_INITIALIZED)) + return 0; + + /* get exclusive "write" access to this port (problem 3) */ + /* This is not a spinlock because we can have a disk access (page + fault) in copy_from_user */ + mutex_lock(& port->port_write_mutex); + + while (1) { + + c = count; + + /* This is safe because we "OWN" the "head". Noone else can + change the "head": we own the port_write_mutex. */ + /* Don't overrun the end of the buffer */ + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + + /* This is safe because the xmit_cnt can only decrease. This + would increase "t", so we might copy too little chars. */ + /* Don't copy past the "head" of the buffer */ + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + /* Can't copy more? break out! */ + if (c <= 0) break; + + memcpy (port->xmit_buf + port->xmit_head, buf, c); + + port -> xmit_cnt += c; + port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1); + buf += c; + count -= c; + total += c; + } + mutex_unlock(& port->port_write_mutex); + + gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", + (port->port.flags & GS_TX_INTEN)?"enabled": "disabled"); + + if (port->xmit_cnt && + !tty->stopped && + !tty->hw_stopped && + !(port->port.flags & GS_TX_INTEN)) { + port->port.flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + } + func_exit (); + return total; +} + + + +int gs_write_room(struct tty_struct * tty) +{ + struct gs_port *port = tty->driver_data; + int ret; + + func_enter (); + ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; + if (ret < 0) + ret = 0; + func_exit (); + return ret; +} + + +int gs_chars_in_buffer(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + func_enter (); + + func_exit (); + return port->xmit_cnt; +} + + +static int gs_real_chars_in_buffer(struct tty_struct *tty) +{ + struct gs_port *port; + func_enter (); + + port = tty->driver_data; + + if (!port->rd) return 0; + if (!port->rd->chars_in_buffer) return 0; + + func_exit (); + return port->xmit_cnt + port->rd->chars_in_buffer (port); +} + + +static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) +{ + struct gs_port *port = ptr; + unsigned long end_jiffies; + int jiffies_to_transmit, charsleft = 0, rv = 0; + int rcib; + + func_enter(); + + gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port); + if (port) { + gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", + port->xmit_cnt, port->xmit_buf, port->port.tty); + } + + if (!port || port->xmit_cnt < 0 || !port->xmit_buf) { + gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n"); + func_exit(); + return -EINVAL; /* This is an error which we don't know how to handle. */ + } + + rcib = gs_real_chars_in_buffer(port->port.tty); + + if(rcib <= 0) { + gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n"); + func_exit(); + return rv; + } + /* stop trying: now + twice the time it would normally take + seconds */ + if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT; + end_jiffies = jiffies; + if (timeout != MAX_SCHEDULE_TIMEOUT) + end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0; + end_jiffies += timeout; + + gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", + jiffies, end_jiffies, end_jiffies-jiffies); + + /* the expression is actually jiffies < end_jiffies, but that won't + work around the wraparound. Tricky eh? */ + while ((charsleft = gs_real_chars_in_buffer (port->port.tty)) && + time_after (end_jiffies, jiffies)) { + /* Units check: + chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies! + check! */ + + charsleft += 16; /* Allow 16 chars more to be transmitted ... */ + jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0; + /* ^^^ Round up.... */ + if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1; + + gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies " + "(%d chars).\n", jiffies_to_transmit, charsleft); + + msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit)); + if (signal_pending (current)) { + gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); + rv = -EINTR; + break; + } + } + + gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); + set_current_state (TASK_RUNNING); + + func_exit(); + return rv; +} + + + +void gs_flush_buffer(struct tty_struct *tty) +{ + struct gs_port *port; + unsigned long flags; + + func_enter (); + + port = tty->driver_data; + + if (!port) return; + + /* XXX Would the write semaphore do? */ + spin_lock_irqsave (&port->driver_lock, flags); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + spin_unlock_irqrestore (&port->driver_lock, flags); + + tty_wakeup(tty); + func_exit (); +} + + +void gs_flush_chars(struct tty_struct * tty) +{ + struct gs_port *port; + + func_enter (); + + port = tty->driver_data; + + if (!port) return; + + if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !port->xmit_buf) { + func_exit (); + return; + } + + /* Beats me -- REW */ + port->port.flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + func_exit (); +} + + +void gs_stop(struct tty_struct * tty) +{ + struct gs_port *port; + + func_enter (); + + port = tty->driver_data; + + if (!port) return; + + if (port->xmit_cnt && + port->xmit_buf && + (port->port.flags & GS_TX_INTEN) ) { + port->port.flags &= ~GS_TX_INTEN; + port->rd->disable_tx_interrupts (port); + } + func_exit (); +} + + +void gs_start(struct tty_struct * tty) +{ + struct gs_port *port; + + port = tty->driver_data; + + if (!port) return; + + if (port->xmit_cnt && + port->xmit_buf && + !(port->port.flags & GS_TX_INTEN) ) { + port->port.flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + } + func_exit (); +} + + +static void gs_shutdown_port (struct gs_port *port) +{ + unsigned long flags; + + func_enter(); + + if (!port) return; + + if (!(port->port.flags & ASYNC_INITIALIZED)) + return; + + spin_lock_irqsave(&port->driver_lock, flags); + + if (port->xmit_buf) { + free_page((unsigned long) port->xmit_buf); + port->xmit_buf = NULL; + } + + if (port->port.tty) + set_bit(TTY_IO_ERROR, &port->port.tty->flags); + + port->rd->shutdown_port (port); + + port->port.flags &= ~ASYNC_INITIALIZED; + spin_unlock_irqrestore(&port->driver_lock, flags); + + func_exit(); +} + + +void gs_hangup(struct tty_struct *tty) +{ + struct gs_port *port; + unsigned long flags; + + func_enter (); + + port = tty->driver_data; + tty = port->port.tty; + if (!tty) + return; + + gs_shutdown_port (port); + spin_lock_irqsave(&port->port.lock, flags); + port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE); + port->port.tty = NULL; + port->port.count = 0; + spin_unlock_irqrestore(&port->port.lock, flags); + + wake_up_interruptible(&port->port.open_wait); + func_exit (); +} + + +int gs_block_til_ready(void *port_, struct file * filp) +{ + struct gs_port *gp = port_; + struct tty_port *port = &gp->port; + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + int CD; + struct tty_struct *tty; + unsigned long flags; + + func_enter (); + + if (!port) return 0; + + tty = port->tty; + + gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&port->close_wait); + if (port->flags & ASYNC_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; + } + + gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); + + if (C_CLOCAL(tty)) + do_clocal = 1; + + /* + * 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, port->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + + add_wait_queue(&port->open_wait, &wait); + + gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) { + port->count--; + } + port->blocked_open++; + spin_unlock_irqrestore(&port->lock, flags); + while (1) { + CD = tty_port_carrier_raised(port); + gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); + set_current_state (TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(port->flags & ASYNC_INITIALIZED)) { + if (port->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + break; + } + if (!(port->flags & ASYNC_CLOSING) && + (do_clocal || CD)) + break; + gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", + (int)signal_pending (current), *(long*)(¤t->blocked)); + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", + port->blocked_open); + set_current_state (TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) { + port->count++; + } + port->blocked_open--; + if (retval == 0) + port->flags |= ASYNC_NORMAL_ACTIVE; + spin_unlock_irqrestore(&port->lock, flags); + func_exit (); + return retval; +} + + +void gs_close(struct tty_struct * tty, struct file * filp) +{ + unsigned long flags; + struct gs_port *port; + + func_enter (); + + port = tty->driver_data; + + if (!port) return; + + if (!port->port.tty) { + /* This seems to happen when this is called from vhangup. */ + gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->port.tty is NULL\n"); + port->port.tty = tty; + } + + spin_lock_irqsave(&port->port.lock, flags); + + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&port->port.lock, flags); + if (port->rd->hungup) + port->rd->hungup (port); + func_exit (); + return; + } + + if ((tty->count == 1) && (port->port.count != 1)) { + printk(KERN_ERR "gs: gs_close port %p: bad port count;" + " tty->count is 1, port count is %d\n", port, port->port.count); + port->port.count = 1; + } + if (--port->port.count < 0) { + printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->port.count); + port->port.count = 0; + } + + if (port->port.count) { + gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count); + spin_unlock_irqrestore(&port->port.lock, flags); + func_exit (); + return; + } + port->port.flags |= ASYNC_CLOSING; + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + /* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, port->closing_wait); */ + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + + spin_lock_irqsave(&port->driver_lock, flags); + port->rd->disable_rx_interrupts (port); + spin_unlock_irqrestore(&port->driver_lock, flags); + spin_unlock_irqrestore(&port->port.lock, flags); + + /* close has no way of returning "EINTR", so discard return value */ + if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) + gs_wait_tx_flushed (port, port->closing_wait); + + port->port.flags &= ~GS_ACTIVE; + + gs_flush_buffer(tty); + + tty_ldisc_flush(tty); + tty->closing = 0; + + spin_lock_irqsave(&port->driver_lock, flags); + port->event = 0; + port->rd->close (port); + port->rd->shutdown_port (port); + spin_unlock_irqrestore(&port->driver_lock, flags); + + spin_lock_irqsave(&port->port.lock, flags); + port->port.tty = NULL; + + if (port->port.blocked_open) { + if (port->close_delay) { + spin_unlock_irqrestore(&port->port.lock, flags); + msleep_interruptible(jiffies_to_msecs(port->close_delay)); + spin_lock_irqsave(&port->port.lock, flags); + } + wake_up_interruptible(&port->port.open_wait); + } + port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED); + spin_unlock_irqrestore(&port->port.lock, flags); + wake_up_interruptible(&port->port.close_wait); + + func_exit (); +} + + +void gs_set_termios (struct tty_struct * tty, + struct ktermios * old_termios) +{ + struct gs_port *port; + int baudrate, tmp, rv; + struct ktermios *tiosp; + + func_enter(); + + port = tty->driver_data; + + if (!port) return; + if (!port->port.tty) { + /* This seems to happen when this is called after gs_close. */ + gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->port.tty is NULL\n"); + port->port.tty = tty; + } + + + tiosp = tty->termios; + + if (gs_debug & GS_DEBUG_TERMIOS) { + gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); + } + + if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { + if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); + if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); + if(tiosp->c_cflag != old_termios->c_cflag) printk("c_cflag changed\n"); + if(tiosp->c_lflag != old_termios->c_lflag) printk("c_lflag changed\n"); + if(tiosp->c_line != old_termios->c_line) printk("c_line changed\n"); + if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); + } + + baudrate = tty_get_baud_rate(tty); + + if ((tiosp->c_cflag & CBAUD) == B38400) { + if ( (port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baudrate = 57600; + else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baudrate = 115200; + else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + baudrate = 230400; + else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + baudrate = 460800; + else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) + baudrate = (port->baud_base / port->custom_divisor); + } + + /* I recommend using THIS instead of the mess in termios (and + duplicating the above code). Next we should create a clean + interface towards this variable. If your card supports arbitrary + baud rates, (e.g. CD1400 or 16550 based cards) then everything + will be very easy..... */ + port->baud = baudrate; + + /* Two timer ticks seems enough to wakeup something like SLIP driver */ + /* Baudrate/10 is cps. Divide by HZ to get chars per tick. */ + tmp = (baudrate / 10 / HZ) * 2; + + if (tmp < 0) tmp = 0; + if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1; + + port->wakeup_chars = tmp; + + /* We should really wait for the characters to be all sent before + changing the settings. -- CAL */ + rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT); + if (rv < 0) return /* rv */; + + rv = port->rd->set_real_termios(port); + if (rv < 0) return /* rv */; + + if ((!old_termios || + (old_termios->c_cflag & CRTSCTS)) && + !( tiosp->c_cflag & CRTSCTS)) { + tty->stopped = 0; + gs_start(tty); + } + +#ifdef tytso_patch_94Nov25_1726 + /* This "makes sense", Why is it commented out? */ + + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&port->gs.open_wait); +#endif + + func_exit(); + return /* 0 */; +} + + + +/* Must be called with interrupts enabled */ +int gs_init_port(struct gs_port *port) +{ + unsigned long flags; + + func_enter (); + + if (port->port.flags & ASYNC_INITIALIZED) { + func_exit (); + return 0; + } + if (!port->xmit_buf) { + /* We may sleep in get_zeroed_page() */ + unsigned long tmp; + + tmp = get_zeroed_page(GFP_KERNEL); + spin_lock_irqsave (&port->driver_lock, flags); + if (port->xmit_buf) + free_page (tmp); + else + port->xmit_buf = (unsigned char *) tmp; + spin_unlock_irqrestore(&port->driver_lock, flags); + if (!port->xmit_buf) { + func_exit (); + return -ENOMEM; + } + } + + spin_lock_irqsave (&port->driver_lock, flags); + if (port->port.tty) + clear_bit(TTY_IO_ERROR, &port->port.tty->flags); + mutex_init(&port->port_write_mutex); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + spin_unlock_irqrestore(&port->driver_lock, flags); + gs_set_termios(port->port.tty, NULL); + spin_lock_irqsave (&port->driver_lock, flags); + port->port.flags |= ASYNC_INITIALIZED; + port->port.flags &= ~GS_TX_INTEN; + + spin_unlock_irqrestore(&port->driver_lock, flags); + func_exit (); + return 0; +} + + +int gs_setserial(struct gs_port *port, struct serial_struct __user *sp) +{ + struct serial_struct sio; + + if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) + return(-EFAULT); + + if (!capable(CAP_SYS_ADMIN)) { + if ((sio.baud_base != port->baud_base) || + (sio.close_delay != port->close_delay) || + ((sio.flags & ~ASYNC_USR_MASK) != + (port->port.flags & ~ASYNC_USR_MASK))) + return(-EPERM); + } + + port->port.flags = (port->port.flags & ~ASYNC_USR_MASK) | + (sio.flags & ASYNC_USR_MASK); + + port->baud_base = sio.baud_base; + port->close_delay = sio.close_delay; + port->closing_wait = sio.closing_wait; + port->custom_divisor = sio.custom_divisor; + + gs_set_termios (port->port.tty, NULL); + + return 0; +} + + +/*****************************************************************************/ + +/* + * Generate the serial struct info. + */ + +int gs_getserial(struct gs_port *port, struct serial_struct __user *sp) +{ + struct serial_struct sio; + + memset(&sio, 0, sizeof(struct serial_struct)); + sio.flags = port->port.flags; + sio.baud_base = port->baud_base; + sio.close_delay = port->close_delay; + sio.closing_wait = port->closing_wait; + sio.custom_divisor = port->custom_divisor; + sio.hub6 = 0; + + /* If you want you can override these. */ + sio.type = PORT_UNKNOWN; + sio.xmit_fifo_size = -1; + sio.line = -1; + sio.port = -1; + sio.irq = -1; + + if (port->rd->getserial) + port->rd->getserial (port, &sio); + + if (copy_to_user(sp, &sio, sizeof(struct serial_struct))) + return -EFAULT; + return 0; + +} + + +void gs_got_break(struct gs_port *port) +{ + func_enter (); + + tty_insert_flip_char(port->port.tty, 0, TTY_BREAK); + tty_schedule_flip(port->port.tty); + if (port->port.flags & ASYNC_SAK) { + do_SAK (port->port.tty); + } + + func_exit (); +} + + +EXPORT_SYMBOL(gs_put_char); +EXPORT_SYMBOL(gs_write); +EXPORT_SYMBOL(gs_write_room); +EXPORT_SYMBOL(gs_chars_in_buffer); +EXPORT_SYMBOL(gs_flush_buffer); +EXPORT_SYMBOL(gs_flush_chars); +EXPORT_SYMBOL(gs_stop); +EXPORT_SYMBOL(gs_start); +EXPORT_SYMBOL(gs_hangup); +EXPORT_SYMBOL(gs_block_til_ready); +EXPORT_SYMBOL(gs_close); +EXPORT_SYMBOL(gs_set_termios); +EXPORT_SYMBOL(gs_init_port); +EXPORT_SYMBOL(gs_setserial); +EXPORT_SYMBOL(gs_getserial); +EXPORT_SYMBOL(gs_got_break); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/generic_serial/rio/Makefile b/drivers/staging/generic_serial/rio/Makefile new file mode 100644 index 000000000000..1661875883fb --- /dev/null +++ b/drivers/staging/generic_serial/rio/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the linux rio-subsystem. +# +# (C) R.E.Wolff@BitWizard.nl +# +# This file is GPL. See other files for the full Blurb. I'm lazy today. +# + +obj-$(CONFIG_RIO) += rio.o + +rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ + rioparam.o rioroute.o riotable.o riotty.o diff --git a/drivers/staging/generic_serial/rio/board.h b/drivers/staging/generic_serial/rio/board.h new file mode 100644 index 000000000000..bdea633a9076 --- /dev/null +++ b/drivers/staging/generic_serial/rio/board.h @@ -0,0 +1,132 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : board.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:07 +** Retrieved : 11/6/98 11:34:20 +** +** ident @(#)board.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_board_h__ +#define __rio_board_h__ + +/* +** board.h contains the definitions for the *hardware* of the host cards. +** It describes the memory overlay for the dual port RAM area. +*/ + +#define DP_SRAM1_SIZE 0x7C00 +#define DP_SRAM2_SIZE 0x0200 +#define DP_SRAM3_SIZE 0x7000 +#define DP_SCRATCH_SIZE 0x1000 +#define DP_PARMMAP_ADDR 0x01FE /* offset into SRAM2 */ +#define DP_STARTUP_ADDR 0x01F8 /* offset into SRAM2 */ + +/* +** The shape of the Host Control area, at offset 0x7C00, Write Only +*/ +struct s_Ctrl { + u8 DpCtl; /* 7C00 */ + u8 Dp_Unused2_[127]; + u8 DpIntSet; /* 7C80 */ + u8 Dp_Unused3_[127]; + u8 DpTpuReset; /* 7D00 */ + u8 Dp_Unused4_[127]; + u8 DpIntReset; /* 7D80 */ + u8 Dp_Unused5_[127]; +}; + +/* +** The PROM data area on the host (0x7C00), Read Only +*/ +struct s_Prom { + u16 DpSlxCode[2]; + u16 DpRev; + u16 Dp_Unused6_; + u16 DpUniq[4]; + u16 DpJahre; + u16 DpWoche; + u16 DpHwFeature[5]; + u16 DpOemId; + u16 DpSiggy[16]; +}; + +/* +** Union of the Ctrl and Prom areas +*/ +union u_CtrlProm { /* This is the control/PROM area (0x7C00) */ + struct s_Ctrl DpCtrl; + struct s_Prom DpProm; +}; + +/* +** The top end of memory! +*/ +struct s_ParmMapS { /* Area containing Parm Map Pointer */ + u8 Dp_Unused8_[DP_PARMMAP_ADDR]; + u16 DpParmMapAd; +}; + +struct s_StartUpS { + u8 Dp_Unused9_[DP_STARTUP_ADDR]; + u8 Dp_LongJump[0x4]; + u8 Dp_Unused10_[2]; + u8 Dp_ShortJump[0x2]; +}; + +union u_Sram2ParmMap { /* This is the top of memory (0x7E00-0x7FFF) */ + u8 DpSramMem[DP_SRAM2_SIZE]; + struct s_ParmMapS DpParmMapS; + struct s_StartUpS DpStartUpS; +}; + +/* +** This is the DP RAM overlay. +*/ +struct DpRam { + u8 DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */ + union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */ + union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */ + u8 DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */ + u8 DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */ +}; + +#define DpControl DpCtrlProm.DpCtrl.DpCtl +#define DpSetInt DpCtrlProm.DpCtrl.DpIntSet +#define DpResetTpu DpCtrlProm.DpCtrl.DpTpuReset +#define DpResetInt DpCtrlProm.DpCtrl.DpIntReset + +#define DpSlx DpCtrlProm.DpProm.DpSlxCode +#define DpRevision DpCtrlProm.DpProm.DpRev +#define DpUnique DpCtrlProm.DpProm.DpUniq +#define DpYear DpCtrlProm.DpProm.DpJahre +#define DpWeek DpCtrlProm.DpProm.DpWoche +#define DpSignature DpCtrlProm.DpProm.DpSiggy + +#define DpParmMapR DpSram2ParmMap.DpParmMapS.DpParmMapAd +#define DpSram2 DpSram2ParmMap.DpSramMem + +#endif diff --git a/drivers/staging/generic_serial/rio/cirrus.h b/drivers/staging/generic_serial/rio/cirrus.h new file mode 100644 index 000000000000..5ab51679caa2 --- /dev/null +++ b/drivers/staging/generic_serial/rio/cirrus.h @@ -0,0 +1,210 @@ +/**************************************************************************** + ******* ******* + ******* CIRRUS.H ******* + ******* ******* + **************************************************************************** + + Author : Jeremy Rolls + Date : 3 Aug 1990 + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _cirrus_h +#define _cirrus_h 1 + +/* Bit fields for particular registers shared with driver */ + +/* COR1 - driver and RTA */ +#define RIOC_COR1_ODD 0x80 /* Odd parity */ +#define RIOC_COR1_EVEN 0x00 /* Even parity */ +#define RIOC_COR1_NOP 0x00 /* No parity */ +#define RIOC_COR1_FORCE 0x20 /* Force parity */ +#define RIOC_COR1_NORMAL 0x40 /* With parity */ +#define RIOC_COR1_1STOP 0x00 /* 1 stop bit */ +#define RIOC_COR1_15STOP 0x04 /* 1.5 stop bits */ +#define RIOC_COR1_2STOP 0x08 /* 2 stop bits */ +#define RIOC_COR1_5BITS 0x00 /* 5 data bits */ +#define RIOC_COR1_6BITS 0x01 /* 6 data bits */ +#define RIOC_COR1_7BITS 0x02 /* 7 data bits */ +#define RIOC_COR1_8BITS 0x03 /* 8 data bits */ + +#define RIOC_COR1_HOST 0xef /* Safe host bits */ + +/* RTA only */ +#define RIOC_COR1_CINPCK 0x00 /* Check parity of received characters */ +#define RIOC_COR1_CNINPCK 0x10 /* Don't check parity */ + +/* COR2 bits for both RTA and driver use */ +#define RIOC_COR2_IXANY 0x80 /* IXANY - any character is XON */ +#define RIOC_COR2_IXON 0x40 /* IXON - enable tx soft flowcontrol */ +#define RIOC_COR2_RTSFLOW 0x02 /* Enable tx hardware flow control */ + +/* Additional driver bits */ +#define RIOC_COR2_HUPCL 0x20 /* Hang up on close */ +#define RIOC_COR2_CTSFLOW 0x04 /* Enable rx hardware flow control */ +#define RIOC_COR2_IXOFF 0x01 /* Enable rx software flow control */ +#define RIOC_COR2_DTRFLOW 0x08 /* Enable tx hardware flow control */ + +/* RTA use only */ +#define RIOC_COR2_ETC 0x20 /* Embedded transmit options */ +#define RIOC_COR2_LOCAL 0x10 /* Local loopback mode */ +#define RIOC_COR2_REMOTE 0x08 /* Remote loopback mode */ +#define RIOC_COR2_HOST 0xc2 /* Safe host bits */ + +/* COR3 - RTA use only */ +#define RIOC_COR3_SCDRNG 0x80 /* Enable special char detect for range */ +#define RIOC_COR3_SCD34 0x40 /* Special character detect for SCHR's 3 + 4 */ +#define RIOC_COR3_FCT 0x20 /* Flow control transparency */ +#define RIOC_COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */ +#define RIOC_COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */ +#define RIOC_COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */ +#define RIOC_COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */ +#define RIOC_COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */ + +#define RIOC_COR3_THRESHOLD RIOC_COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */ + +#define RIOC_COR3_DEFAULT (RIOC_COR3_FCT | RIOC_COR3_THRESHOLD) + /* Default bits for COR3 */ + +/* COR4 driver and RTA use */ +#define RIOC_COR4_IGNCR 0x80 /* Throw away CR's on input */ +#define RIOC_COR4_ICRNL 0x40 /* Map CR -> NL on input */ +#define RIOC_COR4_INLCR 0x20 /* Map NL -> CR on input */ +#define RIOC_COR4_IGNBRK 0x10 /* Ignore Break */ +#define RIOC_COR4_NBRKINT 0x08 /* No interrupt on break (-BRKINT) */ +#define RIOC_COR4_RAISEMOD 0x01 /* Raise modem output lines on non-zero baud */ + + +/* COR4 driver only */ +#define RIOC_COR4_IGNPAR 0x04 /* IGNPAR (ignore characters with errors) */ +#define RIOC_COR4_PARMRK 0x02 /* PARMRK */ + +#define RIOC_COR4_HOST 0xf8 /* Safe host bits */ + +/* COR4 RTA only */ +#define RIOC_COR4_CIGNPAR 0x02 /* Thrown away bad characters */ +#define RIOC_COR4_CPARMRK 0x04 /* PARMRK characters */ +#define RIOC_COR4_CNPARMRK 0x03 /* Don't PARMRK */ + +/* COR5 driver and RTA use */ +#define RIOC_COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */ +#define RIOC_COR5_LNE 0x40 /* Enable LNEXT processing */ +#define RIOC_COR5_CMOE 0x20 /* Match good and errored characters */ +#define RIOC_COR5_ONLCR 0x02 /* NL -> CR NL on output */ +#define RIOC_COR5_OCRNL 0x01 /* CR -> NL on output */ + +/* +** Spare bits - these are not used in the CIRRUS registers, so we use +** them to set various other features. +*/ +/* +** tstop and tbusy indication +*/ +#define RIOC_COR5_TSTATE_ON 0x08 /* Turn on monitoring of tbusy and tstop */ +#define RIOC_COR5_TSTATE_OFF 0x04 /* Turn off monitoring of tbusy and tstop */ +/* +** TAB3 +*/ +#define RIOC_COR5_TAB3 0x10 /* TAB3 mode */ + +#define RIOC_COR5_HOST 0xc3 /* Safe host bits */ + +/* CCSR */ +#define RIOC_CCSR_TXFLOFF 0x04 /* Tx is xoffed */ + +/* MSVR1 */ +/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the + RTA. This is because otherwise DCD would get lost on the 1 parallel / 3 + serial option. +*/ +#define RIOC_MSVR1_CD 0x80 /* CD (DSR on Cirrus) */ +#define RIOC_MSVR1_RTS 0x40 /* RTS (CTS on Cirrus) */ +#define RIOC_MSVR1_RI 0x20 /* RI */ +#define RIOC_MSVR1_DTR 0x10 /* DTR (CD on Cirrus) */ +#define RIOC_MSVR1_CTS 0x01 /* CTS output pin (RTS on Cirrus) */ +/* Next two used to indicate state of tbusy and tstop to driver */ +#define RIOC_MSVR1_TSTOP 0x08 /* Set if port flow controlled */ +#define RIOC_MSVR1_TEMPTY 0x04 /* Set if port tx buffer empty */ + +#define RIOC_MSVR1_HOST 0xf3 /* The bits the host wants */ + +/* Defines for the subscripts of a CONFIG packet */ +#define RIOC_CONFIG_COR1 1 /* Option register 1 */ +#define RIOC_CONFIG_COR2 2 /* Option register 2 */ +#define RIOC_CONFIG_COR4 3 /* Option register 4 */ +#define RIOC_CONFIG_COR5 4 /* Option register 5 */ +#define RIOC_CONFIG_TXXON 5 /* Tx XON character */ +#define RIOC_CONFIG_TXXOFF 6 /* Tx XOFF character */ +#define RIOC_CONFIG_RXXON 7 /* Rx XON character */ +#define RIOC_CONFIG_RXXOFF 8 /* Rx XOFF character */ +#define RIOC_CONFIG_LNEXT 9 /* LNEXT character */ +#define RIOC_CONFIG_TXBAUD 10 /* Tx baud rate */ +#define RIOC_CONFIG_RXBAUD 11 /* Rx baud rate */ + +#define RIOC_PRE_EMPTIVE 0x80 /* Pre-emptive bit in command field */ + +/* Packet types going from Host to remote - with the exception of OPEN, MOPEN, + CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not + be used +*/ +#define RIOC_OPEN 0x00 /* Open a port */ +#define RIOC_CONFIG 0x01 /* Configure a port */ +#define RIOC_MOPEN 0x02 /* Modem open (block for DCD) */ +#define RIOC_CLOSE 0x03 /* Close a port */ +#define RIOC_WFLUSH (0x04 | RIOC_PRE_EMPTIVE) /* Write flush */ +#define RIOC_RFLUSH (0x05 | RIOC_PRE_EMPTIVE) /* Read flush */ +#define RIOC_RESUME (0x06 | RIOC_PRE_EMPTIVE) /* Resume if xoffed */ +#define RIOC_SBREAK 0x07 /* Start break */ +#define RIOC_EBREAK 0x08 /* End break */ +#define RIOC_SUSPEND (0x09 | RIOC_PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */ +#define RIOC_FCLOSE (0x0a | RIOC_PRE_EMPTIVE) /* Force close */ +#define RIOC_XPRINT 0x0b /* Xprint packet */ +#define RIOC_MBIS (0x0c | RIOC_PRE_EMPTIVE) /* Set modem lines */ +#define RIOC_MBIC (0x0d | RIOC_PRE_EMPTIVE) /* Clear modem lines */ +#define RIOC_MSET (0x0e | RIOC_PRE_EMPTIVE) /* Set modem lines */ +#define RIOC_PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */ +#define RIOC_MGET (0x10 | RIOC_PRE_EMPTIVE) /* Force update of modem status */ +#define RIOC_MEMDUMP (0x11 | RIOC_PRE_EMPTIVE) /* Send back mem from addr supplied */ +#define RIOC_READ_REGISTER (0x12 | RIOC_PRE_EMPTIVE) /* Read CD1400 register (debug) */ + +/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS + use data[4] / data[3] to indicate current state and modem status respectively +*/ + +#define RIOC_COMPLETE (0x20 | RIOC_PRE_EMPTIVE) + /* Command complete */ +#define RIOC_BREAK_RECEIVED (0x21 | RIOC_PRE_EMPTIVE) + /* Break received */ +#define RIOC_MODEM_STATUS (0x22 | RIOC_PRE_EMPTIVE) + /* Change in modem status */ + +/* "Command" packet that could go either way - handshake wake-up */ +#define RIOC_HANDSHAKE (0x23 | RIOC_PRE_EMPTIVE) + /* Wake-up to HOST / RTA */ + +#endif diff --git a/drivers/staging/generic_serial/rio/cmdblk.h b/drivers/staging/generic_serial/rio/cmdblk.h new file mode 100644 index 000000000000..9ed4f861675a --- /dev/null +++ b/drivers/staging/generic_serial/rio/cmdblk.h @@ -0,0 +1,53 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : cmdblk.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:09 +** Retrieved : 11/6/98 11:34:20 +** +** ident @(#)cmdblk.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_cmdblk_h__ +#define __rio_cmdblk_h__ + +/* +** the structure of a command block, used to queue commands destined for +** a rup. +*/ + +struct CmdBlk { + struct CmdBlk *NextP; /* Pointer to next command block */ + struct PKT Packet; /* A packet, to copy to the rup */ + /* The func to call to check if OK */ + int (*PreFuncP) (unsigned long, struct CmdBlk *); + int PreArg; /* The arg for the func */ + /* The func to call when completed */ + int (*PostFuncP) (unsigned long, struct CmdBlk *); + int PostArg; /* The arg for the func */ +}; + +#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4)) +#endif diff --git a/drivers/staging/generic_serial/rio/cmdpkt.h b/drivers/staging/generic_serial/rio/cmdpkt.h new file mode 100644 index 000000000000..c1e7a2798070 --- /dev/null +++ b/drivers/staging/generic_serial/rio/cmdpkt.h @@ -0,0 +1,177 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : cmdpkt.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:09 +** Retrieved : 11/6/98 11:34:20 +** +** ident @(#)cmdpkt.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ +#ifndef __rio_cmdpkt_h__ +#define __rio_cmdpkt_h__ + +/* +** overlays for the data area of a packet. Used in both directions +** (to build a packet to send, and to interpret a packet that arrives) +** and is very inconvenient for MIPS, so they appear as two separate +** structures - those used for modifying/reading packets on the card +** and those for modifying/reading packets in real memory, which have an _M +** suffix. +*/ + +#define RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2) + +/* +** The boot information packet looks like this: +** This structure overlays a PktCmd->CmdData structure, and so starts +** at Data[2] in the actual pkt! +*/ +struct BootSequence { + u16 NumPackets; + u16 LoadBase; + u16 CodeSize; +}; + +#define BOOT_SEQUENCE_LEN 8 + +struct SamTop { + u8 Unit; + u8 Link; +}; + +struct CmdHdr { + u8 PcCommand; + union { + u8 PcPhbNum; + u8 PcLinkNum; + u8 PcIDNum; + } U0; +}; + + +struct PktCmd { + union { + struct { + struct CmdHdr CmdHdr; + struct BootSequence PcBootSequence; + } S1; + struct { + u16 PcSequence; + u8 PcBootData[RTA_BOOT_DATA_SIZE]; + } S2; + struct { + u16 __crud__; + u8 PcUniqNum[4]; /* this is really a uint. */ + u8 PcModuleTypes; /* what modules are fitted */ + } S3; + struct { + struct CmdHdr CmdHdr; + u8 __undefined__; + u8 PcModemStatus; + u8 PcPortStatus; + u8 PcSubCommand; /* commands like mem or register dump */ + u16 PcSubAddr; /* Address for command */ + u8 PcSubData[64]; /* Date area for command */ + } S4; + struct { + struct CmdHdr CmdHdr; + u8 PcCommandText[1]; + u8 __crud__[20]; + u8 PcIDNum2; /* It had to go somewhere! */ + } S5; + struct { + struct CmdHdr CmdHdr; + struct SamTop Topology[LINKS_PER_UNIT]; + } S6; + } U1; +}; + +struct PktCmd_M { + union { + struct { + struct { + u8 PcCommand; + union { + u8 PcPhbNum; + u8 PcLinkNum; + u8 PcIDNum; + } U0; + } CmdHdr; + struct { + u16 NumPackets; + u16 LoadBase; + u16 CodeSize; + } PcBootSequence; + } S1; + struct { + u16 PcSequence; + u8 PcBootData[RTA_BOOT_DATA_SIZE]; + } S2; + struct { + u16 __crud__; + u8 PcUniqNum[4]; /* this is really a uint. */ + u8 PcModuleTypes; /* what modules are fitted */ + } S3; + struct { + u16 __cmd_hdr__; + u8 __undefined__; + u8 PcModemStatus; + u8 PcPortStatus; + u8 PcSubCommand; + u16 PcSubAddr; + u8 PcSubData[64]; + } S4; + struct { + u16 __cmd_hdr__; + u8 PcCommandText[1]; + u8 __crud__[20]; + u8 PcIDNum2; /* Tacked on end */ + } S5; + struct { + u16 __cmd_hdr__; + struct Top Topology[LINKS_PER_UNIT]; + } S6; + } U1; +}; + +#define Command U1.S1.CmdHdr.PcCommand +#define PhbNum U1.S1.CmdHdr.U0.PcPhbNum +#define IDNum U1.S1.CmdHdr.U0.PcIDNum +#define IDNum2 U1.S5.PcIDNum2 +#define LinkNum U1.S1.CmdHdr.U0.PcLinkNum +#define Sequence U1.S2.PcSequence +#define BootData U1.S2.PcBootData +#define BootSequence U1.S1.PcBootSequence +#define UniqNum U1.S3.PcUniqNum +#define ModemStatus U1.S4.PcModemStatus +#define PortStatus U1.S4.PcPortStatus +#define SubCommand U1.S4.PcSubCommand +#define SubAddr U1.S4.PcSubAddr +#define SubData U1.S4.PcSubData +#define CommandText U1.S5.PcCommandText +#define RouteTopology U1.S6.Topology +#define ModuleTypes U1.S3.PcModuleTypes + +#endif diff --git a/drivers/staging/generic_serial/rio/daemon.h b/drivers/staging/generic_serial/rio/daemon.h new file mode 100644 index 000000000000..4af90323fd00 --- /dev/null +++ b/drivers/staging/generic_serial/rio/daemon.h @@ -0,0 +1,307 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : daemon.h +** SID : 1.3 +** Last Modified : 11/6/98 11:34:09 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)daemon.h 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_daemon_h__ +#define __rio_daemon_h__ + + +/* +** structures used on /dev/rio +*/ + +struct Error { + unsigned int Error; + unsigned int Entry; + unsigned int Other; +}; + +struct DownLoad { + char __user *DataP; + unsigned int Count; + unsigned int ProductCode; +}; + +/* +** A few constants.... +*/ +#ifndef MAX_VERSION_LEN +#define MAX_VERSION_LEN 256 +#endif + +#ifndef MAX_XP_CTRL_LEN +#define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */ +#endif + +struct PortSetup { + unsigned int From; /* Set/Clear XP & IXANY Control from this port.... */ + unsigned int To; /* .... to this port */ + unsigned int XpCps; /* at this speed */ + char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */ + char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */ + u8 IxAny; /* enable/disable IXANY */ + u8 IxOn; /* enable/disable IXON */ + u8 Lock; /* lock port params */ + u8 Store; /* store params across closes */ + u8 Drain; /* close only when drained */ +}; + +struct LpbReq { + unsigned int Host; + unsigned int Link; + struct LPB __user *LpbP; +}; + +struct RupReq { + unsigned int HostNum; + unsigned int RupNum; + struct RUP __user *RupP; +}; + +struct PortReq { + unsigned int SysPort; + struct Port __user *PortP; +}; + +struct StreamInfo { + unsigned int SysPort; + int RQueue; + int WQueue; +}; + +struct HostReq { + unsigned int HostNum; + struct Host __user *HostP; +}; + +struct HostDpRam { + unsigned int HostNum; + struct DpRam __user *DpRamP; +}; + +struct DebugCtrl { + unsigned int SysPort; + unsigned int Debug; + unsigned int Wait; +}; + +struct MapInfo { + unsigned int FirstPort; /* 8 ports, starting from this (tty) number */ + unsigned int RtaUnique; /* reside on this RTA (unique number) */ +}; + +struct MapIn { + unsigned int NumEntries; /* How many port sets are we mapping? */ + struct MapInfo *MapInfoP; /* Pointer to (user space) info */ +}; + +struct SendPack { + unsigned int PortNum; + unsigned char Len; + unsigned char Data[PKT_MAX_DATA_LEN]; +}; + +struct SpecialRupCmd { + struct PKT Packet; + unsigned short Host; + unsigned short RupNum; +}; + +struct IdentifyRta { + unsigned long RtaUnique; + u8 ID; +}; + +struct KillNeighbour { + unsigned long UniqueNum; + u8 Link; +}; + +struct rioVersion { + char version[MAX_VERSION_LEN]; + char relid[MAX_VERSION_LEN]; + int buildLevel; + char buildDate[MAX_VERSION_LEN]; +}; + + +/* +** RIOC commands are for the daemon type operations +** +** 09.12.1998 ARG - ESIL 0776 part fix +** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a +** #ifndef here first. +** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now +** allowed to be used by customers. +*/ +#ifndef RIOC +#define RIOC ('R'<<8)|('i'<<16)|('o'<<24) +#endif + +/* +** Boot stuff +*/ +#define RIO_GET_TABLE (RIOC | 100) +#define RIO_PUT_TABLE (RIOC | 101) +#define RIO_ASSIGN_RTA (RIOC | 102) +#define RIO_DELETE_RTA (RIOC | 103) +#define RIO_HOST_FOAD (RIOC | 104) +#define RIO_QUICK_CHECK (RIOC | 105) +#define RIO_SIGNALS_ON (RIOC | 106) +#define RIO_SIGNALS_OFF (RIOC | 107) +#define RIO_CHANGE_NAME (RIOC | 108) +#define RIO_DOWNLOAD (RIOC | 109) +#define RIO_GET_LOG (RIOC | 110) +#define RIO_SETUP_PORTS (RIOC | 111) +#define RIO_ALL_MODEM (RIOC | 112) + +/* +** card state, debug stuff +*/ +#define RIO_NUM_HOSTS (RIOC | 120) +#define RIO_HOST_LPB (RIOC | 121) +#define RIO_HOST_RUP (RIOC | 122) +#define RIO_HOST_PORT (RIOC | 123) +#define RIO_PARMS (RIOC | 124) +#define RIO_HOST_REQ (RIOC | 125) +#define RIO_READ_CONFIG (RIOC | 126) +#define RIO_SET_CONFIG (RIOC | 127) +#define RIO_VERSID (RIOC | 128) +#define RIO_FLAGS (RIOC | 129) +#define RIO_SETDEBUG (RIOC | 130) +#define RIO_GETDEBUG (RIOC | 131) +#define RIO_READ_LEVELS (RIOC | 132) +#define RIO_SET_FAST_BUS (RIOC | 133) +#define RIO_SET_SLOW_BUS (RIOC | 134) +#define RIO_SET_BYTE_MODE (RIOC | 135) +#define RIO_SET_WORD_MODE (RIOC | 136) +#define RIO_STREAM_INFO (RIOC | 137) +#define RIO_START_POLLER (RIOC | 138) +#define RIO_STOP_POLLER (RIOC | 139) +#define RIO_LAST_ERROR (RIOC | 140) +#define RIO_TICK (RIOC | 141) +#define RIO_TOCK (RIOC | 241) /* I did this on purpose, you know. */ +#define RIO_SEND_PACKET (RIOC | 142) +#define RIO_SET_BUSY (RIOC | 143) +#define SPECIAL_RUP_CMD (RIOC | 144) +#define RIO_FOAD_RTA (RIOC | 145) +#define RIO_ZOMBIE_RTA (RIOC | 146) +#define RIO_IDENTIFY_RTA (RIOC | 147) +#define RIO_KILL_NEIGHBOUR (RIOC | 148) +#define RIO_DEBUG_MEM (RIOC | 149) +/* +** 150 - 167 used..... See below +*/ +#define RIO_GET_PORT_SETUP (RIOC | 168) +#define RIO_RESUME (RIOC | 169) +#define RIO_MESG (RIOC | 170) +#define RIO_NO_MESG (RIOC | 171) +#define RIO_WHAT_MESG (RIOC | 172) +#define RIO_HOST_DPRAM (RIOC | 173) +#define RIO_MAP_B50_TO_50 (RIOC | 174) +#define RIO_MAP_B50_TO_57600 (RIOC | 175) +#define RIO_MAP_B110_TO_110 (RIOC | 176) +#define RIO_MAP_B110_TO_115200 (RIOC | 177) +#define RIO_GET_PORT_PARAMS (RIOC | 178) +#define RIO_SET_PORT_PARAMS (RIOC | 179) +#define RIO_GET_PORT_TTY (RIOC | 180) +#define RIO_SET_PORT_TTY (RIOC | 181) +#define RIO_SYSLOG_ONLY (RIOC | 182) +#define RIO_SYSLOG_CONS (RIOC | 183) +#define RIO_CONS_ONLY (RIOC | 184) +#define RIO_BLOCK_OPENS (RIOC | 185) + +/* +** 02.03.1999 ARG - ESIL 0820 fix : +** RIOBootMode is no longer use by the driver, so these ioctls +** are now obsolete : +** +#define RIO_GET_BOOT_MODE (RIOC | 186) +#define RIO_SET_BOOT_MODE (RIOC | 187) +** +*/ + +#define RIO_MEM_DUMP (RIOC | 189) +#define RIO_READ_REGISTER (RIOC | 190) +#define RIO_GET_MODTYPE (RIOC | 191) +#define RIO_SET_TIMER (RIOC | 192) +#define RIO_READ_CHECK (RIOC | 196) +#define RIO_WAITING_FOR_RESTART (RIOC | 197) +#define RIO_BIND_RTA (RIOC | 198) +#define RIO_GET_BINDINGS (RIOC | 199) +#define RIO_PUT_BINDINGS (RIOC | 200) + +#define RIO_MAKE_DEV (RIOC | 201) +#define RIO_MINOR (RIOC | 202) + +#define RIO_IDENTIFY_DRIVER (RIOC | 203) +#define RIO_DISPLAY_HOST_CFG (RIOC | 204) + + +/* +** MAKE_DEV / MINOR stuff +*/ +#define RIO_DEV_DIRECT 0x0000 +#define RIO_DEV_MODEM 0x0200 +#define RIO_DEV_XPRINT 0x0400 +#define RIO_DEV_MASK 0x0600 + +/* +** port management, xprint stuff +*/ +#define rIOCN(N) (RIOC|(N)) +#define rIOCR(N,T) (RIOC|(N)) +#define rIOCW(N,T) (RIOC|(N)) + +#define RIO_GET_XP_ON rIOCR(150,char[16]) /* start xprint string */ +#define RIO_SET_XP_ON rIOCW(151,char[16]) +#define RIO_GET_XP_OFF rIOCR(152,char[16]) /* finish xprint string */ +#define RIO_SET_XP_OFF rIOCW(153,char[16]) +#define RIO_GET_XP_CPS rIOCR(154,int) /* xprint CPS */ +#define RIO_SET_XP_CPS rIOCW(155,int) +#define RIO_GET_IXANY rIOCR(156,int) /* ixany allowed? */ +#define RIO_SET_IXANY rIOCW(157,int) +#define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */ +#define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */ +#define RIO_GET_MODEM rIOCR(160,int) /* port is modem/direct line? */ +#define RIO_SET_MODEM rIOCW(161,int) +#define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */ +#define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */ +#define RIO_GET_IXON rIOCR(164,int) /* ixon allowed? */ +#define RIO_SET_IXON rIOCW(165,int) +#define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */ +#define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */ + +#define RIO_GET_SIVIEW ((('s')<<8) | 106) /* backwards compatible with SI */ + +#define RIO_IOCTL_UNKNOWN -2 + +#endif diff --git a/drivers/staging/generic_serial/rio/errors.h b/drivers/staging/generic_serial/rio/errors.h new file mode 100644 index 000000000000..bdb05234090a --- /dev/null +++ b/drivers/staging/generic_serial/rio/errors.h @@ -0,0 +1,98 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : errors.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:10 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)errors.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_errors_h__ +#define __rio_errors_h__ + +/* +** error codes +*/ + +#define NOTHING_WRONG_AT_ALL 0 +#define BAD_CHARACTER_IN_NAME 1 +#define TABLE_ENTRY_ISNT_PROPERLY_NULL 2 +#define UNKNOWN_HOST_NUMBER 3 +#define ZERO_RTA_ID 4 +#define BAD_RTA_ID 5 +#define DUPLICATED_RTA_ID 6 +#define DUPLICATE_UNIQUE_NUMBER 7 +#define BAD_TTY_NUMBER 8 +#define TTY_NUMBER_IN_USE 9 +#define NAME_USED_TWICE 10 +#define HOST_ID_NOT_ZERO 11 +#define BOOT_IN_PROGRESS 12 +#define COPYIN_FAILED 13 +#define HOST_FILE_TOO_LARGE 14 +#define COPYOUT_FAILED 15 +#define NOT_SUPER_USER 16 +#define RIO_ALREADY_POLLING 17 + +#define ID_NUMBER_OUT_OF_RANGE 18 +#define PORT_NUMBER_OUT_OF_RANGE 19 +#define HOST_NUMBER_OUT_OF_RANGE 20 +#define RUP_NUMBER_OUT_OF_RANGE 21 +#define TTY_NUMBER_OUT_OF_RANGE 22 +#define LINK_NUMBER_OUT_OF_RANGE 23 + +#define HOST_NOT_RUNNING 24 +#define IOCTL_COMMAND_UNKNOWN 25 +#define RIO_SYSTEM_HALTED 26 +#define WAIT_FOR_DRAIN_BROKEN 27 +#define PORT_NOT_MAPPED_INTO_SYSTEM 28 +#define EXCLUSIVE_USE_SET 29 +#define WAIT_FOR_NOT_CLOSING_BROKEN 30 +#define WAIT_FOR_PORT_TO_OPEN_BROKEN 31 +#define WAIT_FOR_CARRIER_BROKEN 32 +#define WAIT_FOR_NOT_IN_USE_BROKEN 33 +#define WAIT_FOR_CAN_ADD_COMMAND_BROKEN 34 +#define WAIT_FOR_ADD_COMMAND_BROKEN 35 +#define WAIT_FOR_NOT_PARAM_BROKEN 36 +#define WAIT_FOR_RETRY_BROKEN 37 +#define HOST_HAS_ALREADY_BEEN_BOOTED 38 +#define UNIT_IS_IN_USE 39 +#define COULDNT_FIND_ENTRY 40 +#define RTA_UNIQUE_NUMBER_ZERO 41 +#define CLOSE_COMMAND_FAILED 42 +#define WAIT_FOR_CLOSE_BROKEN 43 +#define CPS_VALUE_OUT_OF_RANGE 44 +#define ID_ALREADY_IN_USE 45 +#define SIGNALS_ALREADY_SET 46 +#define NOT_RECEIVING_PROCESS 47 +#define RTA_NUMBER_WRONG 48 +#define NO_SUCH_PRODUCT 49 +#define HOST_SYSPORT_BAD 50 +#define ID_NOT_TENTATIVE 51 +#define XPRINT_CPS_OUT_OF_RANGE 52 +#define NOT_ENOUGH_CORE_FOR_PCI_COPY 53 + + +#endif /* __rio_errors_h__ */ diff --git a/drivers/staging/generic_serial/rio/func.h b/drivers/staging/generic_serial/rio/func.h new file mode 100644 index 000000000000..078d44f85e45 --- /dev/null +++ b/drivers/staging/generic_serial/rio/func.h @@ -0,0 +1,143 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : func.h +** SID : 1.3 +** Last Modified : 11/6/98 11:34:10 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)func.h 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __func_h_def +#define __func_h_def + +#include + +/* rioboot.c */ +int RIOBootCodeRTA(struct rio_info *, struct DownLoad *); +int RIOBootCodeHOST(struct rio_info *, struct DownLoad *); +int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *); +void msec_timeout(struct Host *); +int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *); +int RIOBootOk(struct rio_info *, struct Host *, unsigned long); +int RIORtaBound(struct rio_info *, unsigned int); +void rio_fill_host_slot(int, int, unsigned int, struct Host *); + +/* riocmd.c */ +int RIOFoadRta(struct Host *, struct Map *); +int RIOZombieRta(struct Host *, struct Map *); +int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *)); +int RIOIdentifyRta(struct rio_info *, void __user *); +int RIOKillNeighbour(struct rio_info *, void __user *); +int RIOSuspendBootRta(struct Host *, int, int); +int RIOFoadWakeup(struct rio_info *); +struct CmdBlk *RIOGetCmdBlk(void); +void RIOFreeCmdBlk(struct CmdBlk *); +int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *); +void RIOPollHostCommands(struct rio_info *, struct Host *); +int RIOWFlushMark(unsigned long, struct CmdBlk *); +int RIORFlushEnable(unsigned long, struct CmdBlk *); +int RIOUnUse(unsigned long, struct CmdBlk *); + +/* rioctrl.c */ +int riocontrol(struct rio_info *, dev_t, int, unsigned long, int); + +int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char); + +/* rioinit.c */ +void rioinit(struct rio_info *, struct RioHostInfo *); +void RIOInitHosts(struct rio_info *, struct RioHostInfo *); +void RIOISAinit(struct rio_info *, int); +int RIODoAT(struct rio_info *, int, int); +caddr_t RIOCheckForATCard(int); +int RIOAssignAT(struct rio_info *, int, void __iomem *, int); +int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int); +void RIOAllocDataStructs(struct rio_info *); +void RIOSetupDataStructs(struct rio_info *); +int RIODefaultName(struct rio_info *, struct Host *, unsigned int); +struct rioVersion *RIOVersid(void); +void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int); + +/* riointr.c */ +void RIOTxEnable(char *); +void RIOServiceHost(struct rio_info *, struct Host *); +int riotproc(struct rio_info *, struct ttystatics *, int, int); + +/* rioparam.c */ +int RIOParam(struct Port *, int, int, int); +int RIODelay(struct Port *PortP, int); +int RIODelay_ni(struct Port *PortP, int); +void ms_timeout(struct Port *); +int can_add_transmit(struct PKT __iomem **, struct Port *); +void add_transmit(struct Port *); +void put_free_end(struct Host *, struct PKT __iomem *); +int can_remove_receive(struct PKT __iomem **, struct Port *); +void remove_receive(struct Port *); + +/* rioroute.c */ +int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *); +void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int); +unsigned int GetUnitType(unsigned int); +int RIOSetChange(struct rio_info *); +int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *); + + +/* riotty.c */ + +int riotopen(struct tty_struct *tty, struct file *filp); +int riotclose(void *ptr); +int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t); +void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg); + +/* riotable.c */ +int RIONewTable(struct rio_info *); +int RIOApel(struct rio_info *); +int RIODeleteRta(struct rio_info *, struct Map *); +int RIOAssignRta(struct rio_info *, struct Map *); +int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *); +int RIOChangeName(struct rio_info *, struct Map *); + +#if 0 +/* riodrvr.c */ +struct rio_info *rio_install(struct RioHostInfo *); +int rio_uninstall(struct rio_info *); +int rio_open(struct rio_info *, int, struct file *); +int rio_close(struct rio_info *, struct file *); +int rio_read(struct rio_info *, struct file *, char *, int); +int rio_write(struct rio_info *, struct file *f, char *, int); +int rio_ioctl(struct rio_info *, struct file *, int, char *); +int rio_select(struct rio_info *, struct file *f, int, struct sel *); +int rio_intr(char *); +int rio_isr_thread(char *); +struct rio_info *rio_info_store(int cmd, struct rio_info *p); +#endif + +extern void rio_copy_to_card(void *from, void __iomem *to, int len); +extern int rio_minor(struct tty_struct *tty); +extern int rio_ismodem(struct tty_struct *tty); + +extern void rio_start_card_running(struct Host *HostP); + +#endif /* __func_h_def */ diff --git a/drivers/staging/generic_serial/rio/host.h b/drivers/staging/generic_serial/rio/host.h new file mode 100644 index 000000000000..78f24540c224 --- /dev/null +++ b/drivers/staging/generic_serial/rio/host.h @@ -0,0 +1,123 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : host.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:10 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)host.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_host_h__ +#define __rio_host_h__ + +/* +** the host structure - one per host card in the system. +*/ + +#define MAX_EXTRA_UNITS 64 + +/* +** Host data structure. This is used for the software equiv. of +** the host. +*/ +struct Host { + struct pci_dev *pdev; + unsigned char Type; /* RIO_EISA, RIO_MCA, ... */ + unsigned char Ivec; /* POLLED or ivec number */ + unsigned char Mode; /* Control stuff */ + unsigned char Slot; /* Slot */ + void __iomem *Caddr; /* KV address of DPRAM */ + struct DpRam __iomem *CardP; /* KV address of DPRAM, with overlay */ + unsigned long PaddrP; /* Phys. address of DPRAM */ + char Name[MAX_NAME_LEN]; /* The name of the host */ + unsigned int UniqueNum; /* host unique number */ + spinlock_t HostLock; /* Lock structure for MPX */ + unsigned int WorkToBeDone; /* set to true each interrupt */ + unsigned int InIntr; /* Being serviced? */ + unsigned int IntSrvDone; /* host's interrupt has been serviced */ + void (*Copy) (void *, void __iomem *, int); /* copy func */ + struct timer_list timer; + /* + ** I M P O R T A N T ! + ** + ** The rest of this data structure is cleared to zero after + ** a RIO_HOST_FOAD command. + */ + + unsigned long Flags; /* Whats going down */ +#define RC_WAITING 0 +#define RC_STARTUP 1 +#define RC_RUNNING 2 +#define RC_STUFFED 3 +#define RC_READY 7 +#define RUN_STATE 7 +/* +** Boot mode applies to the way in which hosts in this system will +** boot RTAs +*/ +#define RC_BOOT_ALL 0x8 /* Boot all RTAs attached */ +#define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */ +#define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */ + + struct Top Topology[LINKS_PER_UNIT]; /* one per link */ + struct Map Mapping[MAX_RUP]; /* Mappings for host */ + struct PHB __iomem *PhbP; /* Pointer to the PHB array */ + unsigned short __iomem *PhbNumP; /* Ptr to Number of PHB's */ + struct LPB __iomem *LinkStrP; /* Link Structure Array */ + struct RUP __iomem *RupP; /* Sixteen real rups here */ + struct PARM_MAP __iomem *ParmMapP; /* points to the parmmap */ + unsigned int ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */ + unsigned int NumExtraBooted; /* how many of the above */ + /* + ** Twenty logical rups. + ** The first sixteen are the real Rup entries (above), the last four + ** are the link RUPs. + */ + struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT]; + int timeout_id; /* For calling 100 ms delays */ + int timeout_sem; /* For calling 100 ms delays */ + unsigned long locks; /* long req'd for set_bit --RR */ + char ____end_marker____; +}; +#define Control CardP->DpControl +#define SetInt CardP->DpSetInt +#define ResetTpu CardP->DpResetTpu +#define ResetInt CardP->DpResetInt +#define Signature CardP->DpSignature +#define Sram1 CardP->DpSram1 +#define Sram2 CardP->DpSram2 +#define Sram3 CardP->DpSram3 +#define Scratch CardP->DpScratch +#define __ParmMapR CardP->DpParmMapR +#define SLX CardP->DpSlx +#define Revision CardP->DpRevision +#define Unique CardP->DpUnique +#define Year CardP->DpYear +#define Week CardP->DpWeek + +#define RIO_DUMBPARM 0x0860 /* what not to expect */ + +#endif diff --git a/drivers/staging/generic_serial/rio/link.h b/drivers/staging/generic_serial/rio/link.h new file mode 100644 index 000000000000..f3bf11a04d41 --- /dev/null +++ b/drivers/staging/generic_serial/rio/link.h @@ -0,0 +1,96 @@ +/**************************************************************************** + ******* ******* + ******* L I N K + ******* ******* + **************************************************************************** + + Author : Ian Nandhra / Jeremy Rolls + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _link_h +#define _link_h 1 + +/************************************************* + * Define the Link Status stuff + ************************************************/ +/* Boot request stuff */ +#define BOOT_REQUEST ((ushort) 0) /* Request for a boot */ +#define BOOT_ABORT ((ushort) 1) /* Abort a boot */ +#define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets + and load address */ +#define BOOT_COMPLETED ((ushort) 3) /* Boot completed */ + + +struct LPB { + u16 link_number; /* Link Number */ + u16 in_ch; /* Link In Channel */ + u16 out_ch; /* Link Out Channel */ + u8 attached_serial[4]; /* Attached serial number */ + u8 attached_host_serial[4]; + /* Serial number of Host who + booted the other end */ + u16 descheduled; /* Currently Descheduled */ + u16 state; /* Current state */ + u16 send_poll; /* Send a Poll Packet */ + u16 ltt_p; /* Process Descriptor */ + u16 lrt_p; /* Process Descriptor */ + u16 lrt_status; /* Current lrt status */ + u16 ltt_status; /* Current ltt status */ + u16 timeout; /* Timeout value */ + u16 topology; /* Topology bits */ + u16 mon_ltt; + u16 mon_lrt; + u16 WaitNoBoot; /* Secs to hold off booting */ + u16 add_packet_list; /* Add packets to here */ + u16 remove_packet_list; /* Send packets from here */ + + u16 lrt_fail_chan; /* Lrt's failure channel */ + u16 ltt_fail_chan; /* Ltt's failure channel */ + + /* RUP structure for HOST to driver communications */ + struct RUP rup; + struct RUP link_rup; /* RUP for the link (POLL, + topology etc.) */ + u16 attached_link; /* Number of attached link */ + u16 csum_errors; /* csum errors */ + u16 num_disconnects; /* number of disconnects */ + u16 num_sync_rcvd; /* # sync's received */ + u16 num_sync_rqst; /* # sync requests */ + u16 num_tx; /* Num pkts sent */ + u16 num_rx; /* Num pkts received */ + u16 module_attached; /* Module tpyes of attached */ + u16 led_timeout; /* LED timeout */ + u16 first_port; /* First port to service */ + u16 last_port; /* Last port to service */ +}; + +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/linux_compat.h b/drivers/staging/generic_serial/rio/linux_compat.h new file mode 100644 index 000000000000..34c0d2899ef1 --- /dev/null +++ b/drivers/staging/generic_serial/rio/linux_compat.h @@ -0,0 +1,77 @@ +/* + * (C) 2000 R.E.Wolff@BitWizard.nl + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + + +#define DEBUG_ALL + +struct ttystatics { + struct termios tm; +}; + +extern int rio_debug; + +#define RIO_DEBUG_INIT 0x000001 +#define RIO_DEBUG_BOOT 0x000002 +#define RIO_DEBUG_CMD 0x000004 +#define RIO_DEBUG_CTRL 0x000008 +#define RIO_DEBUG_INTR 0x000010 +#define RIO_DEBUG_PARAM 0x000020 +#define RIO_DEBUG_ROUTE 0x000040 +#define RIO_DEBUG_TABLE 0x000080 +#define RIO_DEBUG_TTY 0x000100 +#define RIO_DEBUG_FLOW 0x000200 +#define RIO_DEBUG_MODEMSIGNALS 0x000400 +#define RIO_DEBUG_PROBE 0x000800 +#define RIO_DEBUG_CLEANUP 0x001000 +#define RIO_DEBUG_IFLOW 0x002000 +#define RIO_DEBUG_PFE 0x004000 +#define RIO_DEBUG_REC 0x008000 +#define RIO_DEBUG_SPINLOCK 0x010000 +#define RIO_DEBUG_DELAY 0x020000 +#define RIO_DEBUG_MOD_COUNT 0x040000 + + +/* Copied over from riowinif.h . This is ugly. The winif file declares +also much other stuff which is incompatible with the headers from +the older driver. The older driver includes "brates.h" which shadows +the definitions from Linux, and is incompatible... */ + +/* RxBaud and TxBaud definitions... */ +#define RIO_B0 0x00 /* RTS / DTR signals dropped */ +#define RIO_B50 0x01 /* 50 baud */ +#define RIO_B75 0x02 /* 75 baud */ +#define RIO_B110 0x03 /* 110 baud */ +#define RIO_B134 0x04 /* 134.5 baud */ +#define RIO_B150 0x05 /* 150 baud */ +#define RIO_B200 0x06 /* 200 baud */ +#define RIO_B300 0x07 /* 300 baud */ +#define RIO_B600 0x08 /* 600 baud */ +#define RIO_B1200 0x09 /* 1200 baud */ +#define RIO_B1800 0x0A /* 1800 baud */ +#define RIO_B2400 0x0B /* 2400 baud */ +#define RIO_B4800 0x0C /* 4800 baud */ +#define RIO_B9600 0x0D /* 9600 baud */ +#define RIO_B19200 0x0E /* 19200 baud */ +#define RIO_B38400 0x0F /* 38400 baud */ +#define RIO_B56000 0x10 /* 56000 baud */ +#define RIO_B57600 0x11 /* 57600 baud */ +#define RIO_B64000 0x12 /* 64000 baud */ +#define RIO_B115200 0x13 /* 115200 baud */ +#define RIO_B2000 0x14 /* 2000 baud */ diff --git a/drivers/staging/generic_serial/rio/map.h b/drivers/staging/generic_serial/rio/map.h new file mode 100644 index 000000000000..8366978578c1 --- /dev/null +++ b/drivers/staging/generic_serial/rio/map.h @@ -0,0 +1,98 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : map.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:11 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)map.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_map_h__ +#define __rio_map_h__ + +/* +** mapping structure passed to and from the config.rio program to +** determine the current topology of the world +*/ + +#define MAX_MAP_ENTRY 17 +#define TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS) +#define MAX_NAME_LEN 32 + +struct Map { + unsigned int HostUniqueNum; /* Supporting hosts unique number */ + unsigned int RtaUniqueNum; /* Unique number */ + /* + ** The next two IDs must be swapped on big-endian architectures + ** when using a v2.04 /etc/rio/config with a v3.00 driver (when + ** upgrading for example). + */ + unsigned short ID; /* ID used in the subnet */ + unsigned short ID2; /* ID of 2nd block of 8 for 16 port */ + unsigned long Flags; /* Booted, ID Given, Disconnected */ + unsigned long SysPort; /* First tty mapped to this port */ + struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */ + char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */ +}; + +/* +** Flag values: +*/ +#define RTA_BOOTED 0x00000001 +#define RTA_NEWBOOT 0x00000010 +#define MSG_DONE 0x00000020 +#define RTA_INTERCONNECT 0x00000040 +#define RTA16_SECOND_SLOT 0x00000080 +#define BEEN_HERE 0x00000100 +#define SLOT_TENTATIVE 0x40000000 +#define SLOT_IN_USE 0x80000000 + +/* +** HostUniqueNum is the unique number from the host card that this RTA +** is to be connected to. +** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO +** if the slot in the table is unused. If it is the same as the HostUniqueNum +** then this slot represents a host card. +** Flags contains current boot/route state info +** SysPort is a value in the range 0-504, being the number of the first tty +** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8. +** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor +** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256, +** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511 +** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an +** unused slot/unknown ID etc. +** The Topology array contains the ID of the unit connected to each of the +** four links on this unit. The entry will be 0xFFFF if NOTHING is connected +** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link. +** The Name field is a null-terminated string, upto 31 characters, containing +** the 'cute' name that the sysadmin/users know the RTA by. It is permissible +** for this string to contain any character in the range \040 to \176 inclusive. +** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The +** special character '%' IS allowable, and needs no special action. +** +*/ + +#endif diff --git a/drivers/staging/generic_serial/rio/param.h b/drivers/staging/generic_serial/rio/param.h new file mode 100644 index 000000000000..7e9b6283e8aa --- /dev/null +++ b/drivers/staging/generic_serial/rio/param.h @@ -0,0 +1,55 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : param.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:12 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)param.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_param_h__ +#define __rio_param_h__ + +/* +** the param command block, as used in OPEN and PARAM calls. +*/ + +struct phb_param { + u8 Cmd; /* It is very important that these line up */ + u8 Cor1; /* with what is expected at the other end. */ + u8 Cor2; /* to confirm that you've got it right, */ + u8 Cor4; /* check with cirrus/cirrus.h */ + u8 Cor5; + u8 TxXon; /* Transmit X-On character */ + u8 TxXoff; /* Transmit X-Off character */ + u8 RxXon; /* Receive X-On character */ + u8 RxXoff; /* Receive X-Off character */ + u8 LNext; /* Literal-next character */ + u8 TxBaud; /* Transmit baudrate */ + u8 RxBaud; /* Receive baudrate */ +}; + +#endif diff --git a/drivers/staging/generic_serial/rio/parmmap.h b/drivers/staging/generic_serial/rio/parmmap.h new file mode 100644 index 000000000000..acc8fa439df5 --- /dev/null +++ b/drivers/staging/generic_serial/rio/parmmap.h @@ -0,0 +1,81 @@ +/**************************************************************************** + ******* ******* + ******* H O S T M E M O R Y M A P + ******* ******* + **************************************************************************** + + Author : Ian Nandhra / Jeremy Rolls + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- +6/4/1991 jonb Made changes to accommodate Mips R3230 bus + ***************************************************************************/ + +#ifndef _parmap_h +#define _parmap_h + +typedef struct PARM_MAP PARM_MAP; + +struct PARM_MAP { + u16 phb_ptr; /* Pointer to the PHB array */ + u16 phb_num_ptr; /* Ptr to Number of PHB's */ + u16 free_list; /* Free List pointer */ + u16 free_list_end; /* Free List End pointer */ + u16 q_free_list_ptr; /* Ptr to Q_BUF variable */ + u16 unit_id_ptr; /* Unit Id */ + u16 link_str_ptr; /* Link Structure Array */ + u16 bootloader_1; /* 1st Stage Boot Loader */ + u16 bootloader_2; /* 2nd Stage Boot Loader */ + u16 port_route_map_ptr; /* Port Route Map */ + u16 route_ptr; /* Unit Route Map */ + u16 map_present; /* Route Map present */ + s16 pkt_num; /* Total number of packets */ + s16 q_num; /* Total number of Q packets */ + u16 buffers_per_port; /* Number of buffers per port */ + u16 heap_size; /* Initial size of heap */ + u16 heap_left; /* Current Heap left */ + u16 error; /* Error code */ + u16 tx_max; /* Max number of tx pkts per phb */ + u16 rx_max; /* Max number of rx pkts per phb */ + u16 rx_limit; /* For high / low watermarks */ + s16 links; /* Links to use */ + s16 timer; /* Interrupts per second */ + u16 rups; /* Pointer to the RUPs */ + u16 max_phb; /* Mostly for debugging */ + u16 living; /* Just increments!! */ + u16 init_done; /* Initialisation over */ + u16 booting_link; + u16 idle_count; /* Idle time counter */ + u16 busy_count; /* Busy counter */ + u16 idle_control; /* Control Idle Process */ + u16 tx_intr; /* TX interrupt pending */ + u16 rx_intr; /* RX interrupt pending */ + u16 rup_intr; /* RUP interrupt pending */ +}; + +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/pci.h b/drivers/staging/generic_serial/rio/pci.h new file mode 100644 index 000000000000..6032f9135956 --- /dev/null +++ b/drivers/staging/generic_serial/rio/pci.h @@ -0,0 +1,72 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : pci.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:12 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)pci.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_pci_h__ +#define __rio_pci_h__ + +/* +** PCI stuff +*/ + +#define PCITpFastClock 0x80 +#define PCITpSlowClock 0x00 +#define PCITpFastLinks 0x40 +#define PCITpSlowLinks 0x00 +#define PCITpIntEnable 0x04 +#define PCITpIntDisable 0x00 +#define PCITpBusEnable 0x02 +#define PCITpBusDisable 0x00 +#define PCITpBootFromRam 0x01 +#define PCITpBootFromLink 0x00 + +#define RIO_PCI_VENDOR 0x11CB +#define RIO_PCI_DEVICE 0x8000 +#define RIO_PCI_BASE_CLASS 0x02 +#define RIO_PCI_SUB_CLASS 0x80 +#define RIO_PCI_PROG_IFACE 0x00 + +#define RIO_PCI_RID 0x0008 +#define RIO_PCI_BADR0 0x0010 +#define RIO_PCI_INTLN 0x003C +#define RIO_PCI_INTPIN 0x003D + +#define RIO_PCI_MEM_SIZE 65536 + +#define RIO_PCI_TURBO_TP 0x80 +#define RIO_PCI_FAST_LINKS 0x40 +#define RIO_PCI_INT_ENABLE 0x04 +#define RIO_PCI_TP_BUS_ENABLE 0x02 +#define RIO_PCI_BOOT_FROM_RAM 0x01 + +#define RIO_PCI_DEFAULT_MODE 0x05 + +#endif /* __rio_pci_h__ */ diff --git a/drivers/staging/generic_serial/rio/phb.h b/drivers/staging/generic_serial/rio/phb.h new file mode 100644 index 000000000000..a4c48ae4e365 --- /dev/null +++ b/drivers/staging/generic_serial/rio/phb.h @@ -0,0 +1,142 @@ +/**************************************************************************** + ******* ******* + ******* P H B H E A D E R ******* + ******* ******* + **************************************************************************** + + Author : Ian Nandhra, Jeremy Rolls + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _phb_h +#define _phb_h 1 + +/************************************************* + * Handshake asserted. Deasserted by the LTT(s) + ************************************************/ +#define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */ + +#define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */ + +#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET) + /* Reset by ltt */ + + +/************************************************* + * Maximum number of PHB's + ************************************************/ +#define MAX_PHB ((ushort) 128) /* range 0-127 */ + +/************************************************* + * Defines for the mode fields + ************************************************/ +#define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */ +#define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */ +#define TX_TAB3 0x0004 /* TAB3 mode */ +#define TX_OCRNL 0x0008 /* OCRNL mode */ +#define TX_ONLCR 0x0010 /* ONLCR mode */ +#define TX_SENDSPACES 0x0020 /* Send n spaces command needs + completing */ +#define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */ +#define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */ +#define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel + port */ +#define TX_HANGOVER (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL) +#define TX_DTRFLOW 0x0200 /* DTR tx flow control */ +#define TX_DTRFLOWED 0x0400 /* DTR is low - don't allow more data + into the FIFO */ +#define TX_DATAINFIFO 0x0800 /* There is data in the FIFO */ +#define TX_BUSY 0x1000 /* Data in FIFO, shift or holding regs */ + +#define RX_SPARE 0x0001 /* SPARE */ +#define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */ +#define RX_ICRNL 0x0008 /* ICRNL mode */ +#define RX_INLCR 0x0010 /* INLCR mode */ +#define RX_IGNCR 0x0020 /* IGNCR mode */ +#define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */ +#define RX_IXOFF 0x0080 /* IXOFF enabled */ +#define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */ +#define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */ +#define RX_BUFFERED 0x0400 /* Try and pass on complete packets */ + +#define PORT_ISOPEN 0x0001 /* Port open? */ +#define PORT_HUPCL 0x0002 /* Hangup on close? */ +#define PORT_MOPENPEND 0x0004 /* Modem open pending */ +#define PORT_ISPARALLEL 0x0008 /* Parallel port */ +#define PORT_BREAK 0x0010 /* Port on break */ +#define PORT_STATUSPEND 0x0020 /* Status packet pending */ +#define PORT_BREAKPEND 0x0040 /* Break packet pending */ +#define PORT_MODEMPEND 0x0080 /* Modem status packet pending */ +#define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel + port */ +#define PORT_FULLMODEM 0x0200 /* Full modem signals */ +#define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */ +#define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */ + +#define PORT_MODEMBITS 0x0600 /* Mask for modem fields */ + +#define PORT_WCLOSE 0x0800 /* Waiting for close */ +#define PORT_HANDSHAKEFIX 0x1000 /* Port has H/W flow control fix */ +#define PORT_WASPCLOSED 0x2000 /* Port closed with PCLOSE */ +#define DUMPMODE 0x4000 /* Dump RTA mem */ +#define READ_REG 0x8000 /* Read CD1400 register */ + + + +/************************************************************************** + * PHB Structure + * A few words. + * + * Normally Packets are added to the end of the list and removed from + * the start. The pointer tx_add points to a SPACE to put a Packet. + * The pointer tx_remove points to the next Packet to remove + *************************************************************************/ + +struct PHB { + u8 source; + u8 handshake; + u8 status; + u16 timeout; /* Maximum of 1.9 seconds */ + u8 link; /* Send down this link */ + u8 destination; + u16 tx_start; + u16 tx_end; + u16 tx_add; + u16 tx_remove; + + u16 rx_start; + u16 rx_end; + u16 rx_add; + u16 rx_remove; + +}; + +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/pkt.h b/drivers/staging/generic_serial/rio/pkt.h new file mode 100644 index 000000000000..a9458164f02f --- /dev/null +++ b/drivers/staging/generic_serial/rio/pkt.h @@ -0,0 +1,77 @@ +/**************************************************************************** + ******* ******* + ******* P A C K E T H E A D E R F I L E + ******* ******* + **************************************************************************** + + Author : Ian Nandhra / Jeremy Rolls + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _pkt_h +#define _pkt_h 1 + +#define PKT_CMD_BIT ((ushort) 0x080) +#define PKT_CMD_DATA ((ushort) 0x080) + +#define PKT_ACK ((ushort) 0x040) + +#define PKT_TGL ((ushort) 0x020) + +#define PKT_LEN_MASK ((ushort) 0x07f) + +#define DATA_WNDW ((ushort) 0x10) +#define PKT_TTL_MASK ((ushort) 0x0f) + +#define PKT_MAX_DATA_LEN 72 + +#define PKT_LENGTH sizeof(struct PKT) +#define SYNC_PKT_LENGTH (PKT_LENGTH + 4) + +#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK +#define CONTROL_PKT_CMD_BIT PKT_CMD_BIT +#define CONTROL_PKT_ACK (PKT_ACK << 8) +#define CONTROL_PKT_TGL (PKT_TGL << 8) +#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8) +#define CONTROL_DATA_WNDW (DATA_WNDW << 8) + +struct PKT { + u8 dest_unit; /* Destination Unit Id */ + u8 dest_port; /* Destination POrt */ + u8 src_unit; /* Source Unit Id */ + u8 src_port; /* Source POrt */ + u8 len; + u8 control; + u8 data[PKT_MAX_DATA_LEN]; + /* Actual data :-) */ + u16 csum; /* C-SUM */ +}; +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/port.h b/drivers/staging/generic_serial/rio/port.h new file mode 100644 index 000000000000..49cf6d15ee54 --- /dev/null +++ b/drivers/staging/generic_serial/rio/port.h @@ -0,0 +1,179 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : port.h +** SID : 1.3 +** Last Modified : 11/6/98 11:34:12 +** Retrieved : 11/6/98 11:34:21 +** +** ident @(#)port.h 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_port_h__ +#define __rio_port_h__ + +/* +** Port data structure +*/ +struct Port { + struct gs_port gs; + int PortNum; /* RIO port no., 0-511 */ + struct Host *HostP; + void __iomem *Caddr; + unsigned short HostPort; /* Port number on host card */ + unsigned char RupNum; /* Number of RUP for port */ + unsigned char ID2; /* Second ID of RTA for port */ + unsigned long State; /* FLAGS for open & xopen */ +#define RIO_LOPEN 0x00001 /* Local open */ +#define RIO_MOPEN 0x00002 /* Modem open */ +#define RIO_WOPEN 0x00004 /* Waiting for open */ +#define RIO_CLOSING 0x00008 /* The port is being close */ +#define RIO_XPBUSY 0x00010 /* Transparent printer busy */ +#define RIO_BREAKING 0x00020 /* Break in progress */ +#define RIO_DIRECT 0x00040 /* Doing Direct output */ +#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */ +#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */ +#define RIO_CARR_ON 0x00200 /* Stream has carrier present */ +#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */ +#define RIO_RBLK 0x00800 /* Stream is read-blocked */ +#define RIO_BUSY 0x01000 /* Stream is BUSY for write */ +#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */ +#define RIO_TXSTOP 0x04000 /* Stream output is stopped */ +#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */ +#define RIO_DYNOROD 0x10000 /* Drain failed */ +#define RIO_DELETED 0x20000 /* RTA has been deleted */ +#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */ +#define RIO_USING_EUC 0x100000 /* Using extended Unix chars */ +#define RIO_CAN_COOK 0x200000 /* This line can do cooking */ +#define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */ +#define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */ +#define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */ +#define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */ + + unsigned long Config; /* FLAGS for NOREAD.... */ +#define RIO_NOREAD 0x0001 /* Are not allowed to read port */ +#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */ +#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */ +#define RIO_NOMASK 0x0007 /* All not allowed things */ +#define RIO_IXANY 0x0008 /* Port is allowed ixany */ +#define RIO_MODEM 0x0010 /* Stream is a modem device */ +#define RIO_IXON 0x0020 /* Port is allowed ixon */ +#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */ +#define RIO_MAP_50_TO_50 0x0080 /* Map 50 baud to 50 baud */ +#define RIO_MAP_110_TO_110 0x0100 /* Map 110 baud to 110 baud */ + +/* +** 15.10.1998 ARG - ESIL 0761 prt fix +** As LynxOS does not appear to support Hardware Flow Control ..... +** Define our own flow control flags in 'Config'. +*/ +#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */ +#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */ + + + struct PHB __iomem *PhbP; /* pointer to PHB for port */ + u16 __iomem *TxAdd; /* Add packets here */ + u16 __iomem *TxStart; /* Start of add array */ + u16 __iomem *TxEnd; /* End of add array */ + u16 __iomem *RxRemove; /* Remove packets here */ + u16 __iomem *RxStart; /* Start of remove array */ + u16 __iomem *RxEnd; /* End of remove array */ + unsigned int RtaUniqueNum; /* Unique number of RTA */ + unsigned short PortState; /* status of port */ + unsigned short ModemState; /* status of modem lines */ + unsigned long ModemLines; /* Modem bits sent to RTA */ + unsigned char CookMode; /* who expands CR/LF? */ + unsigned char ParamSem; /* Prevent write during param */ + unsigned char Mapped; /* if port mapped onto host */ + unsigned char SecondBlock; /* if port belongs to 2nd block + of 16 port RTA */ + unsigned char InUse; /* how many pre-emptive cmds */ + unsigned char Lock; /* if params locked */ + unsigned char Store; /* if params stored across closes */ + unsigned char FirstOpen; /* TRUE if first time port opened */ + unsigned char FlushCmdBodge; /* if doing a (non)flush */ + unsigned char MagicFlags; /* require intr processing */ +#define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */ +#define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */ +#define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */ + unsigned char WflushFlag; /* 1 How many WFLUSHs active */ +/* +** Transparent print stuff +*/ + struct Xprint { +#ifndef MAX_XP_CTRL_LEN +#define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */ +#endif + unsigned int XpCps; + char XpOn[MAX_XP_CTRL_LEN]; + char XpOff[MAX_XP_CTRL_LEN]; + unsigned short XpLen; /* strlen(XpOn)+strlen(XpOff) */ + unsigned char XpActive; + unsigned char XpLastTickOk; /* TRUE if we can process */ +#define XP_OPEN 00001 +#define XP_RUNABLE 00002 + struct ttystatics *XttyP; + } Xprint; + unsigned char RxDataStart; + unsigned char Cor2Copy; /* copy of COR2 */ + char *Name; /* points to the Rta's name */ + char *TxRingBuffer; + unsigned short TxBufferIn; /* New data arrives here */ + unsigned short TxBufferOut; /* Intr removes data here */ + unsigned short OldTxBufferOut; /* Indicates if draining */ + int TimeoutId; /* Timeout ID */ + unsigned int Debug; + unsigned char WaitUntilBooted; /* True if open should block */ + unsigned int statsGather; /* True if gathering stats */ + unsigned long txchars; /* Chars transmitted */ + unsigned long rxchars; /* Chars received */ + unsigned long opens; /* port open count */ + unsigned long closes; /* port close count */ + unsigned long ioctls; /* ioctl count */ + unsigned char LastRxTgl; /* Last state of rx toggle bit */ + spinlock_t portSem; /* Lock using this sem */ + int MonitorTstate; /* Monitoring ? */ + int timeout_id; /* For calling 100 ms delays */ + int timeout_sem; /* For calling 100 ms delays */ + int firstOpen; /* First time open ? */ + char *p; /* save the global struc here .. */ +}; + +struct ModuleInfo { + char *Name; + unsigned int Flags[4]; /* one per port on a module */ +}; + +/* +** This struct is required because trying to grab an entire Port structure +** runs into problems with differing struct sizes between driver and config. +*/ +struct PortParams { + unsigned int Port; + unsigned long Config; + unsigned long State; + struct ttystatics *TtyP; +}; + +#endif diff --git a/drivers/staging/generic_serial/rio/protsts.h b/drivers/staging/generic_serial/rio/protsts.h new file mode 100644 index 000000000000..8ab79401d3ee --- /dev/null +++ b/drivers/staging/generic_serial/rio/protsts.h @@ -0,0 +1,110 @@ +/**************************************************************************** + ******* ******* + ******* P R O T O C O L S T A T U S S T R U C T U R E ******* + ******* ******* + **************************************************************************** + + Author : Ian Nandhra / Jeremy Rolls + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _protsts_h +#define _protsts_h 1 + +/************************************************* + * ACK bit. Last Packet received OK. Set by + * rxpkt to indicate that the Packet has been + * received OK and that the LTT must set the ACK + * bit in the next outward bound Packet + * and re-set by LTT's after xmit. + * + * Gets shoved into rx_status + ************************************************/ +#define PHB_RX_LAST_PKT_ACKED ((ushort) 0x080) + +/******************************************************* + * The Rx TOGGLE bit. + * Stuffed into rx_status by RXPKT + ******************************************************/ +#define PHB_RX_DATA_WNDW ((ushort) 0x040) + +/******************************************************* + * The Rx TOGGLE bit. Matches the setting in PKT.H + * Stuffed into rx_status + ******************************************************/ +#define PHB_RX_TGL ((ushort) 0x2000) + + +/************************************************* + * This bit is set by the LRT to indicate that + * an ACK (packet) must be returned. + * + * Gets shoved into tx_status + ************************************************/ +#define PHB_TX_SEND_PKT_ACK ((ushort) 0x08) + +/************************************************* + * Set by LTT to indicate that an ACK is required + *************************************************/ +#define PHB_TX_ACK_RQRD ((ushort) 0x01) + + +/******************************************************* + * The Tx TOGGLE bit. + * Stuffed into tx_status by RXPKT from the PKT WndW + * field. Looked by the LTT when the NEXT Packet + * is going to be sent. + ******************************************************/ +#define PHB_TX_DATA_WNDW ((ushort) 0x04) + + +/******************************************************* + * The Tx TOGGLE bit. Matches the setting in PKT.H + * Stuffed into tx_status + ******************************************************/ +#define PHB_TX_TGL ((ushort) 0x02) + +/******************************************************* + * Request intr bit. Set when the queue has gone quiet + * and the PHB has requested an interrupt. + ******************************************************/ +#define PHB_TX_INTR ((ushort) 0x100) + +/******************************************************* + * SET if the PHB cannot send any more data down the + * Link + ******************************************************/ +#define PHB_TX_HANDSHAKE ((ushort) 0x010) + + +#define RUP_SEND_WNDW ((ushort) 0x08) ; + +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/rio.h b/drivers/staging/generic_serial/rio/rio.h new file mode 100644 index 000000000000..1bf36223a4e8 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rio.h @@ -0,0 +1,208 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rio.h +** SID : 1.3 +** Last Modified : 11/6/98 11:34:13 +** Retrieved : 11/6/98 11:34:22 +** +** ident @(#)rio.h 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_rio_h__ +#define __rio_rio_h__ + +/* +** Maximum numbers of things +*/ +#define RIO_SLOTS 4 /* number of configuration slots */ +#define RIO_HOSTS 4 /* number of hosts that can be found */ +#define PORTS_PER_HOST 128 /* number of ports per host */ +#define LINKS_PER_UNIT 4 /* number of links from a host */ +#define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */ +#define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */ +#define PORTS_PER_RTA (PORTS_PER_HOST/RTAS_PER_HOST) /* ports on a rta */ +#define PORTS_PER_MODULE 4 /* number of ports on a plug-in module */ + /* number of modules on an RTA */ +#define MODULES_PER_RTA (PORTS_PER_RTA/PORTS_PER_MODULE) +#define MAX_PRODUCT 16 /* numbr of different product codes */ +#define MAX_MODULE_TYPES 16 /* number of different types of module */ + +#define RIO_CONTROL_DEV 128 /* minor number of host/control device */ +#define RIO_INVALID_MAJOR 0 /* test first host card's major no for validity */ + +/* +** number of RTAs that can be bound to a master +*/ +#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS) + +/* +** Unit types +*/ +#define PC_RTA16 0x90000000 +#define PC_RTA8 0xe0000000 +#define TYPE_HOST 0 +#define TYPE_RTA8 1 +#define TYPE_RTA16 2 + +/* +** Flag values returned by functions +*/ + +#define RIO_FAIL -1 + +/* +** SysPort value for something that hasn't any ports +*/ +#define NO_PORT 0xFFFFFFFF + +/* +** Unit ID Of all hosts +*/ +#define HOST_ID 0 + +/* +** Break bytes into nybles +*/ +#define LONYBLE(X) ((X) & 0xF) +#define HINYBLE(X) (((X)>>4) & 0xF) + +/* +** Flag values passed into some functions +*/ +#define DONT_SLEEP 0 +#define OK_TO_SLEEP 1 + +#define DONT_PRINT 1 +#define DO_PRINT 0 + +#define PRINT_TO_LOG_CONS 0 +#define PRINT_TO_CONS 1 +#define PRINT_TO_LOG 2 + +/* +** Timeout has trouble with times of less than 3 ticks... +*/ +#define MIN_TIMEOUT 3 + +/* +** Generally useful constants +*/ + +#define HUNDRED_MS ((HZ/10)?(HZ/10):1) +#define ONE_MEG 0x100000 +#define SIXTY_FOUR_K 0x10000 + +#define RIO_AT_MEM_SIZE SIXTY_FOUR_K +#define RIO_EISA_MEM_SIZE SIXTY_FOUR_K +#define RIO_MCA_MEM_SIZE SIXTY_FOUR_K + +#define COOK_WELL 0 +#define COOK_MEDIUM 1 +#define COOK_RAW 2 + +/* +** Pointer manipulation stuff +** RIO_PTR takes hostp->Caddr and the offset into the DP RAM area +** and produces a UNIX caddr_t (pointer) to the object +** RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and +** returns the offset into the DP RAM area. +*/ +#define RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O))) +#define RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C)) + +/* +** How to convert from various different device number formats: +** DEV is a dev number, as passed to open, close etc - NOT a minor +** number! +**/ + +#define RIO_MODEM_MASK 0x1FF +#define RIO_MODEM_BIT 0x200 +#define RIO_UNMODEM(DEV) (MINOR(DEV) & RIO_MODEM_MASK) +#define RIO_ISMODEM(DEV) (MINOR(DEV) & RIO_MODEM_BIT) +#define RIO_PORT(DEV,FIRST_MAJ) ( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \ + + MINOR(DEV) +#define CSUM(pkt_ptr) (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \ + ((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \ + ((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \ + ((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \ + ((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] ) + +#define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */ + /* prevent a really stupid race condition. */ + +#define NOT_INITIALISED 0 +#define INITIALISED 1 + +#define NOT_POLLING 0 +#define POLLING 1 + +#define NOT_CHANGED 0 +#define CHANGED 1 + +#define NOT_INUSE 0 + +#define DISCONNECT 0 +#define CONNECT 1 + +/* ------ Control Codes ------ */ + +#define CONTROL '^' +#define IFOAD ( CONTROL + 1 ) +#define IDENTIFY ( CONTROL + 2 ) +#define ZOMBIE ( CONTROL + 3 ) +#define UFOAD ( CONTROL + 4 ) +#define IWAIT ( CONTROL + 5 ) + +#define IFOAD_MAGIC 0xF0AD /* of course */ +#define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */ +#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */ +#define IWAIT_MAGIC 0xB1DE /* Bide your time */ + +/* ------ Error Codes ------ */ + +#define E_NO_ERROR ((ushort) 0) + +/* ------ Free Lists ------ */ + +struct rio_free_list { + u16 next; + u16 prev; +}; + +/* NULL for card side linked lists */ +#define TPNULL ((ushort)(0x8000)) +/* We can add another packet to a transmit queue if the packet pointer pointed + * to by the TxAdd pointer has PKT_IN_USE clear in its address. */ +#define PKT_IN_USE 0x1 + +/* ------ Topology ------ */ + +struct Top { + u8 Unit; + u8 Link; +}; + +#endif /* __rio_h__ */ diff --git a/drivers/staging/generic_serial/rio/rio_linux.c b/drivers/staging/generic_serial/rio/rio_linux.c new file mode 100644 index 000000000000..5e33293d24e3 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rio_linux.c @@ -0,0 +1,1204 @@ + +/* rio_linux.c -- Linux driver for the Specialix RIO series cards. + * + * + * (C) 1999 R.E.Wolff@BitWizard.nl + * + * Specialix pays for the development and support of this driver. + * Please DO contact support@specialix.co.uk if you require + * support. But please read the documentation (rio.txt) first. + * + * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "linux_compat.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" +#include "param.h" +#include "protsts.h" +#include "rioboard.h" + + +#include "rio_linux.h" + +/* I don't think that this driver can handle more than 512 ports on +one machine. Specialix specifies max 4 boards in one machine. I don't +know why. If you want to try anyway you'll have to increase the number +of boards in rio.h. You'll have to allocate more majors if you need +more than 512 ports.... */ + +#ifndef RIO_NORMAL_MAJOR0 +/* This allows overriding on the compiler commandline, or in a "major.h" + include or something like that */ +#define RIO_NORMAL_MAJOR0 154 +#define RIO_NORMAL_MAJOR1 156 +#endif + +#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 +#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 +#endif + +#ifndef RIO_WINDOW_LEN +#define RIO_WINDOW_LEN 0x10000 +#endif + + +/* Configurable options: + (Don't be too sure that it'll work if you toggle them) */ + +/* Am I paranoid or not ? ;-) */ +#undef RIO_PARANOIA_CHECK + + +/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000 + Hz, but it is user configurable. I don't recommend going above 1000 + Hz. The interrupt ratelimit might trigger if the interrupt is + shared with a very active other device. + undef this if you want to disable the check.... +*/ +#define IRQ_RATE_LIMIT 200 + + +/* These constants are derived from SCO Source */ +static DEFINE_MUTEX(rio_fw_mutex); +static struct Conf + RIOConf = { + /* locator */ "RIO Config here", + /* startuptime */ HZ * 2, + /* how long to wait for card to run */ + /* slowcook */ 0, + /* TRUE -> always use line disc. */ + /* intrpolltime */ 1, + /* The frequency of OUR polls */ + /* breakinterval */ 25, + /* x10 mS XXX: units seem to be 1ms not 10! -- REW */ + /* timer */ 10, + /* mS */ + /* RtaLoadBase */ 0x7000, + /* HostLoadBase */ 0x7C00, + /* XpHz */ 5, + /* number of Xprint hits per second */ + /* XpCps */ 120, + /* Xprint characters per second */ + /* XpOn */ "\033d#", + /* start Xprint for a wyse 60 */ + /* XpOff */ "\024", + /* end Xprint for a wyse 60 */ + /* MaxXpCps */ 2000, + /* highest Xprint speed */ + /* MinXpCps */ 10, + /* slowest Xprint speed */ + /* SpinCmds */ 1, + /* non-zero for mega fast boots */ + /* First Addr */ 0x0A0000, + /* First address to look at */ + /* Last Addr */ 0xFF0000, + /* Last address looked at */ + /* BufferSize */ 1024, + /* Bytes per port of buffering */ + /* LowWater */ 256, + /* how much data left before wakeup */ + /* LineLength */ 80, + /* how wide is the console? */ + /* CmdTimeout */ HZ, + /* how long a close command may take */ +}; + + + + +/* Function prototypes */ + +static void rio_disable_tx_interrupts(void *ptr); +static void rio_enable_tx_interrupts(void *ptr); +static void rio_disable_rx_interrupts(void *ptr); +static void rio_enable_rx_interrupts(void *ptr); +static int rio_carrier_raised(struct tty_port *port); +static void rio_shutdown_port(void *ptr); +static int rio_set_real_termios(void *ptr); +static void rio_hungup(void *ptr); +static void rio_close(void *ptr); +static int rio_chars_in_buffer(void *ptr); +static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +static int rio_init_drivers(void); + +static void my_hd(void *addr, int len); + +static struct tty_driver *rio_driver, *rio_driver2; + +/* The name "p" is a bit non-descript. But that's what the rio-lynxos +sources use all over the place. */ +struct rio_info *p; + +int rio_debug; + + +/* You can have the driver poll your card. + - Set rio_poll to 1 to poll every timer tick (10ms on Intel). + This is used when the card cannot use an interrupt for some reason. +*/ +static int rio_poll = 1; + + +/* These are the only open spaces in my computer. Yours may have more + or less.... */ +static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 }; + +#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs) + + +/* Set the mask to all-ones. This alas, only supports 32 interrupts. + Some architectures may need more. -- Changed to LONG to + support up to 64 bits on 64bit architectures. -- REW 20/06/99 */ +static long rio_irqmask = -1; + +MODULE_AUTHOR("Rogier Wolff , Patrick van de Lageweg "); +MODULE_DESCRIPTION("RIO driver"); +MODULE_LICENSE("GPL"); +module_param(rio_poll, int, 0); +module_param(rio_debug, int, 0644); +module_param(rio_irqmask, long, 0); + +static struct real_driver rio_real_driver = { + rio_disable_tx_interrupts, + rio_enable_tx_interrupts, + rio_disable_rx_interrupts, + rio_enable_rx_interrupts, + rio_shutdown_port, + rio_set_real_termios, + rio_chars_in_buffer, + rio_close, + rio_hungup, + NULL +}; + +/* + * Firmware loader driver specific routines + * + */ + +static const struct file_operations rio_fw_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = rio_fw_ioctl, + .llseek = noop_llseek, +}; + +static struct miscdevice rio_fw_device = { + RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops +}; + + + + + +#ifdef RIO_PARANOIA_CHECK + +/* This doesn't work. Who's paranoid around here? Not me! */ + +static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine) +{ + + static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n"; + static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n"; + + if (!port) { + printk(badinfo, name, routine); + return 1; + } + if (port->magic != RIO_MAGIC) { + printk(badmagic, name, routine); + return 1; + } + + return 0; +} +#else +#define rio_paranoia_check(a,b,c) 0 +#endif + + +#ifdef DEBUG +static void my_hd(void *ad, int len) +{ + int i, j, ch; + unsigned char *addr = ad; + + for (i = 0; i < len; i += 16) { + rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i); + for (j = 0; j < 16; j++) { + rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : ""); + } + for (j = 0; j < 16; j++) { + ch = addr[j + i]; + rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch)); + } + rio_dprintk(RIO_DEBUG_PARAM, "\n"); + } +} +#else +#define my_hd(ad,len) do{/* nothing*/ } while (0) +#endif + + +/* Delay a number of jiffies, allowing a signal to interrupt */ +int RIODelay(struct Port *PortP, int njiffies) +{ + func_enter(); + + rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies); + msleep_interruptible(jiffies_to_msecs(njiffies)); + func_exit(); + + if (signal_pending(current)) + return RIO_FAIL; + else + return !RIO_FAIL; +} + + +/* Delay a number of jiffies, disallowing a signal to interrupt */ +int RIODelay_ni(struct Port *PortP, int njiffies) +{ + func_enter(); + + rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies); + msleep(jiffies_to_msecs(njiffies)); + func_exit(); + return !RIO_FAIL; +} + +void rio_copy_to_card(void *from, void __iomem *to, int len) +{ + rio_copy_toio(to, from, len); +} + +int rio_minor(struct tty_struct *tty) +{ + return tty->index + ((tty->driver == rio_driver) ? 0 : 256); +} + +static int rio_set_real_termios(void *ptr) +{ + return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1); +} + + +static void rio_reset_interrupt(struct Host *HostP) +{ + func_enter(); + + switch (HostP->Type) { + case RIO_AT: + case RIO_MCA: + case RIO_PCI: + writeb(0xFF, &HostP->ResetInt); + } + + func_exit(); +} + + +static irqreturn_t rio_interrupt(int irq, void *ptr) +{ + struct Host *HostP; + func_enter(); + + HostP = ptr; /* &p->RIOHosts[(long)ptr]; */ + rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec); + + /* AAargh! The order in which to do these things is essential and + not trivial. + + - hardware twiddling goes before "recursive". Otherwise when we + poll the card, and a recursive interrupt happens, we won't + ack the card, so it might keep on interrupting us. (especially + level sensitive interrupt systems like PCI). + + - Rate limit goes before hardware twiddling. Otherwise we won't + catch a card that has gone bonkers. + + - The "initialized" test goes after the hardware twiddling. Otherwise + the card will stick us in the interrupt routine again. + + - The initialized test goes before recursive. + */ + + rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); + if (HostP->Ivec == irq) { + /* Tell the card we've noticed the interrupt. */ + rio_reset_interrupt(HostP); + } + + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) + return IRQ_HANDLED; + + if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) { + printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec); + return IRQ_HANDLED; + } + + RIOServiceHost(p, HostP); + + rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type); + + clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks); + rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec); + func_exit(); + return IRQ_HANDLED; +} + + +static void rio_pollfunc(unsigned long data) +{ + func_enter(); + + rio_interrupt(0, &p->RIOHosts[data]); + mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll); + + func_exit(); +} + + +/* ********************************************************************** * + * Here are the routines that actually * + * interface with the generic_serial driver * + * ********************************************************************** */ + +/* Ehhm. I don't know how to fiddle with interrupts on the Specialix + cards. .... Hmm. Ok I figured it out. You don't. -- REW */ + +static void rio_disable_tx_interrupts(void *ptr) +{ + func_enter(); + + /* port->gs.port.flags &= ~GS_TX_INTEN; */ + + func_exit(); +} + + +static void rio_enable_tx_interrupts(void *ptr) +{ + struct Port *PortP = ptr; + /* int hn; */ + + func_enter(); + + /* hn = PortP->HostP - p->RIOHosts; + + rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn); + rio_interrupt (-1,(void *) hn, NULL); */ + + RIOTxEnable((char *) PortP); + + /* + * In general we cannot count on "tx empty" interrupts, although + * the interrupt routine seems to be able to tell the difference. + */ + PortP->gs.port.flags &= ~GS_TX_INTEN; + + func_exit(); +} + + +static void rio_disable_rx_interrupts(void *ptr) +{ + func_enter(); + func_exit(); +} + +static void rio_enable_rx_interrupts(void *ptr) +{ + /* struct rio_port *port = ptr; */ + func_enter(); + func_exit(); +} + + +/* Jeez. Isn't this simple? */ +static int rio_carrier_raised(struct tty_port *port) +{ + struct Port *PortP = container_of(port, struct Port, gs.port); + int rv; + + func_enter(); + rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0; + + rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv); + + func_exit(); + return rv; +} + + +/* Jeez. Isn't this simple? Actually, we can sync with the actual port + by just pushing stuff into the queue going to the port... */ +static int rio_chars_in_buffer(void *ptr) +{ + func_enter(); + + func_exit(); + return 0; +} + + +/* Nothing special here... */ +static void rio_shutdown_port(void *ptr) +{ + struct Port *PortP; + + func_enter(); + + PortP = (struct Port *) ptr; + PortP->gs.port.tty = NULL; + func_exit(); +} + + +/* I haven't the foggiest why the decrement use count has to happen + here. The whole linux serial drivers stuff needs to be redesigned. + My guess is that this is a hack to minimize the impact of a bug + elsewhere. Thinking about it some more. (try it sometime) Try + running minicom on a serial port that is driven by a modularized + driver. Have the modem hangup. Then remove the driver module. Then + exit minicom. I expect an "oops". -- REW */ +static void rio_hungup(void *ptr) +{ + struct Port *PortP; + + func_enter(); + + PortP = (struct Port *) ptr; + PortP->gs.port.tty = NULL; + + func_exit(); +} + + +/* The standard serial_close would become shorter if you'd wrap it like + this. + rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;} + */ +static void rio_close(void *ptr) +{ + struct Port *PortP; + + func_enter(); + + PortP = (struct Port *) ptr; + + riotclose(ptr); + + if (PortP->gs.port.count) { + printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.port.count); + PortP->gs.port.count = 0; + } + + PortP->gs.port.tty = NULL; + func_exit(); +} + + + +static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + func_enter(); + + /* The "dev" argument isn't used. */ + mutex_lock(&rio_fw_mutex); + rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); + mutex_unlock(&rio_fw_mutex); + + func_exit(); + return rc; +} + +extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); + +static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int rc; + struct Port *PortP; + int ival; + + func_enter(); + + PortP = (struct Port *) tty->driver_data; + + rc = 0; + switch (cmd) { + case TIOCSSOFTCAR: + if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) { + tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); + } + break; + case TIOCGSERIAL: + rc = -EFAULT; + if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct))) + rc = gs_getserial(&PortP->gs, argp); + break; + case TCSBRK: + if (PortP->State & RIO_DELETED) { + rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n"); + rc = -EIO; + } else { + if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) == + RIO_FAIL) { + rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); + rc = -EIO; + } + } + break; + case TCSBRKP: + if (PortP->State & RIO_DELETED) { + rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n"); + rc = -EIO; + } else { + int l; + l = arg ? arg * 100 : 250; + if (l > 255) + l = 255; + if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, + arg ? arg * 100 : 250) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); + rc = -EIO; + } + } + break; + case TIOCSSERIAL: + rc = -EFAULT; + if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct))) + rc = gs_setserial(&PortP->gs, argp); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + func_exit(); + return rc; +} + + +/* The throttle/unthrottle scheme for the Specialix card is different + * from other drivers and deserves some explanation. + * The Specialix hardware takes care of XON/XOFF + * and CTS/RTS flow control itself. This means that all we have to + * do when signalled by the upper tty layer to throttle/unthrottle is + * to make a note of it here. When we come to read characters from the + * rx buffers on the card (rio_receive_chars()) we look to see if the + * upper layer can accept more (as noted here in rio_rx_throt[]). + * If it can't we simply don't remove chars from the cards buffer. + * When the tty layer can accept chars, we again note that here and when + * rio_receive_chars() is called it will remove them from the cards buffer. + * The card will notice that a ports buffer has drained below some low + * water mark and will unflow control the line itself, using whatever + * flow control scheme is in use for that port. -- Simon Allen + */ + +static void rio_throttle(struct tty_struct *tty) +{ + struct Port *port = (struct Port *) tty->driver_data; + + func_enter(); + /* If the port is using any type of input flow + * control then throttle the port. + */ + + if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) { + port->State |= RIO_THROTTLE_RX; + } + + func_exit(); +} + + +static void rio_unthrottle(struct tty_struct *tty) +{ + struct Port *port = (struct Port *) tty->driver_data; + + func_enter(); + /* Always unthrottle even if flow control is not enabled on + * this port in case we disabled flow control while the port + * was throttled + */ + + port->State &= ~RIO_THROTTLE_RX; + + func_exit(); + return; +} + + + + + +/* ********************************************************************** * + * Here are the initialization routines. * + * ********************************************************************** */ + + +static struct vpd_prom *get_VPD_PROM(struct Host *hp) +{ + static struct vpd_prom vpdp; + char *p; + int i; + + func_enter(); + rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM); + + p = (char *) &vpdp; + for (i = 0; i < sizeof(struct vpd_prom); i++) + *p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2); + /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */ + + /* Terminate the identifier string. + *** requires one extra byte in struct vpd_prom *** */ + *p++ = 0; + + if (rio_debug & RIO_DEBUG_PROBE) + my_hd((char *) &vpdp, 0x20); + + func_exit(); + + return &vpdp; +} + +static const struct tty_operations rio_ops = { + .open = riotopen, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .chars_in_buffer = gs_chars_in_buffer, + .flush_buffer = gs_flush_buffer, + .ioctl = rio_ioctl, + .throttle = rio_throttle, + .unthrottle = rio_unthrottle, + .set_termios = gs_set_termios, + .stop = gs_stop, + .start = gs_start, + .hangup = gs_hangup, +}; + +static int rio_init_drivers(void) +{ + int error = -ENOMEM; + + rio_driver = alloc_tty_driver(256); + if (!rio_driver) + goto out; + rio_driver2 = alloc_tty_driver(256); + if (!rio_driver2) + goto out1; + + func_enter(); + + rio_driver->owner = THIS_MODULE; + rio_driver->driver_name = "specialix_rio"; + rio_driver->name = "ttySR"; + rio_driver->major = RIO_NORMAL_MAJOR0; + rio_driver->type = TTY_DRIVER_TYPE_SERIAL; + rio_driver->subtype = SERIAL_TYPE_NORMAL; + rio_driver->init_termios = tty_std_termios; + rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + rio_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(rio_driver, &rio_ops); + + rio_driver2->owner = THIS_MODULE; + rio_driver2->driver_name = "specialix_rio"; + rio_driver2->name = "ttySR"; + rio_driver2->major = RIO_NORMAL_MAJOR1; + rio_driver2->type = TTY_DRIVER_TYPE_SERIAL; + rio_driver2->subtype = SERIAL_TYPE_NORMAL; + rio_driver2->init_termios = tty_std_termios; + rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + rio_driver2->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(rio_driver2, &rio_ops); + + rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios); + + if ((error = tty_register_driver(rio_driver))) + goto out2; + if ((error = tty_register_driver(rio_driver2))) + goto out3; + func_exit(); + return 0; + out3: + tty_unregister_driver(rio_driver); + out2: + put_tty_driver(rio_driver2); + out1: + put_tty_driver(rio_driver); + out: + printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error); + return 1; +} + +static const struct tty_port_operations rio_port_ops = { + .carrier_raised = rio_carrier_raised, +}; + +static int rio_init_datastructures(void) +{ + int i; + struct Port *port; + func_enter(); + + /* Many drivers statically allocate the maximum number of ports + There is no reason not to allocate them dynamically. Is there? -- REW */ + /* However, the RIO driver allows users to configure their first + RTA as the ports numbered 504-511. We therefore need to allocate + the whole range. :-( -- REW */ + +#define RI_SZ sizeof(struct rio_info) +#define HOST_SZ sizeof(struct Host) +#define PORT_SZ sizeof(struct Port *) +#define TMIO_SZ sizeof(struct termios *) + rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); + + if (!(p = kzalloc(RI_SZ, GFP_KERNEL))) + goto free0; + if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL))) + goto free1; + if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL))) + goto free2; + p->RIOConf = RIOConf; + rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp); + +#if 1 + for (i = 0; i < RIO_PORTS; i++) { + port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL); + if (!port) { + goto free6; + } + rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); + tty_port_init(&port->gs.port); + port->gs.port.ops = &rio_port_ops; + port->PortNum = i; + port->gs.magic = RIO_MAGIC; + port->gs.close_delay = HZ / 2; + port->gs.closing_wait = 30 * HZ; + port->gs.rd = &rio_real_driver; + spin_lock_init(&port->portSem); + } +#else + /* We could postpone initializing them to when they are configured. */ +#endif + + + + if (rio_debug & RIO_DEBUG_INIT) { + my_hd(&rio_real_driver, sizeof(rio_real_driver)); + } + + + func_exit(); + return 0; + + free6:for (i--; i >= 0; i--) + kfree(p->RIOPortp[i]); +/*free5: + free4: + free3:*/ kfree(p->RIOPortp); + free2:kfree(p->RIOHosts); + free1: + rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp); + kfree(p); + free0: + return -ENOMEM; +} + +static void __exit rio_release_drivers(void) +{ + func_enter(); + tty_unregister_driver(rio_driver2); + tty_unregister_driver(rio_driver); + put_tty_driver(rio_driver2); + put_tty_driver(rio_driver); + func_exit(); +} + + +#ifdef CONFIG_PCI + /* This was written for SX, but applies to RIO too... + (including bugs....) + + There is another bit besides Bit 17. Turning that bit off + (on boards shipped with the fix in the eeprom) results in a + hang on the next access to the card. + */ + + /******************************************************** + * Setting bit 17 in the CNTRL register of the PLX 9050 * + * chip forces a retry on writes while a read is pending.* + * This is to prevent the card locking up on Intel Xeon * + * multiprocessor systems with the NX chipset. -- NV * + ********************************************************/ + +/* Newer cards are produced with this bit set from the configuration + EEprom. As the bit is read/write for the CPU, we can fix it here, + if we detect that it isn't set correctly. -- REW */ + +static void fix_rio_pci(struct pci_dev *pdev) +{ + unsigned long hwbase; + unsigned char __iomem *rebase; + unsigned int t; + +#define CNTRL_REG_OFFSET 0x50 +#define CNTRL_REG_GOODVALUE 0x18260000 + + hwbase = pci_resource_start(pdev, 0); + rebase = ioremap(hwbase, 0x80); + t = readl(rebase + CNTRL_REG_OFFSET); + if (t != CNTRL_REG_GOODVALUE) { + printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); + writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); + } + iounmap(rebase); +} +#endif + + +static int __init rio_init(void) +{ + int found = 0; + int i; + struct Host *hp; + int retval; + struct vpd_prom *vpdp; + int okboard; + +#ifdef CONFIG_PCI + struct pci_dev *pdev = NULL; + unsigned short tshort; +#endif + + func_enter(); + rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug); + + if (abs((long) (&rio_debug) - rio_debug) < 0x10000) { + printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug); + rio_debug = -1; + } + + if (misc_register(&rio_fw_device) < 0) { + printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n"); + return -EIO; + } + + retval = rio_init_datastructures(); + if (retval < 0) { + misc_deregister(&rio_fw_device); + return retval; + } +#ifdef CONFIG_PCI + /* First look for the JET devices: */ + while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { + u32 tint; + + if (pci_enable_device(pdev)) + continue; + + /* Specialix has a whole bunch of cards with + 0x2000 as the device ID. They say its because + the standard requires it. Stupid standard. */ + /* It seems that reading a word doesn't work reliably on 2.0. + Also, reading a non-aligned dword doesn't work. So we read the + whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) + ourselves */ + pci_read_config_dword(pdev, 0x2c, &tint); + tshort = (tint >> 16) & 0xffff; + rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); + if (tshort != 0x0100) { + rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort); + continue; + } + rio_dprintk(RIO_DEBUG_PROBE, "cp1\n"); + + hp = &p->RIOHosts[p->RIONumHosts]; + hp->PaddrP = pci_resource_start(pdev, 2); + hp->Ivec = pdev->irq; + if (((1 << hp->Ivec) & rio_irqmask) == 0) + hp->Ivec = 0; + hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); + hp->CardP = (struct DpRam __iomem *) hp->Caddr; + hp->Type = RIO_PCI; + hp->Copy = rio_copy_to_card; + hp->Mode = RIO_PCI_BOOT_FROM_RAM; + spin_lock_init(&hp->HostLock); + rio_reset_interrupt(hp); + rio_start_card_running(hp); + + rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); + if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) { + rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n"); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); + p->RIOHosts[p->RIONumHosts].UniqueNum = + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); + rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); + + fix_rio_pci(pdev); + + p->RIOHosts[p->RIONumHosts].pdev = pdev; + pci_dev_get(pdev); + + p->RIOLastPCISearch = 0; + p->RIONumHosts++; + found++; + } else { + iounmap(p->RIOHosts[p->RIONumHosts].Caddr); + p->RIOHosts[p->RIONumHosts].Caddr = NULL; + } + } + + /* Then look for the older PCI card.... : */ + + /* These older PCI cards have problems (only byte-mode access is + supported), which makes them a bit awkward to support. + They also have problems sharing interrupts. Be careful. + (The driver now refuses to share interrupts for these + cards. This should be sufficient). + */ + + /* Then look for the older RIO/PCI devices: */ + while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) { + if (pci_enable_device(pdev)) + continue; + +#ifdef CONFIG_RIO_OLDPCI + hp = &p->RIOHosts[p->RIONumHosts]; + hp->PaddrP = pci_resource_start(pdev, 0); + hp->Ivec = pdev->irq; + if (((1 << hp->Ivec) & rio_irqmask) == 0) + hp->Ivec = 0; + hp->Ivec |= 0x8000; /* Mark as non-sharable */ + hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); + hp->CardP = (struct DpRam __iomem *) hp->Caddr; + hp->Type = RIO_PCI; + hp->Copy = rio_copy_to_card; + hp->Mode = RIO_PCI_BOOT_FROM_RAM; + spin_lock_init(&hp->HostLock); + + rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); + rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); + + rio_reset_interrupt(hp); + rio_start_card_running(hp); + rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); + if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) { + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); + p->RIOHosts[p->RIONumHosts].UniqueNum = + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); + rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); + + p->RIOHosts[p->RIONumHosts].pdev = pdev; + pci_dev_get(pdev); + + p->RIOLastPCISearch = 0; + p->RIONumHosts++; + found++; + } else { + iounmap(p->RIOHosts[p->RIONumHosts].Caddr); + p->RIOHosts[p->RIONumHosts].Caddr = NULL; + } +#else + printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n"); +#endif + } +#endif /* PCI */ + + /* Now probe for ISA cards... */ + for (i = 0; i < NR_RIO_ADDRS; i++) { + hp = &p->RIOHosts[p->RIONumHosts]; + hp->PaddrP = rio_probe_addrs[i]; + /* There was something about the IRQs of these cards. 'Forget what.--REW */ + hp->Ivec = 0; + hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); + hp->CardP = (struct DpRam __iomem *) hp->Caddr; + hp->Type = RIO_AT; + hp->Copy = rio_copy_to_card; /* AT card PCI???? - PVDL + * -- YES! this is now a normal copy. Only the + * old PCI card uses the special PCI copy. + * Moreover, the ISA card will work with the + * special PCI copy anyway. -- REW */ + hp->Mode = 0; + spin_lock_init(&hp->HostLock); + + vpdp = get_VPD_PROM(hp); + rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n"); + okboard = 0; + if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) { + /* Board is present... */ + if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) { + /* ... and feeling fine!!!! */ + rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); + if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) { + rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum); + okboard++; + found++; + } + } + + if (!okboard) { + iounmap(hp->Caddr); + hp->Caddr = NULL; + } + } + } + + + for (i = 0; i < p->RIONumHosts; i++) { + hp = &p->RIOHosts[i]; + if (hp->Ivec) { + int mode = IRQF_SHARED; + if (hp->Ivec & 0x8000) { + mode = 0; + hp->Ivec &= 0x7fff; + } + rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode); + retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp); + rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval); + if (retval) { + printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); + hp->Ivec = 0; + } + rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec); + if (hp->Ivec != 0) { + rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); + hp->Mode |= RIO_PCI_INT_ENABLE; + } else + hp->Mode &= ~RIO_PCI_INT_ENABLE; + rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode); + rio_start_card_running(hp); + } + /* Init the timer "always" to make sure that it can safely be + deleted when we unload... */ + + setup_timer(&hp->timer, rio_pollfunc, i); + if (!hp->Ivec) { + rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll); + mod_timer(&hp->timer, jiffies + rio_poll); + } + } + + if (found) { + rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found); + rio_init_drivers(); + } else { + /* deregister the misc device we created earlier */ + misc_deregister(&rio_fw_device); + } + + func_exit(); + return found ? 0 : -EIO; +} + + +static void __exit rio_exit(void) +{ + int i; + struct Host *hp; + + func_enter(); + + for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) { + RIOHostReset(hp->Type, hp->CardP, hp->Slot); + if (hp->Ivec) { + free_irq(hp->Ivec, hp); + rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); + } + /* It is safe/allowed to del_timer a non-active timer */ + del_timer_sync(&hp->timer); + if (hp->Caddr) + iounmap(hp->Caddr); + if (hp->Type == RIO_PCI) + pci_dev_put(hp->pdev); + } + + if (misc_deregister(&rio_fw_device) < 0) { + printk(KERN_INFO "rio: couldn't deregister control-device\n"); + } + + + rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n"); + + rio_release_drivers(); + + /* Release dynamically allocated memory */ + kfree(p->RIOPortp); + kfree(p->RIOHosts); + kfree(p); + + func_exit(); +} + +module_init(rio_init); +module_exit(rio_exit); diff --git a/drivers/staging/generic_serial/rio/rio_linux.h b/drivers/staging/generic_serial/rio/rio_linux.h new file mode 100644 index 000000000000..7f26cd7c815e --- /dev/null +++ b/drivers/staging/generic_serial/rio/rio_linux.h @@ -0,0 +1,197 @@ + +/* + * rio_linux.h + * + * Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * RIO serial driver. + * + * Version 1.0 -- July, 1999. + * + */ + +#define RIO_NBOARDS 4 +#define RIO_PORTSPERBOARD 128 +#define RIO_NPORTS (RIO_NBOARDS * RIO_PORTSPERBOARD) + +#define MODEM_SUPPORT + +#ifdef __KERNEL__ + +#define RIO_MAGIC 0x12345678 + + +struct vpd_prom { + unsigned short id; + char hwrev; + char hwass; + int uniqid; + char myear; + char mweek; + char hw_feature[5]; + char oem_id; + char identifier[16]; +}; + + +#define RIO_DEBUG_ALL 0xffffffff + +#define O_OTHER(tty) \ + ((O_OLCUC(tty)) ||\ + (O_ONLCR(tty)) ||\ + (O_OCRNL(tty)) ||\ + (O_ONOCR(tty)) ||\ + (O_ONLRET(tty)) ||\ + (O_OFILL(tty)) ||\ + (O_OFDEL(tty)) ||\ + (O_NLDLY(tty)) ||\ + (O_CRDLY(tty)) ||\ + (O_TABDLY(tty)) ||\ + (O_BSDLY(tty)) ||\ + (O_VTDLY(tty)) ||\ + (O_FFDLY(tty))) + +/* Same for input. */ +#define I_OTHER(tty) \ + ((I_INLCR(tty)) ||\ + (I_IGNCR(tty)) ||\ + (I_ICRNL(tty)) ||\ + (I_IUCLC(tty)) ||\ + (L_ISIG(tty))) + + +#endif /* __KERNEL__ */ + + +#define RIO_BOARD_INTR_LOCK 1 + + +#ifndef RIOCTL_MISC_MINOR +/* Allow others to gather this into "major.h" or something like that */ +#define RIOCTL_MISC_MINOR 169 +#endif + + +/* Allow us to debug "in the field" without requiring clients to + recompile.... */ +#if 1 +#define rio_spin_lock_irqsave(sem, flags) do { \ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \ + sem, __FILE__, __LINE__);\ + spin_lock_irqsave(sem, flags);\ + } while (0) + +#define rio_spin_unlock_irqrestore(sem, flags) do { \ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\ + sem, __FILE__, __LINE__);\ + spin_unlock_irqrestore(sem, flags);\ + } while (0) + +#define rio_spin_lock(sem) do { \ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\ + sem, __FILE__, __LINE__);\ + spin_lock(sem);\ + } while (0) + +#define rio_spin_unlock(sem) do { \ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\ + sem, __FILE__, __LINE__);\ + spin_unlock(sem);\ + } while (0) +#else +#define rio_spin_lock_irqsave(sem, flags) \ + spin_lock_irqsave(sem, flags) + +#define rio_spin_unlock_irqrestore(sem, flags) \ + spin_unlock_irqrestore(sem, flags) + +#define rio_spin_lock(sem) \ + spin_lock(sem) + +#define rio_spin_unlock(sem) \ + spin_unlock(sem) + +#endif + + + +#ifdef CONFIG_RIO_OLDPCI +static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n) +{ + char __iomem *dst = dest; + char *src = source; + + while (n--) { + writeb(*src++, dst++); + (void) readb(dummy); + } + + return dest; +} + +static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n) +{ + char __iomem *dst = dest; + char *src = source; + + while (n--) + writeb(*src++, dst++); + + return dest; +} + + +static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n) +{ + char *dst = dest; + char __iomem *src = source; + + while (n--) + *dst++ = readb(src++); + + return dest; +} + +#else +#define rio_memcpy_toio(dummy,dest,source,n) memcpy_toio(dest, source, n) +#define rio_copy_toio memcpy_toio +#define rio_memcpy_fromio memcpy_fromio +#endif + +#define DEBUG 1 + + +/* + This driver can spew a whole lot of debugging output at you. If you + need maximum performance, you should disable the DEBUG define. To + aid in debugging in the field, I'm leaving the compile-time debug + features enabled, and disable them "runtime". That allows me to + instruct people with problems to enable debugging without requiring + them to recompile... +*/ + +#ifdef DEBUG +#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0) +#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__) +#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __func__) +#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line) +#else +#define rio_dprintk(f, str...) /* nothing */ +#define func_enter() +#define func_exit() +#define func_enter2() +#endif diff --git a/drivers/staging/generic_serial/rio/rioboard.h b/drivers/staging/generic_serial/rio/rioboard.h new file mode 100644 index 000000000000..252230043c82 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioboard.h @@ -0,0 +1,275 @@ +/************************************************************************/ +/* */ +/* Title : RIO Host Card Hardware Definitions */ +/* */ +/* Author : N.P.Vassallo */ +/* */ +/* Creation : 26th April 1999 */ +/* */ +/* Version : 1.0.0 */ +/* */ +/* Copyright : (c) Specialix International Ltd. 1999 * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * */ +/* Description : Prototypes, structures and definitions */ +/* describing the RIO board hardware */ +/* */ +/************************************************************************/ + +#ifndef _rioboard_h /* If RIOBOARD.H not already defined */ +#define _rioboard_h 1 + +/***************************************************************************** +*********************** *********************** +*********************** Hardware Control Registers *********************** +*********************** *********************** +*****************************************************************************/ + +/* Hardware Registers... */ + +#define RIO_REG_BASE 0x7C00 /* Base of control registers */ + +#define RIO_CONFIG RIO_REG_BASE + 0x0000 /* WRITE: Configuration Register */ +#define RIO_INTSET RIO_REG_BASE + 0x0080 /* WRITE: Interrupt Set */ +#define RIO_RESET RIO_REG_BASE + 0x0100 /* WRITE: Host Reset */ +#define RIO_INTRESET RIO_REG_BASE + 0x0180 /* WRITE: Interrupt Reset */ + +#define RIO_VPD_ROM RIO_REG_BASE + 0x0000 /* READ: Vital Product Data ROM */ +#define RIO_INTSTAT RIO_REG_BASE + 0x0080 /* READ: Interrupt Status (Jet boards only) */ +#define RIO_RESETSTAT RIO_REG_BASE + 0x0100 /* READ: Reset Status (Jet boards only) */ + +/* RIO_VPD_ROM definitions... */ +#define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */ +#define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */ +#define VPD_HW_REV 0x02 /* READ: Hardware Revision */ +#define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */ +#define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */ +#define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */ +#define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */ +#define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */ +#define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */ +#define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */ +#define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */ +#define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */ +#define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */ +#define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */ +#define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */ +#define VPD_OEMID 0x0F /* READ: OEM Identifier */ +#define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */ +#define VPD_IDENT_LEN 0x10 + +/* VPD ROM Definitions... */ +#define SLX_ID1 0x4D +#define SLX_ID2 0x98 + +#define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */ + +#define ID_SX_ISA 0x2 +#define ID_RIO_EISA 0x3 +#define ID_SX_PCI 0x5 +#define ID_SX_EISA 0x7 +#define ID_RIO_RTA16 0x9 +#define ID_RIO_ISA 0xA +#define ID_RIO_MCA 0xB +#define ID_RIO_SBUS 0xC +#define ID_RIO_PCI 0xD +#define ID_RIO_RTA8 0xE + +/* Transputer bootstrap definitions... */ + +#define BOOTLOADADDR (0x8000 - 6) +#define BOOTINDICATE (0x8000 - 2) + +/* Firmware load position... */ + +#define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */ + +/***************************************************************************** +***************************** ***************************** +***************************** RIO (Rev1) ISA ***************************** +***************************** ***************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_ISA_IDENT "JBJGPGGHINSMJPJR" + +#define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ +#define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */ +#define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */ +#define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */ +#define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */ +#define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ +#define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */ + +/***************************************************************************** +***************************** ***************************** +***************************** RIO (Rev2) ISA ***************************** +***************************** ***************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_ISA2_IDENT "JBJGPGGHINSMJPJR" + +#define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ +#define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ +#define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */ +#define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */ +#define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */ +#define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */ +#define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */ +#define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */ +#define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ +#define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */ + +/***************************************************************************** +***************************** ****************************** +***************************** RIO (Jet) ISA ****************************** +***************************** ****************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_ISA3_IDENT "JET HOST BY KEV#" + +#define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ +#define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */ +#define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */ +#define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */ +#define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */ +#define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */ +#define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */ + +/***************************************************************************** +********************************* ******************************** +********************************* RIO MCA ******************************** +********************************* ******************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_MCA_IDENT "JBJGPGGHINSMJPJR" + +#define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ +#define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ + +/***************************************************************************** +******************************** ******************************** +******************************** RIO EISA ******************************** +******************************** ******************************** +*****************************************************************************/ + +/* EISA Configuration Space Definitions... */ +#define EISA_PRODUCT_ID1 0xC80 +#define EISA_PRODUCT_ID2 0xC81 +#define EISA_PRODUCT_NUMBER 0xC82 +#define EISA_REVISION_NUMBER 0xC83 +#define EISA_CARD_ENABLE 0xC84 +#define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */ +#define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */ +#define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */ +#define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */ +#define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */ +#define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */ +#define EISA_MEM_ADDR_23_16 0xC00 +#define EISA_MEM_ADDR_31_24 0xC01 +#define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */ +#define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */ +#define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */ + +/* Control Register Definitions... */ +#define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ +#define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */ +#define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */ +#define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */ +#define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */ +#define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */ +#define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */ +#define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */ +#define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */ +#define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */ +#define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */ +#define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */ +#define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */ +#define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */ +#define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */ +#define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */ + +/***************************************************************************** +******************************** ******************************** +******************************** RIO SBus ******************************** +******************************** ******************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_SBUS_IDENT "JBPGK#\0\0\0\0\0\0\0\0\0\0" + +#define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ +#define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ +#define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */ +#define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */ +#define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */ +#define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */ +#define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */ +#define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */ +#define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */ +#define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */ +#define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */ +#define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ +#define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */ + +/***************************************************************************** +********************************* ******************************** +********************************* RIO PCI ******************************** +********************************* ******************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_PCI_IDENT "ECDDPGJGJHJRGSK#" + +#define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ +#define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ +#define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ +#define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */ + +/* PCI Definitions... */ +#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */ +#define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */ +#define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */ +#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */ +#define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */ + +/***************************************************************************** +***************************** ****************************** +***************************** RIO (Jet) PCI ****************************** +***************************** ****************************** +*****************************************************************************/ + +/* Control Register Definitions... */ +#define RIO_PCI2_IDENT "JET HOST BY KEV#" + +#define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */ +#define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ + +/* PCI Definitions... */ +#define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */ + +#endif /*_rioboard_h */ + +/* End of RIOBOARD.H */ diff --git a/drivers/staging/generic_serial/rio/rioboot.c b/drivers/staging/generic_serial/rio/rioboot.c new file mode 100644 index 000000000000..d956dd316005 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioboot.c @@ -0,0 +1,1113 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioboot.c +** SID : 1.3 +** Last Modified : 11/6/98 10:33:36 +** Retrieved : 11/6/98 10:33:48 +** +** ident @(#)rioboot.c 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" + +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP); + +static const unsigned char RIOAtVec2Ctrl[] = { + /* 0 */ INTERRUPT_DISABLE, + /* 1 */ INTERRUPT_DISABLE, + /* 2 */ INTERRUPT_DISABLE, + /* 3 */ INTERRUPT_DISABLE, + /* 4 */ INTERRUPT_DISABLE, + /* 5 */ INTERRUPT_DISABLE, + /* 6 */ INTERRUPT_DISABLE, + /* 7 */ INTERRUPT_DISABLE, + /* 8 */ INTERRUPT_DISABLE, + /* 9 */ IRQ_9 | INTERRUPT_ENABLE, + /* 10 */ INTERRUPT_DISABLE, + /* 11 */ IRQ_11 | INTERRUPT_ENABLE, + /* 12 */ IRQ_12 | INTERRUPT_ENABLE, + /* 13 */ INTERRUPT_DISABLE, + /* 14 */ INTERRUPT_DISABLE, + /* 15 */ IRQ_15 | INTERRUPT_ENABLE +}; + +/** + * RIOBootCodeRTA - Load RTA boot code + * @p: RIO to load + * @rbp: Download descriptor + * + * Called when the user process initiates booting of the card firmware. + * Lads the firmware + */ + +int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp) +{ + int offset; + + func_enter(); + + rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP); + + /* + ** Check that we have set asside enough memory for this + */ + if (rbp->Count > SIXTY_FOUR_K) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); + p->RIOError.Error = HOST_FILE_TOO_LARGE; + func_exit(); + return -ENOMEM; + } + + if (p->RIOBooting) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); + p->RIOError.Error = BOOT_IN_PROGRESS; + func_exit(); + return -EBUSY; + } + + /* + ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary, + ** so calculate how far we have to move the data up the buffer + ** to achieve this. + */ + offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE; + + /* + ** Be clean, and clear the 'unused' portion of the boot buffer, + ** because it will (eventually) be part of the Rta run time environment + ** and so should be zeroed. + */ + memset(p->RIOBootPackets, 0, offset); + + /* + ** Copy the data from user space into the array + */ + + if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) { + rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n"); + p->RIOError.Error = COPYIN_FAILED; + func_exit(); + return -EFAULT; + } + + /* + ** Make sure that our copy of the size includes that offset we discussed + ** earlier. + */ + p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE; + p->RIOBootCount = rbp->Count; + + func_exit(); + return 0; +} + +/** + * rio_start_card_running - host card start + * @HostP: The RIO to kick off + * + * Start a RIO processor unit running. Encapsulates the knowledge + * of the card type. + */ + +void rio_start_card_running(struct Host *HostP) +{ + switch (HostP->Type) { + case RIO_AT: + rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n"); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control); + break; + case RIO_PCI: + /* + ** PCI is much the same as MCA. Everything is once again memory + ** mapped, so we are writing to memory registers instead of io + ** ports. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n"); + writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control); + break; + default: + rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); + break; + } + return; +} + +/* +** Load in the host boot code - load it directly onto all halted hosts +** of the correct type. +** +** Put your rubber pants on before messing with this code - even the magic +** numbers have trouble understanding what they are doing here. +*/ + +int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) +{ + struct Host *HostP; + u8 __iomem *Cad; + PARM_MAP __iomem *ParmMapP; + int RupN; + int PortN; + unsigned int host; + u8 __iomem *StartP; + u8 __iomem *DestP; + int wait_count; + u16 OldParmMap; + u16 offset; /* It is very important that this is a u16 */ + u8 *DownCode = NULL; + unsigned long flags; + + HostP = NULL; /* Assure the compiler we've initialized it */ + + + /* Walk the hosts */ + for (host = 0; host < p->RIONumHosts; host++) { + rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host); + HostP = &p->RIOHosts[host]; + + rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); + + /* Don't boot hosts already running */ + if ((HostP->Flags & RUN_STATE) != RC_WAITING) { + rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host); + continue; + } + + /* + ** Grab a pointer to the card (ioremapped) + */ + Cad = HostP->Caddr; + + /* + ** We are going to (try) and load in rbp->Count bytes. + ** The last byte will reside at p->RIOConf.HostLoadBase-1; + ** Therefore, we need to start copying at address + ** (caddr+p->RIOConf.HostLoadBase-rbp->Count) + */ + StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count]; + + rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad); + rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP); + rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); + rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); + + /* Make sure it fits */ + if (p->RIOConf.HostLoadBase < rbp->Count) { + rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n"); + p->RIOError.Error = HOST_FILE_TOO_LARGE; + func_exit(); + return -EFBIG; + } + /* + ** Ensure that the host really is stopped. + ** Disable it's external bus & twang its reset line. + */ + RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot); + + /* + ** Copy the data directly from user space to the SRAM. + ** This ain't going to be none too clever if the download + ** code is bigger than this segment. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n"); + + /* Buffer to local memory as we want to use I/O space and + some cards only do 8 or 16 bit I/O */ + + DownCode = vmalloc(rbp->Count); + if (!DownCode) { + p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; + func_exit(); + return -ENOMEM; + } + if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) { + kfree(DownCode); + p->RIOError.Error = COPYIN_FAILED; + func_exit(); + return -EFAULT; + } + HostP->Copy(DownCode, StartP, rbp->Count); + vfree(DownCode); + + rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n"); + + /* + ** S T O P ! + ** + ** Upto this point the code has been fairly rational, and possibly + ** even straight forward. What follows is a pile of crud that will + ** magically turn into six bytes of transputer assembler. Normally + ** you would expect an array or something, but, being me, I have + ** chosen [been told] to use a technique whereby the startup code + ** will be correct if we change the loadbase for the code. Which + ** brings us onto another issue - the loadbase is the *end* of the + ** code, not the start. + ** + ** If I were you I wouldn't start from here. + */ + + /* + ** We now need to insert a short boot section into + ** the memory at the end of Sram2. This is normally (de)composed + ** of the last eight bytes of the download code. The + ** download has been assembled/compiled to expect to be + ** loaded from 0x7FFF downwards. We have loaded it + ** at some other address. The startup code goes into the small + ** ram window at Sram2, in the last 8 bytes, which are really + ** at addresses 0x7FF8-0x7FFF. + ** + ** If the loadbase is, say, 0x7C00, then we need to branch to + ** address 0x7BFE to run the host.bin startup code. We assemble + ** this jump manually. + ** + ** The two byte sequence 60 08 is loaded into memory at address + ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0, + ** which adds '0' to the .O register, complements .O, and then shifts + ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will + ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new + ** location. Now, the branch starts from the value of .PC (or .IP or + ** whatever the bloody register is called on this chip), and the .PC + ** will be pointing to the location AFTER the branch, in this case + ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8. + ** + ** A long branch is coded at 0x7FF8. This consists of loading a four + ** byte offset into .O using nfix (as above) and pfix operators. The + ** pfix operates in exactly the same way as the nfix operator, but + ** without the complement operation. The offset, of course, must be + ** relative to the address of the byte AFTER the branch instruction, + ** which will be (urm) 0x7FFC, so, our final destination of the branch + ** (loadbase-2), has to be reached from here. Imagine that the loadbase + ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which + ** is the first byte of the initial two byte short local branch of the + ** download code). + ** + ** To code a jump from 0x7FFC (which is where the branch will start + ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)= + ** 0x7BFE. + ** This will be coded as four bytes: + ** 60 2C 20 02 + ** being nfix .O+0 + ** pfix .O+C + ** pfix .O+0 + ** jump .O+2 + ** + ** The nfix operator is used, so that the startup code will be + ** compatible with the whole Tp family. (lies, damn lies, it'll never + ** work in a month of Sundays). + ** + ** The nfix nyble is the 1s complement of the nyble value you + ** want to load - in this case we wanted 'F' so we nfix loaded '0'. + */ + + + /* + ** Dest points to the top 8 bytes of Sram2. The Tp jumps + ** to 0x7FFE at reset time, and starts executing. This is + ** a short branch to 0x7FF8, where a long branch is coded. + */ + + DestP = &Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ + +#define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */ +#define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */ +#define JUMP(N) (0x00 | (N)) /* .PC = .PC + .O */ + + /* + ** 0x7FFC is the address of the location following the last byte of + ** the four byte jump instruction. + ** READ THE ABOVE COMMENTS + ** + ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about. + ** Memsize is 64K for this range of Tp, so offset is a short (unsigned, + ** cos I don't understand 2's complement). + */ + offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC; + + writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP); + writeb(PFIX((offset >> 8) & 0xF), DestP + 1); + writeb(PFIX((offset >> 4) & 0xF), DestP + 2); + writeb(JUMP(offset & 0xF), DestP + 3); + + writeb(NFIX(0), DestP + 6); + writeb(JUMP(8), DestP + 7); + + rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); + rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset); + + /* + ** Flag what is going on + */ + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STARTUP; + + /* + ** Grab a copy of the current ParmMap pointer, so we + ** can tell when it has changed. + */ + OldParmMap = readw(&HostP->__ParmMapR); + + rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap); + + /* + ** And start it running (I hope). + ** As there is nothing dodgy or obscure about the + ** above code, this is guaranteed to work every time. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); + + rio_start_card_running(HostP); + + rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n"); + + /* + ** Now, wait for upto five seconds for the Tp to setup the parmmap + ** pointer: + */ + for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) { + rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR)); + mdelay(100); + + } + + /* + ** If the parmmap pointer is unchanged, then the host code + ** has crashed & burned in a really spectacular way + */ + if (readw(&HostP->__ParmMapR) == OldParmMap) { + rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STUFFED; + RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); + continue; + } + + rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR)); + + /* + ** Well, the board thought it was OK, and setup its parmmap + ** pointer. For the time being, we will pretend that this + ** board is running, and check out what the error flag says. + */ + + /* + ** Grab a 32 bit pointer to the parmmap structure + */ + ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); + ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); + + /* + ** The links entry should be 0xFFFF; we set it up + ** with a mask to say how many PHBs to use, and + ** which links to use. + */ + if (readw(&ParmMapP->links) != 0xFFFF) { + rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); + rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links)); + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STUFFED; + RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); + continue; + } + + writew(RIO_LINK_ENABLE, &ParmMapP->links); + + /* + ** now wait for the card to set all the parmmap->XXX stuff + ** this is a wait of upto two seconds.... + */ + rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime); + HostP->timeout_id = 0; + for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) { + rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n"); + mdelay(100); + } + rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n"); + + if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) { + rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); + rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STUFFED; + RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); + continue; + } + + rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n"); + + /* + ** It runs! It runs! + */ + rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum); + + /* + ** set the time period between interrupts. + */ + writew(p->RIOConf.Timer, &ParmMapP->timer); + + /* + ** Translate all the 16 bit pointers in the __ParmMapR into + ** 32 bit pointers for the driver in ioremap space. + */ + HostP->ParmMapP = ParmMapP; + HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); + HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups)); + HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); + HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); + + /* + ** point the UnixRups at the real Rups + */ + for (RupN = 0; RupN < MAX_RUP; RupN++) { + HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN]; + HostP->UnixRups[RupN].Id = RupN + 1; + HostP->UnixRups[RupN].BaseSysPort = NO_PORT; + spin_lock_init(&HostP->UnixRups[RupN].RupLock); + } + + for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) { + HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup; + HostP->UnixRups[RupN + MAX_RUP].Id = 0; + HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT; + spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock); + } + + /* + ** point the PortP->Phbs at the real Phbs + */ + for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) { + if (p->RIOPortp[PortN]->HostP == HostP) { + struct Port *PortP = p->RIOPortp[PortN]; + struct PHB __iomem *PhbP; + /* int oldspl; */ + + if (!PortP->Mapped) + continue; + + PhbP = &HostP->PhbP[PortP->HostPort]; + rio_spin_lock_irqsave(&PortP->portSem, flags); + + PortP->PhbP = PhbP; + + PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add)); + PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start)); + PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end)); + PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove)); + PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start)); + PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end)); + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + /* + ** point the UnixRup at the base SysPort + */ + if (!(PortN % PORTS_PER_RTA)) + HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN; + } + } + + rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n"); + /* + ** last thing - show the world that everything is in place + */ + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_RUNNING; + } + /* + ** MPX always uses a poller. This is actually patched into the system + ** configuration and called directly from each clock tick. + ** + */ + p->RIOPolling = 1; + + p->RIOSystemUp++; + + rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec); + func_exit(); + return 0; +} + + + +/** + * RIOBootRup - Boot an RTA + * @p: rio we are working with + * @Rup: Rup number + * @HostP: host object + * @PacketP: packet to use + * + * If we have successfully processed this boot, then + * return 1. If we havent, then return 0. + */ + +int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP) +{ + struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data; + struct PktCmd_M *PktReplyP; + struct CmdBlk *CmdBlkP; + unsigned int sequence; + + /* + ** If we haven't been told what to boot, we can't boot it. + */ + if (p->RIONumBootPkts == 0) { + rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n"); + return 0; + } + + /* + ** Special case of boot completed - if we get one of these then we + ** don't need a command block. For all other cases we do, so handle + ** this first and then get a command block, then handle every other + ** case, relinquishing the command block if disaster strikes! + */ + if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED)) + return RIOBootComplete(p, HostP, Rup, PktCmdP); + + /* + ** Try to allocate a command block. This is in kernel space + */ + if (!(CmdBlkP = RIOGetCmdBlk())) { + rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); + return 0; + } + + /* + ** Fill in the default info on the command block + */ + CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0; + CmdBlkP->Packet.dest_port = BOOT_RUP; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.src_port = BOOT_RUP; + + CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; + PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data; + + /* + ** process COMMANDS on the boot rup! + */ + if (readb(&PacketP->len) & PKT_CMD_BIT) { + /* + ** We only expect one type of command - a BOOT_REQUEST! + */ + if (readb(&PktCmdP->Command) != BOOT_REQUEST) { + rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts); + RIOFreeCmdBlk(CmdBlkP); + return 1; + } + + /* + ** Build a Boot Sequence command block + ** + ** We no longer need to use "Boot Mode", we'll always allow + ** boot requests - the boot will not complete if the device + ** appears in the bindings table. + ** + ** We'll just (always) set the command field in packet reply + ** to allow an attempted boot sequence : + */ + PktReplyP->Command = BOOT_SEQUENCE; + + PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts; + PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase; + PktReplyP->BootSequence.CodeSize = p->RIOBootCount; + + CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT; + + memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4); + + rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase); + + /* + ** If this host is in slave mode, send the RTA an invalid boot + ** sequence command block to force it to kill the boot. We wait + ** for half a second before sending this packet to prevent the RTA + ** attempting to boot too often. The master host should then grab + ** the RTA and make it its own. + */ + p->RIOBooting++; + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); + return 1; + } + + /* + ** It is a request for boot data. + */ + sequence = readw(&PktCmdP->Sequence); + + rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup); + + if (sequence >= p->RIONumBootPkts) { + rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts); + } + + PktReplyP->Sequence = sequence; + memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE); + CmdBlkP->Packet.len = PKT_MAX_DATA_LEN; + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); + return 1; +} + +/** + * RIOBootComplete - RTA boot is done + * @p: RIO we are working with + * @HostP: Host structure + * @Rup: RUP being used + * @PktCmdP: Packet command that was used + * + * This function is called when an RTA been booted. + * If booted by a host, HostP->HostUniqueNum is the booting host. + * If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA. + * RtaUniq is the booted RTA. + */ + +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP) +{ + struct Map *MapP = NULL; + struct Map *MapP2 = NULL; + int Flag; + int found; + int host, rta; + int EmptySlot = -1; + int entry, entry2; + char *MyType, *MyName; + unsigned int MyLink; + unsigned short RtaType; + u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); + + p->RIOBooting = 0; + + rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); + + /* + ** Determine type of unit (16/8 port RTA). + */ + + RtaType = GetUnitType(RtaUniq); + if (Rup >= (unsigned short) MAX_RUP) + rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); + else + rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); + + rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq); + + if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) { + rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); + return 1; + } + + /* + ** If this RTA has just booted an RTA which doesn't belong to this + ** system, or the system is in slave mode, do not attempt to create + ** a new table entry for it. + */ + + if (!RIOBootOk(p, HostP, RtaUniq)) { + MyLink = readb(&PktCmdP->LinkNum); + if (Rup < (unsigned short) MAX_RUP) { + /* + ** RtaUniq was clone booted (by this RTA). Instruct this RTA + ** to hold off further attempts to boot on this link for 30 + ** seconds. + */ + if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink); + } + } else + /* + ** RtaUniq was booted by this host. Set the booting link + ** to hold off for 30 seconds to give another unit a + ** chance to boot it. + */ + writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot); + rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); + return 1; + } + + /* + ** Check for a SLOT_IN_USE entry for this RTA attached to the + ** current host card in the driver table. + ** + ** If it exists, make a note that we have booted it. Other parts of + ** the driver are interested in this information at a later date, + ** in particular when the booting RTA asks for an ID for this unit, + ** we must have set the BOOTED flag, and the NEWBOOT flag is used + ** to force an open on any ports that where previously open on this + ** unit. + */ + for (entry = 0; entry < MAX_RUP; entry++) { + unsigned int sysport; + + if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { + HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT; + if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) { + if (sysport < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = sysport; + if (sysport > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = sysport; + /* + ** For a 16 port RTA, check the second bank of 8 ports + */ + if (RtaType == TYPE_RTA16) { + entry2 = HostP->Mapping[entry].ID2 - 1; + HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT; + sysport = HostP->Mapping[entry2].SysPort; + if (sysport < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = sysport; + if (sysport > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = sysport; + } + } + if (RtaType == TYPE_RTA16) + rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1); + else + rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1); + return 1; + } + } + + rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n"); + + if (Rup >= (unsigned short) MAX_RUP) { + /* + ** It was a host that did the booting + */ + MyType = "Host"; + MyName = HostP->Name; + } else { + /* + ** It was an RTA that did the booting + */ + MyType = "RTA"; + MyName = HostP->Mapping[Rup].Name; + } + MyLink = readb(&PktCmdP->LinkNum); + + /* + ** There is no SLOT_IN_USE entry for this RTA attached to the current + ** host card in the driver table. + ** + ** Check for a SLOT_TENTATIVE entry for this RTA attached to the + ** current host card in the driver table. + ** + ** If we find one, then we re-use that slot. + */ + for (entry = 0; entry < MAX_RUP; entry++) { + if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { + if (RtaType == TYPE_RTA16) { + entry2 = HostP->Mapping[entry].ID2 - 1; + if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq)) + rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2); + else + continue; + } else + rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry); + if (!p->RIONoMessage) + printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); + return 1; + } + } + + /* + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another + ** host for this RTA in the driver table. + ** + ** For a SLOT_IN_USE entry on another host, we need to delete the RTA + ** entry from the other host and add it to this host (using some of + ** the functions from table.c which do this). + ** For a SLOT_TENTATIVE entry on another host, we must cope with the + ** following scenario: + ** + ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry + ** in table) + ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE + ** entries) + ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE) + ** + Unplug RTA and plug back into host A. + ** + Configure RTA on host A. We now have the same RTA configured + ** with different ports on two different hosts. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq); + found = 0; + Flag = 0; /* Convince the compiler this variable is initialized */ + for (host = 0; !found && (host < p->RIONumHosts); host++) { + for (rta = 0; rta < MAX_RUP; rta++) { + if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) { + Flag = p->RIOHosts[host].Mapping[rta].Flags; + MapP = &p->RIOHosts[host].Mapping[rta]; + if (RtaType == TYPE_RTA16) { + MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1]; + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name); + } else + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name); + found = 1; + break; + } + } + } + + /* + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on + ** another host for this RTA in the driver table... + ** + ** Check for a SLOT_IN_USE entry for this RTA in the config table. + */ + if (!MapP) { + rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq); + for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) { + rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum); + + if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) { + MapP = &p->RIOSavedTable[rta]; + Flag = p->RIOSavedTable[rta].Flags; + if (RtaType == TYPE_RTA16) { + for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) { + if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq) + break; + } + MapP2 = &p->RIOSavedTable[entry2]; + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2); + } else + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta); + break; + } + } + } + + /* + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** We may have found a SLOT_IN_USE entry on another host for this + ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry + ** on another host for this RTA in the driver table. + ** + ** Check the driver table for room to fit this newly discovered RTA. + ** RIOFindFreeID() first looks for free slots and if it does not + ** find any free slots it will then attempt to oust any + ** tentative entry in the table. + */ + EmptySlot = 1; + if (RtaType == TYPE_RTA16) { + if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) { + RIODefaultName(p, HostP, entry); + rio_fill_host_slot(entry, entry2, RtaUniq, HostP); + EmptySlot = 0; + } + } else { + if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) { + RIODefaultName(p, HostP, entry); + rio_fill_host_slot(entry, 0, RtaUniq, HostP); + EmptySlot = 0; + } + } + + /* + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** If we found a SLOT_IN_USE entry on another host for this + ** RTA in the config or driver table, and there are enough free + ** slots in the driver table, then we need to move it over and + ** delete it from the other host. + ** If we found a SLOT_TENTATIVE entry on another host for this + ** RTA in the driver table, just delete the other host entry. + */ + if (EmptySlot == 0) { + if (MapP) { + if (Flag & SLOT_IN_USE) { + rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n"); + HostP->Mapping[entry].SysPort = MapP->SysPort; + memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN); + HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; + RIOReMapPorts(p, HostP, &HostP->Mapping[entry]); + if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; + if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort; + rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name); + } else { + rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n"); + HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; + } + if (RtaType == TYPE_RTA16) { + if (Flag & SLOT_IN_USE) { + HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; + HostP->Mapping[entry2].SysPort = MapP2->SysPort; + /* + ** Map second block of ttys for 16 port RTA + */ + RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]); + if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort; + if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort; + rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name); + } else + HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; + memset(MapP2, 0, sizeof(struct Map)); + } + memset(MapP, 0, sizeof(struct Map)); + if (!p->RIONoMessage) + printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A'); + } else if (!p->RIONoMessage) + printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); + RIOSetChange(p); + return 1; + } + + /* + ** There is no room in the driver table to make an entry for the + ** booted RTA. Keep a note of its Uniq Num in the overflow table, + ** so we can ignore it's ID requests. + */ + if (!p->RIONoMessage) + printk("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A'); + for (entry = 0; entry < HostP->NumExtraBooted; entry++) { + if (HostP->ExtraUnits[entry] == RtaUniq) { + /* + ** already got it! + */ + return 1; + } + } + /* + ** If there is room, add the unit to the list of extras + */ + if (HostP->NumExtraBooted < MAX_EXTRA_UNITS) + HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq; + return 1; +} + + +/* +** If the RTA or its host appears in the RIOBindTab[] structure then +** we mustn't boot the RTA and should return 0. +** This operation is slightly different from the other drivers for RIO +** in that this is designed to work with the new utilities +** not config.rio and is FAR SIMPLER. +** We no longer support the RIOBootMode variable. It is all done from the +** "boot/noboot" field in the rio.cf file. +*/ +int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq) +{ + int Entry; + unsigned int HostUniq = HostP->UniqueNum; + + /* + ** Search bindings table for RTA or its parent. + ** If it exists, return 0, else 1. + */ + for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) { + if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq)) + return 0; + } + return 1; +} + +/* +** Make an empty slot tentative. If this is a 16 port RTA, make both +** slots tentative, and the second one RTA_SECOND_SLOT as well. +*/ + +void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host) +{ + int link; + + rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq); + + host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); + host->Mapping[entry].SysPort = NO_PORT; + host->Mapping[entry].RtaUniqueNum = rta_uniq; + host->Mapping[entry].HostUniqueNum = host->UniqueNum; + host->Mapping[entry].ID = entry + 1; + host->Mapping[entry].ID2 = 0; + if (entry2) { + host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT); + host->Mapping[entry2].SysPort = NO_PORT; + host->Mapping[entry2].RtaUniqueNum = rta_uniq; + host->Mapping[entry2].HostUniqueNum = host->UniqueNum; + host->Mapping[entry2].Name[0] = '\0'; + host->Mapping[entry2].ID = entry2 + 1; + host->Mapping[entry2].ID2 = entry + 1; + host->Mapping[entry].ID2 = entry2 + 1; + } + /* + ** Must set these up, so that utilities show + ** topology of 16 port RTAs correctly + */ + for (link = 0; link < LINKS_PER_UNIT; link++) { + host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT; + host->Mapping[entry].Topology[link].Link = NO_LINK; + if (entry2) { + host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT; + host->Mapping[entry2].Topology[link].Link = NO_LINK; + } + } +} diff --git a/drivers/staging/generic_serial/rio/riocmd.c b/drivers/staging/generic_serial/rio/riocmd.c new file mode 100644 index 000000000000..f121357e5af0 --- /dev/null +++ b/drivers/staging/generic_serial/rio/riocmd.c @@ -0,0 +1,939 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** ported from the existing SCO driver source +** + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : riocmd.c +** SID : 1.2 +** Last Modified : 11/6/98 10:33:41 +** Retrieved : 11/6/98 10:33:49 +** +** ident @(#)riocmd.c 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" + + +static struct IdentifyRta IdRta; +static struct KillNeighbour KillUnit; + +int RIOFoadRta(struct Host *HostP, struct Map *MapP) +{ + struct CmdBlk *CmdBlkP; + + rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n"); + + CmdBlkP = RIOGetCmdBlk(); + + if (!CmdBlkP) { + rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n"); + return -ENXIO; + } + + CmdBlkP->Packet.dest_unit = MapP->ID; + CmdBlkP->Packet.dest_port = BOOT_RUP; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.src_port = BOOT_RUP; + CmdBlkP->Packet.len = 0x84; + CmdBlkP->Packet.data[0] = IFOAD; + CmdBlkP->Packet.data[1] = 0; + CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF; + CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF; + + if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n"); + return -EIO; + } + return 0; +} + +int RIOZombieRta(struct Host *HostP, struct Map *MapP) +{ + struct CmdBlk *CmdBlkP; + + rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n"); + + CmdBlkP = RIOGetCmdBlk(); + + if (!CmdBlkP) { + rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n"); + return -ENXIO; + } + + CmdBlkP->Packet.dest_unit = MapP->ID; + CmdBlkP->Packet.dest_port = BOOT_RUP; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.src_port = BOOT_RUP; + CmdBlkP->Packet.len = 0x84; + CmdBlkP->Packet.data[0] = ZOMBIE; + CmdBlkP->Packet.data[1] = 0; + CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF; + CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF; + + if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n"); + return -EIO; + } + return 0; +} + +int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP)) +{ + unsigned int Host; + + rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func); + + if (!RtaUnique) + return (0); + + for (Host = 0; Host < p->RIONumHosts; Host++) { + unsigned int Rta; + struct Host *HostP = &p->RIOHosts[Host]; + + for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) { + struct Map *MapP = &HostP->Mapping[Rta]; + + if (MapP->RtaUniqueNum == RtaUnique) { + uint Link; + + /* + ** now, lets just check we have a route to it... + ** IF the routing stuff is working, then one of the + ** topology entries for this unit will have a legit + ** route *somewhere*. We care not where - if its got + ** any connections, we can get to it. + */ + for (Link = 0; Link < LINKS_PER_UNIT; Link++) { + if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) { + /* + ** Its worth trying the operation... + */ + return (*func) (HostP, MapP); + } + } + } + } + } + return -ENXIO; +} + + +int RIOIdentifyRta(struct rio_info *p, void __user * arg) +{ + unsigned int Host; + + if (copy_from_user(&IdRta, arg, sizeof(IdRta))) { + rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + + for (Host = 0; Host < p->RIONumHosts; Host++) { + unsigned int Rta; + struct Host *HostP = &p->RIOHosts[Host]; + + for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) { + struct Map *MapP = &HostP->Mapping[Rta]; + + if (MapP->RtaUniqueNum == IdRta.RtaUnique) { + uint Link; + /* + ** now, lets just check we have a route to it... + ** IF the routing stuff is working, then one of the + ** topology entries for this unit will have a legit + ** route *somewhere*. We care not where - if its got + ** any connections, we can get to it. + */ + for (Link = 0; Link < LINKS_PER_UNIT; Link++) { + if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) { + /* + ** Its worth trying the operation... + */ + struct CmdBlk *CmdBlkP; + + rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n"); + + CmdBlkP = RIOGetCmdBlk(); + + if (!CmdBlkP) { + rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n"); + return -ENXIO; + } + + CmdBlkP->Packet.dest_unit = MapP->ID; + CmdBlkP->Packet.dest_port = BOOT_RUP; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.src_port = BOOT_RUP; + CmdBlkP->Packet.len = 0x84; + CmdBlkP->Packet.data[0] = IDENTIFY; + CmdBlkP->Packet.data[1] = 0; + CmdBlkP->Packet.data[2] = IdRta.ID; + + if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n"); + return -EIO; + } + return 0; + } + } + } + } + } + return -ENOENT; +} + + +int RIOKillNeighbour(struct rio_info *p, void __user * arg) +{ + uint Host; + uint ID; + struct Host *HostP; + struct CmdBlk *CmdBlkP; + + rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n"); + + if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) { + rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + + if (KillUnit.Link > 3) + return -ENXIO; + + CmdBlkP = RIOGetCmdBlk(); + + if (!CmdBlkP) { + rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n"); + return -ENXIO; + } + + CmdBlkP->Packet.dest_unit = 0; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.dest_port = BOOT_RUP; + CmdBlkP->Packet.src_port = BOOT_RUP; + CmdBlkP->Packet.len = 0x84; + CmdBlkP->Packet.data[0] = UFOAD; + CmdBlkP->Packet.data[1] = KillUnit.Link; + CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF; + CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF; + + for (Host = 0; Host < p->RIONumHosts; Host++) { + ID = 0; + HostP = &p->RIOHosts[Host]; + + if (HostP->UniqueNum == KillUnit.UniqueNum) { + if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); + return -EIO; + } + return 0; + } + + for (ID = 0; ID < RTAS_PER_HOST; ID++) { + if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) { + CmdBlkP->Packet.dest_unit = ID + 1; + if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); + return -EIO; + } + return 0; + } + } + } + RIOFreeCmdBlk(CmdBlkP); + return -ENXIO; +} + +int RIOSuspendBootRta(struct Host *HostP, int ID, int Link) +{ + struct CmdBlk *CmdBlkP; + + rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link); + + CmdBlkP = RIOGetCmdBlk(); + + if (!CmdBlkP) { + rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n"); + return -ENXIO; + } + + CmdBlkP->Packet.dest_unit = ID; + CmdBlkP->Packet.dest_port = BOOT_RUP; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.src_port = BOOT_RUP; + CmdBlkP->Packet.len = 0x84; + CmdBlkP->Packet.data[0] = IWAIT; + CmdBlkP->Packet.data[1] = Link; + CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF; + CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF; + + if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n"); + return -EIO; + } + return 0; +} + +int RIOFoadWakeup(struct rio_info *p) +{ + int port; + struct Port *PortP; + unsigned long flags; + + for (port = 0; port < RIO_PORTS; port++) { + PortP = p->RIOPortp[port]; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->Config = 0; + PortP->State = 0; + PortP->InUse = NOT_INUSE; + PortP->PortState = 0; + PortP->FlushCmdBodge = 0; + PortP->ModemLines = 0; + PortP->ModemState = 0; + PortP->CookMode = 0; + PortP->ParamSem = 0; + PortP->Mapped = 0; + PortP->WflushFlag = 0; + PortP->MagicFlags = 0; + PortP->RxDataStart = 0; + PortP->TxBufferIn = 0; + PortP->TxBufferOut = 0; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + } + return (0); +} + +/* +** Incoming command on the COMMAND_RUP to be processed. +*/ +static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP) +{ + struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data; + struct Port *PortP; + struct UnixRup *UnixRupP; + unsigned short SysPort; + unsigned short ReportedModemStatus; + unsigned short rup; + unsigned short subCommand; + unsigned long flags; + + func_enter(); + + /* + ** 16 port RTA note: + ** Command rup packets coming from the RTA will have pkt->data[1] (which + ** translates to PktCmdP->PhbNum) set to the host port number for the + ** particular unit. To access the correct BaseSysPort for a 16 port RTA, + ** we can use PhbNum to get the rup number for the appropriate 8 port + ** block (for the first block, this should be equal to 'Rup'). + */ + rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA; + UnixRupP = &HostP->UnixRups[rup]; + SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA); + rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); + + if (UnixRupP->BaseSysPort == NO_PORT) { + rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); + rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); + rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); + rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); + + if (Rup < (unsigned short) MAX_RUP) { + rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); + } else + rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); + + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum)); + rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command)); + return 1; + } + PortP = p->RIOPortp[SysPort]; + rio_spin_lock_irqsave(&PortP->portSem, flags); + switch (readb(&PktCmdP->Command)) { + case RIOC_BREAK_RECEIVED: + rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n"); + /* If the current line disc. is not multi-threading and + the current processor is not the default, reset rup_intr + and return 0 to ensure that the command packet is + not freed. */ + /* Call tmgr HANGUP HERE */ + /* Fix this later when every thing works !!!! RAMRAJ */ + gs_got_break(&PortP->gs); + break; + + case RIOC_COMPLETE: + rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts); + subCommand = 1; + switch (readb(&PktCmdP->SubCommand)) { + case RIOC_MEMDUMP: + rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr)); + break; + case RIOC_READ_REGISTER: + rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr)); + p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST); + break; + default: + subCommand = 0; + break; + } + if (subCommand) + break; + rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState); + if (PortP->PortState != readb(&PktCmdP->PortStatus)) { + rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n"); + PortP->PortState = readb(&PktCmdP->PortStatus); + /* What should we do here ... + wakeup( &PortP->PortState ); + */ + } else + rio_dprintk(RIO_DEBUG_CMD, "No change\n"); + + /* FALLTHROUGH */ + case RIOC_MODEM_STATUS: + /* + ** Knock out the tbusy and tstop bits, as these are not relevant + ** to the check for modem status change (they're just there because + ** it's a convenient place to put them!). + */ + ReportedModemStatus = readb(&PktCmdP->ModemStatus); + if ((PortP->ModemState & RIOC_MSVR1_HOST) == + (ReportedModemStatus & RIOC_MSVR1_HOST)) { + rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); + /* + ** Update ModemState just in case tbusy or tstop states have + ** changed. + */ + PortP->ModemState = ReportedModemStatus; + } else { + rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus); + PortP->ModemState = ReportedModemStatus; +#ifdef MODEM_SUPPORT + if (PortP->Mapped) { + /***********************************************************\ + ************************************************************* + *** *** + *** M O D E M S T A T E C H A N G E *** + *** *** + ************************************************************* + \***********************************************************/ + /* + ** If the device is a modem, then check the modem + ** carrier. + */ + if (PortP->gs.port.tty == NULL) + break; + if (PortP->gs.port.tty->termios == NULL) + break; + + if (!(PortP->gs.port.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) { + + rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n"); + /* + ** Is there a carrier? + */ + if (PortP->ModemState & RIOC_MSVR1_CD) { + /* + ** Has carrier just appeared? + */ + if (!(PortP->State & RIO_CARR_ON)) { + rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n"); + PortP->State |= RIO_CARR_ON; + /* + ** wakeup anyone in WOPEN + */ + if (PortP->State & (PORT_ISOPEN | RIO_WOPEN)) + wake_up_interruptible(&PortP->gs.port.open_wait); + } + } else { + /* + ** Has carrier just dropped? + */ + if (PortP->State & RIO_CARR_ON) { + if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN)) + tty_hangup(PortP->gs.port.tty); + PortP->State &= ~RIO_CARR_ON; + rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n"); + } + } + } + } +#endif + } + break; + + default: + rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts); + break; + } + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + + func_exit(); + + return 1; +} + +/* +** The command mechanism: +** Each rup has a chain of commands associated with it. +** This chain is maintained by routines in this file. +** Periodically we are called and we run a quick check of all the +** active chains to determine if there is a command to be executed, +** and if the rup is ready to accept it. +** +*/ + +/* +** Allocate an empty command block. +*/ +struct CmdBlk *RIOGetCmdBlk(void) +{ + struct CmdBlk *CmdBlkP; + + CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC); + return CmdBlkP; +} + +/* +** Return a block to the head of the free list. +*/ +void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP) +{ + kfree(CmdBlkP); +} + +/* +** attach a command block to the list of commands to be performed for +** a given rup. +*/ +int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) +{ + struct CmdBlk **Base; + struct UnixRup *UnixRupP; + unsigned long flags; + + if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) { + rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup); + RIOFreeCmdBlk(CmdBlkP); + return RIO_FAIL; + } + + UnixRupP = &HostP->UnixRups[Rup]; + + rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); + + /* + ** If the RUP is currently inactive, then put the request + ** straight on the RUP.... + */ + if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) + : 1)) { + rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]); + + /* + ** Whammy! blat that pack! + */ + HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); + + /* + ** place command packet on the pending position. + */ + UnixRupP->CmdPendingP = CmdBlkP; + + /* + ** set the command register + */ + writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); + + rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + + return 0; + } + rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n"); + + if (UnixRupP->CmdsWaitingP != NULL) + rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n"); + if (UnixRupP->CmdPendingP != NULL) + rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n"); + if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE) + rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); + + Base = &UnixRupP->CmdsWaitingP; + + rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base); + + while (*Base) { + rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base); + Base = &((*Base)->NextP); + rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base); + } + + rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base); + + *Base = CmdBlkP; + + CmdBlkP->NextP = NULL; + + rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + + return 0; +} + +/* +** Here we go - if there is an empty rup, fill it! +** must be called at splrio() or higher. +*/ +void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) +{ + struct CmdBlk *CmdBlkP; + struct UnixRup *UnixRupP; + struct PKT __iomem *PacketP; + unsigned short Rup; + unsigned long flags; + + + Rup = MAX_RUP + LINKS_PER_UNIT; + + do { /* do this loop for each RUP */ + /* + ** locate the rup we are processing & lock it + */ + UnixRupP = &HostP->UnixRups[--Rup]; + + spin_lock_irqsave(&UnixRupP->RupLock, flags); + + /* + ** First check for incoming commands: + */ + if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { + int FreeMe; + + PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); + + switch (readb(&PacketP->dest_port)) { + case BOOT_RUP: + rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0])); + rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + FreeMe = RIOBootRup(p, Rup, HostP, PacketP); + rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); + break; + + case COMMAND_RUP: + /* + ** Free the RUP lock as loss of carrier causes a + ** ttyflush which will (eventually) call another + ** routine that uses the RUP lock. + */ + rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + FreeMe = RIOCommandRup(p, Rup, HostP, PacketP); + if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) { + rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6]))); + rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32); + } + rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); + break; + + case ROUTE_RUP: + rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + FreeMe = RIORouteRup(p, Rup, HostP, PacketP); + rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); + break; + + default: + rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port)); + FreeMe = 1; + break; + } + + if (FreeMe) { + rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n"); + put_free_end(HostP, PacketP); + + writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol); + + if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) { + rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup); + writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake); + } + } + } + + /* + ** IF a command was running on the port, + ** and it has completed, then tidy it up. + */ + if ((CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ + (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { + /* + ** we are idle. + ** there is a command in pending. + ** Therefore, this command has finished. + ** So, wakeup whoever is waiting for it (and tell them + ** what happened). + */ + if (CmdBlkP->Packet.dest_port == BOOT_RUP) + rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]); + + rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP); + + /* + ** Clear the Rup lock to prevent mutual exclusion. + */ + if (CmdBlkP->PostFuncP) { + rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP); + rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); + } + + /* + ** ....clear the pending flag.... + */ + UnixRupP->CmdPendingP = NULL; + + /* + ** ....and return the command block to the freelist. + */ + RIOFreeCmdBlk(CmdBlkP); + } + + /* + ** If there is a command for this rup, and the rup + ** is idle, then process the command + */ + if ((CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ + (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { + /* + ** if the pre-function is non-zero, call it. + ** If it returns RIO_FAIL then don't + ** send this command yet! + */ + if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) { + rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP); + } else { + rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]); + /* + ** Whammy! blat that pack! + */ + HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); + + /* + ** remove the command from the rup command queue... + */ + UnixRupP->CmdsWaitingP = CmdBlkP->NextP; + + /* + ** ...and place it on the pending position. + */ + UnixRupP->CmdPendingP = CmdBlkP; + + /* + ** set the command register + */ + writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); + + /* + ** the command block will be freed + ** when the command has been processed. + */ + } + } + spin_unlock_irqrestore(&UnixRupP->RupLock, flags); + } while (Rup); +} + +int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP) +{ + struct Port *PortP = (struct Port *) iPortP; + unsigned long flags; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->WflushFlag++; + PortP->MagicFlags |= MAGIC_FLUSH; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return RIOUnUse(iPortP, CmdBlkP); +} + +int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP) +{ + struct Port *PortP = (struct Port *) iPortP; + struct PKT __iomem *PacketP; + unsigned long flags; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + + while (can_remove_receive(&PacketP, PortP)) { + remove_receive(PortP); + put_free_end(PortP->HostP, PacketP); + } + + if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) { + /* + ** MAGIC! (Basically, handshake the RX buffer, so that + ** the RTAs upstream can be re-enabled.) + */ + rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n"); + writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); + } + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return RIOUnUse(iPortP, CmdBlkP); +} + +int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) +{ + struct Port *PortP = (struct Port *) iPortP; + unsigned long flags; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + + rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n"); + + if (PortP->InUse) { + if (--PortP->InUse != NOT_INUSE) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return 0; + } + } + /* + ** While PortP->InUse is set (i.e. a preemptive command has been sent to + ** the RTA and is awaiting completion), any transmit data is prevented from + ** being transferred from the write queue into the transmit packets + ** (add_transmit) and no furthur transmit interrupt will be sent for that + ** data. The next interrupt will occur up to 500ms later (RIOIntr is called + ** twice a second as a saftey measure). This was the case when kermit was + ** used to send data into a RIO port. After each packet was sent, TCFLSH + ** was called to flush the read queue preemptively. PortP->InUse was + ** incremented, thereby blocking the 6 byte acknowledgement packet + ** transmitted back. This acknowledgment hung around for 500ms before + ** being sent, thus reducing input performance substantially!. + ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data + ** hanging around in the transmit buffer is sent immediately. + */ + writew(1, &PortP->HostP->ParmMapP->tx_intr); + /* What to do here .. + wakeup( (caddr_t)&(PortP->InUse) ); + */ + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return 0; +} + +/* +** +** How to use this file: +** +** To send a command down a rup, you need to allocate a command block, fill +** in the packet information, fill in the command number, fill in the pre- +** and post- functions and arguments, and then add the command block to the +** queue of command blocks for the port in question. When the port is idle, +** then the pre-function will be called. If this returns RIO_FAIL then the +** command will be re-queued and tried again at a later date (probably in one +** clock tick). If the pre-function returns NOT RIO_FAIL, then the command +** packet will be queued on the RUP, and the txcontrol field set to the +** command number. When the txcontrol field has changed from being the +** command number, then the post-function will be called, with the argument +** specified earlier, a pointer to the command block, and the value of +** txcontrol. +** +** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer +** to the command block structure allocated, or NULL if there aren't any. +** The block will have been zeroed for you. +** +** The structure has the following fields: +** +** struct CmdBlk +** { +** struct CmdBlk *NextP; ** Pointer to next command block ** +** struct PKT Packet; ** A packet, to copy to the rup ** +** int (*PreFuncP)(); ** The func to call to check if OK ** +** int PreArg; ** The arg for the func ** +** int (*PostFuncP)(); ** The func to call when completed ** +** int PostArg; ** The arg for the func ** +** }; +** +** You need to fill in ALL fields EXCEPT NextP, which is used to link the +** blocks together either on the free list or on the Rup list. +** +** Packet is an actual packet structure to be filled in with the packet +** information associated with the command. You need to fill in everything, +** as the command processor doesn't process the command packet in any way. +** +** The PreFuncP is called before the packet is enqueued on the host rup. +** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must +** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL +** if the packet is NOT to be queued. +** +** The PostFuncP is called when the command has completed. It is called +** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected +** to return a value. PostFuncP does NOT need to free the command block, +** as this happens automatically after PostFuncP returns. +** +** Once the command block has been filled in, it is attached to the correct +** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is +** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer +** to it!), and CmdBlkP is the pointer to the command block allocated using +** RIOGetCmdBlk(). +** +*/ diff --git a/drivers/staging/generic_serial/rio/rioctrl.c b/drivers/staging/generic_serial/rio/rioctrl.c new file mode 100644 index 000000000000..780506326a73 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioctrl.c @@ -0,0 +1,1504 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioctrl.c +** SID : 1.3 +** Last Modified : 11/6/98 10:33:42 +** Retrieved : 11/6/98 10:33:49 +** +** ident @(#)rioctrl.c 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" + + +static struct LpbReq LpbReq; +static struct RupReq RupReq; +static struct PortReq PortReq; +static struct HostReq HostReq; /* oh really? global? and no locking? */ +static struct HostDpRam HostDpRam; +static struct DebugCtrl DebugCtrl; +static struct Map MapEnt; +static struct PortSetup PortSetup; +static struct DownLoad DownLoad; +static struct SendPack SendPack; +/* static struct StreamInfo StreamInfo; */ +/* static char modemtable[RIO_PORTS]; */ +static struct SpecialRupCmd SpecialRupCmd; +static struct PortParams PortParams; +static struct portStats portStats; + +static struct SubCmdStruct { + ushort Host; + ushort Rup; + ushort Port; + ushort Addr; +} SubCmd; + +struct PortTty { + uint port; + struct ttystatics Tty; +}; + +static struct PortTty PortTty; +typedef struct ttystatics TERMIO; + +/* +** This table is used when the config.rio downloads bin code to the +** driver. We index the table using the product code, 0-F, and call +** the function pointed to by the entry, passing the information +** about the boot. +** The RIOBootCodeUNKNOWN entry is there to politely tell the calling +** process to bog off. +*/ +static int + (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = { + /* 0 */ RIOBootCodeHOST, + /* Host Card */ + /* 1 */ RIOBootCodeRTA, + /* RTA */ +}; + +#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff)) + +static int copy_from_io(void __user *to, void __iomem *from, size_t size) +{ + void *buf = kmalloc(size, GFP_KERNEL); + int res = -ENOMEM; + if (buf) { + rio_memcpy_fromio(buf, from, size); + res = copy_to_user(to, buf, size); + kfree(buf); + } + return res; +} + +int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su) +{ + uint Host; /* leave me unsigned! */ + uint port; /* and me! */ + struct Host *HostP; + ushort loop; + int Entry; + struct Port *PortP; + struct PKT __iomem *PacketP; + int retval = 0; + unsigned long flags; + void __user *argp = (void __user *)arg; + + func_enter(); + + /* Confuse the compiler to think that we've initialized these */ + Host = 0; + PortP = NULL; + + rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp); + + switch (cmd) { + /* + ** RIO_SET_TIMER + ** + ** Change the value of the host card interrupt timer. + ** If the host card number is -1 then all host cards are changed + ** otherwise just the specified host card will be changed. + */ + case RIO_SET_TIMER: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg); + { + int host, value; + host = (arg >> 16) & 0x0000FFFF; + value = arg & 0x0000ffff; + if (host == -1) { + for (host = 0; host < p->RIONumHosts; host++) { + if (p->RIOHosts[host].Flags == RC_RUNNING) { + writew(value, &p->RIOHosts[host].ParmMapP->timer); + } + } + } else if (host >= p->RIONumHosts) { + return -EINVAL; + } else { + if (p->RIOHosts[host].Flags == RC_RUNNING) { + writew(value, &p->RIOHosts[host].ParmMapP->timer); + } + } + } + return 0; + + case RIO_FOAD_RTA: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); + return RIOCommandRta(p, arg, RIOFoadRta); + + case RIO_ZOMBIE_RTA: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); + return RIOCommandRta(p, arg, RIOZombieRta); + + case RIO_IDENTIFY_RTA: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); + return RIOIdentifyRta(p, argp); + + case RIO_KILL_NEIGHBOUR: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n"); + return RIOKillNeighbour(p, argp); + + case SPECIAL_RUP_CMD: + { + struct CmdBlk *CmdBlkP; + + rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); + if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) { + rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + CmdBlkP = RIOGetCmdBlk(); + if (!CmdBlkP) { + rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n"); + return -ENXIO; + } + CmdBlkP->Packet = SpecialRupCmd.Packet; + if (SpecialRupCmd.Host >= p->RIONumHosts) + SpecialRupCmd.Host = 0; + rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum); + if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) { + printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n"); + } + return 0; + } + + case RIO_DEBUG_MEM: + return -EPERM; + + case RIO_ALL_MODEM: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n"); + p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; + return -EINVAL; + + case RIO_GET_TABLE: + /* + ** Read the routing table from the device driver to user space + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n"); + + if ((retval = RIOApel(p)) != 0) + return retval; + + if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + + { + int entry; + rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n"); + for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { + if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0)) + continue; + + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link); + rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name); + } + rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n"); + } + p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */ + return 0; + + case RIO_PUT_TABLE: + /* + ** Write the routing table to the device driver from user space + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n"); + + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } +/* +*********************************** + { + int entry; + rio_dprint(RIO_DEBUG_CTRL, ("*****\nMAP ENTRIES\n") ); + for ( entry=0; entryRIOConnectTable[entry].HostUniqueNum ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) ); + rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) ); + } + rio_dprint(RIO_DEBUG_CTRL, ("*****\nEND MAP ENTRIES\n") ); + } +*********************************** +*/ + return RIONewTable(p); + + case RIO_GET_BINDINGS: + /* + ** Send bindings table, containing unique numbers of RTAs owned + ** by this system to user space + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n"); + + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return 0; + + case RIO_PUT_BINDINGS: + /* + ** Receive a bindings table, containing unique numbers of RTAs owned + ** by this system + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n"); + + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + return 0; + + case RIO_BIND_RTA: + { + int EmptySlot = -1; + /* + ** Bind this RTA to host, so that it will be booted by + ** host in 'boot owned RTAs' mode. + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n"); + + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) { + if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L)) + EmptySlot = Entry; + else if (p->RIOBindTab[Entry] == arg) { + /* + ** Already exists - delete + */ + p->RIOBindTab[Entry] = 0L; + rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg); + return 0; + } + } + /* + ** Dosen't exist - add + */ + if (EmptySlot != -1) { + p->RIOBindTab[EmptySlot] = arg; + rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg); + } else { + rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg); + return -ENOMEM; + } + return 0; + } + + case RIO_RESUME: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n"); + port = arg; + if ((port < 0) || (port > 511)) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + PortP = p->RIOPortp[port]; + if (!PortP->Mapped) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port); + p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; + return -EINVAL; + } + if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port); + return -EINVAL; + } + + rio_spin_lock_irqsave(&PortP->portSem, flags); + if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) == + RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return -EBUSY; + } else { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port); + PortP->State |= RIO_BUSY; + } + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_ASSIGN_RTA: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n"); + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { + rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + return RIOAssignRta(p, &MapEnt); + + case RIO_CHANGE_NAME: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n"); + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { + rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + return RIOChangeName(p, &MapEnt); + + case RIO_DELETE_RTA: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n"); + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { + rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + return RIODeleteRta(p, &MapEnt); + + case RIO_QUICK_CHECK: + if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return 0; + + case RIO_LAST_ERROR: + if (copy_to_user(argp, &p->RIOError, sizeof(struct Error))) + return -EFAULT; + return 0; + + case RIO_GET_LOG: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n"); + return -EINVAL; + + case RIO_GET_MODTYPE: + if (copy_from_user(&port, argp, sizeof(unsigned int))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port); + if (port < 0 || port > 511) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + PortP = (p->RIOPortp[port]); + if (!PortP->Mapped) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port); + p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; + return -EINVAL; + } + /* + ** Return module type of port + */ + port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes; + if (copy_to_user(argp, &port, sizeof(unsigned int))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return (0); + case RIO_BLOCK_OPENS: + rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n"); + for (Entry = 0; Entry < RIO_PORTS; Entry++) { + rio_spin_lock_irqsave(&PortP->portSem, flags); + p->RIOPortp[Entry]->WaitUntilBooted = 1; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + } + return 0; + + case RIO_SETUP_PORTS: + rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n"); + if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) { + p->RIOError.Error = COPYIN_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "EFAULT"); + return -EFAULT; + } + if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + rio_dprintk(RIO_DEBUG_CTRL, "ENXIO"); + return -ENXIO; + } + if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) { + p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE; + rio_dprintk(RIO_DEBUG_CTRL, "EINVAL"); + return -EINVAL; + } + if (!p->RIOPortp) { + printk(KERN_ERR "rio: No p->RIOPortp array!\n"); + rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n"); + return -EIO; + } + rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To); + for (loop = PortSetup.From; loop <= PortSetup.To; loop++) { + rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop); + } + rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop); + rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval); + return retval; + + case RIO_GET_PORT_SETUP: + rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n"); + if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (PortSetup.From >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + + port = PortSetup.To = PortSetup.From; + PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0; + PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0; + PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0; + PortSetup.Store = p->RIOPortp[port]->Store; + PortSetup.Lock = p->RIOPortp[port]->Lock; + PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps; + memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN); + memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN); + PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; + PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; + + if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_GET_PORT_PARAMS: + rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n"); + if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (PortParams.Port >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + PortP = (p->RIOPortp[PortParams.Port]); + PortParams.Config = PortP->Config; + PortParams.State = PortP->State; + rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); + + if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_GET_PORT_TTY: + rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n"); + if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (PortTty.port >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + + rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); + PortP = (p->RIOPortp[PortTty.port]); + if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_SET_PORT_TTY: + if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port); + if (PortTty.port >= (ushort) RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + PortP = (p->RIOPortp[PortTty.port]); + RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM, + OK_TO_SLEEP); + return retval; + + case RIO_SET_PORT_PARAMS: + rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n"); + if (copy_from_user(&PortParams, argp, sizeof(PortParams))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (PortParams.Port >= (ushort) RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + PortP = (p->RIOPortp[PortParams.Port]); + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->Config = PortParams.Config; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_GET_PORT_STATS: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n"); + if (copy_from_user(&portStats, argp, sizeof(struct portStats))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (portStats.port < 0 || portStats.port >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + PortP = (p->RIOPortp[portStats.port]); + portStats.gather = PortP->statsGather; + portStats.txchars = PortP->txchars; + portStats.rxchars = PortP->rxchars; + portStats.opens = PortP->opens; + portStats.closes = PortP->closes; + portStats.ioctls = PortP->ioctls; + if (copy_to_user(argp, &portStats, sizeof(struct portStats))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_RESET_PORT_STATS: + port = arg; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); + if (port >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + PortP = (p->RIOPortp[port]); + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->txchars = 0; + PortP->rxchars = 0; + PortP->opens = 0; + PortP->closes = 0; + PortP->ioctls = 0; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_GATHER_PORT_STATS: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n"); + if (copy_from_user(&portStats, argp, sizeof(struct portStats))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (portStats.port < 0 || portStats.port >= RIO_PORTS) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + PortP = (p->RIOPortp[portStats.port]); + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->statsGather = portStats.gather; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_READ_CONFIG: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); + if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_SET_CONFIG: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n"); + if (!su) { + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + /* + ** move a few value around + */ + for (Host = 0; Host < p->RIONumHosts; Host++) + if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING) + writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer); + return retval; + + case RIO_START_POLLER: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n"); + return -EINVAL; + + case RIO_STOP_POLLER: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n"); + if (!su) { + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + p->RIOPolling = NOT_POLLING; + return retval; + + case RIO_SETDEBUG: + case RIO_GETDEBUG: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n"); + if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (DebugCtrl.SysPort == NO_PORT) { + if (cmd == RIO_SETDEBUG) { + if (!su) { + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + p->rio_debug = DebugCtrl.Debug; + p->RIODebugWait = DebugCtrl.Wait; + rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait); + } else { + rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait); + DebugCtrl.Debug = p->rio_debug; + DebugCtrl.Wait = p->RIODebugWait; + if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + } + } else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } else if (cmd == RIO_SETDEBUG) { + if (!su) { + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug); + } else { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug); + DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug; + if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + } + return retval; + + case RIO_VERSID: + /* + ** Enquire about the release and version. + ** We return MAX_VERSION_LEN bytes, being a + ** textual null terminated string. + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n"); + if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_NUM_HOSTS: + /* + ** Enquire as to the number of hosts located + ** at init time. + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); + if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + case RIO_HOST_FOAD: + /* + ** Kill host. This may not be in the final version... + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg); + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + p->RIOHalted = 1; + p->RIOSystemUp = 0; + + for (Host = 0; Host < p->RIONumHosts; Host++) { + (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot); + memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags)); + p->RIOHosts[Host].Flags = RC_WAITING; + } + RIOFoadWakeup(p); + p->RIONumBootPkts = 0; + p->RIOBooting = 0; + printk("HEEEEELP!\n"); + + for (loop = 0; loop < RIO_PORTS; loop++) { + spin_lock_init(&p->RIOPortp[loop]->portSem); + p->RIOPortp[loop]->InUse = NOT_INUSE; + } + + p->RIOSystemUp = 0; + return retval; + + case RIO_DOWNLOAD: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n"); + if (!su) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n"); + p->RIOError.Error = NOT_SUPER_USER; + return -EPERM; + } + if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode); + + /* + ** It is important that the product code is an unsigned object! + */ + if (DownLoad.ProductCode >= MAX_PRODUCT) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode); + p->RIOError.Error = NO_SUCH_PRODUCT; + return -ENXIO; + } + /* + ** do something! + */ + retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad); + /* <-- Panic */ + p->RIOHalted = 0; + /* + ** and go back, content with a job well completed. + */ + return retval; + + case RIO_PARMS: + { + unsigned int host; + + if (copy_from_user(&host, argp, sizeof(host))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + /* + ** Fetch the parmmap + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n"); + if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) { + p->RIOError.Error = COPYOUT_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); + return -EFAULT; + } + } + return retval; + + case RIO_HOST_REQ: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); + if (copy_from_user(&HostReq, argp, sizeof(HostReq))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (HostReq.HostNum >= p->RIONumHosts) { + p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum); + return -ENXIO; + } + rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum); + + if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) { + p->RIOError.Error = COPYOUT_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n"); + return -EFAULT; + } + return retval; + + case RIO_HOST_DPRAM: + rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n"); + if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (HostDpRam.HostNum >= p->RIONumHosts) { + p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum); + return -ENXIO; + } + rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum); + + if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) { + int off; + /* It's hardware like this that really gets on my tits. */ + static unsigned char copy[sizeof(struct DpRam)]; + for (off = 0; off < sizeof(struct DpRam); off++) + copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off); + if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) { + p->RIOError.Error = COPYOUT_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); + return -EFAULT; + } + } else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) { + p->RIOError.Error = COPYOUT_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); + return -EFAULT; + } + return retval; + + case RIO_SET_BUSY: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); + if (arg > 511) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + p->RIOPortp[arg]->State |= RIO_BUSY; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_HOST_PORT: + /* + ** The daemon want port information + ** (probably for debug reasons) + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); + if (copy_from_user(&PortReq, argp, sizeof(PortReq))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + + if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort); + if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) { + p->RIOError.Error = COPYOUT_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n"); + return -EFAULT; + } + return retval; + + case RIO_HOST_RUP: + /* + ** The daemon want rup information + ** (probably for debug reasons) + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); + if (copy_from_user(&RupReq, argp, sizeof(RupReq))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum); + p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) { /* eek! */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum); + p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + HostP = &p->RIOHosts[RupReq.HostNum]; + + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum); + p->RIOError.Error = HOST_NOT_RUNNING; + return -EIO; + } + rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum); + + if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) { + p->RIOError.Error = COPYOUT_FAILED; + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); + return -EFAULT; + } + return retval; + + case RIO_HOST_LPB: + /* + ** The daemon want lpb information + ** (probably for debug reasons) + */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); + if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host); + p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + if (LpbReq.Link >= LINKS_PER_UNIT) { /* eek! */ + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link); + p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + HostP = &p->RIOHosts[LpbReq.Host]; + + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host); + p->RIOError.Error = HOST_NOT_RUNNING; + return -EIO; + } + rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host); + + if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return retval; + + /* + ** Here 3 IOCTL's that allow us to change the way in which + ** rio logs errors. send them just to syslog or send them + ** to both syslog and console or send them to just the console. + ** + ** See RioStrBuf() in util.c for the other half. + */ + case RIO_SYSLOG_ONLY: + p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */ + return 0; + + case RIO_SYSLOG_CONS: + p->RIOPrintLogState = PRINT_TO_LOG_CONS; /* syslog and console */ + return 0; + + case RIO_CONS_ONLY: + p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */ + return 0; + + case RIO_SIGNALS_ON: + if (p->RIOSignalProcess) { + p->RIOError.Error = SIGNALS_ALREADY_SET; + return -EBUSY; + } + /* FIXME: PID tracking */ + p->RIOSignalProcess = current->pid; + p->RIOPrintDisabled = DONT_PRINT; + return retval; + + case RIO_SIGNALS_OFF: + if (p->RIOSignalProcess != current->pid) { + p->RIOError.Error = NOT_RECEIVING_PROCESS; + return -EPERM; + } + rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n"); + p->RIOSignalProcess = 0; + return retval; + + case RIO_SET_BYTE_MODE: + for (Host = 0; Host < p->RIONumHosts; Host++) + if (p->RIOHosts[Host].Type == RIO_AT) + p->RIOHosts[Host].Mode &= ~WORD_OPERATION; + return retval; + + case RIO_SET_WORD_MODE: + for (Host = 0; Host < p->RIONumHosts; Host++) + if (p->RIOHosts[Host].Type == RIO_AT) + p->RIOHosts[Host].Mode |= WORD_OPERATION; + return retval; + + case RIO_SET_FAST_BUS: + for (Host = 0; Host < p->RIONumHosts; Host++) + if (p->RIOHosts[Host].Type == RIO_AT) + p->RIOHosts[Host].Mode |= FAST_AT_BUS; + return retval; + + case RIO_SET_SLOW_BUS: + for (Host = 0; Host < p->RIONumHosts; Host++) + if (p->RIOHosts[Host].Type == RIO_AT) + p->RIOHosts[Host].Mode &= ~FAST_AT_BUS; + return retval; + + case RIO_MAP_B50_TO_50: + case RIO_MAP_B50_TO_57600: + case RIO_MAP_B110_TO_110: + case RIO_MAP_B110_TO_115200: + rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n"); + port = arg; + if (port < 0 || port > 511) { + rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + switch (cmd) { + case RIO_MAP_B50_TO_50: + p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50; + break; + case RIO_MAP_B50_TO_57600: + p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50; + break; + case RIO_MAP_B110_TO_110: + p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110; + break; + case RIO_MAP_B110_TO_115200: + p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110; + break; + } + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_STREAM_INFO: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n"); + return -EINVAL; + + case RIO_SEND_PACKET: + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); + if (copy_from_user(&SendPack, argp, sizeof(SendPack))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + if (SendPack.PortNum >= 128) { + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -ENXIO; + } + + PortP = p->RIOPortp[SendPack.PortNum]; + rio_spin_lock_irqsave(&PortP->portSem, flags); + + if (!can_add_transmit(&PacketP, PortP)) { + p->RIOError.Error = UNIT_IS_IN_USE; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return -ENOSPC; + } + + for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++) + writeb(SendPack.Data[loop], &PacketP->data[loop]); + + writeb(SendPack.Len, &PacketP->len); + + add_transmit(PortP); + /* + ** Count characters transmitted for port statistics reporting + */ + if (PortP->statsGather) + PortP->txchars += (SendPack.Len & 127); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + + case RIO_NO_MESG: + if (su) + p->RIONoMessage = 1; + return su ? 0 : -EPERM; + + case RIO_MESG: + if (su) + p->RIONoMessage = 0; + return su ? 0 : -EPERM; + + case RIO_WHAT_MESG: + if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return 0; + + case RIO_MEM_DUMP: + if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr); + + if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) { + p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + if (SubCmd.Host >= p->RIONumHosts) { + p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort; + + PortP = p->RIOPortp[port]; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + + if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return -EBUSY; + } else + PortP->State |= RIO_BUSY; + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return 0; + + case RIO_TICK: + if (arg >= p->RIONumHosts) + return -EINVAL; + rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg); + writeb(0xFF, &p->RIOHosts[arg].SetInt); + return 0; + + case RIO_TOCK: + if (arg >= p->RIONumHosts) + return -EINVAL; + rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg); + writeb(0xFF, &p->RIOHosts[arg].ResetInt); + return 0; + + case RIO_READ_CHECK: + /* Check reads for pkts with data[0] the same */ + p->RIOReadCheck = !p->RIOReadCheck; + if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) { + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return 0; + + case RIO_READ_REGISTER: + if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) { + p->RIOError.Error = COPYIN_FAILED; + return -EFAULT; + } + rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr); + + if (SubCmd.Port > 511) { + rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port); + p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) { + p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + if (SubCmd.Host >= p->RIONumHosts) { + p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port; + PortP = p->RIOPortp[port]; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + + if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) == + RIO_FAIL) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return -EBUSY; + } else + PortP->State |= RIO_BUSY; + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); + p->RIOError.Error = COPYOUT_FAILED; + return -EFAULT; + } + return 0; + /* + ** rio_make_dev: given port number (0-511) ORed with port type + ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t + ** value to pass to mknod to create the correct device node. + */ + case RIO_MAKE_DEV: + { + unsigned int port = arg & RIO_MODEM_MASK; + unsigned int ret; + + switch (arg & RIO_DEV_MASK) { + case RIO_DEV_DIRECT: + ret = drv_makedev(MAJOR(dev), port); + rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret); + return ret; + case RIO_DEV_MODEM: + ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT)); + rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret); + return ret; + case RIO_DEV_XPRINT: + ret = drv_makedev(MAJOR(dev), port); + rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret); + return ret; + } + rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n"); + return -EINVAL; + } + /* + ** rio_minor: given a dev_t from a stat() call, return + ** the port number (0-511) ORed with the port type + ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT ) + */ + case RIO_MINOR: + { + dev_t dv; + int mino; + unsigned long ret; + + dv = (dev_t) (arg); + mino = RIO_UNMODEM(dv); + + if (RIO_ISMODEM(dv)) { + rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino); + ret = mino | RIO_DEV_MODEM; + } else { + rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino); + ret = mino | RIO_DEV_DIRECT; + } + return ret; + } + } + rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd); + p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; + + func_exit(); + return -EINVAL; +} + +/* +** Pre-emptive commands go on RUPs and are only one byte long. +*/ +int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) +{ + struct CmdBlk *CmdBlkP; + struct PktCmd_M *PktCmdP; + int Ret; + ushort rup; + int port; + + if (PortP->State & RIO_DELETED) { + rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n"); + return RIO_FAIL; + } + + if ((PortP->InUse == (typeof(PortP->InUse))-1) || + !(CmdBlkP = RIOGetCmdBlk())) { + rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block " + "for command %d on port %d\n", Cmd, PortP->PortNum); + return RIO_FAIL; + } + + rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", + CmdBlkP, PortP->InUse); + + PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0]; + + CmdBlkP->Packet.src_unit = 0; + if (PortP->SecondBlock) + rup = PortP->ID2; + else + rup = PortP->RupNum; + CmdBlkP->Packet.dest_unit = rup; + CmdBlkP->Packet.src_port = COMMAND_RUP; + CmdBlkP->Packet.dest_port = COMMAND_RUP; + CmdBlkP->Packet.len = PKT_CMD_BIT | 2; + CmdBlkP->PostFuncP = RIOUnUse; + CmdBlkP->PostArg = (unsigned long) PortP; + PktCmdP->Command = Cmd; + port = PortP->HostPort % (ushort) PORTS_PER_RTA; + /* + ** Index ports 8-15 for 2nd block of 16 port RTA. + */ + if (PortP->SecondBlock) + port += (ushort) PORTS_PER_RTA; + PktCmdP->PhbNum = port; + + switch (Cmd) { + case RIOC_MEMDUMP: + rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p " + "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); + PktCmdP->SubCommand = RIOC_MEMDUMP; + PktCmdP->SubAddr = SubCmd.Addr; + break; + case RIOC_FCLOSE: + rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", + CmdBlkP); + break; + case RIOC_READ_REGISTER: + rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) " + "command blk %p\n", (int) SubCmd.Addr, CmdBlkP); + PktCmdP->SubCommand = RIOC_READ_REGISTER; + PktCmdP->SubAddr = SubCmd.Addr; + break; + case RIOC_RESUME: + rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", + CmdBlkP); + break; + case RIOC_RFLUSH: + rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", + CmdBlkP); + CmdBlkP->PostFuncP = RIORFlushEnable; + break; + case RIOC_SUSPEND: + rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", + CmdBlkP); + break; + + case RIOC_MGET: + rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", + CmdBlkP); + break; + + case RIOC_MSET: + case RIOC_MBIC: + case RIOC_MBIS: + CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; + rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command " + "blk %p\n", CmdBlkP); + break; + + case RIOC_WFLUSH: + /* + ** If we have queued up the maximum number of Write flushes + ** allowed then we should not bother sending any more to the + ** RTA. + */ + if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) { + rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, " + "WflushFlag about to wrap!"); + RIOFreeCmdBlk(CmdBlkP); + return (RIO_FAIL); + } else { + rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command " + "blk %p\n", CmdBlkP); + CmdBlkP->PostFuncP = RIOWFlushMark; + } + break; + } + + PortP->InUse++; + + Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP); + + return Ret; +} diff --git a/drivers/staging/generic_serial/rio/riodrvr.h b/drivers/staging/generic_serial/rio/riodrvr.h new file mode 100644 index 000000000000..0907e711b355 --- /dev/null +++ b/drivers/staging/generic_serial/rio/riodrvr.h @@ -0,0 +1,138 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : riodrvr.h +** SID : 1.3 +** Last Modified : 11/6/98 09:22:46 +** Retrieved : 11/6/98 09:22:46 +** +** ident @(#)riodrvr.h 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __riodrvr_h +#define __riodrvr_h + +#include /* for HZ */ + +#define MEMDUMP_SIZE 32 +#define MOD_DISABLE (RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT) + + +struct rio_info { + int mode; /* Intr or polled, word/byte */ + spinlock_t RIOIntrSem; /* Interrupt thread sem */ + int current_chan; /* current channel */ + int RIOFailed; /* Not initialised ? */ + int RIOInstallAttempts; /* no. of rio-install() calls */ + int RIOLastPCISearch; /* status of last search */ + int RIONumHosts; /* Number of RIO Hosts */ + struct Host *RIOHosts; /* RIO Host values */ + struct Port **RIOPortp; /* RIO port values */ +/* +** 02.03.1999 ARG - ESIL 0820 fix +** We no longer use RIOBootMode +** + int RIOBootMode; * RIO boot mode * +** +*/ + int RIOPrintDisabled; /* RIO printing disabled ? */ + int RIOPrintLogState; /* RIO printing state ? */ + int RIOPolling; /* Polling ? */ +/* +** 09.12.1998 ARG - ESIL 0776 part fix +** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted. +** The fix for this ESIL introduces another member (RIORtaDisCons) here to be +** updated in RIOConCon() - to keep track of RTA connections/disconnections. +** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons. +*/ + int RIOHalted; /* halted ? */ + int RIORtaDisCons; /* RTA connections/disconnections */ + unsigned int RIOReadCheck; /* Rio read check */ + unsigned int RIONoMessage; /* To display message or not */ + unsigned int RIONumBootPkts; /* how many packets for an RTA */ + unsigned int RIOBootCount; /* size of RTA code */ + unsigned int RIOBooting; /* count of outstanding boots */ + unsigned int RIOSystemUp; /* Booted ?? */ + unsigned int RIOCounting; /* for counting interrupts */ + unsigned int RIOIntCount; /* # of intr since last check */ + unsigned int RIOTxCount; /* number of xmit intrs */ + unsigned int RIORxCount; /* number of rx intrs */ + unsigned int RIORupCount; /* number of rup intrs */ + int RIXTimer; + int RIOBufferSize; /* Buffersize */ + int RIOBufferMask; /* Buffersize */ + + int RIOFirstMajor; /* First host card's major no */ + + unsigned int RIOLastPortsMapped; /* highest port number known */ + unsigned int RIOFirstPortsMapped; /* lowest port number known */ + + unsigned int RIOLastPortsBooted; /* highest port number running */ + unsigned int RIOFirstPortsBooted; /* lowest port number running */ + + unsigned int RIOLastPortsOpened; /* highest port number running */ + unsigned int RIOFirstPortsOpened; /* lowest port number running */ + + /* Flag to say that the topology information has been changed. */ + unsigned int RIOQuickCheck; + unsigned int CdRegister; /* ??? */ + int RIOSignalProcess; /* Signalling process */ + int rio_debug; /* To debug ... */ + int RIODebugWait; /* For what ??? */ + int tpri; /* Thread prio */ + int tid; /* Thread id */ + unsigned int _RIO_Polled; /* Counter for polling */ + unsigned int _RIO_Interrupted; /* Counter for interrupt */ + int intr_tid; /* iointset return value */ + int TxEnSem; /* TxEnable Semaphore */ + + + struct Error RIOError; /* to Identify what went wrong */ + struct Conf RIOConf; /* Configuration ??? */ + struct ttystatics channel[RIO_PORTS]; /* channel information */ + char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)] + [RTA_BOOT_DATA_SIZE]; + struct Map RIOConnectTable[TOTAL_MAP_ENTRIES]; + struct Map RIOSavedTable[TOTAL_MAP_ENTRIES]; + + /* RTA to host binding table for master/slave operation */ + unsigned long RIOBindTab[MAX_RTA_BINDINGS]; + /* RTA memory dump variable */ + unsigned char RIOMemDump[MEMDUMP_SIZE]; + struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES]; + +}; + + +#ifdef linux +#define debug(x) printk x +#else +#define debug(x) kkprintf x +#endif + + + +#define RIO_RESET_INT 0x7d80 + +#endif /* __riodrvr.h */ diff --git a/drivers/staging/generic_serial/rio/rioinfo.h b/drivers/staging/generic_serial/rio/rioinfo.h new file mode 100644 index 000000000000..42ff1e79d96f --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioinfo.h @@ -0,0 +1,92 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioinfo.h +** SID : 1.2 +** Last Modified : 11/6/98 14:07:49 +** Retrieved : 11/6/98 14:07:50 +** +** ident @(#)rioinfo.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rioinfo_h +#define __rioinfo_h + +/* +** Host card data structure +*/ +struct RioHostInfo { + long location; /* RIO Card Base I/O address */ + long vector; /* RIO Card IRQ vector */ + int bus; /* ISA/EISA/MCA/PCI */ + int mode; /* pointer to host mode - INTERRUPT / POLLED */ + struct old_sgttyb + *Sg; /* pointer to default term characteristics */ +}; + + +/* Mode in rio device info */ +#define INTERRUPTED_MODE 0x01 /* Interrupt is generated */ +#define POLLED_MODE 0x02 /* No interrupt */ +#define AUTO_MODE 0x03 /* Auto mode */ + +#define WORD_ACCESS_MODE 0x10 /* Word Access Mode */ +#define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */ + + +/* Bus type that RIO supports */ +#define ISA_BUS 0x01 /* The card is ISA */ +#define EISA_BUS 0x02 /* The card is EISA */ +#define MCA_BUS 0x04 /* The card is MCA */ +#define PCI_BUS 0x08 /* The card is PCI */ + +/* +** 11.11.1998 ARG - ESIL ???? part fix +** Moved definition for 'CHAN' here from rioinfo.c (it is now +** called 'DEF_TERM_CHARACTERISTICS'). +*/ + +#define DEF_TERM_CHARACTERISTICS \ +{ \ + B19200, B19200, /* input and output speed */ \ + 'H' - '@', /* erase char */ \ + -1, /* 2nd erase char */ \ + 'U' - '@', /* kill char */ \ + ECHO | CRMOD, /* mode */ \ + 'C' - '@', /* interrupt character */ \ + '\\' - '@', /* quit char */ \ + 'Q' - '@', /* start char */ \ + 'S' - '@', /* stop char */ \ + 'D' - '@', /* EOF */ \ + -1, /* brk */ \ + (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */ \ + 'Z' - '@', /* process stop */ \ + 'Y' - '@', /* delayed stop */ \ + 'R' - '@', /* reprint line */ \ + 'O' - '@', /* flush output */ \ + 'W' - '@', /* word erase */ \ + 'V' - '@' /* literal next char */ \ +} + +#endif /* __rioinfo_h */ diff --git a/drivers/staging/generic_serial/rio/rioinit.c b/drivers/staging/generic_serial/rio/rioinit.c new file mode 100644 index 000000000000..24a282bb89d4 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioinit.c @@ -0,0 +1,421 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioinit.c +** SID : 1.3 +** Last Modified : 11/6/98 10:33:43 +** Retrieved : 11/6/98 10:33:49 +** +** ident @(#)rioinit.c 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +#include "linux_compat.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" +#include "rio_linux.h" + +int RIOPCIinit(struct rio_info *p, int Mode); + +static int RIOScrub(int, u8 __iomem *, int); + + +/** +** RIOAssignAT : +** +** Fill out the fields in the p->RIOHosts structure now we know we know +** we have a board present. +** +** bits < 0 indicates 8 bit operation requested, +** bits > 0 indicates 16 bit operation. +*/ + +int RIOAssignAT(struct rio_info *p, int Base, void __iomem *virtAddr, int mode) +{ + int bits; + struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr; + + if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE)) + bits = BYTE_OPERATION; + else + bits = WORD_OPERATION; + + /* + ** Board has passed its scrub test. Fill in all the + ** transient stuff. + */ + p->RIOHosts[p->RIONumHosts].Caddr = virtAddr; + p->RIOHosts[p->RIONumHosts].CardP = virtAddr; + + /* + ** Revision 01 AT host cards don't support WORD operations, + */ + if (readb(&cardp->DpRevision) == 01) + bits = BYTE_OPERATION; + + p->RIOHosts[p->RIONumHosts].Type = RIO_AT; + p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card; + /* set this later */ + p->RIOHosts[p->RIONumHosts].Slot = -1; + p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits; + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE , + &p->RIOHosts[p->RIONumHosts].Control); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE, + &p->RIOHosts[p->RIONumHosts].Control); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); + p->RIOHosts[p->RIONumHosts].UniqueNum = + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum); + + p->RIONumHosts++; + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base); + return(1); +} + +static u8 val[] = { +#ifdef VERY_LONG_TEST + 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, +#endif + 0xff, 0x00, 0x00 }; + +#define TEST_END sizeof(val) + +/* +** RAM test a board. +** Nothing too complicated, just enough to check it out. +*/ +int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot) +{ + struct DpRam __iomem *DpRam = caddr; + void __iomem *ram[4]; + int size[4]; + int op, bank; + int nbanks; + + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n", + type, DpRam, slot); + + RIOHostReset(type, DpRam, slot); + + /* + ** Scrub the memory. This comes in several banks: + ** DPsram1 - 7000h bytes + ** DPsram2 - 200h bytes + ** DPsram3 - 7000h bytes + ** scratch - 1000h bytes + */ + + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n"); + + size[0] = DP_SRAM1_SIZE; + size[1] = DP_SRAM2_SIZE; + size[2] = DP_SRAM3_SIZE; + size[3] = DP_SCRATCH_SIZE; + + ram[0] = DpRam->DpSram1; + ram[1] = DpRam->DpSram2; + ram[2] = DpRam->DpSram3; + nbanks = (type == RIO_PCI) ? 3 : 4; + if (nbanks == 4) + ram[3] = DpRam->DpScratch; + + + if (nbanks == 3) { + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n", + ram[0], size[0], ram[1], size[1], ram[2], size[2]); + } else { + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n", + ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]); + } + + /* + ** This scrub operation will test for crosstalk between + ** banks. TEST_END is a magic number, and relates to the offset + ** within the 'val' array used by Scrub. + */ + for (op=0; opMapping[UnitId].Name, "UNKNOWN RTA X-XX", 17); + HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts); + if ((UnitId+1) > 9) { + HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10); + HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10); + } + else { + HostP->Mapping[UnitId].Name[14]='1'+UnitId; + HostP->Mapping[UnitId].Name[15]=0; + } + return 0; +} + +#define RIO_RELEASE "Linux" +#define RELEASE_ID "1.0" + +static struct rioVersion stVersion; + +struct rioVersion *RIOVersid(void) +{ + strlcpy(stVersion.version, "RIO driver for linux V1.0", + sizeof(stVersion.version)); + strlcpy(stVersion.buildDate, __DATE__, + sizeof(stVersion.buildDate)); + + return &stVersion; +} + +void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot) +{ + /* + ** Reset the Tpu + */ + rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: type 0x%x", Type); + switch ( Type ) { + case RIO_AT: + rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION | + SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); + writeb(0xFF, &DpRamP->DpResetTpu); + udelay(3); + rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | + BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); + writeb(0xFF, &DpRamP->DpResetTpu); + udelay(3); + break; + case RIO_PCI: + rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); + writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl); + writeb(0xFF, &DpRamP->DpResetInt); + writeb(0xFF, &DpRamP->DpResetTpu); + udelay(100); + break; + default: + rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); + break; + } + return; +} diff --git a/drivers/staging/generic_serial/rio/riointr.c b/drivers/staging/generic_serial/rio/riointr.c new file mode 100644 index 000000000000..2e71aecae206 --- /dev/null +++ b/drivers/staging/generic_serial/rio/riointr.c @@ -0,0 +1,645 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : riointr.c +** SID : 1.2 +** Last Modified : 11/6/98 10:33:44 +** Retrieved : 11/6/98 10:33:49 +** +** ident @(#)riointr.c 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" + + +static void RIOReceive(struct rio_info *, struct Port *); + + +static char *firstchars(char *p, int nch) +{ + static char buf[2][128]; + static int t = 0; + t = !t; + memcpy(buf[t], p, nch); + buf[t][nch] = 0; + return buf[t]; +} + + +#define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask)) +/* Enable and start the transmission of packets */ +void RIOTxEnable(char *en) +{ + struct Port *PortP; + struct rio_info *p; + struct tty_struct *tty; + int c; + struct PKT __iomem *PacketP; + unsigned long flags; + + PortP = (struct Port *) en; + p = (struct rio_info *) PortP->p; + tty = PortP->gs.port.tty; + + + rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt); + + if (!PortP->gs.xmit_cnt) + return; + + + /* This routine is an order of magnitude simpler than the specialix + version. One of the disadvantages is that this version will send + an incomplete packet (usually 64 bytes instead of 72) once for + every 4k worth of data. Let's just say that this won't influence + performance significantly..... */ + + rio_spin_lock_irqsave(&PortP->portSem, flags); + + while (can_add_transmit(&PacketP, PortP)) { + c = PortP->gs.xmit_cnt; + if (c > PKT_MAX_DATA_LEN) + c = PKT_MAX_DATA_LEN; + + /* Don't copy past the end of the source buffer */ + if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail) + c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail; + + { + int t; + t = (c > 10) ? 10 : c; + + rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t)); + } + /* If for one reason or another, we can't copy more data, + we're done! */ + if (c == 0) + break; + + rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c); + /* udelay (1); */ + + writeb(c, &(PacketP->len)); + if (!(PortP->State & RIO_DELETED)) { + add_transmit(PortP); + /* + ** Count chars tx'd for port statistics reporting + */ + if (PortP->statsGather) + PortP->txchars += c; + } + PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1); + PortP->gs.xmit_cnt -= c; + } + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + + if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) + tty_wakeup(PortP->gs.port.tty); + +} + + +/* +** RIO Host Service routine. Does all the work traditionally associated with an +** interrupt. +*/ +static int RupIntr; +static int RxIntr; +static int TxIntr; + +void RIOServiceHost(struct rio_info *p, struct Host *HostP) +{ + rio_spin_lock(&HostP->HostLock); + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { + static int t = 0; + rio_spin_unlock(&HostP->HostLock); + if ((t++ % 200) == 0) + rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags); + return; + } + rio_spin_unlock(&HostP->HostLock); + + if (readw(&HostP->ParmMapP->rup_intr)) { + writew(0, &HostP->ParmMapP->rup_intr); + p->RIORupCount++; + RupIntr++; + rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts); + RIOPollHostCommands(p, HostP); + } + + if (readw(&HostP->ParmMapP->rx_intr)) { + int port; + + writew(0, &HostP->ParmMapP->rx_intr); + p->RIORxCount++; + RxIntr++; + + rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts); + /* + ** Loop through every port. If the port is mapped into + ** the system ( i.e. has /dev/ttyXXXX associated ) then it is + ** worth checking. If the port isn't open, grab any packets + ** hanging on its receive queue and stuff them on the free + ** list; check for commands on the way. + */ + for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { + struct Port *PortP = p->RIOPortp[port]; + struct tty_struct *ttyP; + struct PKT __iomem *PacketP; + + /* + ** not mapped in - most of the RIOPortp[] information + ** has not been set up! + ** Optimise: ports come in bundles of eight. + */ + if (!PortP->Mapped) { + port += 7; + continue; /* with the next port */ + } + + /* + ** If the host board isn't THIS host board, check the next one. + ** optimise: ports come in bundles of eight. + */ + if (PortP->HostP != HostP) { + port += 7; + continue; + } + + /* + ** Let us see - is the port open? If not, then don't service it. + */ + if (!(PortP->PortState & PORT_ISOPEN)) { + continue; + } + + /* + ** find corresponding tty structure. The process of mapping + ** the ports puts these here. + */ + ttyP = PortP->gs.port.tty; + + /* + ** Lock the port before we begin working on it. + */ + rio_spin_lock(&PortP->portSem); + + /* + ** Process received data if there is any. + */ + if (can_remove_receive(&PacketP, PortP)) + RIOReceive(p, PortP); + + /* + ** If there is no data left to be read from the port, and + ** it's handshake bit is set, then we must clear the handshake, + ** so that that downstream RTA is re-enabled. + */ + if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) { + /* + ** MAGIC! ( Basically, handshake the RX buffer, so that + ** the RTAs upstream can be re-enabled. ) + */ + rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n"); + writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); + } + rio_spin_unlock(&PortP->portSem); + } + } + + if (readw(&HostP->ParmMapP->tx_intr)) { + int port; + + writew(0, &HostP->ParmMapP->tx_intr); + + p->RIOTxCount++; + TxIntr++; + rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts); + + /* + ** Loop through every port. + ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX + ** associated ) then it is worth checking. + */ + for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { + struct Port *PortP = p->RIOPortp[port]; + struct tty_struct *ttyP; + struct PKT __iomem *PacketP; + + /* + ** not mapped in - most of the RIOPortp[] information + ** has not been set up! + */ + if (!PortP->Mapped) { + port += 7; + continue; /* with the next port */ + } + + /* + ** If the host board isn't running, then its data structures + ** are no use to us - continue quietly. + */ + if (PortP->HostP != HostP) { + port += 7; + continue; /* with the next port */ + } + + /* + ** Let us see - is the port open? If not, then don't service it. + */ + if (!(PortP->PortState & PORT_ISOPEN)) { + continue; + } + + rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port); + /* + ** Lock the port before we begin working on it. + */ + rio_spin_lock(&PortP->portSem); + + /* + ** If we can't add anything to the transmit queue, then + ** we need do none of this processing. + */ + if (!can_add_transmit(&PacketP, PortP)) { + rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n"); + rio_spin_unlock(&PortP->portSem); + continue; + } + + /* + ** find corresponding tty structure. The process of mapping + ** the ports puts these here. + */ + ttyP = PortP->gs.port.tty; + /* If ttyP is NULL, the port is getting closed. Forget about it. */ + if (!ttyP) { + rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n"); + rio_spin_unlock(&PortP->portSem); + continue; + } + /* + ** If there is more room available we start up the transmit + ** data process again. This can be direct I/O, if the cookmode + ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the + ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch + ** characters via the line discipline. We must always call + ** the line discipline, + ** so that user input characters can be echoed correctly. + ** + ** ++++ Update +++++ + ** With the advent of double buffering, we now see if + ** TxBufferOut-In is non-zero. If so, then we copy a packet + ** to the output place, and set it going. If this empties + ** the buffer, then we must issue a wakeup( ) on OUT. + ** If it frees space in the buffer then we must issue + ** a wakeup( ) on IN. + ** + ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we + ** have to send a WFLUSH command down the PHB, to mark the + ** end point of a WFLUSH. We also need to clear out any + ** data from the double buffer! ( note that WflushFlag is a + ** *count* of the number of WFLUSH commands outstanding! ) + ** + ** ++++ And there's more! + ** If an RTA is powered off, then on again, and rebooted, + ** whilst it has ports open, then we need to re-open the ports. + ** ( reasonable enough ). We can't do this when we spot the + ** re-boot, in interrupt time, because the queue is probably + ** full. So, when we come in here, we need to test if any + ** ports are in this condition, and re-open the port before + ** we try to send any more data to it. Now, the re-booted + ** RTA will be discarding packets from the PHB until it + ** receives this open packet, but don't worry tooo much + ** about that. The one thing that is interesting is the + ** combination of this effect and the WFLUSH effect! + */ + /* For now don't handle RTA reboots. -- REW. + Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */ + if (PortP->MagicFlags) { + if (PortP->MagicFlags & MAGIC_REBOOT) { + /* + ** well, the RTA has been rebooted, and there is room + ** on its queue to add the open packet that is required. + ** + ** The messy part of this line is trying to decide if + ** we need to call the Param function as a tty or as + ** a modem. + ** DONT USE CLOCAL AS A TEST FOR THIS! + ** + ** If we can't param the port, then move on to the + ** next port. + */ + PortP->InUse = NOT_INUSE; + + rio_spin_unlock(&PortP->portSem); + if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) + continue; /* with next port */ + rio_spin_lock(&PortP->portSem); + PortP->MagicFlags &= ~MAGIC_REBOOT; + } + + /* + ** As mentioned above, this is a tacky hack to cope + ** with WFLUSH + */ + if (PortP->WflushFlag) { + rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n"); + + if (PortP->InUse) + rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n"); + } + + while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) { + int p; + struct PktCmd __iomem *PktCmdP; + + rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n"); + /* + ** make it look just like a WFLUSH command + */ + PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0]; + + writeb(RIOC_WFLUSH, &PktCmdP->Command); + + p = PortP->HostPort % (u16) PORTS_PER_RTA; + + /* + ** If second block of ports for 16 port RTA, add 8 + ** to index 8-15. + */ + if (PortP->SecondBlock) + p += PORTS_PER_RTA; + + writeb(p, &PktCmdP->PhbNum); + + /* + ** to make debuggery easier + */ + writeb('W', &PacketP->data[2]); + writeb('F', &PacketP->data[3]); + writeb('L', &PacketP->data[4]); + writeb('U', &PacketP->data[5]); + writeb('S', &PacketP->data[6]); + writeb('H', &PacketP->data[7]); + writeb(' ', &PacketP->data[8]); + writeb('0' + PortP->WflushFlag, &PacketP->data[9]); + writeb(' ', &PacketP->data[10]); + writeb(' ', &PacketP->data[11]); + writeb('\0', &PacketP->data[12]); + + /* + ** its two bytes long! + */ + writeb(PKT_CMD_BIT | 2, &PacketP->len); + + /* + ** queue it! + */ + if (!(PortP->State & RIO_DELETED)) { + add_transmit(PortP); + /* + ** Count chars tx'd for port statistics reporting + */ + if (PortP->statsGather) + PortP->txchars += 2; + } + + if (--(PortP->WflushFlag) == 0) { + PortP->MagicFlags &= ~MAGIC_FLUSH; + } + + rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag); + } + if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) { + if (PortP->MagicFlags & MAGIC_FLUSH) { + PortP->MagicFlags |= MORE_OUTPUT_EYGOR; + } else { + if (!can_add_transmit(&PacketP, PortP)) { + rio_spin_unlock(&PortP->portSem); + continue; + } + rio_spin_unlock(&PortP->portSem); + RIOTxEnable((char *) PortP); + rio_spin_lock(&PortP->portSem); + PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; + } + } + } + + + /* + ** If we can't add anything to the transmit queue, then + ** we need do none of the remaining processing. + */ + if (!can_add_transmit(&PacketP, PortP)) { + rio_spin_unlock(&PortP->portSem); + continue; + } + + rio_spin_unlock(&PortP->portSem); + RIOTxEnable((char *) PortP); + } + } +} + +/* +** Routine for handling received data for tty drivers +*/ +static void RIOReceive(struct rio_info *p, struct Port *PortP) +{ + struct tty_struct *TtyP; + unsigned short transCount; + struct PKT __iomem *PacketP; + register unsigned int DataCnt; + unsigned char __iomem *ptr; + unsigned char *buf; + int copied = 0; + + static int intCount, RxIntCnt; + + /* + ** The receive data process is to remove packets from the + ** PHB until there aren't any more or the current cblock + ** is full. When this occurs, there will be some left over + ** data in the packet, that we must do something with. + ** As we haven't unhooked the packet from the read list + ** yet, we can just leave the packet there, having first + ** made a note of how far we got. This means that we need + ** a pointer per port saying where we start taking the + ** data from - this will normally be zero, but when we + ** run out of space it will be set to the offset of the + ** next byte to copy from the packet data area. The packet + ** length field is decremented by the number of bytes that + ** we successfully removed from the packet. When this reaches + ** zero, we reset the offset pointer to be zero, and free + ** the packet from the front of the queue. + */ + + intCount++; + + TtyP = PortP->gs.port.tty; + if (!TtyP) { + rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n"); + return; + } + + if (PortP->State & RIO_THROTTLE_RX) { + rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n"); + return; + } + + if (PortP->State & RIO_DELETED) { + while (can_remove_receive(&PacketP, PortP)) { + remove_receive(PortP); + put_free_end(PortP->HostP, PacketP); + } + } else { + /* + ** loop, just so long as: + ** i ) there's some data ( i.e. can_remove_receive ) + ** ii ) we haven't been blocked + ** iii ) there's somewhere to put the data + ** iv ) we haven't outstayed our welcome + */ + transCount = 1; + while (can_remove_receive(&PacketP, PortP) + && transCount) { + RxIntCnt++; + + /* + ** check that it is not a command! + */ + if (readb(&PacketP->len) & PKT_CMD_BIT) { + rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n"); + /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */ + rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit)); + rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port)); + rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", readb(&PacketP->src_unit)); + rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", readb(&PacketP->src_port)); + rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", readb(&PacketP->len)); + rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", readb(&PacketP->control)); + rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", readw(&PacketP->csum)); + rio_dprintk(RIO_DEBUG_INTR, " data bytes: "); + for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++) + rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt])); + remove_receive(PortP); + put_free_end(PortP->HostP, PacketP); + continue; /* with next packet */ + } + + /* + ** How many characters can we move 'upstream' ? + ** + ** Determine the minimum of the amount of data + ** available and the amount of space in which to + ** put it. + ** + ** 1. Get the packet length by masking 'len' + ** for only the length bits. + ** 2. Available space is [buffer size] - [space used] + ** + ** Transfer count is the minimum of packet length + ** and available space. + */ + + transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK); + rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount); + /* + ** To use the following 'kkprintfs' for debugging - change the '#undef' + ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the + ** driver). + */ + ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart; + + tty_prepare_flip_string(TtyP, &buf, transCount); + rio_memcpy_fromio(buf, ptr, transCount); + PortP->RxDataStart += transCount; + writeb(readb(&PacketP->len)-transCount, &PacketP->len); + copied += transCount; + + + + if (readb(&PacketP->len) == 0) { + /* + ** If we have emptied the packet, then we can + ** free it, and reset the start pointer for + ** the next packet. + */ + remove_receive(PortP); + put_free_end(PortP->HostP, PacketP); + PortP->RxDataStart = 0; + } + } + } + if (copied) { + rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied); + tty_flip_buffer_push(TtyP); + } + + return; +} + diff --git a/drivers/staging/generic_serial/rio/rioioctl.h b/drivers/staging/generic_serial/rio/rioioctl.h new file mode 100644 index 000000000000..e8af5b30519e --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioioctl.h @@ -0,0 +1,57 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioioctl.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:13 +** Retrieved : 11/6/98 11:34:22 +** +** ident @(#)rioioctl.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rioioctl_h__ +#define __rioioctl_h__ + +/* +** RIO device driver - user ioctls and associated structures. +*/ + +struct portStats { + int port; + int gather; + unsigned long txchars; + unsigned long rxchars; + unsigned long opens; + unsigned long closes; + unsigned long ioctls; +}; + +#define RIOC ('R'<<8)|('i'<<16)|('o'<<24) + +#define RIO_QUICK_CHECK (RIOC | 105) +#define RIO_GATHER_PORT_STATS (RIOC | 193) +#define RIO_RESET_PORT_STATS (RIOC | 194) +#define RIO_GET_PORT_STATS (RIOC | 195) + +#endif /* __rioioctl_h__ */ diff --git a/drivers/staging/generic_serial/rio/rioparam.c b/drivers/staging/generic_serial/rio/rioparam.c new file mode 100644 index 000000000000..6415f3f32a72 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioparam.c @@ -0,0 +1,663 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioparam.c +** SID : 1.3 +** Last Modified : 11/6/98 10:33:45 +** Retrieved : 11/6/98 10:33:50 +** +** ident @(#)rioparam.c 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" +#include "param.h" + + + +/* +** The Scam, based on email from jeremyr@bugs.specialix.co.uk.... +** +** To send a command on a particular port, you put a packet with the +** command bit set onto the port. The command bit is in the len field, +** and gets ORed in with the actual byte count. +** +** When you send a packet with the command bit set the first +** data byte (data[0]) is interpreted as the command to execute. +** It also governs what data structure overlay should accompany the packet. +** Commands are defined in cirrus/cirrus.h +** +** If you want the command to pre-emt data already on the queue for the +** port, set the pre-emptive bit in conjunction with the command bit. +** It is not defined what will happen if you set the preemptive bit +** on a packet that is NOT a command. +** +** Pre-emptive commands should be queued at the head of the queue using +** add_start(), whereas normal commands and data are enqueued using +** add_end(). +** +** Most commands do not use the remaining bytes in the data array. The +** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and +** OPEN are currently analogous). With these three commands the following +** 11 data bytes are all used to pass config information such as baud rate etc. +** The fields are also defined in cirrus.h. Some contain straightforward +** information such as the transmit XON character. Two contain the transmit and +** receive baud rates respectively. For most baud rates there is a direct +** mapping between the rates defined in and the byte in the +** packet. There are additional (non UNIX-standard) rates defined in +** /u/dos/rio/cirrus/h/brates.h. +** +** The rest of the data fields contain approximations to the Cirrus registers +** that are used to program number of bits etc. Each registers bit fields is +** defined in cirrus.h. +** +** NB. Only use those bits that are defined as being driver specific +** or common to the RTA and the driver. +** +** All commands going from RTA->Host will be dealt with by the Host code - you +** will never see them. As with the SI there will be three fields to look out +** for in each phb (not yet defined - needs defining a.s.a.p). +** +** modem_status - current state of handshake pins. +** +** port_status - current port status - equivalent to hi_stat for SI, indicates +** if port is IDLE_OPEN, IDLE_CLOSED etc. +** +** break_status - bit X set if break has been received. +** +** Happy hacking. +** +*/ + +/* +** RIOParam is used to open or configure a port. You pass it a PortP, +** which will have a tty struct attached to it. You also pass a command, +** either OPEN or CONFIG. The port's setup is taken from the t_ fields +** of the tty struct inside the PortP, and the port is either opened +** or re-configured. You must also tell RIOParam if the device is a modem +** device or not (i.e. top bit of minor number set or clear - take special +** care when deciding on this!). +** RIOParam neither flushes nor waits for drain, and is NOT preemptive. +** +** RIOParam assumes it will be called at splrio(), and also assumes +** that CookMode is set correctly in the port structure. +** +** NB. for MPX +** tty lock must NOT have been previously acquired. +*/ +int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) +{ + struct tty_struct *TtyP; + int retval; + struct phb_param __iomem *phb_param_ptr; + struct PKT __iomem *PacketP; + int res; + u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0; + u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0; + u8 LNext = 0, TxBaud = 0, RxBaud = 0; + int retries = 0xff; + unsigned long flags; + + func_enter(); + + TtyP = PortP->gs.port.tty; + + rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP); + + if (!TtyP) { + rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n"); + + func_exit(); + + return RIO_FAIL; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + + if (cmd == RIOC_OPEN) { + /* + ** If the port is set to store or lock the parameters, and it is + ** paramed with OPEN, we want to restore the saved port termio, but + ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot. + */ + } + + /* + ** wait for space + */ + while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) { + if (retries-- <= 0) { + break; + } + if (PortP->InUse != NOT_INUSE) { + rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n"); + } + + if (!res) { + rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n"); + } + + if (SleepFlag != OK_TO_SLEEP) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit(); + + return RIO_FAIL; + } + + rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + retval = RIODelay(PortP, HUNDRED_MS); + rio_spin_lock_irqsave(&PortP->portSem, flags); + if (retval == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit(); + return -EINTR; + } + if (PortP->State & RIO_DELETED) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit(); + return 0; + } + } + + if (!res) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit(); + + return RIO_FAIL; + } + + rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res); + rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP); + + phb_param_ptr = (struct phb_param __iomem *) PacketP->data; + + + switch (TtyP->termios->c_cflag & CSIZE) { + case CS5: + { + rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n"); + Cor1 |= RIOC_COR1_5BITS; + break; + } + case CS6: + { + rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n"); + Cor1 |= RIOC_COR1_6BITS; + break; + } + case CS7: + { + rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n"); + Cor1 |= RIOC_COR1_7BITS; + break; + } + case CS8: + { + rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n"); + Cor1 |= RIOC_COR1_8BITS; + break; + } + } + + if (TtyP->termios->c_cflag & CSTOPB) { + rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n"); + Cor1 |= RIOC_COR1_2STOP; + } else { + rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n"); + Cor1 |= RIOC_COR1_1STOP; + } + + if (TtyP->termios->c_cflag & PARENB) { + rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n"); + Cor1 |= RIOC_COR1_NORMAL; + } else { + rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n"); + Cor1 |= RIOC_COR1_NOP; + } + if (TtyP->termios->c_cflag & PARODD) { + rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n"); + Cor1 |= RIOC_COR1_ODD; + } else { + rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n"); + Cor1 |= RIOC_COR1_EVEN; + } + + /* + ** COR 2 + */ + if (TtyP->termios->c_iflag & IXON) { + rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n"); + Cor2 |= RIOC_COR2_IXON; + } else { + if (PortP->Config & RIO_IXON) { + rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n"); + Cor2 |= RIOC_COR2_IXON; + } else + rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n"); + } + + if (TtyP->termios->c_iflag & IXANY) { + if (PortP->Config & RIO_IXANY) { + rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n"); + Cor2 |= RIOC_COR2_IXANY; + } else + rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n"); + } + + if (TtyP->termios->c_iflag & IXOFF) { + rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n"); + Cor2 |= RIOC_COR2_IXOFF; + } + + if (TtyP->termios->c_cflag & HUPCL) { + rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n"); + Cor2 |= RIOC_COR2_HUPCL; + } + + if (C_CRTSCTS(TtyP)) { + rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n"); + Cor2 |= RIOC_COR2_CTSFLOW; + Cor2 |= RIOC_COR2_RTSFLOW; + } else { + rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n"); + Cor2 &= ~RIOC_COR2_CTSFLOW; + Cor2 &= ~RIOC_COR2_RTSFLOW; + } + + + if (TtyP->termios->c_cflag & CLOCAL) { + rio_dprintk(RIO_DEBUG_PARAM, "Local line\n"); + } else { + rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n"); + } + + /* + ** COR 4 (there is no COR 3) + */ + if (TtyP->termios->c_iflag & IGNBRK) { + rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n"); + Cor4 |= RIOC_COR4_IGNBRK; + } + if (!(TtyP->termios->c_iflag & BRKINT)) { + rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n"); + Cor4 |= RIOC_COR4_NBRKINT; + } else { + rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on break condition\n"); + } + + if (TtyP->termios->c_iflag & INLCR) { + rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n"); + Cor4 |= RIOC_COR4_INLCR; + } + + if (TtyP->termios->c_iflag & IGNCR) { + rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n"); + Cor4 |= RIOC_COR4_IGNCR; + } + + if (TtyP->termios->c_iflag & ICRNL) { + rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n"); + Cor4 |= RIOC_COR4_ICRNL; + } + if (TtyP->termios->c_iflag & IGNPAR) { + rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n"); + Cor4 |= RIOC_COR4_IGNPAR; + } + if (TtyP->termios->c_iflag & PARMRK) { + rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n"); + Cor4 |= RIOC_COR4_PARMRK; + } + + /* + ** Set the RAISEMOD flag to ensure that the modem lines are raised + ** on reception of a config packet. + ** The download code handles the zero baud condition. + */ + Cor4 |= RIOC_COR4_RAISEMOD; + + /* + ** COR 5 + */ + + Cor5 = RIOC_COR5_CMOE; + + /* + ** Set to monitor tbusy/tstop (or not). + */ + + if (PortP->MonitorTstate) + Cor5 |= RIOC_COR5_TSTATE_ON; + else + Cor5 |= RIOC_COR5_TSTATE_OFF; + + /* + ** Could set LNE here if you wanted LNext processing. SVR4 will use it. + */ + if (TtyP->termios->c_iflag & ISTRIP) { + rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n"); + if (!(PortP->State & RIO_TRIAD_MODE)) { + Cor5 |= RIOC_COR5_ISTRIP; + } + } + + if (TtyP->termios->c_oflag & ONLCR) { + rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n"); + if (PortP->CookMode == COOK_MEDIUM) + Cor5 |= RIOC_COR5_ONLCR; + } + if (TtyP->termios->c_oflag & OCRNL) { + rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n"); + if (PortP->CookMode == COOK_MEDIUM) + Cor5 |= RIOC_COR5_OCRNL; + } + if ((TtyP->termios->c_oflag & TABDLY) == TAB3) { + rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n"); + if (PortP->CookMode == COOK_MEDIUM) + Cor5 |= RIOC_COR5_TAB3; + } + + /* + ** Flow control bytes. + */ + TxXon = TtyP->termios->c_cc[VSTART]; + TxXoff = TtyP->termios->c_cc[VSTOP]; + RxXon = TtyP->termios->c_cc[VSTART]; + RxXoff = TtyP->termios->c_cc[VSTOP]; + /* + ** LNEXT byte + */ + LNext = 0; + + /* + ** Baud rate bytes + */ + rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD); + + switch (TtyP->termios->c_cflag & CBAUD) { +#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break + e(50); + e(75); + e(110); + e(134); + e(150); + e(200); + e(300); + e(600); + e(1200); + e(1800); + e(2400); + e(4800); + e(9600); + e(19200); + e(38400); + e(57600); + e(115200); /* e(230400);e(460800); e(921600); */ + } + + rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud); + + + /* + ** Leftovers + */ + if (TtyP->termios->c_cflag & CREAD) + rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n"); +#ifdef RCV1EN + if (TtyP->termios->c_cflag & RCV1EN) + rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n"); +#endif +#ifdef XMT1EN + if (TtyP->termios->c_cflag & XMT1EN) + rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n"); +#endif + if (TtyP->termios->c_lflag & ISIG) + rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n"); + if (TtyP->termios->c_lflag & ICANON) + rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n"); + if (TtyP->termios->c_lflag & XCASE) + rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n"); + if (TtyP->termios->c_lflag & ECHO) + rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n"); + if (TtyP->termios->c_lflag & ECHOE) + rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n"); + if (TtyP->termios->c_lflag & ECHOK) + rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n"); + if (TtyP->termios->c_lflag & ECHONL) + rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n"); + if (TtyP->termios->c_lflag & NOFLSH) + rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n"); +#ifdef TOSTOP + if (TtyP->termios->c_lflag & TOSTOP) + rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n"); +#endif +#ifdef XCLUDE + if (TtyP->termios->c_lflag & XCLUDE) + rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n"); +#endif + if (TtyP->termios->c_iflag & IUCLC) + rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n"); + if (TtyP->termios->c_oflag & OPOST) + rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n"); + if (TtyP->termios->c_oflag & OLCUC) + rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n"); + if (TtyP->termios->c_oflag & ONOCR) + rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n"); + if (TtyP->termios->c_oflag & ONLRET) + rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n"); + if (TtyP->termios->c_oflag & OFILL) + rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n"); + if (TtyP->termios->c_oflag & OFDEL) + rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n"); + if (TtyP->termios->c_oflag & NLDLY) + rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n"); + if (TtyP->termios->c_oflag & CRDLY) + rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n"); + if (TtyP->termios->c_oflag & TABDLY) + rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n"); + /* + ** These things are kind of useful in a later life! + */ + PortP->Cor2Copy = Cor2; + + if (PortP->State & RIO_DELETED) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit(); + + return RIO_FAIL; + } + + /* + ** Actually write the info into the packet to be sent + */ + writeb(cmd, &phb_param_ptr->Cmd); + writeb(Cor1, &phb_param_ptr->Cor1); + writeb(Cor2, &phb_param_ptr->Cor2); + writeb(Cor4, &phb_param_ptr->Cor4); + writeb(Cor5, &phb_param_ptr->Cor5); + writeb(TxXon, &phb_param_ptr->TxXon); + writeb(RxXon, &phb_param_ptr->RxXon); + writeb(TxXoff, &phb_param_ptr->TxXoff); + writeb(RxXoff, &phb_param_ptr->RxXoff); + writeb(LNext, &phb_param_ptr->LNext); + writeb(TxBaud, &phb_param_ptr->TxBaud); + writeb(RxBaud, &phb_param_ptr->RxBaud); + + /* + ** Set the length/command field + */ + writeb(12 | PKT_CMD_BIT, &PacketP->len); + + /* + ** The packet is formed - now, whack it off + ** to its final destination: + */ + add_transmit(PortP); + /* + ** Count characters transmitted for port statistics reporting + */ + if (PortP->statsGather) + PortP->txchars += 12; + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + + rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n"); + /* + ** job done. + */ + func_exit(); + + return 0; +} + + +/* +** We can add another packet to a transmit queue if the packet pointer pointed +** to by the TxAdd pointer has PKT_IN_USE clear in its address. +*/ +int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP) +{ + struct PKT __iomem *tp; + + *PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); + + return !((unsigned long) tp & PKT_IN_USE); +} + +/* +** To add a packet to the queue, you set the PKT_IN_USE bit in the address, +** and then move the TxAdd pointer along one position to point to the next +** packet pointer. You must wrap the pointer from the end back to the start. +*/ +void add_transmit(struct Port *PortP) +{ + if (readw(PortP->TxAdd) & PKT_IN_USE) { + rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!"); + } + writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd); + PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1; + writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add); +} + +/**************************************** + * Put a packet onto the end of the + * free list + ****************************************/ +void put_free_end(struct Host *HostP, struct PKT __iomem *PktP) +{ + struct rio_free_list __iomem *tmp_pointer; + unsigned short old_end, new_end; + unsigned long flags; + + rio_spin_lock_irqsave(&HostP->HostLock, flags); + + /************************************************* + * Put a packet back onto the back of the free list + * + ************************************************/ + + rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP); + + if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) { + new_end = RIO_OFF(HostP->Caddr, PktP); + tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end); + writew(new_end, &tmp_pointer->next); + writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev); + writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next); + writew(new_end, &HostP->ParmMapP->free_list_end); + } else { /* First packet on the free list this should never happen! */ + rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n"); + writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end); + tmp_pointer = (struct rio_free_list __iomem *) PktP; + writew(TPNULL, &tmp_pointer->prev); + writew(TPNULL, &tmp_pointer->next); + } + rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock); + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); +} + +/* +** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set +** for the next packet on the queue. It will also set PktP to point to the +** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, +** then can_remove_receive() returns 0. +*/ +int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP) +{ + if (readw(PortP->RxRemove) & PKT_IN_USE) { + *PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); + return 1; + } + return 0; +} + +/* +** To remove a packet from the receive queue you clear its PKT_IN_USE bit, +** and then bump the pointers. Once the pointers get to the end, they must +** be wrapped back to the start. +*/ +void remove_receive(struct Port *PortP) +{ + writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove); + PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1; + writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove); +} diff --git a/drivers/staging/generic_serial/rio/rioroute.c b/drivers/staging/generic_serial/rio/rioroute.c new file mode 100644 index 000000000000..f9b936ac3394 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rioroute.c @@ -0,0 +1,1039 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : rioroute.c +** SID : 1.3 +** Last Modified : 11/6/98 10:33:46 +** Retrieved : 11/6/98 10:33:50 +** +** ident @(#)rioroute.c 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" +#include "param.h" + +static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int); +static int RIOIsolate(struct rio_info *, struct Host *, unsigned int); +static int RIOCheck(struct Host *, unsigned int); +static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int); + + +/* +** Incoming on the ROUTE_RUP +** I wrote this while I was tired. Forgive me. +*/ +int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP) +{ + struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data; + struct PktCmd_M *PktReplyP; + struct CmdBlk *CmdBlkP; + struct Port *PortP; + struct Map *MapP; + struct Top *TopP; + int ThisLink, ThisLinkMin, ThisLinkMax; + int port; + int Mod, Mod1, Mod2; + unsigned short RtaType; + unsigned int RtaUniq; + unsigned int ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */ + unsigned int OldUnit, NewUnit, OldLink, NewLink; + char *MyType, *MyName; + int Lies; + unsigned long flags; + + /* + ** Is this unit telling us it's current link topology? + */ + if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) { + MapP = HostP->Mapping; + + /* + ** The packet can be sent either by the host or by an RTA. + ** If it comes from the host, then we need to fill in the + ** Topology array in the host structure. If it came in + ** from an RTA then we need to fill in the Mapping structure's + ** Topology array for the unit. + */ + if (Rup >= (unsigned short) MAX_RUP) { + ThisUnit = HOST_ID; + TopP = HostP->Topology; + MyType = "Host"; + MyName = HostP->Name; + ThisLinkMin = ThisLinkMax = Rup - MAX_RUP; + } else { + ThisUnit = Rup + 1; + TopP = HostP->Mapping[Rup].Topology; + MyType = "RTA"; + MyName = HostP->Mapping[Rup].Name; + ThisLinkMin = 0; + ThisLinkMax = LINKS_PER_UNIT - 1; + } + + /* + ** Lies will not be tolerated. + ** If any pair of links claim to be connected to the same + ** place, then ignore this packet completely. + */ + Lies = 0; + for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) { + /* + ** it won't lie about network interconnect, total disconnects + ** and no-IDs. (or at least, it doesn't *matter* if it does) + */ + if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP) + continue; + + for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) { + if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) { + Lies++; + } + } + } + + if (Lies) { + rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies); + rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n", + readb(&PktCmdP->RouteTopology[0].Unit), + 'A' + readb(&PktCmdP->RouteTopology[0].Link), + readb(&PktCmdP->RouteTopology[1].Unit), + 'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link)); + return 1; + } + + /* + ** now, process each link. + */ + for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) { + /* + ** this is what it was connected to + */ + OldUnit = TopP[ThisLink].Unit; + OldLink = TopP[ThisLink].Link; + + /* + ** this is what it is now connected to + */ + NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit); + NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link); + + if (OldUnit != NewUnit || OldLink != NewLink) { + /* + ** something has changed! + */ + + if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) { + rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink); + } else { + /* + ** put the new values in + */ + TopP[ThisLink].Unit = NewUnit; + TopP[ThisLink].Link = NewLink; + + RIOSetChange(p); + + if (OldUnit <= MAX_RUP) { + /* + ** If something has become bust, then re-enable them messages + */ + if (!p->RIONoMessage) + RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT); + } + + if ((NewUnit <= MAX_RUP) && !p->RIONoMessage) + RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT); + + if (NewUnit == ROUTE_NO_ID) + rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink); + + if (NewUnit == ROUTE_INTERCONNECT) { + if (!p->RIONoMessage) + printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink); + } + + /* + ** perform an update for 'the other end', so that these messages + ** only appears once. Only disconnect the other end if it is pointing + ** at us! + */ + if (OldUnit == HOST_ID) { + if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) { + rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A'); + HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT; + HostP->Topology[OldLink].Link = NO_LINK; + } else { + rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A'); + } + } else if (OldUnit <= MAX_RUP) { + if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) { + rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A'); + HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT; + HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK; + } else { + rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A'); + } + } + if (NewUnit == HOST_ID) { + rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A'); + HostP->Topology[NewLink].Unit = ThisUnit; + HostP->Topology[NewLink].Link = ThisLink; + } else if (NewUnit <= MAX_RUP) { + rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A'); + HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit; + HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink; + } + } + RIOSetChange(p); + RIOCheckIsolated(p, HostP, OldUnit); + } + } + return 1; + } + + /* + ** The only other command we recognise is a route_request command + */ + if (readb(&PktCmdP->Command) != ROUTE_REQUEST) { + rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP); + return 1; + } + + RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); + + /* + ** Determine if 8 or 16 port RTA + */ + RtaType = GetUnitType(RtaUniq); + + rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq); + + Mod = readb(&PktCmdP->ModuleTypes); + Mod1 = LONYBLE(Mod); + if (RtaType == TYPE_RTA16) { + /* + ** Only one ident is set for a 16 port RTA. To make compatible + ** with 8 port, set 2nd ident in Mod2 to the same as Mod1. + */ + Mod2 = Mod1; + rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name); + } else { + Mod2 = HINYBLE(Mod); + rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name); + } + + /* + ** try to unhook a command block from the command free list. + */ + if (!(CmdBlkP = RIOGetCmdBlk())) { + rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n"); + return 0; + } + + /* + ** Fill in the default info on the command block + */ + CmdBlkP->Packet.dest_unit = Rup; + CmdBlkP->Packet.dest_port = ROUTE_RUP; + CmdBlkP->Packet.src_unit = HOST_ID; + CmdBlkP->Packet.src_port = ROUTE_RUP; + CmdBlkP->Packet.len = PKT_CMD_BIT | 1; + CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; + PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data; + + if (!RIOBootOk(p, HostP, RtaUniq)) { + rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq); + PktReplyP->Command = ROUTE_FOAD; + memcpy(PktReplyP->CommandText, "RT_FOAD", 7); + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); + return 1; + } + + /* + ** Check to see if the RTA is configured for this host + */ + for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) { + rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n", + ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum); + + /* + ** We have an entry for it. + */ + if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) { + if (RtaType == TYPE_RTA16) { + ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1; + rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2); + } else + rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit); + /* + ** If we have no knowledge of booting it, then the host has + ** been re-booted, and so we must kill the RTA, so that it + ** will be booted again (potentially with new bins) + ** and it will then re-ask for an ID, which we will service. + */ + if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) { + if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) { + if (!p->RIONoMessage) + printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name); + HostP->Mapping[ThisUnit].Flags |= MSG_DONE; + } + PktReplyP->Command = ROUTE_FOAD; + memcpy(PktReplyP->CommandText, "RT_FOAD", 7); + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); + return 1; + } + + /* + ** Send the ID (entry) to this RTA. The ID number is implicit as + ** the offset into the table. It is worth noting at this stage + ** that offset zero in the table contains the entries for the + ** RTA with ID 1!!!! + */ + PktReplyP->Command = ROUTE_ALLOCATE; + PktReplyP->IDNum = ThisUnit + 1; + if (RtaType == TYPE_RTA16) { + if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) + /* + ** Adjust the phb and tx pkt dest_units for 2nd block of 8 + ** only if the RTA has ports associated (SLOT_IN_USE) + */ + RIOFixPhbs(p, HostP, ThisUnit2); + PktReplyP->IDNum2 = ThisUnit2 + 1; + rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2); + } else { + PktReplyP->IDNum2 = ROUTE_NO_ID; + rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum); + } + memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10); + + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); + + /* + ** If this is a freshly booted RTA, then we need to re-open + ** the ports, if any where open, so that data may once more + ** flow around the system! + */ + if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) { + /* + ** look at the ports associated with this beast and + ** see if any where open. If they was, then re-open + ** them, using the info from the tty flags. + */ + for (port = 0; port < PORTS_PER_RTA; port++) { + PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]; + if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) { + rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n"); + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->MagicFlags |= MAGIC_REBOOT; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + } + } + if (RtaType == TYPE_RTA16) { + for (port = 0; port < PORTS_PER_RTA; port++) { + PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]; + if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) { + rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n"); + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->MagicFlags |= MAGIC_REBOOT; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + } + } + } + } + + /* + ** keep a copy of the module types! + */ + HostP->UnixRups[ThisUnit].ModTypes = Mod; + if (RtaType == TYPE_RTA16) + HostP->UnixRups[ThisUnit2].ModTypes = Mod; + + /* + ** If either of the modules on this unit is read-only or write-only + ** or none-xprint, then we need to transfer that info over to the + ** relevant ports. + */ + if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) { + for (port = 0; port < PORTS_PER_MODULE; port++) { + p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; + p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; + p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; + p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; + } + if (RtaType == TYPE_RTA16) { + for (port = 0; port < PORTS_PER_MODULE; port++) { + p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; + p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; + p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; + p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; + } + } + } + + /* + ** Job done, get on with the interrupts! + */ + return 1; + } + } + /* + ** There is no table entry for this RTA at all. + ** + ** Lets check to see if we actually booted this unit - if not, + ** then we reset it and it will go round the loop of being booted + ** we can then worry about trying to fit it into the table. + */ + for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++) + if (HostP->ExtraUnits[ThisUnit] == RtaUniq) + break; + if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) { + /* + ** if the unit wasn't in the table, and the table wasn't full, then + ** we reset the unit, because we didn't boot it. + ** However, if the table is full, it could be that we did boot + ** this unit, and so we won't reboot it, because it isn't really + ** all that disasterous to keep the old bins in most cases. This + ** is a rather tacky feature, but we are on the edge of reallity + ** here, because the implication is that someone has connected + ** 16+MAX_EXTRA_UNITS onto one host. + */ + static int UnknownMesgDone = 0; + + if (!UnknownMesgDone) { + if (!p->RIONoMessage) + printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n"); + UnknownMesgDone = 1; + } + + PktReplyP->Command = ROUTE_FOAD; + memcpy(PktReplyP->CommandText, "RT_FOAD", 7); + } else { + /* + ** we did boot it (as an extra), and there may now be a table + ** slot free (because of a delete), so we will try to make + ** a tentative entry for it, so that the configurator can see it + ** and fill in the details for us. + */ + if (RtaType == TYPE_RTA16) { + if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) { + RIODefaultName(p, HostP, ThisUnit); + rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP); + } + } else { + if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) { + RIODefaultName(p, HostP, ThisUnit); + rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP); + } + } + PktReplyP->Command = ROUTE_USED; + memcpy(PktReplyP->CommandText, "RT_USED", 7); + } + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); + return 1; +} + + +void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit) +{ + unsigned short link, port; + struct Port *PortP; + unsigned long flags; + int PortN = HostP->Mapping[unit].SysPort; + + rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN); + + if (PortN != -1) { + unsigned short dest_unit = HostP->Mapping[unit].ID2; + + /* + ** Get the link number used for the 1st 8 phbs on this unit. + */ + PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort]; + + link = readw(&PortP->PhbP->link); + + for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { + unsigned short dest_port = port + 8; + u16 __iomem *TxPktP; + struct PKT __iomem *Pkt; + + PortP = p->RIOPortp[PortN]; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + /* + ** If RTA is not powered on, the tx packets will be + ** unset, so go no further. + */ + if (!PortP->TxStart) { + rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + break; + } + + /* + ** For the second slot of a 16 port RTA, the driver needs to + ** sort out the phb to port mappings. The dest_unit for this + ** group of 8 phbs is set to the dest_unit of the accompanying + ** 8 port block. The dest_port of the second unit is set to + ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port + ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6 + ** (being the second map ID) will be sent to dest_unit 5, port + ** 14. When this RTA is deleted, dest_unit for ID 6 will be + ** restored, and the dest_port will be reduced by 8. + ** Transmit packets also have a destination field which needs + ** adjusting in the same manner. + ** Note that the unit/port bytes in 'dest' are swapped. + ** We also need to adjust the phb and rup link numbers for the + ** second block of 8 ttys. + */ + for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { + /* + ** *TxPktP is the pointer to the transmit packet on the host + ** card. This needs to be translated into a 32 bit pointer + ** so it can be accessed from the driver. + */ + Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP)); + + /* + ** If the packet is used, reset it. + */ + Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE); + writeb(dest_unit, &Pkt->dest_unit); + writeb(dest_port, &Pkt->dest_port); + } + rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); + writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); + writew(link, &PortP->PhbP->link); + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + } + /* + ** Now make sure the range of ports to be serviced includes + ** the 2nd 8 on this 16 port RTA. + */ + if (link > 3) + return; + if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) { + rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7); + writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port); + } + } +} + +/* +** Check to see if the new disconnection has isolated this unit. +** If it has, then invalidate all its link information, and tell +** the world about it. This is done to ensure that the configurator +** only gets up-to-date information about what is going on. +*/ +static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId) +{ + unsigned long flags; + rio_spin_lock_irqsave(&HostP->HostLock, flags); + + if (RIOCheck(HostP, UnitId)) { + rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId); + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); + return (0); + } + + RIOIsolate(p, HostP, UnitId); + RIOSetChange(p); + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); + return 1; +} + +/* +** Invalidate all the link interconnectivity of this unit, and of +** all the units attached to it. This will mean that the entire +** subnet will re-introduce itself. +*/ +static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId) +{ + unsigned int link, unit; + + UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */ + + if (UnitId >= MAX_RUP) /* dontcha just lurv unsigned maths! */ + return (0); + + if (HostP->Mapping[UnitId].Flags & BEEN_HERE) + return (0); + + HostP->Mapping[UnitId].Flags |= BEEN_HERE; + + if (p->RIOPrintDisabled == DO_PRINT) + rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name); + + for (link = 0; link < LINKS_PER_UNIT; link++) { + unit = HostP->Mapping[UnitId].Topology[link].Unit; + HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT; + HostP->Mapping[UnitId].Topology[link].Link = NO_LINK; + RIOIsolate(p, HostP, unit); + } + HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; + return 1; +} + +static int RIOCheck(struct Host *HostP, unsigned int UnitId) +{ + unsigned char link; + +/* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */ + rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId); + + if (UnitId == HOST_ID) { + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */ + return 1; + } + + UnitId--; + + if (UnitId >= MAX_RUP) { + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */ + return 0; + } + + for (link = 0; link < LINKS_PER_UNIT; link++) { + if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) { + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", + UnitId, 'A'+link)); */ + return 1; + } + } + + if (HostP->Mapping[UnitId].Flags & BEEN_HERE) { + /* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */ + return 0; + } + + HostP->Mapping[UnitId].Flags |= BEEN_HERE; + + for (link = 0; link < LINKS_PER_UNIT; link++) { + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */ + if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) { + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */ + HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; + return 1; + } + } + + HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; + + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */ + + return 0; +} + +/* +** Returns the type of unit (host, 16/8 port RTA) +*/ + +unsigned int GetUnitType(unsigned int Uniq) +{ + switch ((Uniq >> 28) & 0xf) { + case RIO_AT: + case RIO_MCA: + case RIO_EISA: + case RIO_PCI: + rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n"); + return (TYPE_HOST); + case RIO_RTA_16: + rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n"); + return (TYPE_RTA16); + case RIO_RTA: + rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n"); + return (TYPE_RTA8); + default: + rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n"); + return (99); + } +} + +int RIOSetChange(struct rio_info *p) +{ + if (p->RIOQuickCheck != NOT_CHANGED) + return (0); + p->RIOQuickCheck = CHANGED; + if (p->RIOSignalProcess) { + rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP"); + /* + psignal( RIOSignalProcess, SIGHUP ); + */ + } + return (0); +} + +static void RIOConCon(struct rio_info *p, + struct Host *HostP, + unsigned int FromId, + unsigned int FromLink, + unsigned int ToId, + unsigned int ToLink, + int Change) +{ + char *FromName; + char *FromType; + char *ToName; + char *ToType; + unsigned int tp; + +/* +** 15.10.1998 ARG - ESIL 0759 +** (Part) fix for port being trashed when opened whilst RTA "disconnected" +** +** What's this doing in here anyway ? +** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected" +** +** 09.12.1998 ARG - ESIL 0776 - part fix +** Okay, We've found out what this was all about now ! +** Someone had botched this to use RIOHalted to indicated the number of RTAs +** 'disconnected'. The value in RIOHalted was then being used in the +** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA +** is 'disconnected'. The change was put in to satisfy a customer's needs. +** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for +** the customer. +** + if (Change == CONNECT) { + if (p->RIOHalted) p->RIOHalted --; + } + else { + p->RIOHalted ++; + } +** +** So - we need to implement it slightly differently - a new member of the +** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA +** connections and disconnections. +*/ + if (Change == CONNECT) { + if (p->RIORtaDisCons) + p->RIORtaDisCons--; + } else { + p->RIORtaDisCons++; + } + + if (p->RIOPrintDisabled == DONT_PRINT) + return; + + if (FromId > ToId) { + tp = FromId; + FromId = ToId; + ToId = tp; + tp = FromLink; + FromLink = ToLink; + ToLink = tp; + } + + FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name; + FromType = FromId ? "RTA" : "HOST"; + ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name; + ToType = ToId ? "RTA" : "HOST"; + + rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); + printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); +} + +/* +** RIORemoveFromSavedTable : +** +** Delete and RTA entry from the saved table given to us +** by the configuration program. +*/ +static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap) +{ + int entry; + + /* + ** We loop for all entries even after finding an entry and + ** zeroing it because we may have two entries to delete if + ** it's a 16 port RTA. + */ + for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { + if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) { + memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map)); + } + } + return 0; +} + + +/* +** RIOCheckDisconnected : +** +** Scan the unit links to and return zero if the unit is completely +** disconnected. +*/ +static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) +{ + int link; + + + rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit); + /* + ** If the slot is tentative and does not belong to the + ** second half of a 16 port RTA then scan to see if + ** is disconnected. + */ + for (link = 0; link < LINKS_PER_UNIT; link++) { + if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT) + break; + } + + /* + ** If not all links are disconnected then we can forget about it. + */ + if (link < LINKS_PER_UNIT) + return 1; + +#ifdef NEED_TO_FIX_THIS + /* Ok so all the links are disconnected. But we may have only just + ** made this slot tentative and not yet received a topology update. + ** Lets check how long ago we made it tentative. + */ + rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit); + if (drv_getparm(LBOLT, (ulong_t *) & current_time)) + rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n"); + + elapse_time = current_time - TentTime[unit]; + rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time)); + if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) { + rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time)); + return 1; + } +#endif + + /* + ** We have found an usable slot. + ** If it is half of a 16 port RTA then delete the other half. + */ + if (HostP->Mapping[unit].ID2 != 0) { + int nOther = (HostP->Mapping[unit].ID2) - 1; + + rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther); + memset(&HostP->Mapping[nOther], 0, sizeof(struct Map)); + } + RIORemoveFromSavedTable(p, &HostP->Mapping[unit]); + + return 0; +} + + +/* +** RIOFindFreeID : +** +** This function scans the given host table for either one +** or two free unit ID's. +*/ + +int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2) +{ + int unit, tempID; + + /* + ** Initialise the ID's to MAX_RUP. + ** We do this to make the loop for setting the ID's as simple as + ** possible. + */ + *pID1 = MAX_RUP; + if (pID2 != NULL) + *pID2 = MAX_RUP; + + /* + ** Scan all entries of the host mapping table for free slots. + ** We scan for free slots first and then if that is not successful + ** we start all over again looking for tentative slots we can re-use. + */ + for (unit = 0; unit < MAX_RUP; unit++) { + rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit); + /* + ** If the flags are zero then the slot is empty. + */ + if (HostP->Mapping[unit].Flags == 0) { + rio_dprintk(RIO_DEBUG_ROUTE, " This slot is empty.\n"); + /* + ** If we haven't allocated the first ID then do it now. + */ + if (*pID1 == MAX_RUP) { + rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit); + *pID1 = unit; + + /* + ** If the second ID is not needed then we can return + ** now. + */ + if (pID2 == NULL) + return 0; + } else { + /* + ** Allocate the second slot and return. + */ + rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit); + *pID2 = unit; + return 0; + } + } + } + + /* + ** If we manage to come out of the free slot loop then we + ** need to start all over again looking for tentative slots + ** that we can re-use. + */ + rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n"); + for (unit = 0; unit < MAX_RUP; unit++) { + if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) { + rio_dprintk(RIO_DEBUG_ROUTE, " Slot %d looks promising.\n", unit); + + if (unit == *pID1) { + rio_dprintk(RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n"); + continue; + } + + /* + ** Slot is Tentative or Empty, but not a tentative second + ** slot of a 16 porter. + ** Attempt to free up this slot (and its parnter if + ** it is a 16 port slot. The second slot will become + ** empty after a call to RIOFreeDisconnected so thats why + ** we look for empty slots above as well). + */ + if (HostP->Mapping[unit].Flags != 0) + if (RIOFreeDisconnected(p, HostP, unit) != 0) + continue; + /* + ** If we haven't allocated the first ID then do it now. + */ + if (*pID1 == MAX_RUP) { + rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit); + *pID1 = unit; + + /* + ** Clear out this slot now that we intend to use it. + */ + memset(&HostP->Mapping[unit], 0, sizeof(struct Map)); + + /* + ** If the second ID is not needed then we can return + ** now. + */ + if (pID2 == NULL) + return 0; + } else { + /* + ** Allocate the second slot and return. + */ + rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", unit); + *pID2 = unit; + + /* + ** Clear out this slot now that we intend to use it. + */ + memset(&HostP->Mapping[unit], 0, sizeof(struct Map)); + + /* At this point under the right(wrong?) conditions + ** we may have a first unit ID being higher than the + ** second unit ID. This is a bad idea if we are about + ** to fill the slots with a 16 port RTA. + ** Better check and swap them over. + */ + + if (*pID1 > *pID2) { + rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2); + tempID = *pID1; + *pID1 = *pID2; + *pID2 = tempID; + } + return 0; + } + } + } + + /* + ** If we manage to get to the end of the second loop then we + ** can give up and return a failure. + */ + return 1; +} + + +/* +** The link switch scenario. +** +** Rta Wun (A) is connected to Tuw (A). +** The tables are all up to date, and the system is OK. +** +** If Wun (A) is now moved to Wun (B) before Wun (A) can +** become disconnected, then the follow happens: +** +** Tuw (A) spots the change of unit:link at the other end +** of its link and Tuw sends a topology packet reflecting +** the change: Tuw (A) now disconnected from Wun (A), and +** this is closely followed by a packet indicating that +** Tuw (A) is now connected to Wun (B). +** +** Wun (B) will spot that it has now become connected, and +** Wun will send a topology packet, which indicates that +** both Wun (A) and Wun (B) is connected to Tuw (A). +** +** Eventually Wun (A) realises that it is now disconnected +** and Wun will send out a topology packet indicating that +** Wun (A) is now disconnected. +*/ diff --git a/drivers/staging/generic_serial/rio/riospace.h b/drivers/staging/generic_serial/rio/riospace.h new file mode 100644 index 000000000000..ffb31d4332b9 --- /dev/null +++ b/drivers/staging/generic_serial/rio/riospace.h @@ -0,0 +1,154 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : riospace.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:13 +** Retrieved : 11/6/98 11:34:22 +** +** ident @(#)riospace.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_riospace_h__ +#define __rio_riospace_h__ + +#define RIO_LOCATOR_LEN 16 +#define MAX_RIO_BOARDS 4 + +/* +** DONT change this file. At all. Unless you can rebuild the entire +** device driver, which you probably can't, then the rest of the +** driver won't see any changes you make here. So don't make any. +** In particular, it won't be able to see changes to RIO_SLOTS +*/ + +struct Conf { + char Locator[24]; + unsigned int StartupTime; + unsigned int SlowCook; + unsigned int IntrPollTime; + unsigned int BreakInterval; + unsigned int Timer; + unsigned int RtaLoadBase; + unsigned int HostLoadBase; + unsigned int XpHz; + unsigned int XpCps; + char *XpOn; + char *XpOff; + unsigned int MaxXpCps; + unsigned int MinXpCps; + unsigned int SpinCmds; + unsigned int FirstAddr; + unsigned int LastAddr; + unsigned int BufferSize; + unsigned int LowWater; + unsigned int LineLength; + unsigned int CmdTime; +}; + +/* +** Board types - these MUST correspond to product codes! +*/ +#define RIO_EMPTY 0x0 +#define RIO_EISA 0x3 +#define RIO_RTA_16 0x9 +#define RIO_AT 0xA +#define RIO_MCA 0xB +#define RIO_PCI 0xD +#define RIO_RTA 0xE + +/* +** Board data structure. This is used for configuration info +*/ +struct Brd { + unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */ + unsigned char Ivec; /* POLLED or ivec number */ + unsigned char Mode; /* Control stuff, see below */ +}; + +struct Board { + char Locator[RIO_LOCATOR_LEN]; + int NumSlots; + struct Brd Boards[MAX_RIO_BOARDS]; +}; + +#define BOOT_FROM_LINK 0x00 +#define BOOT_FROM_RAM 0x01 +#define EXTERNAL_BUS_OFF 0x00 +#define EXTERNAL_BUS_ON 0x02 +#define INTERRUPT_DISABLE 0x00 +#define INTERRUPT_ENABLE 0x04 +#define BYTE_OPERATION 0x00 +#define WORD_OPERATION 0x08 +#define POLLED INTERRUPT_DISABLE +#define IRQ_15 (0x00 | INTERRUPT_ENABLE) +#define IRQ_12 (0x10 | INTERRUPT_ENABLE) +#define IRQ_11 (0x20 | INTERRUPT_ENABLE) +#define IRQ_9 (0x30 | INTERRUPT_ENABLE) +#define SLOW_LINKS 0x00 +#define FAST_LINKS 0x40 +#define SLOW_AT_BUS 0x00 +#define FAST_AT_BUS 0x80 +#define SLOW_PCI_TP 0x00 +#define FAST_PCI_TP 0x80 +/* +** Debug levels +*/ +#define DBG_NONE 0x00000000 + +#define DBG_INIT 0x00000001 +#define DBG_OPEN 0x00000002 +#define DBG_CLOSE 0x00000004 +#define DBG_IOCTL 0x00000008 + +#define DBG_READ 0x00000010 +#define DBG_WRITE 0x00000020 +#define DBG_INTR 0x00000040 +#define DBG_PROC 0x00000080 + +#define DBG_PARAM 0x00000100 +#define DBG_CMD 0x00000200 +#define DBG_XPRINT 0x00000400 +#define DBG_POLL 0x00000800 + +#define DBG_DAEMON 0x00001000 +#define DBG_FAIL 0x00002000 +#define DBG_MODEM 0x00004000 +#define DBG_LIST 0x00008000 + +#define DBG_ROUTE 0x00010000 +#define DBG_UTIL 0x00020000 +#define DBG_BOOT 0x00040000 +#define DBG_BUFFER 0x00080000 + +#define DBG_MON 0x00100000 +#define DBG_SPECIAL 0x00200000 +#define DBG_VPIX 0x00400000 +#define DBG_FLUSH 0x00800000 + +#define DBG_QENABLE 0x01000000 + +#define DBG_ALWAYS 0x80000000 + +#endif /* __rio_riospace_h__ */ diff --git a/drivers/staging/generic_serial/rio/riotable.c b/drivers/staging/generic_serial/rio/riotable.c new file mode 100644 index 000000000000..3d15802dc0f3 --- /dev/null +++ b/drivers/staging/generic_serial/rio/riotable.c @@ -0,0 +1,941 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : riotable.c +** SID : 1.2 +** Last Modified : 11/6/98 10:33:47 +** Retrieved : 11/6/98 10:33:50 +** +** ident @(#)riotable.c 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" +#include "param.h" +#include "protsts.h" + +/* +** A configuration table has been loaded. It is now up to us +** to sort it out and use the information contained therein. +*/ +int RIONewTable(struct rio_info *p) +{ + int Host, Host1, Host2, NameIsUnique, Entry, SubEnt; + struct Map *MapP; + struct Map *HostMapP; + struct Host *HostP; + + char *cptr; + + /* + ** We have been sent a new table to install. We need to break + ** it down into little bits and spread it around a bit to see + ** what we have got. + */ + /* + ** Things to check: + ** (things marked 'xx' aren't checked any more!) + ** (1) That there are no booted Hosts/RTAs out there. + ** (2) That the names are properly formed + ** (3) That blank entries really are. + ** xx (4) That hosts mentioned in the table actually exist. xx + ** (5) That the IDs are unique (per host). + ** (6) That host IDs are zero + ** (7) That port numbers are valid + ** (8) That port numbers aren't duplicated + ** (9) That names aren't duplicated + ** xx (10) That hosts that actually exist are mentioned in the table. xx + */ + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n"); + if (p->RIOSystemUp) { /* (1) */ + p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED; + return -EBUSY; + } + + p->RIOError.Error = NOTHING_WRONG_AT_ALL; + p->RIOError.Entry = -1; + p->RIOError.Other = -1; + + for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) { + MapP = &p->RIOConnectTable[Entry]; + if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) { + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n"); + cptr = MapP->Name; /* (2) */ + cptr[MAX_NAME_LEN - 1] = '\0'; + if (cptr[0] == '\0') { + memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA NN" : "HOST NN", 8); + MapP->Name[5] = '0' + Entry / 10; + MapP->Name[6] = '0' + Entry % 10; + } + while (*cptr) { + if (*cptr < ' ' || *cptr > '~') { + p->RIOError.Error = BAD_CHARACTER_IN_NAME; + p->RIOError.Entry = Entry; + return -ENXIO; + } + cptr++; + } + } + + /* + ** If the entry saved was a tentative entry then just forget + ** about it. + */ + if (MapP->Flags & SLOT_TENTATIVE) { + MapP->HostUniqueNum = 0; + MapP->RtaUniqueNum = 0; + continue; + } + + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n"); + if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) { /* (3) */ + if (MapP->ID || MapP->SysPort || MapP->Flags) { + rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name); + p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL; + p->RIOError.Entry = Entry; + return -ENXIO; + } + rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n"); + continue; + } + + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n"); + for (Host = 0; Host < p->RIONumHosts; Host++) { /* (4) */ + if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) { + HostP = &p->RIOHosts[Host]; + /* + ** having done the lookup, we don't really want to do + ** it again, so hang the host number in a safe place + */ + MapP->Topology[0].Unit = Host; + break; + } + } + + if (Host >= p->RIONumHosts) { + rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum); + MapP->HostUniqueNum = 0; + /* MapP->RtaUniqueNum = 0; */ + /* MapP->ID = 0; */ + /* MapP->Flags = 0; */ + /* MapP->SysPort = 0; */ + /* MapP->Name[0] = 0; */ + continue; + } + + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n"); + if (MapP->RtaUniqueNum) { /* (5) */ + if (!MapP->ID) { + rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name); + p->RIOError.Error = ZERO_RTA_ID; + p->RIOError.Entry = Entry; + return -ENXIO; + } + if (MapP->ID > MAX_RUP) { + rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID); + p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; + p->RIOError.Entry = Entry; + return -ENXIO; + } + for (SubEnt = 0; SubEnt < Entry; SubEnt++) { + if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) { + rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name); + p->RIOError.Error = DUPLICATED_RTA_ID; + p->RIOError.Entry = Entry; + p->RIOError.Other = SubEnt; + return -ENXIO; + } + /* + ** If the RtaUniqueNum is the same, it may be looking at both + ** entries for a 16 port RTA, so check the ids + */ + if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum) + && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) { + rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name); + rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name); + p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER; + p->RIOError.Entry = Entry; + p->RIOError.Other = SubEnt; + return -ENXIO; + } + } + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n"); + /* (7a) */ + if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) { + rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA); + p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; + p->RIOError.Entry = Entry; + return -ENXIO; + } + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n"); + /* (7b) */ + if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) { + rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name); + p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; + p->RIOError.Entry = Entry; + return -ENXIO; + } + for (SubEnt = 0; SubEnt < Entry; SubEnt++) { + if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT) + continue; + if (p->RIOConnectTable[SubEnt].RtaUniqueNum) { + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n"); + /* (8) */ + if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) { + rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort); + p->RIOError.Error = TTY_NUMBER_IN_USE; + p->RIOError.Entry = Entry; + p->RIOError.Other = SubEnt; + return -ENXIO; + } + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n"); + if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */ + rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name); + p->RIOError.Error = NAME_USED_TWICE; + p->RIOError.Entry = Entry; + p->RIOError.Other = SubEnt; + return -ENXIO; + } + } + } + } else { /* (6) */ + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n"); + if (MapP->ID) { + rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name); + p->RIOError.Error = HOST_ID_NOT_ZERO; + p->RIOError.Entry = Entry; + return -ENXIO; + } + if (MapP->SysPort != NO_PORT) { + rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name); + p->RIOError.Error = HOST_SYSPORT_BAD; + p->RIOError.Entry = Entry; + return -ENXIO; + } + } + } + + /* + ** wow! if we get here then it's a goody! + */ + + /* + ** Zero the (old) entries for each host... + */ + for (Host = 0; Host < RIO_HOSTS; Host++) { + for (Entry = 0; Entry < MAX_RUP; Entry++) { + memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map)); + } + memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name)); + } + + /* + ** Copy in the new table entries + */ + for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) { + rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry); + MapP = &p->RIOConnectTable[Entry]; + + /* + ** Now, if it is an empty slot ignore it! + */ + if (MapP->HostUniqueNum == 0) + continue; + + /* + ** we saved the host number earlier, so grab it back + */ + HostP = &p->RIOHosts[MapP->Topology[0].Unit]; + + /* + ** If it is a host, then we only need to fill in the name field. + */ + if (MapP->ID == 0) { + rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name); + memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN); + continue; + } + + /* + ** Its an RTA entry, so fill in the host mapping entries for it + ** and the port mapping entries. Notice that entry zero is for + ** ID one. + */ + HostMapP = &HostP->Mapping[MapP->ID - 1]; + + if (MapP->Flags & SLOT_IN_USE) { + rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name); + /* + ** structure assign, then sort out the bits we shouldn't have done + */ + *HostMapP = *MapP; + + HostMapP->Flags = SLOT_IN_USE; + if (MapP->Flags & RTA16_SECOND_SLOT) + HostMapP->Flags |= RTA16_SECOND_SLOT; + + RIOReMapPorts(p, HostP, HostMapP); + } else { + rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name); + } + } + + for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) { + p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry]; + } + + for (Host = 0; Host < p->RIONumHosts; Host++) { + for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) { + p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT; + p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK; + } + for (Entry = 0; Entry < MAX_RUP; Entry++) { + for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) { + p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT; + p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK; + } + } + if (!p->RIOHosts[Host].Name[0]) { + memcpy(p->RIOHosts[Host].Name, "HOST 1", 7); + p->RIOHosts[Host].Name[5] += Host; + } + /* + ** Check that default name assigned is unique. + */ + Host1 = Host; + NameIsUnique = 0; + while (!NameIsUnique) { + NameIsUnique = 1; + for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) { + if (Host2 == Host) + continue; + if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name) + == 0) { + NameIsUnique = 0; + Host1++; + if (Host1 >= p->RIONumHosts) + Host1 = 0; + p->RIOHosts[Host].Name[5] = '1' + Host1; + } + } + } + /* + ** Rename host if name already used. + */ + if (Host1 != Host) { + rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name); + memcpy(p->RIOHosts[Host].Name, "HOST 1", 7); + p->RIOHosts[Host].Name[5] += Host1; + } + rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name); + } + return 0; +} + +/* +** User process needs the config table - build it from first +** principles. +** +* FIXME: SMP locking +*/ +int RIOApel(struct rio_info *p) +{ + int Host; + int link; + int Rup; + int Next = 0; + struct Map *MapP; + struct Host *HostP; + unsigned long flags; + + rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n"); + + memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES); + + for (Host = 0; Host < RIO_HOSTS; Host++) { + rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host); + HostP = &p->RIOHosts[Host]; + rio_spin_lock_irqsave(&HostP->HostLock, flags); + + MapP = &p->RIOConnectTable[Next++]; + MapP->HostUniqueNum = HostP->UniqueNum; + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); + continue; + } + MapP->RtaUniqueNum = 0; + MapP->ID = 0; + MapP->Flags = SLOT_IN_USE; + MapP->SysPort = NO_PORT; + for (link = 0; link < LINKS_PER_UNIT; link++) + MapP->Topology[link] = HostP->Topology[link]; + memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN); + for (Rup = 0; Rup < MAX_RUP; Rup++) { + if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) { + p->RIOConnectTable[Next] = HostP->Mapping[Rup]; + if (HostP->Mapping[Rup].Flags & SLOT_IN_USE) + p->RIOConnectTable[Next].Flags |= SLOT_IN_USE; + if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE) + p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE; + if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT) + p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT; + Next++; + } + } + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); + } + return 0; +} + +/* +** config.rio has taken a dislike to one of the gross maps entries. +** if the entry is suitably inactive, then we can gob on it and remove +** it from the table. +*/ +int RIODeleteRta(struct rio_info *p, struct Map *MapP) +{ + int host, entry, port, link; + int SysPort; + struct Host *HostP; + struct Map *HostMapP; + struct Port *PortP; + int work_done = 0; + unsigned long lock_flags, sem_flags; + + rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum); + + for (host = 0; host < p->RIONumHosts; host++) { + HostP = &p->RIOHosts[host]; + + rio_spin_lock_irqsave(&HostP->HostLock, lock_flags); + + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { + rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); + continue; + } + + for (entry = 0; entry < MAX_RUP; entry++) { + if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) { + HostMapP = &HostP->Mapping[entry]; + rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name); + + /* + ** Check all four links of the unit are disconnected + */ + for (link = 0; link < LINKS_PER_UNIT; link++) { + if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) { + rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n"); + p->RIOError.Error = UNIT_IS_IN_USE; + rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); + return -EBUSY; + } + } + /* + ** Slot has been allocated, BUT not booted/routed/ + ** connected/selected or anything else-ed + */ + SysPort = HostMapP->SysPort; + + if (SysPort != NO_PORT) { + for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) { + PortP = p->RIOPortp[port]; + rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n"); + + rio_spin_lock_irqsave(&PortP->portSem, sem_flags); + + PortP->Mapped = 0; + + if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) { + + rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n"); + PortP->TxBufferIn = PortP->TxBufferOut = 0; + /* What should I do + wakeup( &PortP->TxBufferIn ); + wakeup( &PortP->TxBufferOut); + */ + PortP->InUse = NOT_INUSE; + /* What should I do + wakeup( &PortP->InUse ); + signal(PortP->TtyP->t_pgrp,SIGKILL); + ttyflush(PortP->TtyP,(FREAD|FWRITE)); + */ + PortP->State |= RIO_CLOSING | RIO_DELETED; + } + + /* + ** For the second slot of a 16 port RTA, the + ** driver needs to reset the changes made to + ** the phb to port mappings in RIORouteRup. + */ + if (PortP->SecondBlock) { + u16 dest_unit = HostMapP->ID; + u16 dest_port = port - SysPort; + u16 __iomem *TxPktP; + struct PKT __iomem *Pkt; + + for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { + /* + ** *TxPktP is the pointer to the + ** transmit packet on the host card. + ** This needs to be translated into + ** a 32 bit pointer so it can be + ** accessed from the driver. + */ + Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); + rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port); + writew(dest_unit, &Pkt->dest_unit); + writew(dest_port, &Pkt->dest_port); + } + rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); + writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); + } + rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags); + } + } + rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n"); + memset(HostMapP, 0, sizeof(struct Map)); + work_done++; + } + } + rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); + } + + /* XXXXX lock me up */ + for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { + if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) { + memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map)); + work_done++; + } + if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) { + memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map)); + work_done++; + } + } + if (work_done) + return 0; + + rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n"); + p->RIOError.Error = COULDNT_FIND_ENTRY; + return -ENXIO; +} + +int RIOAssignRta(struct rio_info *p, struct Map *MapP) +{ + int host; + struct Map *HostMapP; + char *sptr; + int link; + + + rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort); + + if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) { + rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); + p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + if (MapP->RtaUniqueNum == 0) { + rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n"); + p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO; + return -EINVAL; + } + if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) { + rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA); + p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) { + rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort); + p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + /* + ** Copy the name across to the map entry. + */ + MapP->Name[MAX_NAME_LEN - 1] = '\0'; + sptr = MapP->Name; + while (*sptr) { + if (*sptr < ' ' || *sptr > '~') { + rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); + p->RIOError.Error = BAD_CHARACTER_IN_NAME; + return -EINVAL; + } + sptr++; + } + + for (host = 0; host < p->RIONumHosts; host++) { + if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) { + if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) { + p->RIOError.Error = HOST_NOT_RUNNING; + return -ENXIO; + } + + /* + ** Now we have a host we need to allocate an ID + ** if the entry does not already have one. + */ + if (MapP->ID == (u16) - 1) { + int nNewID; + + rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name); + /* + ** The idea here is to allow RTA's to be assigned + ** before they actually appear on the network. + ** This allows the addition of RTA's without having + ** to plug them in. + ** What we do is: + ** - Find a free ID and allocate it to the RTA. + ** - If this map entry is the second half of a + ** 16 port entry then find the other half and + ** make sure the 2 cross reference each other. + */ + if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) { + p->RIOError.Error = COULDNT_FIND_ENTRY; + return -EBUSY; + } + MapP->ID = (u16) nNewID + 1; + rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID); + HostMapP = &p->RIOHosts[host].Mapping[nNewID]; + HostMapP->RtaUniqueNum = MapP->RtaUniqueNum; + HostMapP->HostUniqueNum = MapP->HostUniqueNum; + HostMapP->ID = MapP->ID; + for (link = 0; link < LINKS_PER_UNIT; link++) { + HostMapP->Topology[link].Unit = ROUTE_DISCONNECT; + HostMapP->Topology[link].Link = NO_LINK; + } + if (MapP->Flags & RTA16_SECOND_SLOT) { + int unit; + + for (unit = 0; unit < MAX_RUP; unit++) + if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum) + break; + if (unit == MAX_RUP) { + p->RIOError.Error = COULDNT_FIND_ENTRY; + return -EBUSY; + } + HostMapP->Flags |= RTA16_SECOND_SLOT; + HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID; + p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID; + rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID); + } + } + + HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1]; + + if (HostMapP->Flags & SLOT_IN_USE) { + rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID); + p->RIOError.Error = ID_ALREADY_IN_USE; + return -EBUSY; + } + + /* + ** Assign the sys ports and the name, and mark the slot as + ** being in use. + */ + HostMapP->SysPort = MapP->SysPort; + if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) + memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN); + HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED; +#ifdef NEED_TO_FIX + RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]); +#endif + if (MapP->Flags & RTA16_SECOND_SLOT) + HostMapP->Flags |= RTA16_SECOND_SLOT; + + RIOReMapPorts(p, &p->RIOHosts[host], HostMapP); + /* + ** Adjust 2nd block of 8 phbs + */ + if (MapP->Flags & RTA16_SECOND_SLOT) + RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1); + + if (HostMapP->SysPort != NO_PORT) { + if (HostMapP->SysPort < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = HostMapP->SysPort; + if (HostMapP->SysPort > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = HostMapP->SysPort; + } + if (MapP->Flags & RTA16_SECOND_SLOT) + rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name); + else + rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name); + return 0; + } + } + p->RIOError.Error = UNKNOWN_HOST_NUMBER; + rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); + return -ENXIO; +} + + +int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP) +{ + struct Port *PortP; + unsigned int SubEnt; + unsigned int HostPort; + unsigned int SysPort; + u16 RtaType; + unsigned long flags; + + rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID); + + /* + ** We need to tell the UnixRups which sysport the rup corresponds to + */ + HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort; + + if (HostMapP->SysPort == NO_PORT) + return (0); + + RtaType = GetUnitType(HostMapP->RtaUniqueNum); + rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1); + + /* + ** now map each of its eight ports + */ + for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) { + rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort); + SysPort = HostMapP->SysPort + SubEnt; /* portnumber within system */ + /* portnumber on host */ + + HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt; + + rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp); + PortP = p->RIOPortp[SysPort]; + rio_dprintk(RIO_DEBUG_TABLE, "Map port\n"); + + /* + ** Point at all the real neat data structures + */ + rio_spin_lock_irqsave(&PortP->portSem, flags); + PortP->HostP = HostP; + PortP->Caddr = HostP->Caddr; + + /* + ** The PhbP cannot be filled in yet + ** unless the host has been booted + */ + if ((HostP->Flags & RUN_STATE) == RC_RUNNING) { + struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; + PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add)); + PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start)); + PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end)); + PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove)); + PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start)); + PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end)); + } else + PortP->PhbP = NULL; + + /* + ** port related flags + */ + PortP->HostPort = HostPort; + /* + ** For each part of a 16 port RTA, RupNum is ID - 1. + */ + PortP->RupNum = HostMapP->ID - 1; + if (HostMapP->Flags & RTA16_SECOND_SLOT) { + PortP->ID2 = HostMapP->ID2 - 1; + PortP->SecondBlock = 1; + } else { + PortP->ID2 = 0; + PortP->SecondBlock = 0; + } + PortP->RtaUniqueNum = HostMapP->RtaUniqueNum; + + /* + ** If the port was already mapped then thats all we need to do. + */ + if (PortP->Mapped) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + continue; + } else + HostMapP->Flags &= ~RTA_NEWBOOT; + + PortP->State = 0; + PortP->Config = 0; + /* + ** Check out the module type - if it is special (read only etc.) + ** then we need to set flags in the PortP->Config. + ** Note: For 16 port RTA, all ports are of the same type. + */ + if (RtaType == TYPE_RTA16) { + PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE]; + } else { + if (SubEnt < PORTS_PER_MODULE) + PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; + else + PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; + } + + /* + ** more port related flags + */ + PortP->PortState = 0; + PortP->ModemLines = 0; + PortP->ModemState = 0; + PortP->CookMode = COOK_WELL; + PortP->ParamSem = 0; + PortP->FlushCmdBodge = 0; + PortP->WflushFlag = 0; + PortP->MagicFlags = 0; + PortP->Lock = 0; + PortP->Store = 0; + PortP->FirstOpen = 1; + + /* + ** Buffers 'n things + */ + PortP->RxDataStart = 0; + PortP->Cor2Copy = 0; + PortP->Name = &HostMapP->Name[0]; + PortP->statsGather = 0; + PortP->txchars = 0; + PortP->rxchars = 0; + PortP->opens = 0; + PortP->closes = 0; + PortP->ioctls = 0; + if (PortP->TxRingBuffer) + memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); + else if (p->RIOBufferSize) { + PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL); + } + PortP->TxBufferOut = 0; + PortP->TxBufferIn = 0; + PortP->Debug = 0; + /* + ** LastRxTgl stores the state of the rx toggle bit for this + ** port, to be compared with the state of the next pkt received. + ** If the same, we have received the same rx pkt from the RTA + ** twice. Initialise to a value not equal to PHB_RX_TGL or 0. + */ + PortP->LastRxTgl = ~(u8) PHB_RX_TGL; + + /* + ** and mark the port as usable + */ + PortP->Mapped = 1; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + } + if (HostMapP->SysPort < p->RIOFirstPortsMapped) + p->RIOFirstPortsMapped = HostMapP->SysPort; + if (HostMapP->SysPort > p->RIOLastPortsMapped) + p->RIOLastPortsMapped = HostMapP->SysPort; + + return 0; +} + +int RIOChangeName(struct rio_info *p, struct Map *MapP) +{ + int host; + struct Map *HostMapP; + char *sptr; + + rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort); + + if (MapP->ID > MAX_RUP) { + rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); + p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; + return -EINVAL; + } + + MapP->Name[MAX_NAME_LEN - 1] = '\0'; + sptr = MapP->Name; + + while (*sptr) { + if (*sptr < ' ' || *sptr > '~') { + rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); + p->RIOError.Error = BAD_CHARACTER_IN_NAME; + return -EINVAL; + } + sptr++; + } + + for (host = 0; host < p->RIONumHosts; host++) { + if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) { + if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) { + p->RIOError.Error = HOST_NOT_RUNNING; + return -ENXIO; + } + if (MapP->ID == 0) { + memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN); + return 0; + } + + HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1]; + + if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) { + p->RIOError.Error = RTA_NUMBER_WRONG; + return -ENXIO; + } + memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN); + return 0; + } + } + p->RIOError.Error = UNKNOWN_HOST_NUMBER; + rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); + return -ENXIO; +} diff --git a/drivers/staging/generic_serial/rio/riotty.c b/drivers/staging/generic_serial/rio/riotty.c new file mode 100644 index 000000000000..8a90393faf3c --- /dev/null +++ b/drivers/staging/generic_serial/rio/riotty.c @@ -0,0 +1,654 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : riotty.c +** SID : 1.3 +** Last Modified : 11/6/98 10:33:47 +** Retrieved : 11/6/98 10:33:50 +** +** ident @(#)riotty.c 1.3 +** +** ----------------------------------------------------------------------------- +*/ + +#define __EXPLICIT_DEF_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + + +#include "linux_compat.h" +#include "rio_linux.h" +#include "pkt.h" +#include "daemon.h" +#include "rio.h" +#include "riospace.h" +#include "cmdpkt.h" +#include "map.h" +#include "rup.h" +#include "port.h" +#include "riodrvr.h" +#include "rioinfo.h" +#include "func.h" +#include "errors.h" +#include "pci.h" + +#include "parmmap.h" +#include "unixrup.h" +#include "board.h" +#include "host.h" +#include "phb.h" +#include "link.h" +#include "cmdblk.h" +#include "route.h" +#include "cirrus.h" +#include "rioioctl.h" +#include "param.h" + +static void RIOClearUp(struct Port *PortP); + +/* Below belongs in func.h */ +int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); + + +extern struct rio_info *p; + + +int riotopen(struct tty_struct *tty, struct file *filp) +{ + unsigned int SysPort; + int repeat_this = 250; + struct Port *PortP; /* pointer to the port structure */ + unsigned long flags; + int retval = 0; + + func_enter(); + + /* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close + is going to oops. + */ + tty->driver_data = NULL; + + SysPort = rio_minor(tty); + + if (p->RIOFailed) { + rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n"); + func_exit(); + return -ENXIO; + } + + rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped); + + /* + ** Validate that we have received a legitimate request. + ** Currently, just check that we are opening a port on + ** a host card that actually exists, and that the port + ** has been mapped onto a host. + */ + if (SysPort >= RIO_PORTS) { /* out of range ? */ + rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort); + func_exit(); + return -ENXIO; + } + + /* + ** Grab pointer to the port stucture + */ + PortP = p->RIOPortp[SysPort]; /* Get control struc */ + rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP); + if (!PortP->Mapped) { /* we aren't mapped yet! */ + /* + ** The system doesn't know which RTA this port + ** corresponds to. + */ + rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n"); + func_exit(); + return -ENXIO; + } + + tty->driver_data = PortP; + + PortP->gs.port.tty = tty; + PortP->gs.port.count++; + + rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt); + + retval = gs_init_port(&PortP->gs); + if (retval) { + PortP->gs.port.count--; + return -ENXIO; + } + /* + ** If the host hasn't been booted yet, then + ** fail + */ + if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) { + rio_dprintk(RIO_DEBUG_TTY, "Host not running\n"); + func_exit(); + return -ENXIO; + } + + /* + ** If the RTA has not booted yet and the user has choosen to block + ** until the RTA is present then we must spin here waiting for + ** the RTA to boot. + */ + /* I find the above code a bit hairy. I find the below code + easier to read and shorter. Now, if it works too that would + be great... -- REW + */ + rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n"); + while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { + if (!PortP->WaitUntilBooted) { + rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n"); + func_exit(); + return -ENXIO; + } + + /* Under Linux you'd normally use a wait instead of this + busy-waiting. I'll stick with the old implementation for + now. --REW + */ + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n"); + func_exit(); + return -EINTR; + } + if (repeat_this-- <= 0) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); + func_exit(); + return -EIO; + } + } + rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n"); + rio_spin_lock_irqsave(&PortP->portSem, flags); + if (p->RIOHalted) { + goto bombout; + } + + /* + ** If the port is in the final throws of being closed, + ** we should wait here (politely), waiting + ** for it to finish, so that it doesn't close us! + */ + while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n"); + if (repeat_this-- <= 0) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + retval = -EINTR; + goto bombout; + } + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_spin_lock_irqsave(&PortP->portSem, flags); + retval = -EINTR; + goto bombout; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + } + + if (!PortP->Mapped) { + rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + retval = -ENXIO; + func_exit(); + return retval; + } + + if (p->RIOHalted) { + goto bombout; + } + +/* +** 15.10.1998 ARG - ESIL 0761 part fix +** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure, +** we need to make sure that the flags are clear when the port is opened. +*/ + /* Uh? Suppose I turn these on and then another process opens + the port again? The flags get cleared! Not good. -- REW */ + if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) { + PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW); + } + + if (!(PortP->firstOpen)) { /* First time ? */ + rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n"); + + + PortP->firstOpen++; + PortP->CookMode = 0; /* XXX RIOCookMode(tp); */ + PortP->InUse = NOT_INUSE; + + /* Tentative fix for bug PR27. Didn't work. */ + /* PortP->gs.xmit_cnt = 0; */ + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + + /* Someone explain to me why this delay/config is + here. If I read the docs correctly the "open" + command piggybacks the parameters immediately. + -- REW */ + RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */ + rio_spin_lock_irqsave(&PortP->portSem, flags); + + /* + ** wait for the port to be not closed. + */ + while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n"); + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + func_exit(); + return -EINTR; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + } + + if (p->RIOHalted) { + retval = -EIO; + bombout: + /* RIOClearUp( PortP ); */ + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return retval; + } + rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n"); + } + rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n"); + /* + ** ACTION + ** insert test for carrier here. -- ??? + ** I already see that test here. What's the deal? -- REW + */ + if ((PortP->gs.port.tty->termios->c_cflag & CLOCAL) || + (PortP->ModemState & RIOC_MSVR1_CD)) { + rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort); + /* + tp->tm.c_state |= CARR_ON; + wakeup((caddr_t) &tp->tm.c_canq); + */ + PortP->State |= RIO_CARR_ON; + wake_up_interruptible(&PortP->gs.port.open_wait); + } else { /* no carrier - wait for DCD */ + /* + while (!(PortP->gs.port.tty->termios->c_state & CARR_ON) && + !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) + */ + while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) { + rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort); + /* + PortP->gs.port.tty->termios->c_state |= WOPEN; + */ + PortP->State |= RIO_WOPEN; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_spin_lock_irqsave(&PortP->portSem, flags); + /* + ** ACTION: verify that this is a good thing + ** to do here. -- ??? + ** I think it's OK. -- REW + */ + rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort); + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + /* + tp->tm.c_state &= ~WOPEN; + */ + PortP->State &= ~RIO_WOPEN; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit(); + return -EINTR; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + } + PortP->State &= ~RIO_WOPEN; + } + if (p->RIOHalted) + goto bombout; + rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); + PortP->State |= RIO_MOPEN; + + if (p->RIOHalted) + goto bombout; + + rio_dprintk(RIO_DEBUG_TTY, "high level open done\n"); + + /* + ** Count opens for port statistics reporting + */ + if (PortP->statsGather) + PortP->opens++; + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n"); + func_exit(); + return 0; +} + +/* +** RIOClose the port. +** The operating system thinks that this is last close for the device. +** As there are two interfaces to the port (Modem and tty), we need to +** check that both are closed before we close the device. +*/ +int riotclose(void *ptr) +{ + struct Port *PortP = ptr; /* pointer to the port structure */ + int deleted = 0; + int try = -1; /* Disable the timeouts by setting them to -1 */ + int repeat_this = -1; /* Congrats to those having 15 years of + uptime! (You get to break the driver.) */ + unsigned long end_time; + struct tty_struct *tty; + unsigned long flags; + int rv = 0; + + rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum); + + /* PortP = p->RIOPortp[SysPort]; */ + rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP); + /* tp = PortP->TtyP; *//* Get tty */ + tty = PortP->gs.port.tty; + rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty); + + if (PortP->gs.closing_wait) + end_time = jiffies + PortP->gs.closing_wait; + else + end_time = jiffies + MAX_SCHEDULE_TIMEOUT; + + rio_spin_lock_irqsave(&PortP->portSem, flags); + + /* + ** Setting this flag will make any process trying to open + ** this port block until we are complete closing it. + */ + PortP->State |= RIO_CLOSING; + + if ((PortP->State & RIO_DELETED)) { + rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n"); + deleted = 1; + } + + if (p->RIOHalted) { + RIOClearUp(PortP); + rv = -EIO; + goto close_end; + } + + rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n"); + /* + ** clear the open bits for this device + */ + PortP->State &= ~RIO_MOPEN; + PortP->State &= ~RIO_CARR_ON; + PortP->ModemState &= ~RIOC_MSVR1_CD; + /* + ** If the device was open as both a Modem and a tty line + ** then we need to wimp out here, as the port has not really + ** been finally closed (gee, whizz!) The test here uses the + ** bit for the OTHER mode of operation, to see if THAT is + ** still active! + */ + if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) { + /* + ** The port is still open for the other task - + ** return, pretending that we are still active. + */ + rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum); + PortP->State &= ~RIO_CLOSING; + if (PortP->firstOpen) + PortP->firstOpen--; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return -EIO; + } + + rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n"); + + PortP->State &= ~RIO_DYNOROD; + + /* + ** This is where we wait for the port + ** to drain down before closing. Bye-bye.... + ** (We never meant to do this) + */ + rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n"); + + if (!deleted) + while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) { + if (repeat_this-- <= 0) { + rv = -EINTR; + rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + goto close_end; + } + rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n"); + rv = -EINTR; + rio_spin_lock_irqsave(&PortP->portSem, flags); + goto close_end; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + } + + PortP->TxBufferIn = PortP->TxBufferOut = 0; + repeat_this = 0xff; + + PortP->InUse = 0; + if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) { + /* + ** The port has been re-opened for the other task - + ** return, pretending that we are still active. + */ + rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum); + PortP->State &= ~RIO_CLOSING; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (PortP->firstOpen) + PortP->firstOpen--; + return -EIO; + } + + if (p->RIOHalted) { + RIOClearUp(PortP); + goto close_end; + } + + /* Can't call RIOShortCommand with the port locked. */ + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + + if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) { + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + rio_spin_lock_irqsave(&PortP->portSem, flags); + goto close_end; + } + + if (!deleted) + while (try && (PortP->PortState & PORT_ISOPEN)) { + try--; + if (time_after(jiffies, end_time)) { + rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n"); + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + break; + } + rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN); + + if (p->RIOHalted) { + RIOClearUp(PortP); + rio_spin_lock_irqsave(&PortP->portSem, flags); + goto close_end; + } + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n"); + RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); + break; + } + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try); + + /* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */ + +/* +** 15.10.1998 ARG - ESIL 0761 part fix +** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened. +*/ + PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW); + + /* + ** Count opens for port statistics reporting + */ + if (PortP->statsGather) + PortP->closes++; + +close_end: + /* XXX: Why would a "DELETED" flag be reset here? I'd have + thought that a "deleted" flag means that the port was + permanently gone, but here we can make it reappear by it + being in close during the "deletion". + */ + PortP->State &= ~(RIO_CLOSING | RIO_DELETED); + if (PortP->firstOpen) + PortP->firstOpen--; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + rio_dprintk(RIO_DEBUG_TTY, "Return from close\n"); + return rv; +} + + + +static void RIOClearUp(struct Port *PortP) +{ + rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n"); + PortP->Config = 0; /* Direct semaphore */ + PortP->PortState = 0; + PortP->firstOpen = 0; + PortP->FlushCmdBodge = 0; + PortP->ModemState = PortP->CookMode = 0; + PortP->Mapped = 0; + PortP->WflushFlag = 0; + PortP->MagicFlags = 0; + PortP->RxDataStart = 0; + PortP->TxBufferIn = 0; + PortP->TxBufferOut = 0; +} + +/* +** Put a command onto a port. +** The PortPointer, command, length and arg are passed. +** The len is the length *inclusive* of the command byte, +** and so for a command that takes no data, len==1. +** The arg is a single byte, and is only used if len==2. +** Other values of len aren't allowed, and will cause +** a panic. +*/ +int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg) +{ + struct PKT __iomem *PacketP; + int retries = 20; /* at 10 per second -> 2 seconds */ + unsigned long flags; + + rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n"); + + if (PortP->State & RIO_DELETED) { + rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); + return RIO_FAIL; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + + /* + ** If the port is in use for pre-emptive command, then wait for it to + ** be free again. + */ + while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (retries-- <= 0) { + return RIO_FAIL; + } + if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) { + return RIO_FAIL; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + } + if (PortP->State & RIO_DELETED) { + rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return RIO_FAIL; + } + + while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) { + rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (retries-- <= 0) { + rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n"); + return RIO_FAIL; + } + if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) { + return RIO_FAIL; + } + rio_spin_lock_irqsave(&PortP->portSem, flags); + } + + if (p->RIOHalted) { + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return RIO_FAIL; + } + + /* + ** set the command byte and the argument byte + */ + writeb(command, &PacketP->data[0]); + + if (len == 2) + writeb(arg, &PacketP->data[1]); + + /* + ** set the length of the packet and set the command bit. + */ + writeb(PKT_CMD_BIT | len, &PacketP->len); + + add_transmit(PortP); + /* + ** Count characters transmitted for port statistics reporting + */ + if (PortP->statsGather) + PortP->txchars += len; + + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL; +} + + diff --git a/drivers/staging/generic_serial/rio/route.h b/drivers/staging/generic_serial/rio/route.h new file mode 100644 index 000000000000..46e963771c30 --- /dev/null +++ b/drivers/staging/generic_serial/rio/route.h @@ -0,0 +1,101 @@ +/**************************************************************************** + ******* ******* + ******* R O U T E H E A D E R + ******* ******* + **************************************************************************** + + Author : Ian Nandhra / Jeremy Rolls + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _route_h +#define _route_h + +#define MAX_LINKS 4 +#define MAX_NODES 17 /* Maximum nodes in a subnet */ +#define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for + 1 bit per node */ +#define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete + info about cost etc. */ +#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE) + /* Number of nodes we can squeeze + into one packet */ +#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1) +/************************************************ + * Define the types of command for the ROUTE RUP. + ************************************************/ +#define ROUTE_REQUEST 0 /* Request an ID */ +#define ROUTE_FOAD 1 /* Kill the RTA */ +#define ROUTE_ALREADY 2 /* ID given already */ +#define ROUTE_USED 3 /* All ID's used */ +#define ROUTE_ALLOCATE 4 /* Here it is */ +#define ROUTE_REQ_TOP 5 /* I bet you didn't expect.... + the Topological Inquisition */ +#define ROUTE_TOPOLOGY 6 /* Topology request answered FD */ +/******************************************************************* + * Define the Route Map Structure + * + * The route map gives a pointer to a Link Structure to use. + * This allows Disconnected Links to be checked quickly + ******************************************************************/ +typedef struct COST_ROUTE COST_ROUTE; +struct COST_ROUTE { + unsigned char cost; /* Cost down this link */ + unsigned char route[NODE_BYTES]; /* Nodes through this route */ +}; + +typedef struct ROUTE_STR ROUTE_STR; +struct ROUTE_STR { + COST_ROUTE cost_route[MAX_LINKS]; + /* cost / route for this link */ + ushort favoured; /* favoured link */ +}; + + +#define NO_LINK (short) 5 /* Link unattached */ +#define ROUTE_NO_ID (short) 100 /* No Id */ +#define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */ +#define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */ + + +#define SYNC_RUP (ushort) 255 +#define COMMAND_RUP (ushort) 254 +#define ERROR_RUP (ushort) 253 +#define POLL_RUP (ushort) 252 +#define BOOT_RUP (ushort) 251 +#define ROUTE_RUP (ushort) 250 +#define STATUS_RUP (ushort) 249 +#define POWER_RUP (ushort) 248 + +#define HIGHEST_RUP (ushort) 255 /* Set to Top one */ +#define LOWEST_RUP (ushort) 248 /* Set to bottom one */ + +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/rup.h b/drivers/staging/generic_serial/rio/rup.h new file mode 100644 index 000000000000..4ae90cb207a9 --- /dev/null +++ b/drivers/staging/generic_serial/rio/rup.h @@ -0,0 +1,69 @@ +/**************************************************************************** + ******* ******* + ******* R U P S T R U C T U R E + ******* ******* + **************************************************************************** + + Author : Ian Nandhra + Date : + + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Version : 0.01 + + + Mods + ---------------------------------------------------------------------------- + Date By Description + ---------------------------------------------------------------------------- + + ***************************************************************************/ + +#ifndef _rup_h +#define _rup_h 1 + +#define MAX_RUP ((short) 16) +#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ + +/************************************************* + * Define all the packet request stuff + ************************************************/ +#define TX_RUP_INACTIVE 0 /* Nothing to transmit */ +#define TX_PACKET_READY 1 /* Transmit packet ready */ +#define TX_LOCK_RUP 2 /* Transmit side locked */ + +#define RX_RUP_INACTIVE 0 /* Nothing received */ +#define RX_PACKET_READY 1 /* Packet received */ + +#define RUP_NO_OWNER 0xff /* RUP not owned by any process */ + +struct RUP { + u16 txpkt; /* Outgoing packet */ + u16 rxpkt; /* Incoming packet */ + u16 link; /* Which link to send down? */ + u8 rup_dest_unit[2]; /* Destination unit */ + u16 handshake; /* For handshaking */ + u16 timeout; /* Timeout */ + u16 status; /* Status */ + u16 txcontrol; /* Transmit control */ + u16 rxcontrol; /* Receive control */ +}; + +#endif + +/*********** end of file ***********/ diff --git a/drivers/staging/generic_serial/rio/unixrup.h b/drivers/staging/generic_serial/rio/unixrup.h new file mode 100644 index 000000000000..7abf0cba0f2c --- /dev/null +++ b/drivers/staging/generic_serial/rio/unixrup.h @@ -0,0 +1,51 @@ +/* +** ----------------------------------------------------------------------------- +** +** Perle Specialix driver for Linux +** Ported from existing RIO Driver for SCO sources. + * + * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Module : unixrup.h +** SID : 1.2 +** Last Modified : 11/6/98 11:34:20 +** Retrieved : 11/6/98 11:34:22 +** +** ident @(#)unixrup.h 1.2 +** +** ----------------------------------------------------------------------------- +*/ + +#ifndef __rio_unixrup_h__ +#define __rio_unixrup_h__ + +/* +** UnixRup data structure. This contains pointers to actual RUPs on the +** host card, and all the command/boot control stuff. +*/ +struct UnixRup { + struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */ + struct CmdBlk *CmdPendingP; /* The command currently being sent */ + struct RUP __iomem *RupP; /* the Rup to send it to */ + unsigned int Id; /* Id number */ + unsigned int BaseSysPort; /* SysPort of first tty on this RTA */ + unsigned int ModTypes; /* Modules on this RTA */ + spinlock_t RupLock; /* Lock structure for MPX */ + /* struct lockb RupLock; *//* Lock structure for MPX */ +}; + +#endif /* __rio_unixrup_h__ */ diff --git a/drivers/staging/generic_serial/ser_a2232.c b/drivers/staging/generic_serial/ser_a2232.c new file mode 100644 index 000000000000..3f47c2ead8e5 --- /dev/null +++ b/drivers/staging/generic_serial/ser_a2232.c @@ -0,0 +1,831 @@ +/* drivers/char/ser_a2232.c */ + +/* $Id: ser_a2232.c,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */ + +/* Linux serial driver for the Amiga A2232 board */ + +/* This driver is MAINTAINED. Before applying any changes, please contact + * the author. + */ + +/* Copyright (c) 2000-2001 Enver Haase + * alias The A2232 driver project + * All rights reserved. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +/***************************** Documentation ************************/ +/* + * This driver is in EXPERIMENTAL state. That means I could not find + * someone with five A2232 boards with 35 ports running at 19200 bps + * at the same time and test the machine's behaviour. + * However, I know that you can performance-tweak this driver (see + * the source code). + * One thing to consider is the time this driver consumes during the + * Amiga's vertical blank interrupt. Everything that is to be done + * _IS DONE_ when entering the vertical blank interrupt handler of + * this driver. + * However, it would be more sane to only do the job for only ONE card + * instead of ALL cards at a time; or, more generally, to handle only + * SOME ports instead of ALL ports at a time. + * However, as long as no-one runs into problems I guess I shouldn't + * change the driver as it runs fine for me :) . + * + * Version history of this file: + * 0.4 Resolved licensing issues. + * 0.3 Inclusion in the Linux/m68k tree, small fixes. + * 0.2 Added documentation, minor typo fixes. + * 0.1 Initial release. + * + * TO DO: + * - Handle incoming BREAK events. I guess "Stevens: Advanced + * Programming in the UNIX(R) Environment" is a good reference + * on what is to be done. + * - When installing as a module, don't simply 'printk' text, but + * send it to the TTY used by the user. + * + * THANKS TO: + * - Jukka Marin (65EC02 code). + * - The other NetBSD developers on whose A2232 driver I had a + * pretty close look. However, I didn't copy any code so it + * is okay to put my code under the GPL and include it into + * Linux. + */ +/***************************** End of Documentation *****************/ + +/***************************** Defines ******************************/ +/* + * Enables experimental 115200 (normal) 230400 (turbo) baud rate. + * The A2232 specification states it can only operate at speeds up to + * 19200 bits per second, and I was not able to send a file via + * "sz"/"rz" and a null-modem cable from one A2232 port to another + * at 115200 bits per second. + * However, this might work for you. + */ +#undef A2232_SPEEDHACK +/* + * Default is not to use RTS/CTS so you could be talked to death. + */ +#define A2232_SUPPRESS_RTSCTS_WARNING +/************************* End of Defines ***************************/ + +/***************************** Includes *****************************/ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "ser_a2232.h" +#include "ser_a2232fw.h" +/************************* End of Includes **************************/ + +/***************************** Prototypes ***************************/ +/* The interrupt service routine */ +static irqreturn_t a2232_vbl_inter(int irq, void *data); +/* Initialize the port structures */ +static void a2232_init_portstructs(void); +/* Initialize and register TTY drivers. */ +/* returns 0 IFF successful */ +static int a2232_init_drivers(void); + +/* BEGIN GENERIC_SERIAL PROTOTYPES */ +static void a2232_disable_tx_interrupts(void *ptr); +static void a2232_enable_tx_interrupts(void *ptr); +static void a2232_disable_rx_interrupts(void *ptr); +static void a2232_enable_rx_interrupts(void *ptr); +static int a2232_carrier_raised(struct tty_port *port); +static void a2232_shutdown_port(void *ptr); +static int a2232_set_real_termios(void *ptr); +static int a2232_chars_in_buffer(void *ptr); +static void a2232_close(void *ptr); +static void a2232_hungup(void *ptr); +/* static void a2232_getserial (void *ptr, struct serial_struct *sp); */ +/* END GENERIC_SERIAL PROTOTYPES */ + +/* Functions that the TTY driver struct expects */ +static int a2232_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg); +static void a2232_throttle(struct tty_struct *tty); +static void a2232_unthrottle(struct tty_struct *tty); +static int a2232_open(struct tty_struct * tty, struct file * filp); +/************************* End of Prototypes ************************/ + +/***************************** Global variables *********************/ +/*--------------------------------------------------------------------------- + * Interface from generic_serial.c back here + *--------------------------------------------------------------------------*/ +static struct real_driver a2232_real_driver = { + a2232_disable_tx_interrupts, + a2232_enable_tx_interrupts, + a2232_disable_rx_interrupts, + a2232_enable_rx_interrupts, + a2232_shutdown_port, + a2232_set_real_termios, + a2232_chars_in_buffer, + a2232_close, + a2232_hungup, + NULL /* a2232_getserial */ +}; + +static void *a2232_driver_ID = &a2232_driver_ID; // Some memory address WE own. + +/* Ports structs */ +static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES]; + +/* TTY driver structs */ +static struct tty_driver *a2232_driver; + +/* nr of cards completely (all ports) and correctly configured */ +static int nr_a2232; + +/* zorro_dev structs for the A2232's */ +static struct zorro_dev *zd_a2232[MAX_A2232_BOARDS]; +/***************************** End of Global variables **************/ + +/* Helper functions */ + +static inline volatile struct a2232memory *a2232mem(unsigned int board) +{ + return (volatile struct a2232memory *)ZTWO_VADDR(zd_a2232[board]->resource.start); +} + +static inline volatile struct a2232status *a2232stat(unsigned int board, + unsigned int portonboard) +{ + volatile struct a2232memory *mem = a2232mem(board); + return &(mem->Status[portonboard]); +} + +static inline void a2232_receive_char(struct a2232_port *port, int ch, int err) +{ +/* Mostly stolen from other drivers. + Maybe one could implement a more efficient version by not only + transferring one character at a time. +*/ + struct tty_struct *tty = port->gs.port.tty; + +#if 0 + switch(err) { + case TTY_BREAK: + break; + case TTY_PARITY: + break; + case TTY_OVERRUN: + break; + case TTY_FRAME: + break; + } +#endif + + tty_insert_flip_char(tty, ch, err); + tty_flip_buffer_push(tty); +} + +/***************************** Functions ****************************/ +/*** BEGIN OF REAL_DRIVER FUNCTIONS ***/ + +static void a2232_disable_tx_interrupts(void *ptr) +{ + struct a2232_port *port; + volatile struct a2232status *stat; + unsigned long flags; + + port = ptr; + stat = a2232stat(port->which_a2232, port->which_port_on_a2232); + stat->OutDisable = -1; + + /* Does this here really have to be? */ + local_irq_save(flags); + port->gs.port.flags &= ~GS_TX_INTEN; + local_irq_restore(flags); +} + +static void a2232_enable_tx_interrupts(void *ptr) +{ + struct a2232_port *port; + volatile struct a2232status *stat; + unsigned long flags; + + port = ptr; + stat = a2232stat(port->which_a2232, port->which_port_on_a2232); + stat->OutDisable = 0; + + /* Does this here really have to be? */ + local_irq_save(flags); + port->gs.port.flags |= GS_TX_INTEN; + local_irq_restore(flags); +} + +static void a2232_disable_rx_interrupts(void *ptr) +{ + struct a2232_port *port; + port = ptr; + port->disable_rx = -1; +} + +static void a2232_enable_rx_interrupts(void *ptr) +{ + struct a2232_port *port; + port = ptr; + port->disable_rx = 0; +} + +static int a2232_carrier_raised(struct tty_port *port) +{ + struct a2232_port *ap = container_of(port, struct a2232_port, gs.port); + return ap->cd_status; +} + +static void a2232_shutdown_port(void *ptr) +{ + struct a2232_port *port; + volatile struct a2232status *stat; + unsigned long flags; + + port = ptr; + stat = a2232stat(port->which_a2232, port->which_port_on_a2232); + + local_irq_save(flags); + + port->gs.port.flags &= ~GS_ACTIVE; + + if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { + /* Set DTR and RTS to Low, flush output. + The NetBSD driver "msc.c" does it this way. */ + stat->Command = ( (stat->Command & ~A2232CMD_CMask) | + A2232CMD_Close ); + stat->OutFlush = -1; + stat->Setup = -1; + } + + local_irq_restore(flags); + + /* After analyzing control flow, I think a2232_shutdown_port + is actually the last call from the system when at application + level someone issues a "echo Hello >>/dev/ttyY0". + Therefore I think the MOD_DEC_USE_COUNT should be here and + not in "a2232_close()". See the comment in "sx.c", too. + If you run into problems, compile this driver into the + kernel instead of compiling it as a module. */ +} + +static int a2232_set_real_termios(void *ptr) +{ + unsigned int cflag, baud, chsize, stopb, parity, softflow; + int rate; + int a2232_param, a2232_cmd; + unsigned long flags; + unsigned int i; + struct a2232_port *port = ptr; + volatile struct a2232status *status; + volatile struct a2232memory *mem; + + if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; + + status = a2232stat(port->which_a2232, port->which_port_on_a2232); + mem = a2232mem(port->which_a2232); + + a2232_param = a2232_cmd = 0; + + // get baud rate + baud = port->gs.baud; + if (baud == 0) { + /* speed == 0 -> drop DTR, do nothing else */ + local_irq_save(flags); + // Clear DTR (and RTS... mhhh). + status->Command = ( (status->Command & ~A2232CMD_CMask) | + A2232CMD_Close ); + status->OutFlush = -1; + status->Setup = -1; + + local_irq_restore(flags); + return 0; + } + + rate = A2232_BAUD_TABLE_NOAVAIL; + for (i=0; i < A2232_BAUD_TABLE_NUM_RATES * 3; i += 3){ + if (a2232_baud_table[i] == baud){ + if (mem->Common.Crystal == A2232_TURBO) rate = a2232_baud_table[i+2]; + else rate = a2232_baud_table[i+1]; + } + } + if (rate == A2232_BAUD_TABLE_NOAVAIL){ + printk("a2232: Board %d Port %d unsupported baud rate: %d baud. Using another.\n",port->which_a2232,port->which_port_on_a2232,baud); + // This is useful for both (turbo or normal) Crystal versions. + rate = A2232PARAM_B9600; + } + a2232_param |= rate; + + cflag = port->gs.port.tty->termios->c_cflag; + + // get character size + chsize = cflag & CSIZE; + switch (chsize){ + case CS8: a2232_param |= A2232PARAM_8Bit; break; + case CS7: a2232_param |= A2232PARAM_7Bit; break; + case CS6: a2232_param |= A2232PARAM_6Bit; break; + case CS5: a2232_param |= A2232PARAM_5Bit; break; + default: printk("a2232: Board %d Port %d unsupported character size: %d. Using 8 data bits.\n", + port->which_a2232,port->which_port_on_a2232,chsize); + a2232_param |= A2232PARAM_8Bit; break; + } + + // get number of stop bits + stopb = cflag & CSTOPB; + if (stopb){ // two stop bits instead of one + printk("a2232: Board %d Port %d 2 stop bits unsupported. Using 1 stop bit.\n", + port->which_a2232,port->which_port_on_a2232); + } + + // Warn if RTS/CTS not wanted + if (!(cflag & CRTSCTS)){ +#ifndef A2232_SUPPRESS_RTSCTS_WARNING + printk("a2232: Board %d Port %d cannot switch off firmware-implemented RTS/CTS hardware flow control.\n", + port->which_a2232,port->which_port_on_a2232); +#endif + } + + /* I think this is correct. + However, IXOFF means _input_ flow control and I wonder + if one should care about IXON _output_ flow control, + too. If this makes problems, one should turn the A2232 + firmware XON/XOFF "SoftFlow" flow control off and use + the conventional way of inserting START/STOP characters + by hand in throttle()/unthrottle(). + */ + softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF ); + + // get Parity (Enabled/Disabled? If Enabled, Odd or Even?) + parity = cflag & (PARENB | PARODD); + if (parity & PARENB){ + if (parity & PARODD){ + a2232_cmd |= A2232CMD_OddParity; + } + else{ + a2232_cmd |= A2232CMD_EvenParity; + } + } + else a2232_cmd |= A2232CMD_NoParity; + + + /* Hmm. Maybe an own a2232_port structure + member would be cleaner? */ + if (cflag & CLOCAL) + port->gs.port.flags &= ~ASYNC_CHECK_CD; + else + port->gs.port.flags |= ASYNC_CHECK_CD; + + + /* Now we have all parameters and can go to set them: */ + local_irq_save(flags); + + status->Param = a2232_param | A2232PARAM_RcvBaud; + status->Command = a2232_cmd | A2232CMD_Open | A2232CMD_Enable; + status->SoftFlow = softflow; + status->OutDisable = 0; + status->Setup = -1; + + local_irq_restore(flags); + return 0; +} + +static int a2232_chars_in_buffer(void *ptr) +{ + struct a2232_port *port; + volatile struct a2232status *status; + unsigned char ret; /* we need modulo-256 arithmetics */ + port = ptr; + status = a2232stat(port->which_a2232, port->which_port_on_a2232); +#if A2232_IOBUFLEN != 256 +#error "Re-Implement a2232_chars_in_buffer()!" +#endif + ret = (status->OutHead - status->OutTail); + return ret; +} + +static void a2232_close(void *ptr) +{ + a2232_disable_tx_interrupts(ptr); + a2232_disable_rx_interrupts(ptr); + /* see the comment in a2232_shutdown_port above. */ +} + +static void a2232_hungup(void *ptr) +{ + a2232_close(ptr); +} +/*** END OF REAL_DRIVER FUNCTIONS ***/ + +/*** BEGIN FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/ +static int a2232_ioctl( struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + +static void a2232_throttle(struct tty_struct *tty) +{ +/* Throttle: System cannot take another chars: Drop RTS or + send the STOP char or whatever. + The A2232 firmware does RTS/CTS anyway, and XON/XOFF + if switched on. So the only thing we can do at this + layer here is not taking any characters out of the + A2232 buffer any more. */ + struct a2232_port *port = tty->driver_data; + port->throttle_input = -1; +} + +static void a2232_unthrottle(struct tty_struct *tty) +{ +/* Unthrottle: dual to "throttle()" above. */ + struct a2232_port *port = tty->driver_data; + port->throttle_input = 0; +} + +static int a2232_open(struct tty_struct * tty, struct file * filp) +{ +/* More or less stolen from other drivers. */ + int line; + int retval; + struct a2232_port *port; + + line = tty->index; + port = &a2232_ports[line]; + + tty->driver_data = port; + port->gs.port.tty = tty; + port->gs.port.count++; + retval = gs_init_port(&port->gs); + if (retval) { + port->gs.port.count--; + return retval; + } + port->gs.port.flags |= GS_ACTIVE; + retval = gs_block_til_ready(port, filp); + + if (retval) { + port->gs.port.count--; + return retval; + } + + a2232_enable_rx_interrupts(port); + + return 0; +} +/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/ + +static irqreturn_t a2232_vbl_inter(int irq, void *data) +{ +#if A2232_IOBUFLEN != 256 +#error "Re-Implement a2232_vbl_inter()!" +#endif + +struct a2232_port *port; +volatile struct a2232memory *mem; +volatile struct a2232status *status; +unsigned char newhead; +unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */ +unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */ +volatile u_char *ibuf, *cbuf, *obuf; +int ch, err, n, p; + for (n = 0; n < nr_a2232; n++){ /* for every completely initialized A2232 board */ + mem = a2232mem(n); + for (p = 0; p < NUMLINES; p++){ /* for every port on this board */ + err = 0; + port = &a2232_ports[n*NUMLINES+p]; + if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */ + + status = a2232stat(n,p); + + if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */ + newhead = status->InHead; /* 65EC02 write pointer */ + bufpos = status->InTail; + + /* check for input for this port */ + if (newhead != bufpos) { + /* buffer for input chars/events */ + ibuf = mem->InBuf[p]; + + /* data types of bytes in ibuf */ + cbuf = mem->InCtl[p]; + + /* do for all chars */ + while (bufpos != newhead) { + /* which type of input data? */ + switch (cbuf[bufpos]) { + /* switch on input event (CD, BREAK, etc.) */ + case A2232INCTL_EVENT: + switch (ibuf[bufpos++]) { + case A2232EVENT_Break: + /* TODO: Handle BREAK signal */ + break; + /* A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are + handled in a separate queue and should not occur here. */ + case A2232EVENT_Sync: + printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring."); + break; + default: + printk("A2232: 65EC02 software broken, unknown event type %d occurred.\n",ibuf[bufpos-1]); + } /* event type switch */ + break; + case A2232INCTL_CHAR: + /* Receive incoming char */ + a2232_receive_char(port, ibuf[bufpos], err); + bufpos++; + break; + default: + printk("A2232: 65EC02 software broken, unknown data type %d occurred.\n",cbuf[bufpos]); + bufpos++; + } /* switch on input data type */ + } /* while there's something in the buffer */ + + status->InTail = bufpos; /* tell 65EC02 what we've read */ + + } /* if there was something in the buffer */ + } /* If input is not disabled */ + + /* Now check if there's something to output */ + obuf = mem->OutBuf[p]; + bufpos = status->OutHead; + while ( (port->gs.xmit_cnt > 0) && + (!port->gs.port.tty->stopped) && + (!port->gs.port.tty->hw_stopped) ){ /* While there are chars to transmit */ + if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */ + ch = port->gs.xmit_buf[port->gs.xmit_tail]; /* get the next char to transmit */ + port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */ + obuf[bufpos++] = ch; /* put it into the A2232 buffer */ + port->gs.xmit_cnt--; + } + else{ /* If A2232 the buffer is full */ + break; /* simply stop filling it. */ + } + } + status->OutHead = bufpos; + + /* WakeUp if output buffer runs low */ + if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { + tty_wakeup(port->gs.port.tty); + } + } // if the port is used + } // for every port on the board + + /* Now check the CD message queue */ + newhead = mem->Common.CDHead; + bufpos = mem->Common.CDTail; + if (newhead != bufpos){ /* There are CD events in queue */ + ocd = mem->Common.CDStatus; /* get old status bits */ + while (newhead != bufpos){ /* read all events */ + ncd = mem->CDBuf[bufpos++]; /* get one event */ + ccd = ncd ^ ocd; /* mask of changed lines */ + ocd = ncd; /* save new status bits */ + for(p=0; p < NUMLINES; p++){ /* for all ports */ + if (ccd & 1){ /* this one changed */ + + struct a2232_port *port = &a2232_ports[n*7+p]; + port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */ + + if (!(port->gs.port.flags & ASYNC_CHECK_CD)) + ; /* Don't report DCD changes */ + else if (port->cd_status) { // if DCD on: DCD went UP! + + /* Are we blocking in open?*/ + wake_up_interruptible(&port->gs.port.open_wait); + } + else { // if DCD off: DCD went DOWN! + if (port->gs.port.tty) + tty_hangup (port->gs.port.tty); + } + + } // if CD changed for this port + ccd >>= 1; + ncd >>= 1; /* Shift bits for next line */ + } // for every port + } // while CD events in queue + mem->Common.CDStatus = ocd; /* save new status */ + mem->Common.CDTail = bufpos; /* remove events */ + } // if events in CD queue + + } // for every completely initialized A2232 board + return IRQ_HANDLED; +} + +static const struct tty_port_operations a2232_port_ops = { + .carrier_raised = a2232_carrier_raised, +}; + +static void a2232_init_portstructs(void) +{ + struct a2232_port *port; + int i; + + for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) { + port = a2232_ports + i; + tty_port_init(&port->gs.port); + port->gs.port.ops = &a2232_port_ops; + port->which_a2232 = i/NUMLINES; + port->which_port_on_a2232 = i%NUMLINES; + port->disable_rx = port->throttle_input = port->cd_status = 0; + port->gs.magic = A2232_MAGIC; + port->gs.close_delay = HZ/2; + port->gs.closing_wait = 30 * HZ; + port->gs.rd = &a2232_real_driver; + } +} + +static const struct tty_operations a2232_ops = { + .open = a2232_open, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .chars_in_buffer = gs_chars_in_buffer, + .flush_buffer = gs_flush_buffer, + .ioctl = a2232_ioctl, + .throttle = a2232_throttle, + .unthrottle = a2232_unthrottle, + .set_termios = gs_set_termios, + .stop = gs_stop, + .start = gs_start, + .hangup = gs_hangup, +}; + +static int a2232_init_drivers(void) +{ + int error; + + a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232); + if (!a2232_driver) + return -ENOMEM; + a2232_driver->owner = THIS_MODULE; + a2232_driver->driver_name = "commodore_a2232"; + a2232_driver->name = "ttyY"; + a2232_driver->major = A2232_NORMAL_MAJOR; + a2232_driver->type = TTY_DRIVER_TYPE_SERIAL; + a2232_driver->subtype = SERIAL_TYPE_NORMAL; + a2232_driver->init_termios = tty_std_termios; + a2232_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + a2232_driver->init_termios.c_ispeed = 9600; + a2232_driver->init_termios.c_ospeed = 9600; + a2232_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(a2232_driver, &a2232_ops); + if ((error = tty_register_driver(a2232_driver))) { + printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n", + error); + put_tty_driver(a2232_driver); + return 1; + } + return 0; +} + +static int __init a2232board_init(void) +{ + struct zorro_dev *z; + + unsigned int boardaddr; + int bcount; + short start; + u_char *from; + volatile u_char *to; + volatile struct a2232memory *mem; + int error, i; + +#ifdef CONFIG_SMP + return -ENODEV; /* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */ +#endif + + if (!MACH_IS_AMIGA){ + return -ENODEV; + } + + printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */ + + z = NULL; + nr_a2232 = 0; + while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){ + if ( (z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && + (z->id != ZORRO_PROD_CBM_A2232) ){ + continue; // The board found was no A2232 + } + if (!zorro_request_device(z,"A2232 driver")) + continue; + + printk("Commodore A2232 found (#%d).\n",nr_a2232); + + zd_a2232[nr_a2232] = z; + + boardaddr = ZTWO_VADDR( z->resource.start ); + printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start))); + + mem = (volatile struct a2232memory *) boardaddr; + + (void) mem->Enable6502Reset; /* copy the code across to the board */ + to = (u_char *)mem; from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2; + start = *(short *)from; + from += sizeof(start); + to += start; + while(bcount--) *to++ = *from++; + printk("65EC02 software uploaded to the A2232 memory.\n"); + + mem->Common.Crystal = A2232_UNKNOWN; /* use automatic speed check */ + + /* start 6502 running */ + (void) mem->ResetBoard; + printk("A2232's 65EC02 CPU up and running.\n"); + + /* wait until speed detector has finished */ + for (bcount = 0; bcount < 2000; bcount++) { + udelay(1000); + if (mem->Common.Crystal) + break; + } + printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: ")); + switch (mem->Common.Crystal){ + case A2232_UNKNOWN: + printk("Unknown crystal.\n"); + break; + case A2232_NORMAL: + printk ("Normal crystal.\n"); + break; + case A2232_TURBO: + printk ("Turbo crystal.\n"); + break; + default: + printk ("0x%x. Huh?\n",mem->Common.Crystal); + } + + nr_a2232++; + + } + + printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */ + + a2232_init_portstructs(); + + /* + a2232_init_drivers also registers the drivers. Must be here because all boards + have to be detected first. + */ + if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx? + + error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0, + "A2232 serial VBL", a2232_driver_ID); + if (error) { + for (i = 0; i < nr_a2232; i++) + zorro_release_device(zd_a2232[i]); + tty_unregister_driver(a2232_driver); + put_tty_driver(a2232_driver); + } + return error; +} + +static void __exit a2232board_exit(void) +{ + int i; + + for (i = 0; i < nr_a2232; i++) { + zorro_release_device(zd_a2232[i]); + } + + tty_unregister_driver(a2232_driver); + put_tty_driver(a2232_driver); + free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID); +} + +module_init(a2232board_init); +module_exit(a2232board_exit); + +MODULE_AUTHOR("Enver Haase"); +MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/generic_serial/ser_a2232.h b/drivers/staging/generic_serial/ser_a2232.h new file mode 100644 index 000000000000..bc09eb9e118b --- /dev/null +++ b/drivers/staging/generic_serial/ser_a2232.h @@ -0,0 +1,202 @@ +/* drivers/char/ser_a2232.h */ + +/* $Id: ser_a2232.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */ + +/* Linux serial driver for the Amiga A2232 board */ + +/* This driver is MAINTAINED. Before applying any changes, please contact + * the author. + */ + +/* Copyright (c) 2000-2001 Enver Haase + * alias The A2232 driver project + * All rights reserved. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _SER_A2232_H_ +#define _SER_A2232_H_ + +/* + How many boards are to be supported at maximum; + "up to five A2232 Multiport Serial Cards may be installed in a + single Amiga 2000" states the A2232 User's Guide. If you have + more slots available, you might want to change the value below. +*/ +#define MAX_A2232_BOARDS 5 + +#ifndef A2232_NORMAL_MAJOR +/* This allows overriding on the compiler commandline, or in a "major.h" + include or something like that */ +#define A2232_NORMAL_MAJOR 224 /* /dev/ttyY* */ +#define A2232_CALLOUT_MAJOR 225 /* /dev/cuy* */ +#endif + +/* Some magic is always good - Who knows :) */ +#define A2232_MAGIC 0x000a2232 + +/* A2232 port structure to keep track of the + status of every single line used */ +struct a2232_port{ + struct gs_port gs; + unsigned int which_a2232; + unsigned int which_port_on_a2232; + short disable_rx; + short throttle_input; + short cd_status; +}; + +#define NUMLINES 7 /* number of lines per board */ +#define A2232_IOBUFLEN 256 /* number of bytes per buffer */ +#define A2232_IOBUFLENMASK 0xff /* mask for maximum number of bytes */ + + +#define A2232_UNKNOWN 0 /* crystal not known */ +#define A2232_NORMAL 1 /* normal A2232 (1.8432 MHz oscillator) */ +#define A2232_TURBO 2 /* turbo A2232 (3.6864 MHz oscillator) */ + + +struct a2232common { + char Crystal; /* normal (1) or turbo (2) board? */ + u_char Pad_a; + u_char TimerH; /* timer value after speed check */ + u_char TimerL; + u_char CDHead; /* head pointer for CD message queue */ + u_char CDTail; /* tail pointer for CD message queue */ + u_char CDStatus; + u_char Pad_b; +}; + +struct a2232status { + u_char InHead; /* input queue head */ + u_char InTail; /* input queue tail */ + u_char OutDisable; /* disables output */ + u_char OutHead; /* output queue head */ + u_char OutTail; /* output queue tail */ + u_char OutCtrl; /* soft flow control character to send */ + u_char OutFlush; /* flushes output buffer */ + u_char Setup; /* causes reconfiguration */ + u_char Param; /* parameter byte - see A2232PARAM */ + u_char Command; /* command byte - see A2232CMD */ + u_char SoftFlow; /* enables xon/xoff flow control */ + /* private 65EC02 fields: */ + u_char XonOff; /* stores XON/XOFF enable/disable */ +}; + +#define A2232_MEMPAD1 \ + (0x0200 - NUMLINES * sizeof(struct a2232status) - \ + sizeof(struct a2232common)) +#define A2232_MEMPAD2 (0x2000 - NUMLINES * A2232_IOBUFLEN - A2232_IOBUFLEN) + +struct a2232memory { + struct a2232status Status[NUMLINES]; /* 0x0000-0x006f status areas */ + struct a2232common Common; /* 0x0070-0x0077 common flags */ + u_char Dummy1[A2232_MEMPAD1]; /* 0x00XX-0x01ff */ + u_char OutBuf[NUMLINES][A2232_IOBUFLEN];/* 0x0200-0x08ff output bufs */ + u_char InBuf[NUMLINES][A2232_IOBUFLEN]; /* 0x0900-0x0fff input bufs */ + u_char InCtl[NUMLINES][A2232_IOBUFLEN]; /* 0x1000-0x16ff control data */ + u_char CDBuf[A2232_IOBUFLEN]; /* 0x1700-0x17ff CD event buffer */ + u_char Dummy2[A2232_MEMPAD2]; /* 0x1800-0x2fff */ + u_char Code[0x1000]; /* 0x3000-0x3fff code area */ + u_short InterruptAck; /* 0x4000 intr ack */ + u_char Dummy3[0x3ffe]; /* 0x4002-0x7fff */ + u_short Enable6502Reset; /* 0x8000 Stop board, */ + /* 6502 RESET line held low */ + u_char Dummy4[0x3ffe]; /* 0x8002-0xbfff */ + u_short ResetBoard; /* 0xc000 reset board & run, */ + /* 6502 RESET line held high */ +}; + +#undef A2232_MEMPAD1 +#undef A2232_MEMPAD2 + +#define A2232INCTL_CHAR 0 /* corresponding byte in InBuf is a character */ +#define A2232INCTL_EVENT 1 /* corresponding byte in InBuf is an event */ + +#define A2232EVENT_Break 1 /* break set */ +#define A2232EVENT_CarrierOn 2 /* carrier raised */ +#define A2232EVENT_CarrierOff 3 /* carrier dropped */ +#define A2232EVENT_Sync 4 /* don't know, defined in 2232.ax */ + +#define A2232CMD_Enable 0x1 /* enable/DTR bit */ +#define A2232CMD_Close 0x2 /* close the device */ +#define A2232CMD_Open 0xb /* open the device */ +#define A2232CMD_CMask 0xf /* command mask */ +#define A2232CMD_RTSOff 0x0 /* turn off RTS */ +#define A2232CMD_RTSOn 0x8 /* turn on RTS */ +#define A2232CMD_Break 0xd /* transmit a break */ +#define A2232CMD_RTSMask 0xc /* mask for RTS stuff */ +#define A2232CMD_NoParity 0x00 /* don't use parity */ +#define A2232CMD_OddParity 0x20 /* odd parity */ +#define A2232CMD_EvenParity 0x60 /* even parity */ +#define A2232CMD_ParityMask 0xe0 /* parity mask */ + +#define A2232PARAM_B115200 0x0 /* baud rates */ +#define A2232PARAM_B50 0x1 +#define A2232PARAM_B75 0x2 +#define A2232PARAM_B110 0x3 +#define A2232PARAM_B134 0x4 +#define A2232PARAM_B150 0x5 +#define A2232PARAM_B300 0x6 +#define A2232PARAM_B600 0x7 +#define A2232PARAM_B1200 0x8 +#define A2232PARAM_B1800 0x9 +#define A2232PARAM_B2400 0xa +#define A2232PARAM_B3600 0xb +#define A2232PARAM_B4800 0xc +#define A2232PARAM_B7200 0xd +#define A2232PARAM_B9600 0xe +#define A2232PARAM_B19200 0xf +#define A2232PARAM_BaudMask 0xf /* baud rate mask */ +#define A2232PARAM_RcvBaud 0x10 /* enable receive baud rate */ +#define A2232PARAM_8Bit 0x00 /* numbers of bits */ +#define A2232PARAM_7Bit 0x20 +#define A2232PARAM_6Bit 0x40 +#define A2232PARAM_5Bit 0x60 +#define A2232PARAM_BitMask 0x60 /* numbers of bits mask */ + + +/* Standard speeds tables, -1 means unavailable, -2 means 0 baud: switch off line */ +#define A2232_BAUD_TABLE_NOAVAIL -1 +#define A2232_BAUD_TABLE_NUM_RATES (18) +static int a2232_baud_table[A2232_BAUD_TABLE_NUM_RATES*3] = { + //Baud //Normal //Turbo + 50, A2232PARAM_B50, A2232_BAUD_TABLE_NOAVAIL, + 75, A2232PARAM_B75, A2232_BAUD_TABLE_NOAVAIL, + 110, A2232PARAM_B110, A2232_BAUD_TABLE_NOAVAIL, + 134, A2232PARAM_B134, A2232_BAUD_TABLE_NOAVAIL, + 150, A2232PARAM_B150, A2232PARAM_B75, + 200, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL, + 300, A2232PARAM_B300, A2232PARAM_B150, + 600, A2232PARAM_B600, A2232PARAM_B300, + 1200, A2232PARAM_B1200, A2232PARAM_B600, + 1800, A2232PARAM_B1800, A2232_BAUD_TABLE_NOAVAIL, + 2400, A2232PARAM_B2400, A2232PARAM_B1200, + 4800, A2232PARAM_B4800, A2232PARAM_B2400, + 9600, A2232PARAM_B9600, A2232PARAM_B4800, + 19200, A2232PARAM_B19200, A2232PARAM_B9600, + 38400, A2232_BAUD_TABLE_NOAVAIL, A2232PARAM_B19200, + 57600, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL, +#ifdef A2232_SPEEDHACK + 115200, A2232PARAM_B115200, A2232_BAUD_TABLE_NOAVAIL, + 230400, A2232_BAUD_TABLE_NOAVAIL, A2232PARAM_B115200 +#else + 115200, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL, + 230400, A2232_BAUD_TABLE_NOAVAIL, A2232_BAUD_TABLE_NOAVAIL +#endif +}; +#endif diff --git a/drivers/staging/generic_serial/ser_a2232fw.ax b/drivers/staging/generic_serial/ser_a2232fw.ax new file mode 100644 index 000000000000..736438032768 --- /dev/null +++ b/drivers/staging/generic_serial/ser_a2232fw.ax @@ -0,0 +1,529 @@ +;.lib "axm" +; +;begin +;title "A2232 serial board driver" +; +;set modules "2232" +;set executable "2232.bin" +; +;;;;set nolink +; +;set temporary directory "t:" +; +;set assembly options "-m6502 -l60:t:list" +;set link options "bin"; loadadr" +;;;bin2c 2232.bin msc6502.h msc6502code +;end +; +; +; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ### +; +; - Created 950501 by JM - +; +; +; Serial board driver software. +; +; +% Copyright (c) 1995 Jukka Marin . +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions +% are met: +% 1. Redistributions of source code must retain the above copyright +% notice, and the entire permission notice in its entirety, +% including the disclaimer of warranties. +% 2. Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% 3. The name of the author may not be used to endorse or promote +% products derived from this software without specific prior +% written permission. +% +% ALTERNATIVELY, this product may be distributed under the terms of +% the GNU General Public License, in which case the provisions of the +% GPL are required INSTEAD OF the above restrictions. (This clause is +% necessary due to a potential bad interaction between the GPL and +% the restrictions contained in a BSD-style copyright.) +% +% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED +% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +% DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +% OF THE POSSIBILITY OF SUCH DAMAGE. +; +; +; Bugs: +; +; - Can't send a break yet +; +; +; +; Edited: +; +; - 950501 by JM -> v0.1 - Created this file. +; - 951029 by JM -> v1.3 - Carrier Detect events now queued in a separate +; queue. +; +; + + +CODE equ $3800 ; start address for program code + + +CTL_CHAR equ $00 ; byte in ibuf is a character +CTL_EVENT equ $01 ; byte in ibuf is an event + +EVENT_BREAK equ $01 +EVENT_CDON equ $02 +EVENT_CDOFF equ $03 +EVENT_SYNC equ $04 + +XON equ $11 +XOFF equ $13 + + +VARBASE macro *starting_address ; was VARINIT +_varbase set \1 + endm + +VARDEF macro *name space_needs +\1 equ _varbase +_varbase set _varbase+\2 + endm + + +stz macro * address + db $64,\1 + endm + +stzax macro * address + db $9e,<\1,>\1 + endm + + +biti macro * immediate value + db $89,\1 + endm + +smb0 macro * address + db $87,\1 + endm +smb1 macro * address + db $97,\1 + endm +smb2 macro * address + db $a7,\1 + endm +smb3 macro * address + db $b7,\1 + endm +smb4 macro * address + db $c7,\1 + endm +smb5 macro * address + db $d7,\1 + endm +smb6 macro * address + db $e7,\1 + endm +smb7 macro * address + db $f7,\1 + endm + + + +;-----------------------------------------------------------------------; +; ; +; stuff common for all ports, non-critical (run once / loop) ; +; ; +DO_SLOW macro * port_number ; + .local ; ; + lda CIA+C_PA ; check all CD inputs ; + cmp CommonCDo ; changed from previous accptd? ; + beq =over ; nope, do nothing else here ; + ; ; + cmp CommonCDb ; bouncing? ; + beq =nobounce ; nope -> ; + ; ; + sta CommonCDb ; save current state ; + lda #64 ; reinitialize counter ; + sta CommonCDc ; ; + jmp =over ; skip CD save ; + ; ; +=nobounce dec CommonCDc ; no, decrement bounce counter ; + bpl =over ; not done yet, so skip CD save ; + ; ; +=saveCD ldx CDHead ; get write index ; + sta cdbuf,x ; save status in buffer ; + inx ; ; + cpx CDTail ; buffer full? ; + .if ne ; no: preserve status: ; + stx CDHead ; update index in RAM ; + sta CommonCDo ; save state for the next check ; + .end ; ; +=over .end local ; + endm ; + ; +;-----------------------------------------------------------------------; + + +; port specific stuff (no data transfer) + +DO_PORT macro * port_number + .local ; ; + lda SetUp\1 ; reconfiguration request? ; + .if ne ; yes: ; + lda SoftFlow\1 ; get XON/XOFF flag ; + sta XonOff\1 ; save it ; + lda Param\1 ; get parameter ; + ora #%00010000 ; use baud generator for Rx ; + sta ACIA\1+A_CTRL ; store in control register ; + stz OutDisable\1 ; enable transmit output ; + stz SetUp\1 ; no reconfiguration no more ; + .end ; ; + ; ; + lda InHead\1 ; get write index ; + sbc InTail\1 ; buffer full soon? ; + cmp #200 ; 200 chars or more in buffer? ; + lda Command\1 ; get Command reg value ; + and #%11110011 ; turn RTS OFF by default ; + .if cc ; still room in buffer: ; + ora #%00001000 ; turn RTS ON ; + .end ; ; + sta ACIA\1+A_CMD ; set/clear RTS ; + ; ; + lda OutFlush\1 ; request to flush output buffer; + .if ne ; yessh! ; + lda OutHead\1 ; get head ; + sta OutTail\1 ; save as tail ; + stz OutDisable\1 ; enable transmit output ; + stz OutFlush\1 ; clear request ; + .end + .end local + endm + + +DO_DATA macro * port number + .local + lda ACIA\1+A_SR ; read ACIA status register ; + biti [1<<3] ; something received? ; + .if ne ; yes: ; + biti [1<<1] ; framing error? ; + .if ne ; yes: ; + lda ACIA\1+A_DATA ; read received character ; + bne =SEND ; not break -> ignore it ; + ldx InHead\1 ; get write pointer ; + lda #CTL_EVENT ; get type of byte ; + sta ictl\1,x ; save it in InCtl buffer ; + lda #EVENT_BREAK ; event code ; + sta ibuf\1,x ; save it as well ; + inx ; ; + cpx InTail\1 ; still room in buffer? ; + .if ne ; absolutely: ; + stx InHead\1 ; update index in memory ; + .end ; ; + jmp =SEND ; go check if anything to send ; + .end ; ; + ; normal char received: ; + ldx InHead\1 ; get write index ; + lda ACIA\1+A_DATA ; read received character ; + sta ibuf\1,x ; save char in buffer ; + stzax ictl\1 ; set type to CTL_CHAR ; + inx ; ; + cpx InTail\1 ; buffer full? ; + .if ne ; no: preserve character: ; + stx InHead\1 ; update index in RAM ; + .end ; ; + and #$7f ; mask off parity if any ; + cmp #XOFF ; XOFF from remote host? ; + .if eq ; yes: ; + lda XonOff\1 ; if XON/XOFF handshaking.. ; + sta OutDisable\1 ; ..disable transmitter ; + .end ; ; + .end ; ; + ; ; + ; BUFFER FULL CHECK WAS HERE ; + ; ; +=SEND lda ACIA\1+A_SR ; transmit register empty? ; + and #[1<<4] ; ; + .if ne ; yes: ; + ldx OutCtrl\1 ; sending out XON/XOFF? ; + .if ne ; yes: ; + lda CIA+C_PB ; check CTS signal ; + and #[1<<\1] ; (for this port only) ; + bne =DONE ; not allowed to send -> done ; + stx ACIA\1+A_DATA ; transmit control char ; + stz OutCtrl\1 ; clear flag ; + jmp =DONE ; and we're done ; + .end ; ; + ; ; + ldx OutTail\1 ; anything to transmit? ; + cpx OutHead\1 ; ; + .if ne ; yes: ; + lda OutDisable\1 ; allowed to transmit? ; + .if eq ; yes: ; + lda CIA+C_PB ; check CTS signal ; + and #[1<<\1] ; (for this port only) ; + bne =DONE ; not allowed to send -> done ; + lda obuf\1,x ; get a char from buffer ; + sta ACIA\1+A_DATA ; send it away ; + inc OutTail\1 ; update read index ; + .end ; ; + .end ; ; + .end ; ; +=DONE .end local + endm + + + +PORTVAR macro * port number + VARDEF InHead\1 1 + VARDEF InTail\1 1 + VARDEF OutDisable\1 1 + VARDEF OutHead\1 1 + VARDEF OutTail\1 1 + VARDEF OutCtrl\1 1 + VARDEF OutFlush\1 1 + VARDEF SetUp\1 1 + VARDEF Param\1 1 + VARDEF Command\1 1 + VARDEF SoftFlow\1 1 + ; private: + VARDEF XonOff\1 1 + endm + + + VARBASE 0 ; start variables at address $0000 + PORTVAR 0 ; define variables for port 0 + PORTVAR 1 ; define variables for port 1 + PORTVAR 2 ; define variables for port 2 + PORTVAR 3 ; define variables for port 3 + PORTVAR 4 ; define variables for port 4 + PORTVAR 5 ; define variables for port 5 + PORTVAR 6 ; define variables for port 6 + + + + VARDEF Crystal 1 ; 0 = unknown, 1 = normal, 2 = turbo + VARDEF Pad_a 1 + VARDEF TimerH 1 + VARDEF TimerL 1 + VARDEF CDHead 1 + VARDEF CDTail 1 + VARDEF CDStatus 1 + VARDEF Pad_b 1 + + VARDEF CommonCDo 1 ; for carrier detect optimization + VARDEF CommonCDc 1 ; for carrier detect debouncing + VARDEF CommonCDb 1 ; for carrier detect debouncing + + + VARBASE $0200 + VARDEF obuf0 256 ; output data (characters only) + VARDEF obuf1 256 + VARDEF obuf2 256 + VARDEF obuf3 256 + VARDEF obuf4 256 + VARDEF obuf5 256 + VARDEF obuf6 256 + + VARDEF ibuf0 256 ; input data (characters, events etc - see ictl) + VARDEF ibuf1 256 + VARDEF ibuf2 256 + VARDEF ibuf3 256 + VARDEF ibuf4 256 + VARDEF ibuf5 256 + VARDEF ibuf6 256 + + VARDEF ictl0 256 ; input control information (type of data in ibuf) + VARDEF ictl1 256 + VARDEF ictl2 256 + VARDEF ictl3 256 + VARDEF ictl4 256 + VARDEF ictl5 256 + VARDEF ictl6 256 + + VARDEF cdbuf 256 ; CD event queue + + +ACIA0 equ $4400 +ACIA1 equ $4c00 +ACIA2 equ $5400 +ACIA3 equ $5c00 +ACIA4 equ $6400 +ACIA5 equ $6c00 +ACIA6 equ $7400 + +A_DATA equ $00 +A_SR equ $02 +A_CMD equ $04 +A_CTRL equ $06 +; 00 write transmit data read received data +; 02 reset ACIA read status register +; 04 write command register read command register +; 06 write control register read control register + +CIA equ $7c00 ; 8520 CIA +C_PA equ $00 ; port A data register +C_PB equ $02 ; port B data register +C_DDRA equ $04 ; data direction register for port A +C_DDRB equ $06 ; data direction register for port B +C_TAL equ $08 ; timer A +C_TAH equ $0a +C_TBL equ $0c ; timer B +C_TBH equ $0e +C_TODL equ $10 ; TOD LSB +C_TODM equ $12 ; TOD middle byte +C_TODH equ $14 ; TOD MSB +C_DATA equ $18 ; serial data register +C_INTCTRL equ $1a ; interrupt control register +C_CTRLA equ $1c ; control register A +C_CTRLB equ $1e ; control register B + + + + + + section main,code,CODE-2 + + db >CODE,. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* This is the 65EC02 code by Jukka Marin that is executed by + the A2232's 65EC02 processor (base address: 0x3800) + Source file: ser_a2232fw.ax + Version: 1.3 (951029) + Known Bugs: Cannot send a break yet +*/ +static unsigned char a2232_65EC02code[] = { + 0x38, 0x00, 0xA2, 0xFF, 0x9A, 0xD8, 0xA2, 0x00, + 0xA9, 0x00, 0xA0, 0x54, 0x95, 0x00, 0xE8, 0x88, + 0xD0, 0xFA, 0x64, 0x5C, 0x64, 0x5E, 0x64, 0x58, + 0x64, 0x59, 0xA9, 0x00, 0x85, 0x55, 0xA9, 0xAA, + 0xC9, 0x64, 0x90, 0x02, 0xE6, 0x55, 0xA5, 0x54, + 0xF0, 0x03, 0x4C, 0x92, 0x38, 0xA9, 0x98, 0x8D, + 0x06, 0x44, 0xA9, 0x0B, 0x8D, 0x04, 0x44, 0xAD, + 0x02, 0x44, 0xA9, 0x80, 0x8D, 0x1A, 0x7C, 0xA9, + 0xFF, 0x8D, 0x08, 0x7C, 0x8D, 0x0A, 0x7C, 0xA2, + 0x00, 0x8E, 0x00, 0x44, 0xEA, 0xEA, 0xAD, 0x02, + 0x44, 0xEA, 0xEA, 0x8E, 0x00, 0x44, 0xAD, 0x02, + 0x44, 0x29, 0x10, 0xF0, 0xF9, 0xA9, 0x11, 0x8E, + 0x00, 0x44, 0x8D, 0x1C, 0x7C, 0xAD, 0x02, 0x44, + 0x29, 0x10, 0xF0, 0xF9, 0x8E, 0x1C, 0x7C, 0xAD, + 0x08, 0x7C, 0x85, 0x57, 0xAD, 0x0A, 0x7C, 0x85, + 0x56, 0xC9, 0xD0, 0x90, 0x05, 0xA9, 0x02, 0x4C, + 0x82, 0x38, 0xA9, 0x01, 0x85, 0x54, 0xA9, 0x00, + 0x8D, 0x02, 0x44, 0x8D, 0x06, 0x44, 0x8D, 0x04, + 0x44, 0x4C, 0x92, 0x38, 0xAD, 0x00, 0x7C, 0xC5, + 0x5C, 0xF0, 0x1F, 0xC5, 0x5E, 0xF0, 0x09, 0x85, + 0x5E, 0xA9, 0x40, 0x85, 0x5D, 0x4C, 0xB8, 0x38, + 0xC6, 0x5D, 0x10, 0x0E, 0xA6, 0x58, 0x9D, 0x00, + 0x17, 0xE8, 0xE4, 0x59, 0xF0, 0x04, 0x86, 0x58, + 0x85, 0x5C, 0x20, 0x23, 0x3A, 0xA5, 0x07, 0xF0, + 0x0F, 0xA5, 0x0A, 0x85, 0x0B, 0xA5, 0x08, 0x09, + 0x10, 0x8D, 0x06, 0x44, 0x64, 0x02, 0x64, 0x07, + 0xA5, 0x00, 0xE5, 0x01, 0xC9, 0xC8, 0xA5, 0x09, + 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, + 0x44, 0xA5, 0x06, 0xF0, 0x08, 0xA5, 0x03, 0x85, + 0x04, 0x64, 0x02, 0x64, 0x06, 0x20, 0x23, 0x3A, + 0xA5, 0x13, 0xF0, 0x0F, 0xA5, 0x16, 0x85, 0x17, + 0xA5, 0x14, 0x09, 0x10, 0x8D, 0x06, 0x4C, 0x64, + 0x0E, 0x64, 0x13, 0xA5, 0x0C, 0xE5, 0x0D, 0xC9, + 0xC8, 0xA5, 0x15, 0x29, 0xF3, 0xB0, 0x02, 0x09, + 0x08, 0x8D, 0x04, 0x4C, 0xA5, 0x12, 0xF0, 0x08, + 0xA5, 0x0F, 0x85, 0x10, 0x64, 0x0E, 0x64, 0x12, + 0x20, 0x23, 0x3A, 0xA5, 0x1F, 0xF0, 0x0F, 0xA5, + 0x22, 0x85, 0x23, 0xA5, 0x20, 0x09, 0x10, 0x8D, + 0x06, 0x54, 0x64, 0x1A, 0x64, 0x1F, 0xA5, 0x18, + 0xE5, 0x19, 0xC9, 0xC8, 0xA5, 0x21, 0x29, 0xF3, + 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x54, 0xA5, + 0x1E, 0xF0, 0x08, 0xA5, 0x1B, 0x85, 0x1C, 0x64, + 0x1A, 0x64, 0x1E, 0x20, 0x23, 0x3A, 0xA5, 0x2B, + 0xF0, 0x0F, 0xA5, 0x2E, 0x85, 0x2F, 0xA5, 0x2C, + 0x09, 0x10, 0x8D, 0x06, 0x5C, 0x64, 0x26, 0x64, + 0x2B, 0xA5, 0x24, 0xE5, 0x25, 0xC9, 0xC8, 0xA5, + 0x2D, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, + 0x04, 0x5C, 0xA5, 0x2A, 0xF0, 0x08, 0xA5, 0x27, + 0x85, 0x28, 0x64, 0x26, 0x64, 0x2A, 0x20, 0x23, + 0x3A, 0xA5, 0x37, 0xF0, 0x0F, 0xA5, 0x3A, 0x85, + 0x3B, 0xA5, 0x38, 0x09, 0x10, 0x8D, 0x06, 0x64, + 0x64, 0x32, 0x64, 0x37, 0xA5, 0x30, 0xE5, 0x31, + 0xC9, 0xC8, 0xA5, 0x39, 0x29, 0xF3, 0xB0, 0x02, + 0x09, 0x08, 0x8D, 0x04, 0x64, 0xA5, 0x36, 0xF0, + 0x08, 0xA5, 0x33, 0x85, 0x34, 0x64, 0x32, 0x64, + 0x36, 0x20, 0x23, 0x3A, 0xA5, 0x43, 0xF0, 0x0F, + 0xA5, 0x46, 0x85, 0x47, 0xA5, 0x44, 0x09, 0x10, + 0x8D, 0x06, 0x6C, 0x64, 0x3E, 0x64, 0x43, 0xA5, + 0x3C, 0xE5, 0x3D, 0xC9, 0xC8, 0xA5, 0x45, 0x29, + 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x6C, + 0xA5, 0x42, 0xF0, 0x08, 0xA5, 0x3F, 0x85, 0x40, + 0x64, 0x3E, 0x64, 0x42, 0x20, 0x23, 0x3A, 0xA5, + 0x4F, 0xF0, 0x0F, 0xA5, 0x52, 0x85, 0x53, 0xA5, + 0x50, 0x09, 0x10, 0x8D, 0x06, 0x74, 0x64, 0x4A, + 0x64, 0x4F, 0xA5, 0x48, 0xE5, 0x49, 0xC9, 0xC8, + 0xA5, 0x51, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, + 0x8D, 0x04, 0x74, 0xA5, 0x4E, 0xF0, 0x08, 0xA5, + 0x4B, 0x85, 0x4C, 0x64, 0x4A, 0x64, 0x4E, 0x20, + 0x23, 0x3A, 0x4C, 0x92, 0x38, 0xAD, 0x02, 0x44, + 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, + 0xAD, 0x00, 0x44, 0xD0, 0x32, 0xA6, 0x00, 0xA9, + 0x01, 0x9D, 0x00, 0x10, 0xA9, 0x01, 0x9D, 0x00, + 0x09, 0xE8, 0xE4, 0x01, 0xF0, 0x02, 0x86, 0x00, + 0x4C, 0x65, 0x3A, 0xA6, 0x00, 0xAD, 0x00, 0x44, + 0x9D, 0x00, 0x09, 0x9E, 0x00, 0x10, 0xE8, 0xE4, + 0x01, 0xF0, 0x02, 0x86, 0x00, 0x29, 0x7F, 0xC9, + 0x13, 0xD0, 0x04, 0xA5, 0x0B, 0x85, 0x02, 0xAD, + 0x02, 0x44, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x05, + 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 0xD0, + 0x21, 0x8E, 0x00, 0x44, 0x64, 0x05, 0x4C, 0x98, + 0x3A, 0xA6, 0x04, 0xE4, 0x03, 0xF0, 0x13, 0xA5, + 0x02, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, + 0xD0, 0x08, 0xBD, 0x00, 0x02, 0x8D, 0x00, 0x44, + 0xE6, 0x04, 0xAD, 0x02, 0x4C, 0x89, 0x08, 0xF0, + 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x4C, + 0xD0, 0x32, 0xA6, 0x0C, 0xA9, 0x01, 0x9D, 0x00, + 0x11, 0xA9, 0x01, 0x9D, 0x00, 0x0A, 0xE8, 0xE4, + 0x0D, 0xF0, 0x02, 0x86, 0x0C, 0x4C, 0xDA, 0x3A, + 0xA6, 0x0C, 0xAD, 0x00, 0x4C, 0x9D, 0x00, 0x0A, + 0x9E, 0x00, 0x11, 0xE8, 0xE4, 0x0D, 0xF0, 0x02, + 0x86, 0x0C, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, + 0xA5, 0x17, 0x85, 0x0E, 0xAD, 0x02, 0x4C, 0x29, + 0x10, 0xF0, 0x2C, 0xA6, 0x11, 0xF0, 0x0F, 0xAD, + 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x21, 0x8E, 0x00, + 0x4C, 0x64, 0x11, 0x4C, 0x0D, 0x3B, 0xA6, 0x10, + 0xE4, 0x0F, 0xF0, 0x13, 0xA5, 0x0E, 0xD0, 0x0F, + 0xAD, 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x08, 0xBD, + 0x00, 0x03, 0x8D, 0x00, 0x4C, 0xE6, 0x10, 0xAD, + 0x02, 0x54, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, + 0xF0, 0x1B, 0xAD, 0x00, 0x54, 0xD0, 0x32, 0xA6, + 0x18, 0xA9, 0x01, 0x9D, 0x00, 0x12, 0xA9, 0x01, + 0x9D, 0x00, 0x0B, 0xE8, 0xE4, 0x19, 0xF0, 0x02, + 0x86, 0x18, 0x4C, 0x4F, 0x3B, 0xA6, 0x18, 0xAD, + 0x00, 0x54, 0x9D, 0x00, 0x0B, 0x9E, 0x00, 0x12, + 0xE8, 0xE4, 0x19, 0xF0, 0x02, 0x86, 0x18, 0x29, + 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x23, 0x85, + 0x1A, 0xAD, 0x02, 0x54, 0x29, 0x10, 0xF0, 0x2C, + 0xA6, 0x1D, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, + 0x04, 0xD0, 0x21, 0x8E, 0x00, 0x54, 0x64, 0x1D, + 0x4C, 0x82, 0x3B, 0xA6, 0x1C, 0xE4, 0x1B, 0xF0, + 0x13, 0xA5, 0x1A, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, + 0x29, 0x04, 0xD0, 0x08, 0xBD, 0x00, 0x04, 0x8D, + 0x00, 0x54, 0xE6, 0x1C, 0xAD, 0x02, 0x5C, 0x89, + 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, + 0x00, 0x5C, 0xD0, 0x32, 0xA6, 0x24, 0xA9, 0x01, + 0x9D, 0x00, 0x13, 0xA9, 0x01, 0x9D, 0x00, 0x0C, + 0xE8, 0xE4, 0x25, 0xF0, 0x02, 0x86, 0x24, 0x4C, + 0xC4, 0x3B, 0xA6, 0x24, 0xAD, 0x00, 0x5C, 0x9D, + 0x00, 0x0C, 0x9E, 0x00, 0x13, 0xE8, 0xE4, 0x25, + 0xF0, 0x02, 0x86, 0x24, 0x29, 0x7F, 0xC9, 0x13, + 0xD0, 0x04, 0xA5, 0x2F, 0x85, 0x26, 0xAD, 0x02, + 0x5C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x29, 0xF0, + 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 0x21, + 0x8E, 0x00, 0x5C, 0x64, 0x29, 0x4C, 0xF7, 0x3B, + 0xA6, 0x28, 0xE4, 0x27, 0xF0, 0x13, 0xA5, 0x26, + 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, + 0x08, 0xBD, 0x00, 0x05, 0x8D, 0x00, 0x5C, 0xE6, + 0x28, 0xAD, 0x02, 0x64, 0x89, 0x08, 0xF0, 0x3B, + 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x64, 0xD0, + 0x32, 0xA6, 0x30, 0xA9, 0x01, 0x9D, 0x00, 0x14, + 0xA9, 0x01, 0x9D, 0x00, 0x0D, 0xE8, 0xE4, 0x31, + 0xF0, 0x02, 0x86, 0x30, 0x4C, 0x39, 0x3C, 0xA6, + 0x30, 0xAD, 0x00, 0x64, 0x9D, 0x00, 0x0D, 0x9E, + 0x00, 0x14, 0xE8, 0xE4, 0x31, 0xF0, 0x02, 0x86, + 0x30, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, + 0x3B, 0x85, 0x32, 0xAD, 0x02, 0x64, 0x29, 0x10, + 0xF0, 0x2C, 0xA6, 0x35, 0xF0, 0x0F, 0xAD, 0x02, + 0x7C, 0x29, 0x10, 0xD0, 0x21, 0x8E, 0x00, 0x64, + 0x64, 0x35, 0x4C, 0x6C, 0x3C, 0xA6, 0x34, 0xE4, + 0x33, 0xF0, 0x13, 0xA5, 0x32, 0xD0, 0x0F, 0xAD, + 0x02, 0x7C, 0x29, 0x10, 0xD0, 0x08, 0xBD, 0x00, + 0x06, 0x8D, 0x00, 0x64, 0xE6, 0x34, 0xAD, 0x02, + 0x6C, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, + 0x1B, 0xAD, 0x00, 0x6C, 0xD0, 0x32, 0xA6, 0x3C, + 0xA9, 0x01, 0x9D, 0x00, 0x15, 0xA9, 0x01, 0x9D, + 0x00, 0x0E, 0xE8, 0xE4, 0x3D, 0xF0, 0x02, 0x86, + 0x3C, 0x4C, 0xAE, 0x3C, 0xA6, 0x3C, 0xAD, 0x00, + 0x6C, 0x9D, 0x00, 0x0E, 0x9E, 0x00, 0x15, 0xE8, + 0xE4, 0x3D, 0xF0, 0x02, 0x86, 0x3C, 0x29, 0x7F, + 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x47, 0x85, 0x3E, + 0xAD, 0x02, 0x6C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, + 0x41, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x20, + 0xD0, 0x21, 0x8E, 0x00, 0x6C, 0x64, 0x41, 0x4C, + 0xE1, 0x3C, 0xA6, 0x40, 0xE4, 0x3F, 0xF0, 0x13, + 0xA5, 0x3E, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, + 0x20, 0xD0, 0x08, 0xBD, 0x00, 0x07, 0x8D, 0x00, + 0x6C, 0xE6, 0x40, 0xAD, 0x02, 0x74, 0x89, 0x08, + 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, + 0x74, 0xD0, 0x32, 0xA6, 0x48, 0xA9, 0x01, 0x9D, + 0x00, 0x16, 0xA9, 0x01, 0x9D, 0x00, 0x0F, 0xE8, + 0xE4, 0x49, 0xF0, 0x02, 0x86, 0x48, 0x4C, 0x23, + 0x3D, 0xA6, 0x48, 0xAD, 0x00, 0x74, 0x9D, 0x00, + 0x0F, 0x9E, 0x00, 0x16, 0xE8, 0xE4, 0x49, 0xF0, + 0x02, 0x86, 0x48, 0x29, 0x7F, 0xC9, 0x13, 0xD0, + 0x04, 0xA5, 0x53, 0x85, 0x4A, 0xAD, 0x02, 0x74, + 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x4D, 0xF0, 0x0F, + 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x21, 0x8E, + 0x00, 0x74, 0x64, 0x4D, 0x4C, 0x56, 0x3D, 0xA6, + 0x4C, 0xE4, 0x4B, 0xF0, 0x13, 0xA5, 0x4A, 0xD0, + 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x08, + 0xBD, 0x00, 0x08, 0x8D, 0x00, 0x74, 0xE6, 0x4C, + 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xD0, 0x00, 0x38, + 0xCE, 0xC0, +}; diff --git a/drivers/staging/generic_serial/sx.c b/drivers/staging/generic_serial/sx.c new file mode 100644 index 000000000000..1291462bcddb --- /dev/null +++ b/drivers/staging/generic_serial/sx.c @@ -0,0 +1,2894 @@ +/* sx.c -- driver for the Specialix SX series cards. + * + * This driver will also support the older SI, and XIO cards. + * + * + * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl + * + * Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous + * version of this driver. Some fragments may have been copied. (none + * yet :-) + * + * Specialix pays for the development and support of this driver. + * Please DO contact support@specialix.co.uk if you require + * support. But please read the documentation (sx.txt) first. + * + * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * Revision history: + * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff + * - Fixed module and port counting + * - Fixed signal handling + * - Fixed an Ooops + * + * Revision 1.32 2000/03/07 09:00:00 wolff,pvdl + * - Fixed some sx_dprintk typos + * - added detection for an invalid board/module configuration + * + * Revision 1.31 2000/03/06 12:00:00 wolff,pvdl + * - Added support for EISA + * + * Revision 1.30 2000/01/21 17:43:06 wolff + * - Added support for SX+ + * + * Revision 1.26 1999/08/05 15:22:14 wolff + * - Port to 2.3.x + * - Reformatted to Linus' liking. + * + * Revision 1.25 1999/07/30 14:24:08 wolff + * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0). + * + * Revision 1.24 1999/07/28 09:41:52 wolff + * - I noticed the remark about use-count straying in sx.txt. I checked + * sx_open, and found a few places where that could happen. I hope it's + * fixed now. + * + * Revision 1.23 1999/07/28 08:56:06 wolff + * - Fixed crash when sx_firmware run twice. + * - Added sx_slowpoll as a module parameter (I guess nobody really wanted + * to change it from the default... ) + * - Fixed a stupid editing problem I introduced in 1.22. + * - Fixed dropping characters on a termios change. + * + * Revision 1.22 1999/07/26 21:01:43 wolff + * Russell Brown noticed that I had overlooked 4 out of six modem control + * signals in sx_getsignals. Ooops. + * + * Revision 1.21 1999/07/23 09:11:33 wolff + * I forgot to free dynamically allocated memory when the driver is unloaded. + * + * Revision 1.20 1999/07/20 06:25:26 wolff + * The "closing wait" wasn't honoured. Thanks to James Griffiths for + * reporting this. + * + * Revision 1.19 1999/07/11 08:59:59 wolff + * Fixed an oops in close, when an open was pending. Changed the memtest + * a bit. Should also test the board in word-mode, however my card fails the + * memtest then. I still have to figure out what is wrong... + * + * Revision 1.18 1999/06/10 09:38:42 wolff + * Changed the format of the firmware revision from %04x to %x.%02x . + * + * Revision 1.17 1999/06/04 09:44:35 wolff + * fixed problem: reference to pci stuff when config_pci was off... + * Thanks to Jorge Novo for noticing this. + * + * Revision 1.16 1999/06/02 08:30:15 wolff + * added/removed the workaround for the DCD bug in the Firmware. + * A bit more debugging code to locate that... + * + * Revision 1.15 1999/06/01 11:35:30 wolff + * when DCD is left low (floating?), on TA's the firmware first tells us + * that DCD is high, but after a short while suddenly comes to the + * conclusion that it is low. All this would be fine, if it weren't that + * Unix requires us to send a "hangup" signal in that case. This usually + * all happens BEFORE the program has had a chance to ioctl the device + * into clocal mode.. + * + * Revision 1.14 1999/05/25 11:18:59 wolff + * Added PCI-fix. + * Added checks for return code of sx_sendcommand. + * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...) + * + * Revision 1.13 1999/04/29 15:18:01 wolff + * Fixed an "oops" that showed on SuSE 6.0 systems. + * Activate DTR again after stty 0. + * + * Revision 1.12 1999/04/29 07:49:52 wolff + * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming + * the connection would be dropped anyway. That is not always the case, + * and confuses people). + * Told the card to always monitor the modem signals. + * Added support for dynamic gs_debug adjustments. + * Now tells the rest of the system the number of ports. + * + * Revision 1.11 1999/04/24 11:11:30 wolff + * Fixed two stupid typos in the memory test. + * + * Revision 1.10 1999/04/24 10:53:39 wolff + * Added some of Christian's suggestions. + * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the + * card to send the signal to the process.....) + * + * Revision 1.9 1999/04/23 07:26:38 wolff + * Included Christian Lademann's 2.0 compile-warning fixes and interrupt + * assignment redesign. + * Cleanup of some other stuff. + * + * Revision 1.8 1999/04/16 13:05:30 wolff + * fixed a DCD change unnoticed bug. + * + * Revision 1.7 1999/04/14 22:19:51 wolff + * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!) + * + * Revision 1.6 1999/04/13 18:40:20 wolff + * changed misc-minor to 161, as assigned by HPA. + * + * Revision 1.5 1999/04/13 15:12:25 wolff + * Fixed use-count leak when "hangup" occurred. + * Added workaround for a stupid-PCIBIOS bug. + * + * + * Revision 1.4 1999/04/01 22:47:40 wolff + * Fixed < 1M linux-2.0 problem. + * (vremap isn't compatible with ioremap in that case) + * + * Revision 1.3 1999/03/31 13:45:45 wolff + * Firmware loading is now done through a separate IOCTL. + * + * Revision 1.2 1999/03/28 12:22:29 wolff + * rcs cleanup + * + * Revision 1.1 1999/03/28 12:10:34 wolff + * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). + * + * Revision 0.12 1999/03/28 09:20:10 wolff + * Fixed problem in 0.11, continueing cleanup. + * + * Revision 0.11 1999/03/28 08:46:44 wolff + * cleanup. Not good. + * + * Revision 0.10 1999/03/28 08:09:43 wolff + * Fixed loosing characters on close. + * + * Revision 0.9 1999/03/21 22:52:01 wolff + * Ported back to 2.2.... (minor things) + * + * Revision 0.8 1999/03/21 22:40:33 wolff + * Port to 2.0 + * + * Revision 0.7 1999/03/21 19:06:34 wolff + * Fixed hangup processing. + * + * Revision 0.6 1999/02/05 08:45:14 wolff + * fixed real_raw problems. Inclusion into kernel imminent. + * + * Revision 0.5 1998/12/21 23:51:06 wolff + * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it + * shouldn't have. THATs why I want to have transmit interrupts even when + * the buffer is empty. + * + * Revision 0.4 1998/12/17 09:34:46 wolff + * PPP works. ioctl works. Basically works! + * + * Revision 0.3 1998/12/15 13:05:18 wolff + * It works! Wow! Gotta start implementing IOCTL and stuff.... + * + * Revision 0.2 1998/12/01 08:33:53 wolff + * moved over to 2.1.130 + * + * Revision 0.1 1998/11/03 21:23:51 wolff + * Initial revision. Detects SX card. + * + * */ + +#define SX_VERSION 1.33 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */ +#define BYTE u8 +#define WORD u16 + +/* .... but the 3.0.4 version uses _u8 and _u16. */ +#define _u8 u8 +#define _u16 u16 + +#include "sxboards.h" +#include "sxwindow.h" + +#include +#include "sx.h" + +/* I don't think that this driver can handle more than 256 ports on + one machine. You'll have to increase the number of boards in sx.h + if you want more than 4 boards. */ + +#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 +#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 +#endif + +/* Configurable options: + (Don't be too sure that it'll work if you toggle them) */ + +/* Am I paranoid or not ? ;-) */ +#undef SX_PARANOIA_CHECK + +/* 20 -> 2000 per second. The card should rate-limit interrupts at 100 + Hz, but it is user configurable. I don't recommend going above 1000 + Hz. The interrupt ratelimit might trigger if the interrupt is + shared with a very active other device. */ +#define IRQ_RATE_LIMIT 20 + +/* Sharing interrupts is possible now. If the other device wants more + than 2000 interrupts per second, we'd gracefully decline further + interrupts. That's not what we want. On the other hand, if the + other device interrupts 2000 times a second, don't use the SX + interrupt. Use polling. */ +#undef IRQ_RATE_LIMIT + +#if 0 +/* Not implemented */ +/* + * The following defines are mostly for testing purposes. But if you need + * some nice reporting in your syslog, you can define them also. + */ +#define SX_REPORT_FIFO +#define SX_REPORT_OVERRUN +#endif + +/* Function prototypes */ +static void sx_disable_tx_interrupts(void *ptr); +static void sx_enable_tx_interrupts(void *ptr); +static void sx_disable_rx_interrupts(void *ptr); +static void sx_enable_rx_interrupts(void *ptr); +static int sx_carrier_raised(struct tty_port *port); +static void sx_shutdown_port(void *ptr); +static int sx_set_real_termios(void *ptr); +static void sx_close(void *ptr); +static int sx_chars_in_buffer(void *ptr); +static int sx_init_board(struct sx_board *board); +static int sx_init_portstructs(int nboards, int nports); +static long sx_fw_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); +static int sx_init_drivers(void); + +static struct tty_driver *sx_driver; + +static DEFINE_MUTEX(sx_boards_lock); +static struct sx_board boards[SX_NBOARDS]; +static struct sx_port *sx_ports; +static int sx_initialized; +static int sx_nports; +static int sx_debug; + +/* You can have the driver poll your card. + - Set sx_poll to 1 to poll every timer tick (10ms on Intel). + This is used when the card cannot use an interrupt for some reason. + + - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If + the driver misses an interrupt (report this if it DOES happen to you!) + everything will continue to work.... + */ +static int sx_poll = 1; +static int sx_slowpoll; + +/* The card limits the number of interrupts per second. + At 115k2 "100" should be sufficient. + If you're using higher baudrates, you can increase this... + */ + +static int sx_maxints = 100; + +#ifdef CONFIG_ISA + +/* These are the only open spaces in my computer. Yours may have more + or less.... -- REW + duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl +*/ +static int sx_probe_addrs[] = { + 0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000 +}; +static int si_probe_addrs[] = { + 0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000, 0xa0000 +}; +static int si1_probe_addrs[] = { + 0xd0000 +}; + +#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs) +#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs) +#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs) + +module_param_array(sx_probe_addrs, int, NULL, 0); +module_param_array(si_probe_addrs, int, NULL, 0); +#endif + +/* Set the mask to all-ones. This alas, only supports 32 interrupts. + Some architectures may need more. */ +static int sx_irqmask = -1; + +module_param(sx_poll, int, 0); +module_param(sx_slowpoll, int, 0); +module_param(sx_maxints, int, 0); +module_param(sx_debug, int, 0); +module_param(sx_irqmask, int, 0); + +MODULE_LICENSE("GPL"); + +static struct real_driver sx_real_driver = { + sx_disable_tx_interrupts, + sx_enable_tx_interrupts, + sx_disable_rx_interrupts, + sx_enable_rx_interrupts, + sx_shutdown_port, + sx_set_real_termios, + sx_chars_in_buffer, + sx_close, +}; + +/* + This driver can spew a whole lot of debugging output at you. If you + need maximum performance, you should disable the DEBUG define. To + aid in debugging in the field, I'm leaving the compile-time debug + features enabled, and disable them "runtime". That allows me to + instruct people with problems to enable debugging without requiring + them to recompile... +*/ +#define DEBUG + +#ifdef DEBUG +#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) +#else +#define sx_dprintk(f, str...) /* nothing */ +#endif + +#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__) +#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__) + +#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ + __func__, port->line) + +/* + * Firmware loader driver specific routines + * + */ + +static const struct file_operations sx_fw_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = sx_fw_ioctl, + .llseek = noop_llseek, +}; + +static struct miscdevice sx_fw_device = { + SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops +}; + +#ifdef SX_PARANOIA_CHECK + +/* This doesn't work. Who's paranoid around here? Not me! */ + +static inline int sx_paranoia_check(struct sx_port const *port, + char *name, const char *routine) +{ + static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic " + "number for device %s in %s\n"; + static const char *badinfo = KERN_ERR "sx: Warning: null sx port for " + "device %s in %s\n"; + + if (!port) { + printk(badinfo, name, routine); + return 1; + } + if (port->magic != SX_MAGIC) { + printk(badmagic, name, routine); + return 1; + } + + return 0; +} +#else +#define sx_paranoia_check(a,b,c) 0 +#endif + +/* The timeouts. First try 30 times as fast as possible. Then give + the card some time to breathe between accesses. (Otherwise the + processor on the card might not be able to access its OWN bus... */ + +#define TIMEOUT_1 30 +#define TIMEOUT_2 1000000 + +#ifdef DEBUG +static void my_hd_io(void __iomem *p, int len) +{ + int i, j, ch; + unsigned char __iomem *addr = p; + + for (i = 0; i < len; i += 16) { + printk("%p ", addr + i); + for (j = 0; j < 16; j++) { + printk("%02x %s", readb(addr + j + i), + (j == 7) ? " " : ""); + } + for (j = 0; j < 16; j++) { + ch = readb(addr + j + i); + printk("%c", (ch < 0x20) ? '.' : + ((ch > 0x7f) ? '.' : ch)); + } + printk("\n"); + } +} +static void my_hd(void *p, int len) +{ + int i, j, ch; + unsigned char *addr = p; + + for (i = 0; i < len; i += 16) { + printk("%p ", addr + i); + for (j = 0; j < 16; j++) { + printk("%02x %s", addr[j + i], (j == 7) ? " " : ""); + } + for (j = 0; j < 16; j++) { + ch = addr[j + i]; + printk("%c", (ch < 0x20) ? '.' : + ((ch > 0x7f) ? '.' : ch)); + } + printk("\n"); + } +} +#endif + +/* This needs redoing for Alpha -- REW -- Done. */ + +static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte) +{ + writeb(byte, board->base + offset); +} + +static inline u8 read_sx_byte(struct sx_board *board, int offset) +{ + return readb(board->base + offset); +} + +static inline void write_sx_word(struct sx_board *board, int offset, u16 word) +{ + writew(word, board->base + offset); +} + +static inline u16 read_sx_word(struct sx_board *board, int offset) +{ + return readw(board->base + offset); +} + +static int sx_busy_wait_eq(struct sx_board *board, + int offset, int mask, int correctval) +{ + int i; + + func_enter(); + + for (i = 0; i < TIMEOUT_1; i++) + if ((read_sx_byte(board, offset) & mask) == correctval) { + func_exit(); + return 1; + } + + for (i = 0; i < TIMEOUT_2; i++) { + if ((read_sx_byte(board, offset) & mask) == correctval) { + func_exit(); + return 1; + } + udelay(1); + } + + func_exit(); + return 0; +} + +static int sx_busy_wait_neq(struct sx_board *board, + int offset, int mask, int badval) +{ + int i; + + func_enter(); + + for (i = 0; i < TIMEOUT_1; i++) + if ((read_sx_byte(board, offset) & mask) != badval) { + func_exit(); + return 1; + } + + for (i = 0; i < TIMEOUT_2; i++) { + if ((read_sx_byte(board, offset) & mask) != badval) { + func_exit(); + return 1; + } + udelay(1); + } + + func_exit(); + return 0; +} + +/* 5.6.4 of 6210028 r2.3 */ +static int sx_reset(struct sx_board *board) +{ + func_enter(); + + if (IS_SX_BOARD(board)) { + + write_sx_byte(board, SX_CONFIG, 0); + write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */ + + if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) { + printk(KERN_INFO "sx: Card doesn't respond to " + "reset...\n"); + return 0; + } + } else if (IS_EISA_BOARD(board)) { + outb(board->irq << 4, board->eisa_base + 0xc02); + } else if (IS_SI1_BOARD(board)) { + write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/ + } else { + /* Gory details of the SI/ISA board */ + write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET); + write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); + write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); + write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); + } + + func_exit(); + return 1; +} + +/* This doesn't work on machines where "NULL" isn't 0 */ +/* If you have one of those, someone will need to write + the equivalent of this, which will amount to about 3 lines. I don't + want to complicate this right now. -- REW + (See, I do write comments every now and then :-) */ +#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) + +#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) +#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) +#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) + +#define sx_write_channel_byte(port, elem, val) \ + write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) + +#define sx_read_channel_byte(port, elem) \ + read_sx_byte (port->board, CHAN_OFFSET (port, elem)) + +#define sx_write_channel_word(port, elem, val) \ + write_sx_word (port->board, CHAN_OFFSET (port, elem), val) + +#define sx_read_channel_word(port, elem) \ + read_sx_word (port->board, CHAN_OFFSET (port, elem)) + +#define sx_write_module_byte(board, addr, elem, val) \ + write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) + +#define sx_read_module_byte(board, addr, elem) \ + read_sx_byte (board, MODU_OFFSET (board, addr, elem)) + +#define sx_write_module_word(board, addr, elem, val) \ + write_sx_word (board, MODU_OFFSET (board, addr, elem), val) + +#define sx_read_module_word(board, addr, elem) \ + read_sx_word (board, MODU_OFFSET (board, addr, elem)) + +#define sx_write_board_byte(board, elem, val) \ + write_sx_byte (board, BRD_OFFSET (board, elem), val) + +#define sx_read_board_byte(board, elem) \ + read_sx_byte (board, BRD_OFFSET (board, elem)) + +#define sx_write_board_word(board, elem, val) \ + write_sx_word (board, BRD_OFFSET (board, elem), val) + +#define sx_read_board_word(board, elem) \ + read_sx_word (board, BRD_OFFSET (board, elem)) + +static int sx_start_board(struct sx_board *board) +{ + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN); + } else if (IS_EISA_BOARD(board)) { + write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL); + outb((board->irq << 4) | 4, board->eisa_base + 0xc02); + } else if (IS_SI1_BOARD(board)) { + write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0); + write_sx_byte(board, SI1_ISA_INTCL, 0); + } else { + /* Don't bug me about the clear_set. + I haven't the foggiest idea what it's about -- REW */ + write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + } + return 1; +} + +#define SX_IRQ_REG_VAL(board) \ + ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0) + +/* Note. The SX register is write-only. Therefore, we have to enable the + bus too. This is a no-op, if you don't mess with this driver... */ +static int sx_start_interrupts(struct sx_board *board) +{ + + /* Don't call this with board->irq == 0 */ + + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) | + SX_CONF_BUSEN | SX_CONF_HOSTIRQ); + } else if (IS_EISA_BOARD(board)) { + inb(board->eisa_base + 0xc03); + } else if (IS_SI1_BOARD(board)) { + write_sx_byte(board, SI1_ISA_INTCL, 0); + write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0); + } else { + switch (board->irq) { + case 11: + write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET); + break; + case 12: + write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET); + break; + case 15: + write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET); + break; + default: + printk(KERN_INFO "sx: SI/XIO card doesn't support " + "interrupt %d.\n", board->irq); + return 0; + } + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + } + + return 1; +} + +static int sx_send_command(struct sx_port *port, + int command, int mask, int newstat) +{ + func_enter2(); + write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command); + func_exit(); + return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask, + newstat); +} + +static char *mod_type_s(int module_type) +{ + switch (module_type) { + case TA4: + return "TA4"; + case TA8: + return "TA8"; + case TA4_ASIC: + return "TA4_ASIC"; + case TA8_ASIC: + return "TA8_ASIC"; + case MTA_CD1400: + return "MTA_CD1400"; + case SXDC: + return "SXDC"; + default: + return "Unknown/invalid"; + } +} + +static char *pan_type_s(int pan_type) +{ + switch (pan_type) { + case MOD_RS232DB25: + return "MOD_RS232DB25"; + case MOD_RS232RJ45: + return "MOD_RS232RJ45"; + case MOD_RS422DB25: + return "MOD_RS422DB25"; + case MOD_PARALLEL: + return "MOD_PARALLEL"; + case MOD_2_RS232DB25: + return "MOD_2_RS232DB25"; + case MOD_2_RS232RJ45: + return "MOD_2_RS232RJ45"; + case MOD_2_RS422DB25: + return "MOD_2_RS422DB25"; + case MOD_RS232DB25MALE: + return "MOD_RS232DB25MALE"; + case MOD_2_PARALLEL: + return "MOD_2_PARALLEL"; + case MOD_BLANK: + return "empty"; + default: + return "invalid"; + } +} + +static int mod_compat_type(int module_type) +{ + return module_type >> 4; +} + +static void sx_reconfigure_port(struct sx_port *port) +{ + if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) { + if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { + printk(KERN_WARNING "sx: Sent reconfigure command, but " + "card didn't react.\n"); + } + } else { + sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: " + "port isn't open (%02x).\n", + sx_read_channel_byte(port, hi_hstat)); + } +} + +static void sx_setsignals(struct sx_port *port, int dtr, int rts) +{ + int t; + func_enter2(); + + t = sx_read_channel_byte(port, hi_op); + if (dtr >= 0) + t = dtr ? (t | OP_DTR) : (t & ~OP_DTR); + if (rts >= 0) + t = rts ? (t | OP_RTS) : (t & ~OP_RTS); + sx_write_channel_byte(port, hi_op, t); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); + + func_exit(); +} + +static int sx_getsignals(struct sx_port *port) +{ + int i_stat, o_stat; + + o_stat = sx_read_channel_byte(port, hi_op); + i_stat = sx_read_channel_byte(port, hi_ip); + + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " + "%02x/%02x\n", + (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, + port->c_dcd, tty_port_carrier_raised(&port->gs.port), + sx_read_channel_byte(port, hi_ip), + sx_read_channel_byte(port, hi_state)); + + return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) | + ((o_stat & OP_RTS) ? TIOCM_RTS : 0) | + ((i_stat & IP_CTS) ? TIOCM_CTS : 0) | + ((i_stat & IP_DCD) ? TIOCM_CAR : 0) | + ((i_stat & IP_DSR) ? TIOCM_DSR : 0) | + ((i_stat & IP_RI) ? TIOCM_RNG : 0)); +} + +static void sx_set_baud(struct sx_port *port) +{ + int t; + + if (port->board->ta_type == MOD_SXDC) { + switch (port->gs.baud) { + /* Save some typing work... */ +#define e(x) case x: t = BAUD_ ## x; break + e(50); + e(75); + e(110); + e(150); + e(200); + e(300); + e(600); + e(1200); + e(1800); + e(2000); + e(2400); + e(4800); + e(7200); + e(9600); + e(14400); + e(19200); + e(28800); + e(38400); + e(56000); + e(57600); + e(64000); + e(76800); + e(115200); + e(128000); + e(150000); + e(230400); + e(256000); + e(460800); + e(921600); + case 134: + t = BAUD_134_5; + break; + case 0: + t = -1; + break; + default: + /* Can I return "invalid"? */ + t = BAUD_9600; + printk(KERN_INFO "sx: unsupported baud rate: %d.\n", + port->gs.baud); + break; + } +#undef e + if (t > 0) { +/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ + sx_setsignals(port, 1, -1); + /* XXX This is not TA & MTA compatible */ + sx_write_channel_byte(port, hi_csr, 0xff); + + sx_write_channel_byte(port, hi_txbaud, t); + sx_write_channel_byte(port, hi_rxbaud, t); + } else { + sx_setsignals(port, 0, -1); + } + } else { + switch (port->gs.baud) { +#define e(x) case x: t = CSR_ ## x; break + e(75); + e(150); + e(300); + e(600); + e(1200); + e(2400); + e(4800); + e(1800); + e(9600); + e(19200); + e(57600); + e(38400); +/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ + case 110: + if (port->board->ta_type == MOD_TA) { + t = CSR_110; + break; + } else { + t = CSR_9600; + printk(KERN_INFO "sx: Unsupported baud rate: " + "%d.\n", port->gs.baud); + break; + } + case 115200: + if (port->board->ta_type == MOD_TA) { + t = CSR_9600; + printk(KERN_INFO "sx: Unsupported baud rate: " + "%d.\n", port->gs.baud); + break; + } else { + t = CSR_110; + break; + } + case 0: + t = -1; + break; + default: + t = CSR_9600; + printk(KERN_INFO "sx: Unsupported baud rate: %d.\n", + port->gs.baud); + break; + } +#undef e + if (t >= 0) { + sx_setsignals(port, 1, -1); + sx_write_channel_byte(port, hi_csr, t * 0x11); + } else { + sx_setsignals(port, 0, -1); + } + } +} + +/* Simon Allen's version of this routine was 225 lines long. 85 is a lot + better. -- REW */ + +static int sx_set_real_termios(void *ptr) +{ + struct sx_port *port = ptr; + + func_enter2(); + + if (!port->gs.port.tty) + return 0; + + /* What is this doing here? -- REW + Ha! figured it out. It is to allow you to get DTR active again + if you've dropped it with stty 0. Moved to set_baud, where it + belongs (next to the drop dtr if baud == 0) -- REW */ + /* sx_setsignals (port, 1, -1); */ + + sx_set_baud(port); + +#define CFLAG port->gs.port.tty->termios->c_cflag + sx_write_channel_byte(port, hi_mr1, + (C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) | + (C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) | + (C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) | + (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) | + (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) | + (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) | + (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0)); + + sx_write_channel_byte(port, hi_mr2, + (C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) | + (C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP : + MR2_1_STOP)); + + switch (CFLAG & CSIZE) { + case CS8: + sx_write_channel_byte(port, hi_mask, 0xff); + break; + case CS7: + sx_write_channel_byte(port, hi_mask, 0x7f); + break; + case CS6: + sx_write_channel_byte(port, hi_mask, 0x3f); + break; + case CS5: + sx_write_channel_byte(port, hi_mask, 0x1f); + break; + default: + printk(KERN_INFO "sx: Invalid wordsize: %u\n", + (unsigned int)CFLAG & CSIZE); + break; + } + + sx_write_channel_byte(port, hi_prtcl, + (I_IXON(port->gs.port.tty) ? SP_TXEN : 0) | + (I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) | + (I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN); + + sx_write_channel_byte(port, hi_break, + (I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 | + I_BRKINT(port->gs.port.tty) ? BR_INT : 0)); + + sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty)); + sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty)); + sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty)); + sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty)); + + sx_reconfigure_port(port); + + /* Tell line discipline whether we will do input cooking */ + if (I_OTHER(port->gs.port.tty)) { + clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags); + } else { + set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags); + } + sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ", + (unsigned int)port->gs.port.tty->termios->c_iflag, + I_OTHER(port->gs.port.tty)); + +/* Tell line discipline whether we will do output cooking. + * If OPOST is set and no other output flags are set then we can do output + * processing. Even if only *one* other flag in the O_OTHER group is set + * we do cooking in software. + */ + if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) { + set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags); + } else { + clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags); + } + sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", + (unsigned int)port->gs.port.tty->termios->c_oflag, + O_OTHER(port->gs.port.tty)); + /* port->c_dcd = sx_get_CD (port); */ + func_exit(); + return 0; +} + +/* ********************************************************************** * + * the interrupt related routines * + * ********************************************************************** */ + +/* Note: + Other drivers use the macro "MIN" to calculate how much to copy. + This has the disadvantage that it will evaluate parts twice. That's + expensive when it's IO (and the compiler cannot optimize those away!). + Moreover, I'm not sure that you're race-free. + + I assign a value, and then only allow the value to decrease. This + is always safe. This makes the code a few lines longer, and you + know I'm dead against that, but I think it is required in this + case. */ + +static void sx_transmit_chars(struct sx_port *port) +{ + int c; + int tx_ip; + int txroom; + + func_enter2(); + sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", + port, port->gs.xmit_cnt); + + if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) { + return; + } + + while (1) { + c = port->gs.xmit_cnt; + + sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c); + tx_ip = sx_read_channel_byte(port, hi_txipos); + + /* Took me 5 minutes to deduce this formula. + Luckily it is literally in the manual in section 6.5.4.3.5 */ + txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) & + 0xff; + + /* Don't copy more bytes than there is room for in the buffer */ + if (c > txroom) + c = txroom; + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom); + + /* Don't copy past the end of the hardware transmit buffer */ + if (c > 0x100 - tx_ip) + c = 0x100 - tx_ip; + + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip); + + /* Don't copy pas the end of the source buffer */ + if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) + c = SERIAL_XMIT_SIZE - port->gs.xmit_tail; + + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n", + c, SERIAL_XMIT_SIZE - port->gs.xmit_tail); + + /* If for one reason or another, we can't copy more data, we're + done! */ + if (c == 0) + break; + + memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) + + tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c); + + /* Update the pointer in the card */ + sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff); + + /* Update the kernel buffer end */ + port->gs.xmit_tail = (port->gs.xmit_tail + c) & + (SERIAL_XMIT_SIZE - 1); + + /* This one last. (this is essential) + It would allow others to start putting more data into the + buffer! */ + port->gs.xmit_cnt -= c; + } + + if (port->gs.xmit_cnt == 0) { + sx_disable_tx_interrupts(port); + } + + if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { + tty_wakeup(port->gs.port.tty); + sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", + port->gs.wakeup_chars); + } + + clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks); + func_exit(); +} + +/* Note the symmetry between receiving chars and transmitting them! + Note: The kernel should have implemented both a receive buffer and + a transmit buffer. */ + +/* Inlined: Called only once. Remove the inline when you add another call */ +static inline void sx_receive_chars(struct sx_port *port) +{ + int c; + int rx_op; + struct tty_struct *tty; + int copied = 0; + unsigned char *rp; + + func_enter2(); + tty = port->gs.port.tty; + while (1) { + rx_op = sx_read_channel_byte(port, hi_rxopos); + c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff; + + sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); + + /* Don't copy past the end of the hardware receive buffer */ + if (rx_op + c > 0x100) + c = 0x100 - rx_op; + + sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); + + /* Don't copy more bytes than there is room for in the buffer */ + + c = tty_prepare_flip_string(tty, &rp, c); + + sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); + + /* If for one reason or another, we can't copy more data, we're done! */ + if (c == 0) + break; + + sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is " + "%d at %lx\n", c, read_sx_byte(port->board, + CHAN_OFFSET(port, hi_rxbuf) + rx_op), + CHAN_OFFSET(port, hi_rxbuf)); + memcpy_fromio(rp, port->board->base + + CHAN_OFFSET(port, hi_rxbuf) + rx_op, c); + + /* This one last. ( Not essential.) + It allows the card to start putting more data into the + buffer! + Update the pointer in the card */ + sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff); + + copied += c; + } + if (copied) { + struct timeval tv; + + do_gettimeofday(&tv); + sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d " + "chars): %d.%06d (%d/%d)\n", port->line, + copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec, + tty->raw, tty->real_raw); + + /* Tell the rest of the system the news. Great news. New + characters! */ + tty_flip_buffer_push(tty); + /* tty_schedule_flip (tty); */ + } + + func_exit(); +} + +/* Inlined: it is called only once. Remove the inline if you add another + call */ +static inline void sx_check_modem_signals(struct sx_port *port) +{ + int hi_state; + int c_dcd; + + hi_state = sx_read_channel_byte(port, hi_state); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", + port->c_dcd, tty_port_carrier_raised(&port->gs.port)); + + if (hi_state & ST_BREAK) { + hi_state &= ~ST_BREAK; + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n"); + sx_write_channel_byte(port, hi_state, hi_state); + gs_got_break(&port->gs); + } + if (hi_state & ST_DCD) { + hi_state &= ~ST_DCD; + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); + sx_write_channel_byte(port, hi_state, hi_state); + c_dcd = tty_port_carrier_raised(&port->gs.port); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); + if (c_dcd != port->c_dcd) { + port->c_dcd = c_dcd; + if (tty_port_carrier_raised(&port->gs.port)) { + /* DCD went UP */ + if ((sx_read_channel_byte(port, hi_hstat) != + HS_IDLE_CLOSED) && + !(port->gs.port.tty->termios-> + c_cflag & CLOCAL)) { + /* Are we blocking in open? */ + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "active, unblocking open\n"); + wake_up_interruptible(&port->gs.port. + open_wait); + } else { + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "raised. Ignoring.\n"); + } + } else { + /* DCD went down! */ + if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){ + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "dropped. hanging up....\n"); + tty_hangup(port->gs.port.tty); + } else { + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "dropped. ignoring.\n"); + } + } + } else { + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us " + "DCD changed, but it didn't.\n"); + } + } +} + +/* This is what an interrupt routine should look like. + * Small, elegant, clear. + */ + +static irqreturn_t sx_interrupt(int irq, void *ptr) +{ + struct sx_board *board = ptr; + struct sx_port *port; + int i; + + func_enter(); + sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, + board->irq); + + /* AAargh! The order in which to do these things is essential and + not trivial. + + - Rate limit goes before "recursive". Otherwise a series of + recursive calls will hang the machine in the interrupt routine. + + - hardware twiddling goes before "recursive". Otherwise when we + poll the card, and a recursive interrupt happens, we won't + ack the card, so it might keep on interrupting us. (especially + level sensitive interrupt systems like PCI). + + - Rate limit goes before hardware twiddling. Otherwise we won't + catch a card that has gone bonkers. + + - The "initialized" test goes after the hardware twiddling. Otherwise + the card will stick us in the interrupt routine again. + + - The initialized test goes before recursive. + */ + +#ifdef IRQ_RATE_LIMIT + /* Aaargh! I'm ashamed. This costs more lines-of-code than the + actual interrupt routine!. (Well, used to when I wrote that + comment) */ + { + static int lastjif; + static int nintr = 0; + + if (lastjif == jiffies) { + if (++nintr > IRQ_RATE_LIMIT) { + free_irq(board->irq, board); + printk(KERN_ERR "sx: Too many interrupts. " + "Turning off interrupt %d.\n", + board->irq); + } + } else { + lastjif = jiffies; + nintr = 0; + } + } +#endif + + if (board->irq == irq) { + /* Tell the card we've noticed the interrupt. */ + + sx_write_board_word(board, cc_int_pending, 0); + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_RESET_IRQ, 1); + } else if (IS_EISA_BOARD(board)) { + inb(board->eisa_base + 0xc03); + write_sx_word(board, 8, 0); + } else { + write_sx_byte(board, SI2_ISA_INTCLEAR, + SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, + SI2_ISA_INTCLEAR_SET); + } + } + + if (!sx_initialized) + return IRQ_HANDLED; + if (!(board->flags & SX_BOARD_INITIALIZED)) + return IRQ_HANDLED; + + if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) { + printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq); + return IRQ_HANDLED; + } + + for (i = 0; i < board->nports; i++) { + port = &board->ports[i]; + if (port->gs.port.flags & GS_ACTIVE) { + if (sx_read_channel_byte(port, hi_state)) { + sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: " + "modem signal change?... \n",i); + sx_check_modem_signals(port); + } + if (port->gs.xmit_cnt) { + sx_transmit_chars(port); + } + if (!(port->gs.port.flags & SX_RX_THROTTLE)) { + sx_receive_chars(port); + } + } + } + + clear_bit(SX_BOARD_INTR_LOCK, &board->locks); + + sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, + board->irq); + func_exit(); + return IRQ_HANDLED; +} + +static void sx_pollfunc(unsigned long data) +{ + struct sx_board *board = (struct sx_board *)data; + + func_enter(); + + sx_interrupt(0, board); + + mod_timer(&board->timer, jiffies + sx_poll); + func_exit(); +} + +/* ********************************************************************** * + * Here are the routines that actually * + * interface with the generic_serial driver * + * ********************************************************************** */ + +/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */ +/* Hmm. Ok I figured it out. You don't. */ + +static void sx_disable_tx_interrupts(void *ptr) +{ + struct sx_port *port = ptr; + func_enter2(); + + port->gs.port.flags &= ~GS_TX_INTEN; + + func_exit(); +} + +static void sx_enable_tx_interrupts(void *ptr) +{ + struct sx_port *port = ptr; + int data_in_buffer; + func_enter2(); + + /* First transmit the characters that we're supposed to */ + sx_transmit_chars(port); + + /* The sx card will never interrupt us if we don't fill the buffer + past 25%. So we keep considering interrupts off if that's the case. */ + data_in_buffer = (sx_read_channel_byte(port, hi_txipos) - + sx_read_channel_byte(port, hi_txopos)) & 0xff; + + /* XXX Must be "HIGH_WATER" for SI card according to doc. */ + if (data_in_buffer < LOW_WATER) + port->gs.port.flags &= ~GS_TX_INTEN; + + func_exit(); +} + +static void sx_disable_rx_interrupts(void *ptr) +{ + /* struct sx_port *port = ptr; */ + func_enter(); + + func_exit(); +} + +static void sx_enable_rx_interrupts(void *ptr) +{ + /* struct sx_port *port = ptr; */ + func_enter(); + + func_exit(); +} + +/* Jeez. Isn't this simple? */ +static int sx_carrier_raised(struct tty_port *port) +{ + struct sx_port *sp = container_of(port, struct sx_port, gs.port); + return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0); +} + +/* Jeez. Isn't this simple? */ +static int sx_chars_in_buffer(void *ptr) +{ + struct sx_port *port = ptr; + func_enter2(); + + func_exit(); + return ((sx_read_channel_byte(port, hi_txipos) - + sx_read_channel_byte(port, hi_txopos)) & 0xff); +} + +static void sx_shutdown_port(void *ptr) +{ + struct sx_port *port = ptr; + + func_enter(); + + port->gs.port.flags &= ~GS_ACTIVE; + if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) { + sx_setsignals(port, 0, 0); + sx_reconfigure_port(port); + } + + func_exit(); +} + +/* ********************************************************************** * + * Here are the routines that actually * + * interface with the rest of the system * + * ********************************************************************** */ + +static int sx_open(struct tty_struct *tty, struct file *filp) +{ + struct sx_port *port; + int retval, line; + unsigned long flags; + + func_enter(); + + if (!sx_initialized) { + return -EIO; + } + + line = tty->index; + sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, " + "np=%d)\n", task_pid_nr(current), line, tty, + current->signal->tty, sx_nports); + + if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports)) + return -ENODEV; + + port = &sx_ports[line]; + port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a + 1 -> 0 transition. */ + + sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); + + spin_lock_irqsave(&port->gs.driver_lock, flags); + + tty->driver_data = port; + port->gs.port.tty = tty; + port->gs.port.count++; + spin_unlock_irqrestore(&port->gs.driver_lock, flags); + + sx_dprintk(SX_DEBUG_OPEN, "starting port\n"); + + /* + * Start up serial port + */ + retval = gs_init_port(&port->gs); + sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n"); + if (retval) { + port->gs.port.count--; + return retval; + } + + port->gs.port.flags |= GS_ACTIVE; + if (port->gs.port.count <= 1) + sx_setsignals(port, 1, 1); + +#if 0 + if (sx_debug & SX_DEBUG_OPEN) + my_hd(port, sizeof(*port)); +#else + if (sx_debug & SX_DEBUG_OPEN) + my_hd_io(port->board->base + port->ch_base, sizeof(*port)); +#endif + + if (port->gs.port.count <= 1) { + if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { + printk(KERN_ERR "sx: Card didn't respond to LOPEN " + "command.\n"); + spin_lock_irqsave(&port->gs.driver_lock, flags); + port->gs.port.count--; + spin_unlock_irqrestore(&port->gs.driver_lock, flags); + return -EIO; + } + } + + retval = gs_block_til_ready(port, filp); + sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", + retval, port->gs.port.count); + + if (retval) { +/* + * Don't lower gs.port.count here because sx_close() will be called later + */ + + return retval; + } + /* tty->low_latency = 1; */ + + port->c_dcd = sx_carrier_raised(&port->gs.port); + sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); + + func_exit(); + return 0; + +} + +static void sx_close(void *ptr) +{ + struct sx_port *port = ptr; + /* Give the port 5 seconds to close down. */ + int to = 5 * HZ; + + func_enter(); + + sx_setsignals(port, 0, 0); + sx_reconfigure_port(port); + sx_send_command(port, HS_CLOSE, 0, 0); + + while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) + if (msleep_interruptible(10)) + break; + if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) { + if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) + != 1) { + printk(KERN_ERR "sx: sent the force_close command, but " + "card didn't react\n"); + } else + sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close " + "command.\n"); + } + + sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", + 5 * HZ - to - 1, port->gs.port.count); + + if (port->gs.port.count) { + sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", + port->gs.port.count); + /*printk("%s SETTING port count to zero: %p count: %d\n", + __func__, port, port->gs.port.count); + port->gs.port.count = 0;*/ + } + + func_exit(); +} + +/* This is relatively thorough. But then again it is only 20 lines. */ +#define MARCHUP for (i = min; i < max; i++) +#define MARCHDOWN for (i = max - 1; i >= min; i--) +#define W0 write_sx_byte(board, i, 0x55) +#define W1 write_sx_byte(board, i, 0xaa) +#define R0 if (read_sx_byte(board, i) != 0x55) return 1 +#define R1 if (read_sx_byte(board, i) != 0xaa) return 1 + +/* This memtest takes a human-noticable time. You normally only do it + once a boot, so I guess that it is worth it. */ +static int do_memtest(struct sx_board *board, int min, int max) +{ + int i; + + /* This is a marchb. Theoretically, marchb catches much more than + simpler tests. In practise, the longer test just catches more + intermittent errors. -- REW + (For the theory behind memory testing see: + Testing Semiconductor Memories by A.J. van de Goor.) */ + MARCHUP { + W0; + } + MARCHUP { + R0; + W1; + R1; + W0; + R0; + W1; + } + MARCHUP { + R1; + W0; + W1; + } + MARCHDOWN { + R1; + W0; + W1; + W0; + } + MARCHDOWN { + R0; + W1; + W0; + } + + return 0; +} + +#undef MARCHUP +#undef MARCHDOWN +#undef W0 +#undef W1 +#undef R0 +#undef R1 + +#define MARCHUP for (i = min; i < max; i += 2) +#define MARCHDOWN for (i = max - 1; i >= min; i -= 2) +#define W0 write_sx_word(board, i, 0x55aa) +#define W1 write_sx_word(board, i, 0xaa55) +#define R0 if (read_sx_word(board, i) != 0x55aa) return 1 +#define R1 if (read_sx_word(board, i) != 0xaa55) return 1 + +#if 0 +/* This memtest takes a human-noticable time. You normally only do it + once a boot, so I guess that it is worth it. */ +static int do_memtest_w(struct sx_board *board, int min, int max) +{ + int i; + + MARCHUP { + W0; + } + MARCHUP { + R0; + W1; + R1; + W0; + R0; + W1; + } + MARCHUP { + R1; + W0; + W1; + } + MARCHDOWN { + R1; + W0; + W1; + W0; + } + MARCHDOWN { + R0; + W1; + W0; + } + + return 0; +} +#endif + +static long sx_fw_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + long rc = 0; + int __user *descr = (int __user *)arg; + int i; + static struct sx_board *board = NULL; + int nbytes, offset; + unsigned long data; + char *tmp; + + func_enter(); + + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + tty_lock(); + + sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); + + if (!board) + board = &boards[0]; + if (board->flags & SX_BOARD_PRESENT) { + sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n", + board->flags); + } else { + sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", + board->flags); + for (i = 0; i < SX_NBOARDS; i++) + sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); + sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); + rc = -EIO; + goto out; + } + + switch (cmd) { + case SXIO_SET_BOARD: + sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); + rc = -EIO; + if (arg >= SX_NBOARDS) + break; + sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); + if (!(boards[arg].flags & SX_BOARD_PRESENT)) + break; + sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); + board = &boards[arg]; + rc = 0; + /* FIXME: And this does ... nothing?? */ + break; + case SXIO_GET_TYPE: + rc = -ENOENT; /* If we manage to miss one, return error. */ + if (IS_SX_BOARD(board)) + rc = SX_TYPE_SX; + if (IS_CF_BOARD(board)) + rc = SX_TYPE_CF; + if (IS_SI_BOARD(board)) + rc = SX_TYPE_SI; + if (IS_SI1_BOARD(board)) + rc = SX_TYPE_SI; + if (IS_EISA_BOARD(board)) + rc = SX_TYPE_SI; + sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); + break; + case SXIO_DO_RAMTEST: + if (sx_initialized) { /* Already initialized: better not ramtest the board. */ + rc = -EPERM; + break; + } + if (IS_SX_BOARD(board)) { + rc = do_memtest(board, 0, 0x7000); + if (!rc) + rc = do_memtest(board, 0, 0x7000); + /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */ + } else { + rc = do_memtest(board, 0, 0x7ff8); + /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ + } + sx_dprintk(SX_DEBUG_FIRMWARE, + "returning memtest result= %ld\n", rc); + break; + case SXIO_DOWNLOAD: + if (sx_initialized) {/* Already initialized */ + rc = -EEXIST; + break; + } + if (!sx_reset(board)) { + rc = -EIO; + break; + } + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); + + tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); + if (!tmp) { + rc = -ENOMEM; + break; + } + /* FIXME: check returns */ + get_user(nbytes, descr++); + get_user(offset, descr++); + get_user(data, descr++); + while (nbytes && data) { + for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) { + if (copy_from_user(tmp, (char __user *)data + i, + (i + SX_CHUNK_SIZE > nbytes) ? + nbytes - i : SX_CHUNK_SIZE)) { + kfree(tmp); + rc = -EFAULT; + goto out; + } + memcpy_toio(board->base2 + offset + i, tmp, + (i + SX_CHUNK_SIZE > nbytes) ? + nbytes - i : SX_CHUNK_SIZE); + } + + get_user(nbytes, descr++); + get_user(offset, descr++); + get_user(data, descr++); + } + kfree(tmp); + sx_nports += sx_init_board(board); + rc = sx_nports; + break; + case SXIO_INIT: + if (sx_initialized) { /* Already initialized */ + rc = -EEXIST; + break; + } + /* This is not allowed until all boards are initialized... */ + for (i = 0; i < SX_NBOARDS; i++) { + if ((boards[i].flags & SX_BOARD_PRESENT) && + !(boards[i].flags & SX_BOARD_INITIALIZED)) { + rc = -EIO; + break; + } + } + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, " + "%d channels, first board: %d ports\n", + i, sx_nports, boards[0].nports); + rc = sx_init_portstructs(i, sx_nports); + sx_init_drivers(); + if (rc >= 0) + sx_initialized++; + break; + case SXIO_SETDEBUG: + sx_debug = arg; + break; + case SXIO_GETDEBUG: + rc = sx_debug; + break; + case SXIO_GETGSDEBUG: + case SXIO_SETGSDEBUG: + rc = -EINVAL; + break; + case SXIO_GETNPORTS: + rc = sx_nports; + break; + default: + rc = -ENOTTY; + break; + } +out: + tty_unlock(); + func_exit(); + return rc; +} + +static int sx_break(struct tty_struct *tty, int flag) +{ + struct sx_port *port = tty->driver_data; + int rv; + + func_enter(); + tty_lock(); + + if (flag) + rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); + else + rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN); + if (rv != 1) + printk(KERN_ERR "sx: couldn't send break (%x).\n", + read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); + tty_unlock(); + func_exit(); + return 0; +} + +static int sx_tiocmget(struct tty_struct *tty) +{ + struct sx_port *port = tty->driver_data; + return sx_getsignals(port); +} + +static int sx_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct sx_port *port = tty->driver_data; + int rts = -1, dtr = -1; + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + sx_setsignals(port, dtr, rts); + sx_reconfigure_port(port); + return 0; +} + +static int sx_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + int rc; + struct sx_port *port = tty->driver_data; + void __user *argp = (void __user *)arg; + + /* func_enter2(); */ + + rc = 0; + tty_lock(); + switch (cmd) { + case TIOCGSERIAL: + rc = gs_getserial(&port->gs, argp); + break; + case TIOCSSERIAL: + rc = gs_setserial(&port->gs, argp); + break; + default: + rc = -ENOIOCTLCMD; + break; + } + tty_unlock(); + + /* func_exit(); */ + return rc; +} + +/* The throttle/unthrottle scheme for the Specialix card is different + * from other drivers and deserves some explanation. + * The Specialix hardware takes care of XON/XOFF + * and CTS/RTS flow control itself. This means that all we have to + * do when signalled by the upper tty layer to throttle/unthrottle is + * to make a note of it here. When we come to read characters from the + * rx buffers on the card (sx_receive_chars()) we look to see if the + * upper layer can accept more (as noted here in sx_rx_throt[]). + * If it can't we simply don't remove chars from the cards buffer. + * When the tty layer can accept chars, we again note that here and when + * sx_receive_chars() is called it will remove them from the cards buffer. + * The card will notice that a ports buffer has drained below some low + * water mark and will unflow control the line itself, using whatever + * flow control scheme is in use for that port. -- Simon Allen + */ + +static void sx_throttle(struct tty_struct *tty) +{ + struct sx_port *port = tty->driver_data; + + func_enter2(); + /* If the port is using any type of input flow + * control then throttle the port. + */ + if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) { + port->gs.port.flags |= SX_RX_THROTTLE; + } + func_exit(); +} + +static void sx_unthrottle(struct tty_struct *tty) +{ + struct sx_port *port = tty->driver_data; + + func_enter2(); + /* Always unthrottle even if flow control is not enabled on + * this port in case we disabled flow control while the port + * was throttled + */ + port->gs.port.flags &= ~SX_RX_THROTTLE; + func_exit(); + return; +} + +/* ********************************************************************** * + * Here are the initialization routines. * + * ********************************************************************** */ + +static int sx_init_board(struct sx_board *board) +{ + int addr; + int chans; + int type; + + func_enter(); + + /* This is preceded by downloading the download code. */ + + board->flags |= SX_BOARD_INITIALIZED; + + if (read_sx_byte(board, 0)) + /* CF boards may need this. */ + write_sx_byte(board, 0, 0); + + /* This resets the processor again, to make sure it didn't do any + foolish things while we were downloading the image */ + if (!sx_reset(board)) + return 0; + + sx_start_board(board); + udelay(10); + if (!sx_busy_wait_neq(board, 0, 0xff, 0)) { + printk(KERN_ERR "sx: Ooops. Board won't initialize.\n"); + return 0; + } + + /* Ok. So now the processor on the card is running. It gathered + some info for us... */ + sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n"); + if (sx_debug & SX_DEBUG_INIT) + my_hd_io(board->base, 0x10); + sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n"); + if (sx_debug & SX_DEBUG_INIT) + my_hd_io(board->base + 0x80, 0x30); + + sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware " + "V%x.%02x,\n", + read_sx_byte(board, 0), read_sx_byte(board, 1), + read_sx_byte(board, 5), read_sx_byte(board, 4)); + + if (read_sx_byte(board, 0) == 0xff) { + printk(KERN_INFO "sx: No modules found. Sorry.\n"); + board->nports = 0; + return 0; + } + + chans = 0; + + if (IS_SX_BOARD(board)) { + sx_write_board_word(board, cc_int_count, sx_maxints); + } else { + if (sx_maxints) + sx_write_board_word(board, cc_int_count, + SI_PROCESSOR_CLOCK / 8 / sx_maxints); + } + + /* grab the first module type... */ + /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ + board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80, + mc_chip)); + + /* XXX byteorder */ + for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){ + type = sx_read_module_byte(board, addr, mc_chip); + sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n", + addr, read_sx_byte(board, addr + 2)); + + chans += sx_read_module_byte(board, addr, mc_type); + + sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s " + "panels\n", + mod_type_s(type), + pan_type_s(sx_read_module_byte(board, addr, + mc_mods) & 0xf), + pan_type_s(sx_read_module_byte(board, addr, + mc_mods) >> 4)); + + sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC " + "version: %x\n", + sx_read_module_byte(board, addr, mc_rev1), + sx_read_module_byte(board, addr, mc_rev2), + sx_read_module_byte(board, addr, mc_mtaasic_rev)); + + /* The following combinations are illegal: It should theoretically + work, but timing problems make the bus HANG. */ + + if (mod_compat_type(type) != board->ta_type) { + printk(KERN_ERR "sx: This is an invalid " + "configuration.\nDon't mix TA/MTA/SXDC on the " + "same hostadapter.\n"); + chans = 0; + break; + } + if ((IS_EISA_BOARD(board) || + IS_SI_BOARD(board)) && + (mod_compat_type(type) == 4)) { + printk(KERN_ERR "sx: This is an invalid " + "configuration.\nDon't use SXDCs on an SI/XIO " + "adapter.\n"); + chans = 0; + break; + } +#if 0 /* Problem fixed: firmware 3.05 */ + if (IS_SX_BOARD(board) && (type == TA8)) { + /* There are some issues with the firmware and the DCD/RTS + lines. It might work if you tie them together or something. + It might also work if you get a newer sx_firmware. Therefore + this is just a warning. */ + printk(KERN_WARNING + "sx: The SX host doesn't work too well " + "with the TA8 adapters.\nSpecialix is working on it.\n"); + } +#endif + } + + if (chans) { + if (board->irq > 0) { + /* fixed irq, probably PCI */ + if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ + if (request_irq(board->irq, sx_interrupt, + IRQF_SHARED | IRQF_DISABLED, + "sx", board)) { + printk(KERN_ERR "sx: Cannot allocate " + "irq %d.\n", board->irq); + board->irq = 0; + } + } else + board->irq = 0; + } else if (board->irq < 0 && sx_irqmask) { + /* auto-allocate irq */ + int irqnr; + int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? + SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); + for (irqnr = 15; irqnr > 0; irqnr--) + if (irqmask & (1 << irqnr)) + if (!request_irq(irqnr, sx_interrupt, + IRQF_SHARED | IRQF_DISABLED, + "sx", board)) + break; + if (!irqnr) + printk(KERN_ERR "sx: Cannot allocate IRQ.\n"); + board->irq = irqnr; + } else + board->irq = 0; + + if (board->irq) { + /* Found a valid interrupt, start up interrupts! */ + sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n", + board->irq); + sx_start_interrupts(board); + board->poll = sx_slowpoll; + board->flags |= SX_IRQ_ALLOCATED; + } else { + /* no irq: setup board for polled operation */ + board->poll = sx_poll; + sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n", + board->poll); + } + + /* The timer should be initialized anyway: That way we can + safely del_timer it when the module is unloaded. */ + setup_timer(&board->timer, sx_pollfunc, (unsigned long)board); + + if (board->poll) + mod_timer(&board->timer, jiffies + board->poll); + } else { + board->irq = 0; + } + + board->nports = chans; + sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports); + + func_exit(); + return chans; +} + +static void __devinit printheader(void) +{ + static int header_printed; + + if (!header_printed) { + printk(KERN_INFO "Specialix SX driver " + "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n"); + printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n"); + header_printed = 1; + } +} + +static int __devinit probe_sx(struct sx_board *board) +{ + struct vpd_prom vpdp; + char *p; + int i; + + func_enter(); + + if (!IS_CF_BOARD(board)) { + sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", + board->base + SX_VPD_ROM); + + if (sx_debug & SX_DEBUG_PROBE) + my_hd_io(board->base + SX_VPD_ROM, 0x40); + + p = (char *)&vpdp; + for (i = 0; i < sizeof(struct vpd_prom); i++) + *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2); + + if (sx_debug & SX_DEBUG_PROBE) + my_hd(&vpdp, 0x20); + + sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n"); + + if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { + sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: " + "'%s'\n", vpdp.identifier); + return 0; + } + } + + printheader(); + + if (!IS_CF_BOARD(board)) { + printk(KERN_DEBUG "sx: Found an SX board at %lx\n", + board->hw_base); + printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, " + "uniq ID:%08x, ", + vpdp.hwrev, vpdp.hwass, vpdp.uniqid); + printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek); + + if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != + SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) & + SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { + /* This might be a bit harsh. This was the primary + reason the SX/ISA card didn't work at first... */ + printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA " + "card. Sorry: giving up.\n"); + return (0); + } + + if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == + SX_ISA_UNIQUEID1) { + if (((unsigned long)board->hw_base) & 0x8000) { + printk(KERN_WARNING "sx: Warning: There may be " + "hardware problems with the card at " + "%lx.\n", board->hw_base); + printk(KERN_WARNING "sx: Read sx.txt for more " + "info.\n"); + } + } + } + + board->nports = -1; + + /* This resets the processor, and keeps it off the bus. */ + if (!sx_reset(board)) + return 0; + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); + + func_exit(); + return 1; +} + +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) + +/* Specialix probes for this card at 32k increments from 640k to 16M. + I consider machines with less than 16M unlikely nowadays, so I'm + not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA + card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves + 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */ + +static int __devinit probe_si(struct sx_board *board) +{ + int i; + + func_enter(); + sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at " + "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE); + + if (sx_debug & SX_DEBUG_PROBE) + my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8); + + if (!IS_EISA_BOARD(board)) { + if (IS_SI1_BOARD(board)) { + for (i = 0; i < 8; i++) { + write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i); + } + } + for (i = 0; i < 8; i++) { + if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7) + != i) { + func_exit(); + return 0; + } + } + } + + /* Now we're pretty much convinced that there is an SI board here, + but to prevent trouble, we'd better double check that we don't + have an SI1 board when we're probing for an SI2 board.... */ + + write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); + if (IS_SI1_BOARD(board)) { + /* This should be an SI1 board, which has this + location writable... */ + if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { + func_exit(); + return 0; + } + } else { + /* This should be an SI2 board, which has the bottom + 3 bits non-writable... */ + if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { + func_exit(); + return 0; + } + } + + /* Now we're pretty much convinced that there is an SI board here, + but to prevent trouble, we'd better double check that we don't + have an SI1 board when we're probing for an SI2 board.... */ + + write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); + if (IS_SI1_BOARD(board)) { + /* This should be an SI1 board, which has this + location writable... */ + if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { + func_exit(); + return 0; + } + } else { + /* This should be an SI2 board, which has the bottom + 3 bits non-writable... */ + if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { + func_exit(); + return 0; + } + } + + printheader(); + + printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); + /* Compared to the SX boards, it is a complete guess as to what + this card is up to... */ + + board->nports = -1; + + /* This resets the processor, and keeps it off the bus. */ + if (!sx_reset(board)) + return 0; + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); + + func_exit(); + return 1; +} +#endif + +static const struct tty_operations sx_ops = { + .break_ctl = sx_break, + .open = sx_open, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .chars_in_buffer = gs_chars_in_buffer, + .flush_buffer = gs_flush_buffer, + .ioctl = sx_ioctl, + .throttle = sx_throttle, + .unthrottle = sx_unthrottle, + .set_termios = gs_set_termios, + .stop = gs_stop, + .start = gs_start, + .hangup = gs_hangup, + .tiocmget = sx_tiocmget, + .tiocmset = sx_tiocmset, +}; + +static const struct tty_port_operations sx_port_ops = { + .carrier_raised = sx_carrier_raised, +}; + +static int sx_init_drivers(void) +{ + int error; + + func_enter(); + + sx_driver = alloc_tty_driver(sx_nports); + if (!sx_driver) + return 1; + sx_driver->owner = THIS_MODULE; + sx_driver->driver_name = "specialix_sx"; + sx_driver->name = "ttyX"; + sx_driver->major = SX_NORMAL_MAJOR; + sx_driver->type = TTY_DRIVER_TYPE_SERIAL; + sx_driver->subtype = SERIAL_TYPE_NORMAL; + sx_driver->init_termios = tty_std_termios; + sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver->init_termios.c_ispeed = 9600; + sx_driver->init_termios.c_ospeed = 9600; + sx_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(sx_driver, &sx_ops); + + if ((error = tty_register_driver(sx_driver))) { + put_tty_driver(sx_driver); + printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n", + error); + return 1; + } + func_exit(); + return 0; +} + +static int sx_init_portstructs(int nboards, int nports) +{ + struct sx_board *board; + struct sx_port *port; + int i, j; + int addr, chans; + int portno; + + func_enter(); + + /* Many drivers statically allocate the maximum number of ports + There is no reason not to allocate them dynamically. + Is there? -- REW */ + sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL); + if (!sx_ports) + return -ENOMEM; + + port = sx_ports; + for (i = 0; i < nboards; i++) { + board = &boards[i]; + board->ports = port; + for (j = 0; j < boards[i].nports; j++) { + sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); + tty_port_init(&port->gs.port); + port->gs.port.ops = &sx_port_ops; + port->gs.magic = SX_MAGIC; + port->gs.close_delay = HZ / 2; + port->gs.closing_wait = 30 * HZ; + port->board = board; + port->gs.rd = &sx_real_driver; +#ifdef NEW_WRITE_LOCKING + port->gs.port_write_mutex = MUTEX; +#endif + spin_lock_init(&port->gs.driver_lock); + /* + * Initializing wait queue + */ + port++; + } + } + + port = sx_ports; + portno = 0; + for (i = 0; i < nboards; i++) { + board = &boards[i]; + board->port_base = portno; + /* Possibly the configuration was rejected. */ + sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n", + board->nports); + if (board->nports <= 0) + continue; + /* XXX byteorder ?? */ + for (addr = 0x80; addr != 0; + addr = read_sx_word(board, addr) & 0x7fff) { + chans = sx_read_module_byte(board, addr, mc_type); + sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d " + "channels\n", addr, chans); + sx_dprintk(SX_DEBUG_PROBE, "Port at"); + for (j = 0; j < chans; j++) { + /* The "sx-way" is the way it SHOULD be done. + That way in the future, the firmware may for + example pack the structures a bit more + efficient. Neil tells me it isn't going to + happen anytime soon though. */ + if (IS_SX_BOARD(board)) + port->ch_base = sx_read_module_word( + board, addr + j * 2, + mc_chan_pointer); + else + port->ch_base = addr + 0x100 + 0x300 *j; + + sx_dprintk(SX_DEBUG_PROBE, " %x", + port->ch_base); + port->line = portno++; + port++; + } + sx_dprintk(SX_DEBUG_PROBE, "\n"); + } + /* This has to be done earlier. */ + /* board->flags |= SX_BOARD_INITIALIZED; */ + } + + func_exit(); + return 0; +} + +static unsigned int sx_find_free_board(void) +{ + unsigned int i; + + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + return i; +} + +static void __exit sx_release_drivers(void) +{ + func_enter(); + tty_unregister_driver(sx_driver); + put_tty_driver(sx_driver); + func_exit(); +} + +static void __devexit sx_remove_card(struct sx_board *board, + struct pci_dev *pdev) +{ + if (board->flags & SX_BOARD_INITIALIZED) { + /* The board should stop messing with us. (actually I mean the + interrupt) */ + sx_reset(board); + if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) + free_irq(board->irq, board); + + /* It is safe/allowed to del_timer a non-active timer */ + del_timer(&board->timer); + if (pdev) { +#ifdef CONFIG_PCI + iounmap(board->base2); + pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); +#endif + } else { + iounmap(board->base); + release_region(board->hw_base, board->hw_len); + } + + board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT); + } +} + +#ifdef CONFIG_EISA + +static int __devinit sx_eisa_probe(struct device *dev) +{ + struct eisa_device *edev = to_eisa_device(dev); + struct sx_board *board; + unsigned long eisa_slot = edev->base_addr; + unsigned int i; + int retval = -EIO; + + mutex_lock(&sx_boards_lock); + i = sx_find_free_board(); + if (i == SX_NBOARDS) { + mutex_unlock(&sx_boards_lock); + goto err; + } + board = &boards[i]; + board->flags |= SX_BOARD_PRESENT; + mutex_unlock(&sx_boards_lock); + + dev_info(dev, "XIO : Signature found in EISA slot %lu, " + "Product %d Rev %d (REPORT THIS TO LKLM)\n", + eisa_slot >> 12, + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); + + board->eisa_base = eisa_slot; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI_EISA_BOARD; + + board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + + inb(eisa_slot + 0xc00)) << 16; + board->hw_len = SI2_EISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) { + dev_err(dev, "can't request region\n"); + goto err_flag; + } + board->base2 = + board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN); + if (!board->base) { + dev_err(dev, "can't remap memory\n"); + goto err_reg; + } + + sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); + sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); + board->irq = inb(eisa_slot + 0xc02) >> 4; + sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); + + if (!probe_si(board)) + goto err_unmap; + + dev_set_drvdata(dev, board); + + return 0; +err_unmap: + iounmap(board->base); +err_reg: + release_region(board->hw_base, board->hw_len); +err_flag: + board->flags &= ~SX_BOARD_PRESENT; +err: + return retval; +} + +static int __devexit sx_eisa_remove(struct device *dev) +{ + struct sx_board *board = dev_get_drvdata(dev); + + sx_remove_card(board, NULL); + + return 0; +} + +static struct eisa_device_id sx_eisa_tbl[] = { + { "SLX" }, + { "" } +}; + +MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl); + +static struct eisa_driver sx_eisadriver = { + .id_table = sx_eisa_tbl, + .driver = { + .name = "sx", + .probe = sx_eisa_probe, + .remove = __devexit_p(sx_eisa_remove), + } +}; + +#endif + +#ifdef CONFIG_PCI + /******************************************************** + * Setting bit 17 in the CNTRL register of the PLX 9050 * + * chip forces a retry on writes while a read is pending.* + * This is to prevent the card locking up on Intel Xeon * + * multiprocessor systems with the NX chipset. -- NV * + ********************************************************/ + +/* Newer cards are produced with this bit set from the configuration + EEprom. As the bit is read/write for the CPU, we can fix it here, + if we detect that it isn't set correctly. -- REW */ + +static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board) +{ + unsigned int hwbase; + void __iomem *rebase; + unsigned int t; + +#define CNTRL_REG_OFFSET 0x50 +#define CNTRL_REG_GOODVALUE 0x18260000 + + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); + hwbase &= PCI_BASE_ADDRESS_MEM_MASK; + rebase = ioremap_nocache(hwbase, 0x80); + t = readl(rebase + CNTRL_REG_OFFSET); + if (t != CNTRL_REG_GOODVALUE) { + printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> " + "%08x\n", t, CNTRL_REG_GOODVALUE); + writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); + } + iounmap(rebase); +} +#endif + +static int __devinit sx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ +#ifdef CONFIG_PCI + struct sx_board *board; + unsigned int i, reg; + int retval = -EIO; + + mutex_lock(&sx_boards_lock); + i = sx_find_free_board(); + if (i == SX_NBOARDS) { + mutex_unlock(&sx_boards_lock); + goto err; + } + board = &boards[i]; + board->flags |= SX_BOARD_PRESENT; + mutex_unlock(&sx_boards_lock); + + retval = pci_enable_device(pdev); + if (retval) + goto err_flag; + + board->flags &= ~SX_BOARD_TYPE; + board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : + SX_CFPCI_BOARD; + + /* CF boards use base address 3.... */ + reg = IS_CF_BOARD(board) ? 3 : 2; + retval = pci_request_region(pdev, reg, "sx"); + if (retval) { + dev_err(&pdev->dev, "can't request region\n"); + goto err_flag; + } + board->hw_base = pci_resource_start(pdev, reg); + board->base2 = + board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board)); + if (!board->base) { + dev_err(&pdev->dev, "ioremap failed\n"); + goto err_reg; + } + + /* Most of the stuff on the CF board is offset by 0x18000 .... */ + if (IS_CF_BOARD(board)) + board->base += 0x18000; + + board->irq = pdev->irq; + + dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base, + board->irq, board->flags); + + if (!probe_sx(board)) { + retval = -EIO; + goto err_unmap; + } + + fix_sx_pci(pdev, board); + + pci_set_drvdata(pdev, board); + + return 0; +err_unmap: + iounmap(board->base2); +err_reg: + pci_release_region(pdev, reg); +err_flag: + board->flags &= ~SX_BOARD_PRESENT; +err: + return retval; +#else + return -ENODEV; +#endif +} + +static void __devexit sx_pci_remove(struct pci_dev *pdev) +{ + struct sx_board *board = pci_get_drvdata(pdev); + + sx_remove_card(board, pdev); +} + +/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say + its because the standard requires it. So check for SUBVENDOR_ID. */ +static struct pci_device_id sx_pci_tbl[] = { + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + .subvendor = PCI_ANY_ID, .subdevice = 0x0200 }, + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + .subvendor = PCI_ANY_ID, .subdevice = 0x0300 }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, sx_pci_tbl); + +static struct pci_driver sx_pcidriver = { + .name = "sx", + .id_table = sx_pci_tbl, + .probe = sx_pci_probe, + .remove = __devexit_p(sx_pci_remove) +}; + +static int __init sx_init(void) +{ +#ifdef CONFIG_EISA + int retval1; +#endif +#ifdef CONFIG_ISA + struct sx_board *board; + unsigned int i; +#endif + unsigned int found = 0; + int retval; + + func_enter(); + sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", + sx_debug); + if (abs((long)(&sx_debug) - sx_debug) < 0x10000) { + printk(KERN_WARNING "sx: sx_debug is an address, instead of a " + "value. Assuming -1.\n(%p)\n", &sx_debug); + sx_debug = -1; + } + + if (misc_register(&sx_fw_device) < 0) { + printk(KERN_ERR "SX: Unable to register firmware loader " + "driver.\n"); + return -EIO; + } +#ifdef CONFIG_ISA + for (i = 0; i < NR_SX_ADDRS; i++) { + board = &boards[found]; + board->hw_base = sx_probe_addrs[i]; + board->hw_len = SX_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; + board->base2 = + board->base = ioremap_nocache(board->hw_base, board->hw_len); + if (!board->base) + goto err_sx_reg; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SX_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; + + if (probe_sx(board)) { + board->flags |= SX_BOARD_PRESENT; + found++; + } else { + iounmap(board->base); +err_sx_reg: + release_region(board->hw_base, board->hw_len); + } + } + + for (i = 0; i < NR_SI_ADDRS; i++) { + board = &boards[found]; + board->hw_base = si_probe_addrs[i]; + board->hw_len = SI2_ISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; + board->base2 = + board->base = ioremap_nocache(board->hw_base, board->hw_len); + if (!board->base) + goto err_si_reg; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; + + if (probe_si(board)) { + board->flags |= SX_BOARD_PRESENT; + found++; + } else { + iounmap(board->base); +err_si_reg: + release_region(board->hw_base, board->hw_len); + } + } + for (i = 0; i < NR_SI1_ADDRS; i++) { + board = &boards[found]; + board->hw_base = si1_probe_addrs[i]; + board->hw_len = SI1_ISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; + board->base2 = + board->base = ioremap_nocache(board->hw_base, board->hw_len); + if (!board->base) + goto err_si1_reg; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI1_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; + + if (probe_si(board)) { + board->flags |= SX_BOARD_PRESENT; + found++; + } else { + iounmap(board->base); +err_si1_reg: + release_region(board->hw_base, board->hw_len); + } + } +#endif +#ifdef CONFIG_EISA + retval1 = eisa_driver_register(&sx_eisadriver); +#endif + retval = pci_register_driver(&sx_pcidriver); + + if (found) { + printk(KERN_INFO "sx: total of %d boards detected.\n", found); + retval = 0; + } else if (retval) { +#ifdef CONFIG_EISA + retval = retval1; + if (retval1) +#endif + misc_deregister(&sx_fw_device); + } + + func_exit(); + return retval; +} + +static void __exit sx_exit(void) +{ + int i; + + func_enter(); +#ifdef CONFIG_EISA + eisa_driver_unregister(&sx_eisadriver); +#endif + pci_unregister_driver(&sx_pcidriver); + + for (i = 0; i < SX_NBOARDS; i++) + sx_remove_card(&boards[i], NULL); + + if (misc_deregister(&sx_fw_device) < 0) { + printk(KERN_INFO "sx: couldn't deregister firmware loader " + "device\n"); + } + sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", + sx_initialized); + if (sx_initialized) + sx_release_drivers(); + + kfree(sx_ports); + func_exit(); +} + +module_init(sx_init); +module_exit(sx_exit); diff --git a/drivers/staging/generic_serial/sx.h b/drivers/staging/generic_serial/sx.h new file mode 100644 index 000000000000..87c2defdead7 --- /dev/null +++ b/drivers/staging/generic_serial/sx.h @@ -0,0 +1,201 @@ + +/* + * sx.h + * + * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl + * + * SX serial driver. + * -- Supports SI, XIO and SX host cards. + * -- Supports TAs, MTAs and SXDCs. + * + * Version 1.3 -- March, 1999. + * + */ + +#define SX_NBOARDS 4 +#define SX_PORTSPERBOARD 32 +#define SX_NPORTS (SX_NBOARDS * SX_PORTSPERBOARD) + +#ifdef __KERNEL__ + +#define SX_MAGIC 0x12345678 + +struct sx_port { + struct gs_port gs; + struct wait_queue *shutdown_wait; + int ch_base; + int c_dcd; + struct sx_board *board; + int line; + unsigned long locks; +}; + +struct sx_board { + int magic; + void __iomem *base; + void __iomem *base2; + unsigned long hw_base; + resource_size_t hw_len; + int eisa_base; + int port_base; /* Number of the first port */ + struct sx_port *ports; + int nports; + int flags; + int irq; + int poll; + int ta_type; + struct timer_list timer; + unsigned long locks; +}; + +struct vpd_prom { + unsigned short id; + char hwrev; + char hwass; + int uniqid; + char myear; + char mweek; + char hw_feature[5]; + char oem_id; + char identifier[16]; +}; + +#ifndef MOD_RS232DB25MALE +#define MOD_RS232DB25MALE 0x0a +#endif + +#define SI_ISA_BOARD 0x00000001 +#define SX_ISA_BOARD 0x00000002 +#define SX_PCI_BOARD 0x00000004 +#define SX_CFPCI_BOARD 0x00000008 +#define SX_CFISA_BOARD 0x00000010 +#define SI_EISA_BOARD 0x00000020 +#define SI1_ISA_BOARD 0x00000040 + +#define SX_BOARD_PRESENT 0x00001000 +#define SX_BOARD_INITIALIZED 0x00002000 +#define SX_IRQ_ALLOCATED 0x00004000 + +#define SX_BOARD_TYPE 0x000000ff + +#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \ + SX_ISA_BOARD | SX_CFISA_BOARD)) + +#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD) +#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD) + +#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD) + +#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD)) + +/* The SI processor clock is required to calculate the cc_int_count register + value for the SI cards. */ +#define SI_PROCESSOR_CLOCK 25000000 + + +/* port flags */ +/* Make sure these don't clash with gs flags or async flags */ +#define SX_RX_THROTTLE 0x0000001 + + + +#define SX_PORT_TRANSMIT_LOCK 0 +#define SX_BOARD_INTR_LOCK 0 + + + +/* Debug flags. Add these together to get more debug info. */ + +#define SX_DEBUG_OPEN 0x00000001 +#define SX_DEBUG_SETTING 0x00000002 +#define SX_DEBUG_FLOW 0x00000004 +#define SX_DEBUG_MODEMSIGNALS 0x00000008 +#define SX_DEBUG_TERMIOS 0x00000010 +#define SX_DEBUG_TRANSMIT 0x00000020 +#define SX_DEBUG_RECEIVE 0x00000040 +#define SX_DEBUG_INTERRUPTS 0x00000080 +#define SX_DEBUG_PROBE 0x00000100 +#define SX_DEBUG_INIT 0x00000200 +#define SX_DEBUG_CLEANUP 0x00000400 +#define SX_DEBUG_CLOSE 0x00000800 +#define SX_DEBUG_FIRMWARE 0x00001000 +#define SX_DEBUG_MEMTEST 0x00002000 + +#define SX_DEBUG_ALL 0xffffffff + + +#define O_OTHER(tty) \ + ((O_OLCUC(tty)) ||\ + (O_ONLCR(tty)) ||\ + (O_OCRNL(tty)) ||\ + (O_ONOCR(tty)) ||\ + (O_ONLRET(tty)) ||\ + (O_OFILL(tty)) ||\ + (O_OFDEL(tty)) ||\ + (O_NLDLY(tty)) ||\ + (O_CRDLY(tty)) ||\ + (O_TABDLY(tty)) ||\ + (O_BSDLY(tty)) ||\ + (O_VTDLY(tty)) ||\ + (O_FFDLY(tty))) + +/* Same for input. */ +#define I_OTHER(tty) \ + ((I_INLCR(tty)) ||\ + (I_IGNCR(tty)) ||\ + (I_ICRNL(tty)) ||\ + (I_IUCLC(tty)) ||\ + (L_ISIG(tty))) + +#define MOD_TA ( TA>>4) +#define MOD_MTA (MTA_CD1400>>4) +#define MOD_SXDC ( SXDC>>4) + + +/* We copy the download code over to the card in chunks of ... bytes */ +#define SX_CHUNK_SIZE 128 + +#endif /* __KERNEL__ */ + + + +/* Specialix document 6210046-11 page 3 */ +#define SPX(X) (('S'<<24) | ('P' << 16) | (X)) + +/* Specialix-Linux specific IOCTLS. */ +#define SPXL(X) (SPX(('L' << 8) | (X))) + + +#define SXIO_SET_BOARD SPXL(0x01) +#define SXIO_GET_TYPE SPXL(0x02) +#define SXIO_DOWNLOAD SPXL(0x03) +#define SXIO_INIT SPXL(0x04) +#define SXIO_SETDEBUG SPXL(0x05) +#define SXIO_GETDEBUG SPXL(0x06) +#define SXIO_DO_RAMTEST SPXL(0x07) +#define SXIO_SETGSDEBUG SPXL(0x08) +#define SXIO_GETGSDEBUG SPXL(0x09) +#define SXIO_GETNPORTS SPXL(0x0a) + + +#ifndef SXCTL_MISC_MINOR +/* Allow others to gather this into "major.h" or something like that */ +#define SXCTL_MISC_MINOR 167 +#endif + +#ifndef SX_NORMAL_MAJOR +/* This allows overriding on the compiler commandline, or in a "major.h" + include or something like that */ +#define SX_NORMAL_MAJOR 32 +#define SX_CALLOUT_MAJOR 33 +#endif + + +#define SX_TYPE_SX 0x01 +#define SX_TYPE_SI 0x02 +#define SX_TYPE_CF 0x03 + + +#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN) +/* Need a #define for ^^^^^^^ !!! */ + diff --git a/drivers/staging/generic_serial/sxboards.h b/drivers/staging/generic_serial/sxboards.h new file mode 100644 index 000000000000..427927dc7dbf --- /dev/null +++ b/drivers/staging/generic_serial/sxboards.h @@ -0,0 +1,206 @@ +/************************************************************************/ +/* */ +/* Title : SX/SI/XIO Board Hardware Definitions */ +/* */ +/* Author : N.P.Vassallo */ +/* */ +/* Creation : 16th March 1998 */ +/* */ +/* Version : 3.0.0 */ +/* */ +/* Copyright : (c) Specialix International Ltd. 1998 */ +/* */ +/* Description : Prototypes, structures and definitions */ +/* describing the SX/SI/XIO board hardware */ +/* */ +/************************************************************************/ + +/* History... + +3.0.0 16/03/98 NPV Creation. + +*/ + +#ifndef _sxboards_h /* If SXBOARDS.H not already defined */ +#define _sxboards_h 1 + +/***************************************************************************** +******************************* ****************************** +******************************* Board Types ****************************** +******************************* ****************************** +*****************************************************************************/ + +/* BUS types... */ +#define BUS_ISA 0 +#define BUS_MCA 1 +#define BUS_EISA 2 +#define BUS_PCI 3 + +/* Board phases... */ +#define SI1_Z280 1 +#define SI2_Z280 2 +#define SI3_T225 3 + +/* Board types... */ +#define CARD_TYPE(bus,phase) (bus<<4|phase) +#define CARD_BUS(type) ((type>>4)&0xF) +#define CARD_PHASE(type) (type&0xF) + +#define TYPE_SI1_ISA CARD_TYPE(BUS_ISA,SI1_Z280) +#define TYPE_SI2_ISA CARD_TYPE(BUS_ISA,SI2_Z280) +#define TYPE_SI2_EISA CARD_TYPE(BUS_EISA,SI2_Z280) +#define TYPE_SI2_PCI CARD_TYPE(BUS_PCI,SI2_Z280) + +#define TYPE_SX_ISA CARD_TYPE(BUS_ISA,SI3_T225) +#define TYPE_SX_PCI CARD_TYPE(BUS_PCI,SI3_T225) +/***************************************************************************** +****************************** ****************************** +****************************** Phase 1 Z280 ****************************** +****************************** ****************************** +*****************************************************************************/ + +/* ISA board details... */ +#define SI1_ISA_WINDOW_LEN 0x10000 /* 64 Kbyte shared memory window */ +//#define SI1_ISA_MEMORY_LEN 0x8000 /* Usable memory - unused define*/ +//#define SI1_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ +//#define SI1_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ +//#define SI2_ISA_ADDR_STEP SI2_ISA_WINDOW_LEN/* ISA board address step */ +//#define SI2_ISA_IRQ_MASK 0x9800 /* IRQs 15,12,11 */ + +/* ISA board, register definitions... */ +//#define SI2_ISA_ID_BASE 0x7FF8 /* READ: Board ID string */ +#define SI1_ISA_RESET 0x8000 /* WRITE: Host Reset */ +#define SI1_ISA_RESET_CLEAR 0xc000 /* WRITE: Host Reset clear*/ +#define SI1_ISA_WAIT 0x9000 /* WRITE: Host wait */ +#define SI1_ISA_WAIT_CLEAR 0xd000 /* WRITE: Host wait clear */ +#define SI1_ISA_INTCL 0xa000 /* WRITE: Host Reset */ +#define SI1_ISA_INTCL_CLEAR 0xe000 /* WRITE: Host Reset */ + + +/***************************************************************************** +****************************** ****************************** +****************************** Phase 2 Z280 ****************************** +****************************** ****************************** +*****************************************************************************/ + +/* ISA board details... */ +#define SI2_ISA_WINDOW_LEN 0x8000 /* 32 Kbyte shared memory window */ +#define SI2_ISA_MEMORY_LEN 0x7FF8 /* Usable memory */ +#define SI2_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ +#define SI2_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ +#define SI2_ISA_ADDR_STEP SI2_ISA_WINDOW_LEN/* ISA board address step */ +#define SI2_ISA_IRQ_MASK 0x9800 /* IRQs 15,12,11 */ + +/* ISA board, register definitions... */ +#define SI2_ISA_ID_BASE 0x7FF8 /* READ: Board ID string */ +#define SI2_ISA_RESET SI2_ISA_ID_BASE /* WRITE: Host Reset */ +#define SI2_ISA_IRQ11 (SI2_ISA_ID_BASE+1) /* WRITE: Set IRQ11 */ +#define SI2_ISA_IRQ12 (SI2_ISA_ID_BASE+2) /* WRITE: Set IRQ12 */ +#define SI2_ISA_IRQ15 (SI2_ISA_ID_BASE+3) /* WRITE: Set IRQ15 */ +#define SI2_ISA_IRQSET (SI2_ISA_ID_BASE+4) /* WRITE: Set Host Interrupt */ +#define SI2_ISA_INTCLEAR (SI2_ISA_ID_BASE+5) /* WRITE: Enable Host Interrupt */ + +#define SI2_ISA_IRQ11_SET 0x10 +#define SI2_ISA_IRQ11_CLEAR 0x00 +#define SI2_ISA_IRQ12_SET 0x10 +#define SI2_ISA_IRQ12_CLEAR 0x00 +#define SI2_ISA_IRQ15_SET 0x10 +#define SI2_ISA_IRQ15_CLEAR 0x00 +#define SI2_ISA_INTCLEAR_SET 0x10 +#define SI2_ISA_INTCLEAR_CLEAR 0x00 +#define SI2_ISA_IRQSET_CLEAR 0x10 +#define SI2_ISA_IRQSET_SET 0x00 +#define SI2_ISA_RESET_SET 0x00 +#define SI2_ISA_RESET_CLEAR 0x10 + +/* PCI board details... */ +#define SI2_PCI_WINDOW_LEN 0x100000 /* 1 Mbyte memory window */ + +/* PCI board register definitions... */ +#define SI2_PCI_SET_IRQ 0x40001 /* Set Host Interrupt */ +#define SI2_PCI_RESET 0xC0001 /* Host Reset */ + +/***************************************************************************** +****************************** ****************************** +****************************** Phase 3 T225 ****************************** +****************************** ****************************** +*****************************************************************************/ + +/* General board details... */ +#define SX_WINDOW_LEN 64*1024 /* 64 Kbyte memory window */ + +/* ISA board details... */ +#define SX_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ +#define SX_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ +#define SX_ISA_ADDR_STEP SX_WINDOW_LEN /* ISA board address step */ +#define SX_ISA_IRQ_MASK 0x9E00 /* IRQs 15,12,11,10,9 */ + +/* Hardware register definitions... */ +#define SX_EVENT_STATUS 0x7800 /* READ: T225 Event Status */ +#define SX_EVENT_STROBE 0x7800 /* WRITE: T225 Event Strobe */ +#define SX_EVENT_ENABLE 0x7880 /* WRITE: T225 Event Enable */ +#define SX_VPD_ROM 0x7C00 /* READ: Vital Product Data ROM */ +#define SX_CONFIG 0x7C00 /* WRITE: Host Configuration Register */ +#define SX_IRQ_STATUS 0x7C80 /* READ: Host Interrupt Status */ +#define SX_SET_IRQ 0x7C80 /* WRITE: Set Host Interrupt */ +#define SX_RESET_STATUS 0x7D00 /* READ: Host Reset Status */ +#define SX_RESET 0x7D00 /* WRITE: Host Reset */ +#define SX_RESET_IRQ 0x7D80 /* WRITE: Reset Host Interrupt */ + +/* SX_VPD_ROM definitions... */ +#define SX_VPD_SLX_ID1 0x00 +#define SX_VPD_SLX_ID2 0x01 +#define SX_VPD_HW_REV 0x02 +#define SX_VPD_HW_ASSEM 0x03 +#define SX_VPD_UNIQUEID4 0x04 +#define SX_VPD_UNIQUEID3 0x05 +#define SX_VPD_UNIQUEID2 0x06 +#define SX_VPD_UNIQUEID1 0x07 +#define SX_VPD_MANU_YEAR 0x08 +#define SX_VPD_MANU_WEEK 0x09 +#define SX_VPD_IDENT 0x10 +#define SX_VPD_IDENT_STRING "JET HOST BY KEV#" + +/* SX unique identifiers... */ +#define SX_UNIQUEID_MASK 0xF0 +#define SX_ISA_UNIQUEID1 0x20 +#define SX_PCI_UNIQUEID1 0x50 + +/* SX_CONFIG definitions... */ +#define SX_CONF_BUSEN 0x02 /* Enable T225 memory and I/O */ +#define SX_CONF_HOSTIRQ 0x04 /* Enable board to host interrupt */ + +/* SX bootstrap... */ +#define SX_BOOTSTRAP "\x28\x20\x21\x02\x60\x0a" +#define SX_BOOTSTRAP_SIZE 6 +#define SX_BOOTSTRAP_ADDR (0x8000-SX_BOOTSTRAP_SIZE) + +/***************************************************************************** +********************************** ********************************** +********************************** EISA ********************************** +********************************** ********************************** +*****************************************************************************/ + +#define SI2_EISA_OFF 0x42 +#define SI2_EISA_VAL 0x01 +#define SI2_EISA_WINDOW_LEN 0x10000 + +/***************************************************************************** +*********************************** ********************************** +*********************************** PCI ********************************** +*********************************** ********************************** +*****************************************************************************/ + +/* General definitions... */ + +#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */ +#define SPX_DEVICE_ID 0x4000 /* SI/XIO boards */ +#define SPX_PLXDEVICE_ID 0x2000 /* SX boards */ + +#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */ +#define SI2_SUB_SYS_ID 0x400 /* Phase 2 (Z280) board */ +#define SX_SUB_SYS_ID 0x200 /* Phase 3 (t225) board */ + +#endif /*_sxboards_h */ + +/* End of SXBOARDS.H */ diff --git a/drivers/staging/generic_serial/sxwindow.h b/drivers/staging/generic_serial/sxwindow.h new file mode 100644 index 000000000000..cf01b662aefc --- /dev/null +++ b/drivers/staging/generic_serial/sxwindow.h @@ -0,0 +1,393 @@ +/************************************************************************/ +/* */ +/* Title : SX Shared Memory Window Structure */ +/* */ +/* Author : N.P.Vassallo */ +/* */ +/* Creation : 16th March 1998 */ +/* */ +/* Version : 3.0.0 */ +/* */ +/* Copyright : (c) Specialix International Ltd. 1998 */ +/* */ +/* Description : Prototypes, structures and definitions */ +/* describing the SX/SI/XIO cards shared */ +/* memory window structure: */ +/* SXCARD */ +/* SXMODULE */ +/* SXCHANNEL */ +/* */ +/************************************************************************/ + +/* History... + +3.0.0 16/03/98 NPV Creation. (based on STRUCT.H) + +*/ + +#ifndef _sxwindow_h /* If SXWINDOW.H not already defined */ +#define _sxwindow_h 1 + +/***************************************************************************** +*************************** *************************** +*************************** Common Definitions *************************** +*************************** *************************** +*****************************************************************************/ + +typedef struct _SXCARD *PSXCARD; /* SXCARD structure pointer */ +typedef struct _SXMODULE *PMOD; /* SXMODULE structure pointer */ +typedef struct _SXCHANNEL *PCHAN; /* SXCHANNEL structure pointer */ + +/***************************************************************************** +********************************* ********************************* +********************************* SXCARD ********************************* +********************************* ********************************* +*****************************************************************************/ + +typedef struct _SXCARD +{ + BYTE cc_init_status; /* 0x00 Initialisation status */ + BYTE cc_mem_size; /* 0x01 Size of memory on card */ + WORD cc_int_count; /* 0x02 Interrupt count */ + WORD cc_revision; /* 0x04 Download code revision */ + BYTE cc_isr_count; /* 0x06 Count when ISR is run */ + BYTE cc_main_count; /* 0x07 Count when main loop is run */ + WORD cc_int_pending; /* 0x08 Interrupt pending */ + WORD cc_poll_count; /* 0x0A Count when poll is run */ + BYTE cc_int_set_count; /* 0x0C Count when host interrupt is set */ + BYTE cc_rfu[0x80 - 0x0D]; /* 0x0D Pad structure to 128 bytes (0x80) */ + +} SXCARD; + +/* SXCARD.cc_init_status definitions... */ +#define ADAPTERS_FOUND (BYTE)0x01 +#define NO_ADAPTERS_FOUND (BYTE)0xFF + +/* SXCARD.cc_mem_size definitions... */ +#define SX_MEMORY_SIZE (BYTE)0x40 + +/* SXCARD.cc_int_count definitions... */ +#define INT_COUNT_DEFAULT 100 /* Hz */ + +/***************************************************************************** +******************************** ******************************** +******************************** SXMODULE ******************************** +******************************** ******************************** +*****************************************************************************/ + +#define TOP_POINTER(a) ((a)|0x8000) /* Sets top bit of word */ +#define UNTOP_POINTER(a) ((a)&~0x8000) /* Clears top bit of word */ + +typedef struct _SXMODULE +{ + WORD mc_next; /* 0x00 Next module "pointer" (ORed with 0x8000) */ + BYTE mc_type; /* 0x02 Type of TA in terms of number of channels */ + BYTE mc_mod_no; /* 0x03 Module number on SI bus cable (0 closest to card) */ + BYTE mc_dtr; /* 0x04 Private DTR copy (TA only) */ + BYTE mc_rfu1; /* 0x05 Reserved */ + WORD mc_uart; /* 0x06 UART base address for this module */ + BYTE mc_chip; /* 0x08 Chip type / number of ports */ + BYTE mc_current_uart; /* 0x09 Current uart selected for this module */ +#ifdef DOWNLOAD + PCHAN mc_chan_pointer[8]; /* 0x0A Pointer to each channel structure */ +#else + WORD mc_chan_pointer[8]; /* 0x0A Define as WORD if not compiling into download */ +#endif + WORD mc_rfu2; /* 0x1A Reserved */ + BYTE mc_opens1; /* 0x1C Number of open ports on first four ports on MTA/SXDC */ + BYTE mc_opens2; /* 0x1D Number of open ports on second four ports on MTA/SXDC */ + BYTE mc_mods; /* 0x1E Types of connector module attached to MTA/SXDC */ + BYTE mc_rev1; /* 0x1F Revision of first CD1400 on MTA/SXDC */ + BYTE mc_rev2; /* 0x20 Revision of second CD1400 on MTA/SXDC */ + BYTE mc_mtaasic_rev; /* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */ + BYTE mc_rfu3[0x100 - 0x22]; /* 0x22 Pad structure to 256 bytes (0x100) */ + +} SXMODULE; + +/* SXMODULE.mc_type definitions... */ +#define FOUR_PORTS (BYTE)4 +#define EIGHT_PORTS (BYTE)8 + +/* SXMODULE.mc_chip definitions... */ +#define CHIP_MASK 0xF0 +#define TA (BYTE)0 +#define TA4 (TA | FOUR_PORTS) +#define TA8 (TA | EIGHT_PORTS) +#define TA4_ASIC (BYTE)0x0A +#define TA8_ASIC (BYTE)0x0B +#define MTA_CD1400 (BYTE)0x28 +#define SXDC (BYTE)0x48 + +/* SXMODULE.mc_mods definitions... */ +#define MOD_RS232DB25 0x00 /* RS232 DB25 (socket/plug) */ +#define MOD_RS232RJ45 0x01 /* RS232 RJ45 (shielded/opto-isolated) */ +#define MOD_RESERVED_2 0x02 /* Reserved (RS485) */ +#define MOD_RS422DB25 0x03 /* RS422 DB25 Socket */ +#define MOD_RESERVED_4 0x04 /* Reserved */ +#define MOD_PARALLEL 0x05 /* Parallel */ +#define MOD_RESERVED_6 0x06 /* Reserved (RS423) */ +#define MOD_RESERVED_7 0x07 /* Reserved */ +#define MOD_2_RS232DB25 0x08 /* Rev 2.0 RS232 DB25 (socket/plug) */ +#define MOD_2_RS232RJ45 0x09 /* Rev 2.0 RS232 RJ45 */ +#define MOD_RESERVED_A 0x0A /* Rev 2.0 Reserved */ +#define MOD_2_RS422DB25 0x0B /* Rev 2.0 RS422 DB25 */ +#define MOD_RESERVED_C 0x0C /* Rev 2.0 Reserved */ +#define MOD_2_PARALLEL 0x0D /* Rev 2.0 Parallel */ +#define MOD_RESERVED_E 0x0E /* Rev 2.0 Reserved */ +#define MOD_BLANK 0x0F /* Blank Panel */ + +/***************************************************************************** +******************************** ******************************* +******************************** SXCHANNEL ******************************* +******************************** ******************************* +*****************************************************************************/ + +#define TX_BUFF_OFFSET 0x60 /* Transmit buffer offset in channel structure */ +#define BUFF_POINTER(a) (((a)+TX_BUFF_OFFSET)|0x8000) +#define UNBUFF_POINTER(a) (jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) +#define BUFFER_SIZE 256 +#define HIGH_WATER ((BUFFER_SIZE / 4) * 3) +#define LOW_WATER (BUFFER_SIZE / 4) + +typedef struct _SXCHANNEL +{ + WORD next_item; /* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */ + WORD addr_uart; /* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */ + WORD module; /* 0x04 Offset from window base of parent SXMODULE structure */ + BYTE type; /* 0x06 Chip type / number of ports (copy of mc_chip) */ + BYTE chan_number; /* 0x07 Channel number on the TA/MTA/SXDC */ + WORD xc_status; /* 0x08 Flow control and I/O status */ + BYTE hi_rxipos; /* 0x0A Receive buffer input index */ + BYTE hi_rxopos; /* 0x0B Receive buffer output index */ + BYTE hi_txopos; /* 0x0C Transmit buffer output index */ + BYTE hi_txipos; /* 0x0D Transmit buffer input index */ + BYTE hi_hstat; /* 0x0E Command register */ + BYTE dtr_bit; /* 0x0F INTERNAL DTR control byte (TA only) */ + BYTE txon; /* 0x10 INTERNAL copy of hi_txon */ + BYTE txoff; /* 0x11 INTERNAL copy of hi_txoff */ + BYTE rxon; /* 0x12 INTERNAL copy of hi_rxon */ + BYTE rxoff; /* 0x13 INTERNAL copy of hi_rxoff */ + BYTE hi_mr1; /* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/ + BYTE hi_mr2; /* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/ + BYTE hi_csr; /* 0x16 Clock Select Register (baud rate) */ + BYTE hi_op; /* 0x17 Modem Output Signal */ + BYTE hi_ip; /* 0x18 Modem Input Signal */ + BYTE hi_state; /* 0x19 Channel status */ + BYTE hi_prtcl; /* 0x1A Channel protocol (flow control) */ + BYTE hi_txon; /* 0x1B Transmit XON character */ + BYTE hi_txoff; /* 0x1C Transmit XOFF character */ + BYTE hi_rxon; /* 0x1D Receive XON character */ + BYTE hi_rxoff; /* 0x1E Receive XOFF character */ + BYTE close_prev; /* 0x1F INTERNAL channel previously closed flag */ + BYTE hi_break; /* 0x20 Break and error control */ + BYTE break_state; /* 0x21 INTERNAL copy of hi_break */ + BYTE hi_mask; /* 0x22 Mask for received data */ + BYTE mask; /* 0x23 INTERNAL copy of hi_mask */ + BYTE mod_type; /* 0x24 MTA/SXDC hardware module type */ + BYTE ccr_state; /* 0x25 INTERNAL MTA/SXDC state of CCR register */ + BYTE ip_mask; /* 0x26 Input handshake mask */ + BYTE hi_parallel; /* 0x27 Parallel port flag */ + BYTE par_error; /* 0x28 Error code for parallel loopback test */ + BYTE any_sent; /* 0x29 INTERNAL data sent flag */ + BYTE asic_txfifo_size; /* 0x2A INTERNAL SXDC transmit FIFO size */ + BYTE rfu1[2]; /* 0x2B Reserved */ + BYTE csr; /* 0x2D INTERNAL copy of hi_csr */ +#ifdef DOWNLOAD + PCHAN nextp; /* 0x2E Offset from window base of next channel structure */ +#else + WORD nextp; /* 0x2E Define as WORD if not compiling into download */ +#endif + BYTE prtcl; /* 0x30 INTERNAL copy of hi_prtcl */ + BYTE mr1; /* 0x31 INTERNAL copy of hi_mr1 */ + BYTE mr2; /* 0x32 INTERNAL copy of hi_mr2 */ + BYTE hi_txbaud; /* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */ + BYTE hi_rxbaud; /* 0x34 Extended receive baud rate (SXDC only if((hi_csr&0xF0)==0xF0) */ + BYTE txbreak_state; /* 0x35 INTERNAL MTA/SXDC transmit break state */ + BYTE txbaud; /* 0x36 INTERNAL copy of hi_txbaud */ + BYTE rxbaud; /* 0x37 INTERNAL copy of hi_rxbaud */ + WORD err_framing; /* 0x38 Count of receive framing errors */ + WORD err_parity; /* 0x3A Count of receive parity errors */ + WORD err_overrun; /* 0x3C Count of receive overrun errors */ + WORD err_overflow; /* 0x3E Count of receive buffer overflow errors */ + BYTE rfu2[TX_BUFF_OFFSET - 0x40]; /* 0x40 Reserved until hi_txbuf */ + BYTE hi_txbuf[BUFFER_SIZE]; /* 0x060 Transmit buffer */ + BYTE hi_rxbuf[BUFFER_SIZE]; /* 0x160 Receive buffer */ + BYTE rfu3[0x300 - 0x260]; /* 0x260 Reserved until 768 bytes (0x300) */ + +} SXCHANNEL; + +/* SXCHANNEL.addr_uart definitions... */ +#define FASTPATH 0x1000 /* Set to indicate fast rx/tx processing (TA only) */ + +/* SXCHANNEL.xc_status definitions... */ +#define X_TANY 0x0001 /* XON is any character (TA only) */ +#define X_TION 0x0001 /* Tx interrupts on (MTA only) */ +#define X_TXEN 0x0002 /* Tx XON/XOFF enabled (TA only) */ +#define X_RTSEN 0x0002 /* RTS FLOW enabled (MTA only) */ +#define X_TXRC 0x0004 /* XOFF received (TA only) */ +#define X_RTSLOW 0x0004 /* RTS dropped (MTA only) */ +#define X_RXEN 0x0008 /* Rx XON/XOFF enabled */ +#define X_ANYXO 0x0010 /* XOFF pending/sent or RTS dropped */ +#define X_RXSE 0x0020 /* Rx XOFF sent */ +#define X_NPEND 0x0040 /* Rx XON pending or XOFF pending */ +#define X_FPEND 0x0080 /* Rx XOFF pending */ +#define C_CRSE 0x0100 /* Carriage return sent (TA only) */ +#define C_TEMR 0x0100 /* Tx empty requested (MTA only) */ +#define C_TEMA 0x0200 /* Tx empty acked (MTA only) */ +#define C_ANYP 0x0200 /* Any protocol bar tx XON/XOFF (TA only) */ +#define C_EN 0x0400 /* Cooking enabled (on MTA means port is also || */ +#define C_HIGH 0x0800 /* Buffer previously hit high water */ +#define C_CTSEN 0x1000 /* CTS automatic flow-control enabled */ +#define C_DCDEN 0x2000 /* DCD/DTR checking enabled */ +#define C_BREAK 0x4000 /* Break detected */ +#define C_RTSEN 0x8000 /* RTS automatic flow control enabled (MTA only) */ +#define C_PARITY 0x8000 /* Parity checking enabled (TA only) */ + +/* SXCHANNEL.hi_hstat definitions... */ +#define HS_IDLE_OPEN 0x00 /* Channel open state */ +#define HS_LOPEN 0x02 /* Local open command (no modem monitoring) */ +#define HS_MOPEN 0x04 /* Modem open command (wait for DCD signal) */ +#define HS_IDLE_MPEND 0x06 /* Waiting for DCD signal state */ +#define HS_CONFIG 0x08 /* Configuration command */ +#define HS_CLOSE 0x0A /* Close command */ +#define HS_START 0x0C /* Start transmit break command */ +#define HS_STOP 0x0E /* Stop transmit break command */ +#define HS_IDLE_CLOSED 0x10 /* Closed channel state */ +#define HS_IDLE_BREAK 0x12 /* Transmit break state */ +#define HS_FORCE_CLOSED 0x14 /* Force close command */ +#define HS_RESUME 0x16 /* Clear pending XOFF command */ +#define HS_WFLUSH 0x18 /* Flush transmit buffer command */ +#define HS_RFLUSH 0x1A /* Flush receive buffer command */ +#define HS_SUSPEND 0x1C /* Suspend output command (like XOFF received) */ +#define PARALLEL 0x1E /* Parallel port loopback test command (Diagnostics Only) */ +#define ENABLE_RX_INTS 0x20 /* Enable receive interrupts command (Diagnostics Only) */ +#define ENABLE_TX_INTS 0x22 /* Enable transmit interrupts command (Diagnostics Only) */ +#define ENABLE_MDM_INTS 0x24 /* Enable modem interrupts command (Diagnostics Only) */ +#define DISABLE_INTS 0x26 /* Disable interrupts command (Diagnostics Only) */ + +/* SXCHANNEL.hi_mr1 definitions... */ +#define MR1_BITS 0x03 /* Data bits mask */ +#define MR1_5_BITS 0x00 /* 5 data bits */ +#define MR1_6_BITS 0x01 /* 6 data bits */ +#define MR1_7_BITS 0x02 /* 7 data bits */ +#define MR1_8_BITS 0x03 /* 8 data bits */ +#define MR1_PARITY 0x1C /* Parity mask */ +#define MR1_ODD 0x04 /* Odd parity */ +#define MR1_EVEN 0x00 /* Even parity */ +#define MR1_WITH 0x00 /* Parity enabled */ +#define MR1_FORCE 0x08 /* Force parity */ +#define MR1_NONE 0x10 /* No parity */ +#define MR1_NOPARITY MR1_NONE /* No parity */ +#define MR1_ODDPARITY (MR1_WITH|MR1_ODD) /* Odd parity */ +#define MR1_EVENPARITY (MR1_WITH|MR1_EVEN) /* Even parity */ +#define MR1_MARKPARITY (MR1_FORCE|MR1_ODD) /* Mark parity */ +#define MR1_SPACEPARITY (MR1_FORCE|MR1_EVEN) /* Space parity */ +#define MR1_RTS_RXFLOW 0x80 /* RTS receive flow control */ + +/* SXCHANNEL.hi_mr2 definitions... */ +#define MR2_STOP 0x0F /* Stop bits mask */ +#define MR2_1_STOP 0x07 /* 1 stop bit */ +#define MR2_2_STOP 0x0F /* 2 stop bits */ +#define MR2_CTS_TXFLOW 0x10 /* CTS transmit flow control */ +#define MR2_RTS_TOGGLE 0x20 /* RTS toggle on transmit */ +#define MR2_NORMAL 0x00 /* Normal mode */ +#define MR2_AUTO 0x40 /* Auto-echo mode (TA only) */ +#define MR2_LOCAL 0x80 /* Local echo mode */ +#define MR2_REMOTE 0xC0 /* Remote echo mode (TA only) */ + +/* SXCHANNEL.hi_csr definitions... */ +#define CSR_75 0x0 /* 75 baud */ +#define CSR_110 0x1 /* 110 baud (TA), 115200 (MTA/SXDC) */ +#define CSR_38400 0x2 /* 38400 baud */ +#define CSR_150 0x3 /* 150 baud */ +#define CSR_300 0x4 /* 300 baud */ +#define CSR_600 0x5 /* 600 baud */ +#define CSR_1200 0x6 /* 1200 baud */ +#define CSR_2000 0x7 /* 2000 baud */ +#define CSR_2400 0x8 /* 2400 baud */ +#define CSR_4800 0x9 /* 4800 baud */ +#define CSR_1800 0xA /* 1800 baud */ +#define CSR_9600 0xB /* 9600 baud */ +#define CSR_19200 0xC /* 19200 baud */ +#define CSR_57600 0xD /* 57600 baud */ +#define CSR_EXTBAUD 0xF /* Extended baud rate (hi_txbaud/hi_rxbaud) */ + +/* SXCHANNEL.hi_op definitions... */ +#define OP_RTS 0x01 /* RTS modem output signal */ +#define OP_DTR 0x02 /* DTR modem output signal */ + +/* SXCHANNEL.hi_ip definitions... */ +#define IP_CTS 0x02 /* CTS modem input signal */ +#define IP_DCD 0x04 /* DCD modem input signal */ +#define IP_DSR 0x20 /* DTR modem input signal */ +#define IP_RI 0x40 /* RI modem input signal */ + +/* SXCHANNEL.hi_state definitions... */ +#define ST_BREAK 0x01 /* Break received (clear with config) */ +#define ST_DCD 0x02 /* DCD signal changed state */ + +/* SXCHANNEL.hi_prtcl definitions... */ +#define SP_TANY 0x01 /* Transmit XON/XANY (if SP_TXEN enabled) */ +#define SP_TXEN 0x02 /* Transmit XON/XOFF flow control */ +#define SP_CEN 0x04 /* Cooking enabled */ +#define SP_RXEN 0x08 /* Rx XON/XOFF enabled */ +#define SP_DCEN 0x20 /* DCD / DTR check */ +#define SP_DTR_RXFLOW 0x40 /* DTR receive flow control */ +#define SP_PAEN 0x80 /* Parity checking enabled */ + +/* SXCHANNEL.hi_break definitions... */ +#define BR_IGN 0x01 /* Ignore any received breaks */ +#define BR_INT 0x02 /* Interrupt on received break */ +#define BR_PARMRK 0x04 /* Enable parmrk parity error processing */ +#define BR_PARIGN 0x08 /* Ignore chars with parity errors */ +#define BR_ERRINT 0x80 /* Treat parity/framing/overrun errors as exceptions */ + +/* SXCHANNEL.par_error definitions.. */ +#define DIAG_IRQ_RX 0x01 /* Indicate serial receive interrupt (diags only) */ +#define DIAG_IRQ_TX 0x02 /* Indicate serial transmit interrupt (diags only) */ +#define DIAG_IRQ_MD 0x04 /* Indicate serial modem interrupt (diags only) */ + +/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */ +#define BAUD_75 0x00 /* 75 baud */ +#define BAUD_115200 0x01 /* 115200 baud */ +#define BAUD_38400 0x02 /* 38400 baud */ +#define BAUD_150 0x03 /* 150 baud */ +#define BAUD_300 0x04 /* 300 baud */ +#define BAUD_600 0x05 /* 600 baud */ +#define BAUD_1200 0x06 /* 1200 baud */ +#define BAUD_2000 0x07 /* 2000 baud */ +#define BAUD_2400 0x08 /* 2400 baud */ +#define BAUD_4800 0x09 /* 4800 baud */ +#define BAUD_1800 0x0A /* 1800 baud */ +#define BAUD_9600 0x0B /* 9600 baud */ +#define BAUD_19200 0x0C /* 19200 baud */ +#define BAUD_57600 0x0D /* 57600 baud */ +#define BAUD_230400 0x0E /* 230400 baud */ +#define BAUD_460800 0x0F /* 460800 baud */ +#define BAUD_921600 0x10 /* 921600 baud */ +#define BAUD_50 0x11 /* 50 baud */ +#define BAUD_110 0x12 /* 110 baud */ +#define BAUD_134_5 0x13 /* 134.5 baud */ +#define BAUD_200 0x14 /* 200 baud */ +#define BAUD_7200 0x15 /* 7200 baud */ +#define BAUD_56000 0x16 /* 56000 baud */ +#define BAUD_64000 0x17 /* 64000 baud */ +#define BAUD_76800 0x18 /* 76800 baud */ +#define BAUD_128000 0x19 /* 128000 baud */ +#define BAUD_150000 0x1A /* 150000 baud */ +#define BAUD_14400 0x1B /* 14400 baud */ +#define BAUD_256000 0x1C /* 256000 baud */ +#define BAUD_28800 0x1D /* 28800 baud */ + +/* SXCHANNEL.txbreak_state definiions... */ +#define TXBREAK_OFF 0 /* Not sending break */ +#define TXBREAK_START 1 /* Begin sending break */ +#define TXBREAK_START1 2 /* Begin sending break, part 1 */ +#define TXBREAK_ON 3 /* Sending break */ +#define TXBREAK_STOP 4 /* Stop sending break */ +#define TXBREAK_STOP1 5 /* Stop sending break, part 1 */ + +#endif /* _sxwindow_h */ + +/* End of SXWINDOW.H */ + diff --git a/drivers/staging/generic_serial/vme_scc.c b/drivers/staging/generic_serial/vme_scc.c new file mode 100644 index 000000000000..96838640f575 --- /dev/null +++ b/drivers/staging/generic_serial/vme_scc.c @@ -0,0 +1,1145 @@ +/* + * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports + * implementation. + * Copyright 1999 Richard Hirst + * + * Based on atari_SCC.c which was + * Copyright 1994-95 Roman Hodek + * Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MVME147_SCC +#include +#endif +#ifdef CONFIG_MVME162_SCC +#include +#endif +#ifdef CONFIG_BVME6000_SCC +#include +#endif + +#include +#include "scc.h" + + +#define CHANNEL_A 0 +#define CHANNEL_B 1 + +#define SCC_MINOR_BASE 64 + +/* Shadows for all SCC write registers */ +static unsigned char scc_shadow[2][16]; + +/* Location to access for SCC register access delay */ +static volatile unsigned char *scc_del = NULL; + +/* To keep track of STATUS_REG state for detection of Ext/Status int source */ +static unsigned char scc_last_status_reg[2]; + +/***************************** Prototypes *****************************/ + +/* Function prototypes */ +static void scc_disable_tx_interrupts(void * ptr); +static void scc_enable_tx_interrupts(void * ptr); +static void scc_disable_rx_interrupts(void * ptr); +static void scc_enable_rx_interrupts(void * ptr); +static int scc_carrier_raised(struct tty_port *port); +static void scc_shutdown_port(void * ptr); +static int scc_set_real_termios(void *ptr); +static void scc_hungup(void *ptr); +static void scc_close(void *ptr); +static int scc_chars_in_buffer(void * ptr); +static int scc_open(struct tty_struct * tty, struct file * filp); +static int scc_ioctl(struct tty_struct * tty, + unsigned int cmd, unsigned long arg); +static void scc_throttle(struct tty_struct *tty); +static void scc_unthrottle(struct tty_struct *tty); +static irqreturn_t scc_tx_int(int irq, void *data); +static irqreturn_t scc_rx_int(int irq, void *data); +static irqreturn_t scc_stat_int(int irq, void *data); +static irqreturn_t scc_spcond_int(int irq, void *data); +static void scc_setsignals(struct scc_port *port, int dtr, int rts); +static int scc_break_ctl(struct tty_struct *tty, int break_state); + +static struct tty_driver *scc_driver; + +static struct scc_port scc_ports[2]; + +/*--------------------------------------------------------------------------- + * Interface from generic_serial.c back here + *--------------------------------------------------------------------------*/ + +static struct real_driver scc_real_driver = { + scc_disable_tx_interrupts, + scc_enable_tx_interrupts, + scc_disable_rx_interrupts, + scc_enable_rx_interrupts, + scc_shutdown_port, + scc_set_real_termios, + scc_chars_in_buffer, + scc_close, + scc_hungup, + NULL +}; + + +static const struct tty_operations scc_ops = { + .open = scc_open, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .chars_in_buffer = gs_chars_in_buffer, + .flush_buffer = gs_flush_buffer, + .ioctl = scc_ioctl, + .throttle = scc_throttle, + .unthrottle = scc_unthrottle, + .set_termios = gs_set_termios, + .stop = gs_stop, + .start = gs_start, + .hangup = gs_hangup, + .break_ctl = scc_break_ctl, +}; + +static const struct tty_port_operations scc_port_ops = { + .carrier_raised = scc_carrier_raised, +}; + +/*---------------------------------------------------------------------------- + * vme_scc_init() and support functions + *---------------------------------------------------------------------------*/ + +static int __init scc_init_drivers(void) +{ + int error; + + scc_driver = alloc_tty_driver(2); + if (!scc_driver) + return -ENOMEM; + scc_driver->owner = THIS_MODULE; + scc_driver->driver_name = "scc"; + scc_driver->name = "ttyS"; + scc_driver->major = TTY_MAJOR; + scc_driver->minor_start = SCC_MINOR_BASE; + scc_driver->type = TTY_DRIVER_TYPE_SERIAL; + scc_driver->subtype = SERIAL_TYPE_NORMAL; + scc_driver->init_termios = tty_std_termios; + scc_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + scc_driver->init_termios.c_ispeed = 9600; + scc_driver->init_termios.c_ospeed = 9600; + scc_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(scc_driver, &scc_ops); + + if ((error = tty_register_driver(scc_driver))) { + printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n", + error); + put_tty_driver(scc_driver); + return 1; + } + + return 0; +} + + +/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1). + */ + +static void __init scc_init_portstructs(void) +{ + struct scc_port *port; + int i; + + for (i = 0; i < 2; i++) { + port = scc_ports + i; + tty_port_init(&port->gs.port); + port->gs.port.ops = &scc_port_ops; + port->gs.magic = SCC_MAGIC; + port->gs.close_delay = HZ/2; + port->gs.closing_wait = 30 * HZ; + port->gs.rd = &scc_real_driver; +#ifdef NEW_WRITE_LOCKING + port->gs.port_write_mutex = MUTEX; +#endif + init_waitqueue_head(&port->gs.port.open_wait); + init_waitqueue_head(&port->gs.port.close_wait); + } +} + + +#ifdef CONFIG_MVME147_SCC +static int __init mvme147_scc_init(void) +{ + struct scc_port *port; + int error; + + printk(KERN_INFO "SCC: MVME147 Serial Driver\n"); + /* Init channel A */ + port = &scc_ports[0]; + port->channel = CHANNEL_A; + port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR; + port->datap = port->ctrlp + 1; + port->port_a = &scc_ports[0]; + port->port_b = &scc_ports[1]; + error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED, + "SCC-A TX", port); + if (error) + goto fail; + error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED, + "SCC-A status", port); + if (error) + goto fail_free_a_tx; + error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED, + "SCC-A RX", port); + if (error) + goto fail_free_a_stat; + error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, + IRQF_DISABLED, "SCC-A special cond", port); + if (error) + goto fail_free_a_rx; + + { + SCC_ACCESS_INIT(port); + + /* disable interrupts for this channel */ + SCCwrite(INT_AND_DMA_REG, 0); + /* Set the interrupt vector */ + SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE); + /* Interrupt parameters: vector includes status, status low */ + SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); + SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); + } + + /* Init channel B */ + port = &scc_ports[1]; + port->channel = CHANNEL_B; + port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR; + port->datap = port->ctrlp + 1; + port->port_a = &scc_ports[0]; + port->port_b = &scc_ports[1]; + error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED, + "SCC-B TX", port); + if (error) + goto fail_free_a_spcond; + error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED, + "SCC-B status", port); + if (error) + goto fail_free_b_tx; + error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED, + "SCC-B RX", port); + if (error) + goto fail_free_b_stat; + error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, + IRQF_DISABLED, "SCC-B special cond", port); + if (error) + goto fail_free_b_rx; + + { + SCC_ACCESS_INIT(port); + + /* disable interrupts for this channel */ + SCCwrite(INT_AND_DMA_REG, 0); + } + + /* Ensure interrupts are enabled in the PCC chip */ + m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB; + + /* Initialise the tty driver structures and register */ + scc_init_portstructs(); + scc_init_drivers(); + + return 0; + +fail_free_b_rx: + free_irq(MVME147_IRQ_SCCB_RX, port); +fail_free_b_stat: + free_irq(MVME147_IRQ_SCCB_STAT, port); +fail_free_b_tx: + free_irq(MVME147_IRQ_SCCB_TX, port); +fail_free_a_spcond: + free_irq(MVME147_IRQ_SCCA_SPCOND, port); +fail_free_a_rx: + free_irq(MVME147_IRQ_SCCA_RX, port); +fail_free_a_stat: + free_irq(MVME147_IRQ_SCCA_STAT, port); +fail_free_a_tx: + free_irq(MVME147_IRQ_SCCA_TX, port); +fail: + return error; +} +#endif + + +#ifdef CONFIG_MVME162_SCC +static int __init mvme162_scc_init(void) +{ + struct scc_port *port; + int error; + + if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA)) + return (-ENODEV); + + printk(KERN_INFO "SCC: MVME162 Serial Driver\n"); + /* Init channel A */ + port = &scc_ports[0]; + port->channel = CHANNEL_A; + port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR; + port->datap = port->ctrlp + 2; + port->port_a = &scc_ports[0]; + port->port_b = &scc_ports[1]; + error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED, + "SCC-A TX", port); + if (error) + goto fail; + error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED, + "SCC-A status", port); + if (error) + goto fail_free_a_tx; + error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED, + "SCC-A RX", port); + if (error) + goto fail_free_a_stat; + error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, + IRQF_DISABLED, "SCC-A special cond", port); + if (error) + goto fail_free_a_rx; + + { + SCC_ACCESS_INIT(port); + + /* disable interrupts for this channel */ + SCCwrite(INT_AND_DMA_REG, 0); + /* Set the interrupt vector */ + SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE); + /* Interrupt parameters: vector includes status, status low */ + SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); + SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); + } + + /* Init channel B */ + port = &scc_ports[1]; + port->channel = CHANNEL_B; + port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR; + port->datap = port->ctrlp + 2; + port->port_a = &scc_ports[0]; + port->port_b = &scc_ports[1]; + error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED, + "SCC-B TX", port); + if (error) + goto fail_free_a_spcond; + error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED, + "SCC-B status", port); + if (error) + goto fail_free_b_tx; + error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED, + "SCC-B RX", port); + if (error) + goto fail_free_b_stat; + error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, + IRQF_DISABLED, "SCC-B special cond", port); + if (error) + goto fail_free_b_rx; + + { + SCC_ACCESS_INIT(port); /* Either channel will do */ + + /* disable interrupts for this channel */ + SCCwrite(INT_AND_DMA_REG, 0); + } + + /* Ensure interrupts are enabled in the MC2 chip */ + *(volatile char *)0xfff4201d = 0x14; + + /* Initialise the tty driver structures and register */ + scc_init_portstructs(); + scc_init_drivers(); + + return 0; + +fail_free_b_rx: + free_irq(MVME162_IRQ_SCCB_RX, port); +fail_free_b_stat: + free_irq(MVME162_IRQ_SCCB_STAT, port); +fail_free_b_tx: + free_irq(MVME162_IRQ_SCCB_TX, port); +fail_free_a_spcond: + free_irq(MVME162_IRQ_SCCA_SPCOND, port); +fail_free_a_rx: + free_irq(MVME162_IRQ_SCCA_RX, port); +fail_free_a_stat: + free_irq(MVME162_IRQ_SCCA_STAT, port); +fail_free_a_tx: + free_irq(MVME162_IRQ_SCCA_TX, port); +fail: + return error; +} +#endif + + +#ifdef CONFIG_BVME6000_SCC +static int __init bvme6000_scc_init(void) +{ + struct scc_port *port; + int error; + + printk(KERN_INFO "SCC: BVME6000 Serial Driver\n"); + /* Init channel A */ + port = &scc_ports[0]; + port->channel = CHANNEL_A; + port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR; + port->datap = port->ctrlp + 4; + port->port_a = &scc_ports[0]; + port->port_b = &scc_ports[1]; + error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED, + "SCC-A TX", port); + if (error) + goto fail; + error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED, + "SCC-A status", port); + if (error) + goto fail_free_a_tx; + error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED, + "SCC-A RX", port); + if (error) + goto fail_free_a_stat; + error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, + IRQF_DISABLED, "SCC-A special cond", port); + if (error) + goto fail_free_a_rx; + + { + SCC_ACCESS_INIT(port); + + /* disable interrupts for this channel */ + SCCwrite(INT_AND_DMA_REG, 0); + /* Set the interrupt vector */ + SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE); + /* Interrupt parameters: vector includes status, status low */ + SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); + SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); + } + + /* Init channel B */ + port = &scc_ports[1]; + port->channel = CHANNEL_B; + port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR; + port->datap = port->ctrlp + 4; + port->port_a = &scc_ports[0]; + port->port_b = &scc_ports[1]; + error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED, + "SCC-B TX", port); + if (error) + goto fail_free_a_spcond; + error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED, + "SCC-B status", port); + if (error) + goto fail_free_b_tx; + error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED, + "SCC-B RX", port); + if (error) + goto fail_free_b_stat; + error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, + IRQF_DISABLED, "SCC-B special cond", port); + if (error) + goto fail_free_b_rx; + + { + SCC_ACCESS_INIT(port); /* Either channel will do */ + + /* disable interrupts for this channel */ + SCCwrite(INT_AND_DMA_REG, 0); + } + + /* Initialise the tty driver structures and register */ + scc_init_portstructs(); + scc_init_drivers(); + + return 0; + +fail: + free_irq(BVME_IRQ_SCCA_STAT, port); +fail_free_a_tx: + free_irq(BVME_IRQ_SCCA_RX, port); +fail_free_a_stat: + free_irq(BVME_IRQ_SCCA_SPCOND, port); +fail_free_a_rx: + free_irq(BVME_IRQ_SCCB_TX, port); +fail_free_a_spcond: + free_irq(BVME_IRQ_SCCB_STAT, port); +fail_free_b_tx: + free_irq(BVME_IRQ_SCCB_RX, port); +fail_free_b_stat: + free_irq(BVME_IRQ_SCCB_SPCOND, port); +fail_free_b_rx: + return error; +} +#endif + + +static int __init vme_scc_init(void) +{ + int res = -ENODEV; + +#ifdef CONFIG_MVME147_SCC + if (MACH_IS_MVME147) + res = mvme147_scc_init(); +#endif +#ifdef CONFIG_MVME162_SCC + if (MACH_IS_MVME16x) + res = mvme162_scc_init(); +#endif +#ifdef CONFIG_BVME6000_SCC + if (MACH_IS_BVME6000) + res = bvme6000_scc_init(); +#endif + return res; +} + +module_init(vme_scc_init); + + +/*--------------------------------------------------------------------------- + * Interrupt handlers + *--------------------------------------------------------------------------*/ + +static irqreturn_t scc_rx_int(int irq, void *data) +{ + unsigned char ch; + struct scc_port *port = data; + struct tty_struct *tty = port->gs.port.tty; + SCC_ACCESS_INIT(port); + + ch = SCCread_NB(RX_DATA_REG); + if (!tty) { + printk(KERN_WARNING "scc_rx_int with NULL tty!\n"); + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + return IRQ_HANDLED; + } + tty_insert_flip_char(tty, ch, 0); + + /* Check if another character is already ready; in that case, the + * spcond_int() function must be used, because this character may have an + * error condition that isn't signalled by the interrupt vector used! + */ + if (SCCread(INT_PENDING_REG) & + (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) { + scc_spcond_int (irq, data); + return IRQ_HANDLED; + } + + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + + tty_flip_buffer_push(tty); + return IRQ_HANDLED; +} + + +static irqreturn_t scc_spcond_int(int irq, void *data) +{ + struct scc_port *port = data; + struct tty_struct *tty = port->gs.port.tty; + unsigned char stat, ch, err; + int int_pending_mask = port->channel == CHANNEL_A ? + IPR_A_RX : IPR_B_RX; + SCC_ACCESS_INIT(port); + + if (!tty) { + printk(KERN_WARNING "scc_spcond_int with NULL tty!\n"); + SCCwrite(COMMAND_REG, CR_ERROR_RESET); + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + return IRQ_HANDLED; + } + do { + stat = SCCread(SPCOND_STATUS_REG); + ch = SCCread_NB(RX_DATA_REG); + + if (stat & SCSR_RX_OVERRUN) + err = TTY_OVERRUN; + else if (stat & SCSR_PARITY_ERR) + err = TTY_PARITY; + else if (stat & SCSR_CRC_FRAME_ERR) + err = TTY_FRAME; + else + err = 0; + + tty_insert_flip_char(tty, ch, err); + + /* ++TeSche: *All* errors have to be cleared manually, + * else the condition persists for the next chars + */ + if (err) + SCCwrite(COMMAND_REG, CR_ERROR_RESET); + + } while(SCCread(INT_PENDING_REG) & int_pending_mask); + + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + + tty_flip_buffer_push(tty); + return IRQ_HANDLED; +} + + +static irqreturn_t scc_tx_int(int irq, void *data) +{ + struct scc_port *port = data; + SCC_ACCESS_INIT(port); + + if (!port->gs.port.tty) { + printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); + SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); + SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + return IRQ_HANDLED; + } + while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) { + if (port->x_char) { + SCCwrite(TX_DATA_REG, port->x_char); + port->x_char = 0; + } + else if ((port->gs.xmit_cnt <= 0) || + port->gs.port.tty->stopped || + port->gs.port.tty->hw_stopped) + break; + else { + SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]); + port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1); + if (--port->gs.xmit_cnt <= 0) + break; + } + } + if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped || + port->gs.port.tty->hw_stopped) { + /* disable tx interrupts */ + SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); + SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ + port->gs.port.flags &= ~GS_TX_INTEN; + } + if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) + tty_wakeup(port->gs.port.tty); + + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + return IRQ_HANDLED; +} + + +static irqreturn_t scc_stat_int(int irq, void *data) +{ + struct scc_port *port = data; + unsigned channel = port->channel; + unsigned char last_sr, sr, changed; + SCC_ACCESS_INIT(port); + + last_sr = scc_last_status_reg[channel]; + sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG); + changed = last_sr ^ sr; + + if (changed & SR_DCD) { + port->c_dcd = !!(sr & SR_DCD); + if (!(port->gs.port.flags & ASYNC_CHECK_CD)) + ; /* Don't report DCD changes */ + else if (port->c_dcd) { + wake_up_interruptible(&port->gs.port.open_wait); + } + else { + if (port->gs.port.tty) + tty_hangup (port->gs.port.tty); + } + } + SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); + SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); + return IRQ_HANDLED; +} + + +/*--------------------------------------------------------------------------- + * generic_serial.c callback funtions + *--------------------------------------------------------------------------*/ + +static void scc_disable_tx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + unsigned long flags; + SCC_ACCESS_INIT(port); + + local_irq_save(flags); + SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); + port->gs.port.flags &= ~GS_TX_INTEN; + local_irq_restore(flags); +} + + +static void scc_enable_tx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + unsigned long flags; + SCC_ACCESS_INIT(port); + + local_irq_save(flags); + SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB); + /* restart the transmitter */ + scc_tx_int (0, port); + local_irq_restore(flags); +} + + +static void scc_disable_rx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + unsigned long flags; + SCC_ACCESS_INIT(port); + + local_irq_save(flags); + SCCmod(INT_AND_DMA_REG, + ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0); + local_irq_restore(flags); +} + + +static void scc_enable_rx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + unsigned long flags; + SCC_ACCESS_INIT(port); + + local_irq_save(flags); + SCCmod(INT_AND_DMA_REG, 0xff, + IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL); + local_irq_restore(flags); +} + + +static int scc_carrier_raised(struct tty_port *port) +{ + struct scc_port *sc = container_of(port, struct scc_port, gs.port); + unsigned channel = sc->channel; + + return !!(scc_last_status_reg[channel] & SR_DCD); +} + + +static void scc_shutdown_port(void *ptr) +{ + struct scc_port *port = ptr; + + port->gs.port.flags &= ~ GS_ACTIVE; + if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) { + scc_setsignals (port, 0, 0); + } +} + + +static int scc_set_real_termios (void *ptr) +{ + /* the SCC has char sizes 5,7,6,8 in that order! */ + static int chsize_map[4] = { 0, 2, 1, 3 }; + unsigned cflag, baud, chsize, channel, brgval = 0; + unsigned long flags; + struct scc_port *port = ptr; + SCC_ACCESS_INIT(port); + + if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; + + channel = port->channel; + + if (channel == CHANNEL_A) + return 0; /* Settings controlled by boot PROM */ + + cflag = port->gs.port.tty->termios->c_cflag; + baud = port->gs.baud; + chsize = (cflag & CSIZE) >> 4; + + if (baud == 0) { + /* speed == 0 -> drop DTR */ + local_irq_save(flags); + SCCmod(TX_CTRL_REG, ~TCR_DTR, 0); + local_irq_restore(flags); + return 0; + } + else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) || + (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) || + (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) { + printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud); + return 0; + } + + if (cflag & CLOCAL) + port->gs.port.flags &= ~ASYNC_CHECK_CD; + else + port->gs.port.flags |= ASYNC_CHECK_CD; + +#ifdef CONFIG_MVME147_SCC + if (MACH_IS_MVME147) + brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; +#endif +#ifdef CONFIG_MVME162_SCC + if (MACH_IS_MVME16x) + brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; +#endif +#ifdef CONFIG_BVME6000_SCC + if (MACH_IS_BVME6000) + brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2; +#endif + /* Now we have all parameters and can go to set them: */ + local_irq_save(flags); + + /* receiver's character size and auto-enables */ + SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE), + (chsize_map[chsize] << 6) | + ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0)); + /* parity and stop bits (both, Tx and Rx), clock mode never changes */ + SCCmod (AUX1_CTRL_REG, + ~(A1CR_PARITY_MASK | A1CR_MODE_MASK), + ((cflag & PARENB + ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN) + : A1CR_PARITY_NONE) + | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1))); + /* sender's character size, set DTR for valid baud rate */ + SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR); + /* clock sources never change */ + /* disable BRG before changing the value */ + SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0); + /* BRG value */ + SCCwrite(TIMER_LOW_REG, brgval & 0xff); + SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff); + /* BRG enable, and clock source never changes */ + SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB); + + local_irq_restore(flags); + + return 0; +} + + +static int scc_chars_in_buffer (void *ptr) +{ + struct scc_port *port = ptr; + SCC_ACCESS_INIT(port); + + return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1; +} + + +/* Comment taken from sx.c (2.4.0): + I haven't the foggiest why the decrement use count has to happen + here. The whole linux serial drivers stuff needs to be redesigned. + My guess is that this is a hack to minimize the impact of a bug + elsewhere. Thinking about it some more. (try it sometime) Try + running minicom on a serial port that is driven by a modularized + driver. Have the modem hangup. Then remove the driver module. Then + exit minicom. I expect an "oops". -- REW */ + +static void scc_hungup(void *ptr) +{ + scc_disable_tx_interrupts(ptr); + scc_disable_rx_interrupts(ptr); +} + + +static void scc_close(void *ptr) +{ + scc_disable_tx_interrupts(ptr); + scc_disable_rx_interrupts(ptr); +} + + +/*--------------------------------------------------------------------------- + * Internal support functions + *--------------------------------------------------------------------------*/ + +static void scc_setsignals(struct scc_port *port, int dtr, int rts) +{ + unsigned long flags; + unsigned char t; + SCC_ACCESS_INIT(port); + + local_irq_save(flags); + t = SCCread(TX_CTRL_REG); + if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR); + if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS); + SCCwrite(TX_CTRL_REG, t); + local_irq_restore(flags); +} + + +static void scc_send_xchar(struct tty_struct *tty, char ch) +{ + struct scc_port *port = tty->driver_data; + + port->x_char = ch; + if (ch) + scc_enable_tx_interrupts(port); +} + + +/*--------------------------------------------------------------------------- + * Driver entrypoints referenced from above + *--------------------------------------------------------------------------*/ + +static int scc_open (struct tty_struct * tty, struct file * filp) +{ + int line = tty->index; + int retval; + struct scc_port *port = &scc_ports[line]; + int i, channel = port->channel; + unsigned long flags; + SCC_ACCESS_INIT(port); +#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC) + static const struct { + unsigned reg, val; + } mvme_init_tab[] = { + /* Values for MVME162 and MVME147 */ + /* no parity, 1 stop bit, async, 1:16 */ + { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 }, + /* parity error is special cond, ints disabled, no DMA */ + { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB }, + /* Rx 8 bits/char, no auto enable, Rx off */ + { RX_CTRL_REG, RCR_CHSIZE_8 }, + /* DTR off, Tx 8 bits/char, RTS off, Tx off */ + { TX_CTRL_REG, TCR_CHSIZE_8 }, + /* special features off */ + { AUX2_CTRL_REG, 0 }, + { CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG }, + { DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK }, + /* Start Rx */ + { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 }, + /* Start Tx */ + { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 }, + /* Ext/Stat ints: DCD only */ + { INT_CTRL_REG, ICR_ENAB_DCD_INT }, + /* Reset Ext/Stat ints */ + { COMMAND_REG, CR_EXTSTAT_RESET }, + /* ...again */ + { COMMAND_REG, CR_EXTSTAT_RESET }, + }; +#endif +#if defined(CONFIG_BVME6000_SCC) + static const struct { + unsigned reg, val; + } bvme_init_tab[] = { + /* Values for BVME6000 */ + /* no parity, 1 stop bit, async, 1:16 */ + { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 }, + /* parity error is special cond, ints disabled, no DMA */ + { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB }, + /* Rx 8 bits/char, no auto enable, Rx off */ + { RX_CTRL_REG, RCR_CHSIZE_8 }, + /* DTR off, Tx 8 bits/char, RTS off, Tx off */ + { TX_CTRL_REG, TCR_CHSIZE_8 }, + /* special features off */ + { AUX2_CTRL_REG, 0 }, + { CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG }, + { DPLL_CTRL_REG, DCR_BRG_ENAB }, + /* Start Rx */ + { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 }, + /* Start Tx */ + { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 }, + /* Ext/Stat ints: DCD only */ + { INT_CTRL_REG, ICR_ENAB_DCD_INT }, + /* Reset Ext/Stat ints */ + { COMMAND_REG, CR_EXTSTAT_RESET }, + /* ...again */ + { COMMAND_REG, CR_EXTSTAT_RESET }, + }; +#endif + if (!(port->gs.port.flags & ASYNC_INITIALIZED)) { + local_irq_save(flags); +#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) + if (MACH_IS_MVME147 || MACH_IS_MVME16x) { + for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i) + SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val); + } +#endif +#if defined(CONFIG_BVME6000_SCC) + if (MACH_IS_BVME6000) { + for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i) + SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val); + } +#endif + + /* remember status register for detection of DCD and CTS changes */ + scc_last_status_reg[channel] = SCCread(STATUS_REG); + + port->c_dcd = 0; /* Prevent initial 1->0 interrupt */ + scc_setsignals (port, 1,1); + local_irq_restore(flags); + } + + tty->driver_data = port; + port->gs.port.tty = tty; + port->gs.port.count++; + retval = gs_init_port(&port->gs); + if (retval) { + port->gs.port.count--; + return retval; + } + port->gs.port.flags |= GS_ACTIVE; + retval = gs_block_til_ready(port, filp); + + if (retval) { + port->gs.port.count--; + return retval; + } + + port->c_dcd = tty_port_carrier_raised(&port->gs.port); + + scc_enable_rx_interrupts(port); + + return 0; +} + + +static void scc_throttle (struct tty_struct * tty) +{ + struct scc_port *port = tty->driver_data; + unsigned long flags; + SCC_ACCESS_INIT(port); + + if (tty->termios->c_cflag & CRTSCTS) { + local_irq_save(flags); + SCCmod(TX_CTRL_REG, ~TCR_RTS, 0); + local_irq_restore(flags); + } + if (I_IXOFF(tty)) + scc_send_xchar(tty, STOP_CHAR(tty)); +} + + +static void scc_unthrottle (struct tty_struct * tty) +{ + struct scc_port *port = tty->driver_data; + unsigned long flags; + SCC_ACCESS_INIT(port); + + if (tty->termios->c_cflag & CRTSCTS) { + local_irq_save(flags); + SCCmod(TX_CTRL_REG, 0xff, TCR_RTS); + local_irq_restore(flags); + } + if (I_IXOFF(tty)) + scc_send_xchar(tty, START_CHAR(tty)); +} + + +static int scc_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + + +static int scc_break_ctl(struct tty_struct *tty, int break_state) +{ + struct scc_port *port = tty->driver_data; + unsigned long flags; + SCC_ACCESS_INIT(port); + + local_irq_save(flags); + SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, + break_state ? TCR_SEND_BREAK : 0); + local_irq_restore(flags); + return 0; +} + + +/*--------------------------------------------------------------------------- + * Serial console stuff... + *--------------------------------------------------------------------------*/ + +#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0) + +static void scc_ch_write (char ch) +{ + volatile char *p = NULL; + +#ifdef CONFIG_MVME147_SCC + if (MACH_IS_MVME147) + p = (volatile char *)M147_SCC_A_ADDR; +#endif +#ifdef CONFIG_MVME162_SCC + if (MACH_IS_MVME16x) + p = (volatile char *)MVME_SCC_A_ADDR; +#endif +#ifdef CONFIG_BVME6000_SCC + if (MACH_IS_BVME6000) + p = (volatile char *)BVME_SCC_A_ADDR; +#endif + + do { + scc_delay(); + } + while (!(*p & 4)); + scc_delay(); + *p = 8; + scc_delay(); + *p = ch; +} + +/* The console must be locked when we get here. */ + +static void scc_console_write (struct console *co, const char *str, unsigned count) +{ + unsigned long flags; + + local_irq_save(flags); + + while (count--) + { + if (*str == '\n') + scc_ch_write ('\r'); + scc_ch_write (*str++); + } + local_irq_restore(flags); +} + +static struct tty_driver *scc_console_device(struct console *c, int *index) +{ + *index = c->index; + return scc_driver; +} + +static struct console sercons = { + .name = "ttyS", + .write = scc_console_write, + .device = scc_console_device, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + + +static int __init vme_scc_console_init(void) +{ + if (vme_brdtype == VME_TYPE_MVME147 || + vme_brdtype == VME_TYPE_MVME162 || + vme_brdtype == VME_TYPE_MVME172 || + vme_brdtype == VME_TYPE_BVME4000 || + vme_brdtype == VME_TYPE_BVME6000) + register_console(&sercons); + return 0; +} +console_initcall(vme_scc_console_init); -- cgit v1.2.3 From 49495d44dfa4ba76cf7d1ed8fe84746dd9552255 Mon Sep 17 00:00:00 2001 From: Florian Mickler Date: Mon, 7 Feb 2011 23:29:31 +0100 Subject: amd64-agp: fix crash at second module load The module forgot to sometimes unregister some resources. This fixes Bug #22882. [Patch updated to 2.6.38-rc3 by Randy Dunlap.] Tested-by: Randy Dunlap Signed-off-by: Florian Mickler Signed-off-by: Dave Airlie --- drivers/char/agp/amd64-agp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 9252e85706ef..780498d76581 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -773,18 +773,23 @@ int __init agp_amd64_init(void) #else printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n"); #endif + pci_unregister_driver(&agp_amd64_pci_driver); return -ENODEV; } /* First check that we have at least one AMD64 NB */ - if (!pci_dev_present(amd_nb_misc_ids)) + if (!pci_dev_present(amd_nb_misc_ids)) { + pci_unregister_driver(&agp_amd64_pci_driver); return -ENODEV; + } /* Look for any AGP bridge */ agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table; err = driver_attach(&agp_amd64_pci_driver.driver); - if (err == 0 && agp_bridges_found == 0) + if (err == 0 && agp_bridges_found == 0) { + pci_unregister_driver(&agp_amd64_pci_driver); err = -ENODEV; + } } return err; } -- cgit v1.2.3 From aa25afad2ca60d19457849ea75e9c31236f4e174 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Feb 2011 15:55:00 +0000 Subject: ARM: amba: make probe() functions take const id tables Make Primecell driver probe functions take a const pointer to their ID tables. Drivers should never modify their ID tables in their probe handler. Signed-off-by: Russell King --- arch/arm/kernel/etm.c | 4 ++-- drivers/char/hw_random/nomadik-rng.c | 2 +- drivers/dma/amba-pl08x.c | 2 +- drivers/dma/pl330.c | 2 +- drivers/gpio/pl061.c | 2 +- drivers/input/serio/ambakmi.c | 3 ++- drivers/mmc/host/mmci.c | 3 ++- drivers/rtc/rtc-pl030.c | 2 +- drivers/rtc/rtc-pl031.c | 2 +- drivers/spi/amba-pl022.c | 2 +- drivers/tty/serial/amba-pl010.c | 2 +- drivers/tty/serial/amba-pl011.c | 2 +- drivers/video/amba-clcd.c | 2 +- drivers/watchdog/sp805_wdt.c | 2 +- include/linux/amba/bus.h | 2 +- sound/arm/aaci.c | 3 ++- 16 files changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/char') diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 11db62806a1a..052b509e2d5f 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -338,7 +338,7 @@ static struct miscdevice etb_miscdev = { .fops = &etb_fops, }; -static int __init etb_probe(struct amba_device *dev, struct amba_id *id) +static int __init etb_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; @@ -530,7 +530,7 @@ static ssize_t trace_mode_store(struct kobject *kobj, static struct kobj_attribute trace_mode_attr = __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); -static int __init etm_probe(struct amba_device *dev, struct amba_id *id) +static int __init etm_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index a348c7e9aa0b..dd1d143eb8ea 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c @@ -39,7 +39,7 @@ static struct hwrng nmk_rng = { .read = nmk_rng_read, }; -static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id) +static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) { void __iomem *base; int ret; diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 07bca4970e50..e6d7228b1479 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1845,7 +1845,7 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) } #endif -static int pl08x_probe(struct amba_device *adev, struct amba_id *id) +static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) { struct pl08x_driver_data *pl08x; const struct vendor_data *vd = id->data; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 7c50f6dfd3f4..6abe1ec1f2ce 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -657,7 +657,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data) } static int __devinit -pl330_probe(struct amba_device *adev, struct amba_id *id) +pl330_probe(struct amba_device *adev, const struct amba_id *id) { struct dma_pl330_platdata *pdat; struct dma_pl330_dmac *pdmac; diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 2975d22daffe..838ddbdf90cc 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -232,7 +232,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) desc->irq_data.chip->irq_unmask(&desc->irq_data); } -static int pl061_probe(struct amba_device *dev, struct amba_id *id) +static int pl061_probe(struct amba_device *dev, const struct amba_id *id) { struct pl061_platform_data *pdata; struct pl061_gpio *chip; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 92563a681d65..12abc50508e5 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -107,7 +107,8 @@ static void amba_kmi_close(struct serio *io) clk_disable(kmi->clk); } -static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit amba_kmi_probe(struct amba_device *dev, + const struct amba_id *id) { struct amba_kmi_port *kmi; struct serio *io; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2d6de3e03e2d..67f17d61b978 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -713,7 +713,8 @@ static const struct mmc_host_ops mmci_ops = { .get_cd = mmci_get_cd, }; -static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit mmci_probe(struct amba_device *dev, + const struct amba_id *id) { struct mmci_platform_data *plat = dev->dev.platform_data; struct variant_data *variant = id->data; diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index bbdb2f02798a..baff724cd40f 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -103,7 +103,7 @@ static const struct rtc_class_ops pl030_ops = { .set_alarm = pl030_set_alarm, }; -static int pl030_probe(struct amba_device *dev, struct amba_id *id) +static int pl030_probe(struct amba_device *dev, const struct amba_id *id) { struct pl030_rtc *rtc; int ret; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index b7a6690e5b35..6568f4b37e19 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -358,7 +358,7 @@ static int pl031_remove(struct amba_device *adev) return 0; } -static int pl031_probe(struct amba_device *adev, struct amba_id *id) +static int pl031_probe(struct amba_device *adev, const struct amba_id *id) { int ret; struct pl031_local *ldata; diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 71a1219a995d..95e58c70a2c9 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -2021,7 +2021,7 @@ static void pl022_cleanup(struct spi_device *spi) static int __devinit -pl022_probe(struct amba_device *adev, struct amba_id *id) +pl022_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct pl022_ssp_controller *platform_info = adev->dev.platform_data; diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 2904aa044126..d742dd2c525c 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -676,7 +676,7 @@ static struct uart_driver amba_reg = { .cons = AMBA_CONSOLE, }; -static int pl010_probe(struct amba_device *dev, struct amba_id *id) +static int pl010_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; void __iomem *base; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e76d7d000128..0dae46f91021 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1349,7 +1349,7 @@ static struct uart_driver amba_reg = { .cons = AMBA_CONSOLE, }; -static int pl011_probe(struct amba_device *dev, struct amba_id *id) +static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; struct vendor_data *vendor = id->data; diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 1c2c68356ea7..013c8ce57205 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -461,7 +461,7 @@ static int clcdfb_register(struct clcd_fb *fb) return ret; } -static int clcdfb_probe(struct amba_device *dev, struct amba_id *id) +static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id) { struct clcd_board *board = dev->dev.platform_data; struct clcd_fb *fb; diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 9127eda2145b..0a0efe713bc8 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -278,7 +278,7 @@ static struct miscdevice sp805_wdt_miscdev = { }; static int __devinit -sp805_wdt_probe(struct amba_device *adev, struct amba_id *id) +sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index a0ccf28e9741..07b6374652dc 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -43,7 +43,7 @@ struct amba_id { struct amba_driver { struct device_driver drv; - int (*probe)(struct amba_device *, struct amba_id *); + int (*probe)(struct amba_device *, const struct amba_id *); int (*remove)(struct amba_device *); void (*shutdown)(struct amba_device *); int (*suspend)(struct amba_device *, pm_message_t); diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 7c1fc64cb53d..d0821f8974a4 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -1011,7 +1011,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) return i; } -static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit aaci_probe(struct amba_device *dev, + const struct amba_id *id) { struct aaci *aaci; int ret, i; -- cgit v1.2.3 From 310388beea4d00bb1c56e81ded82bdc25bdcf719 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 25 Feb 2011 09:53:41 -0800 Subject: tty: forgot to remove ipwireless from drivers/char/pcmcia/Makefile This caused a build error. Many thanks to Stephen Rothwell for pointing this mistake out. Reported-by: Stephen Rothwell Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/Makefile | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile index be8f287aa398..0aae20985d57 100644 --- a/drivers/char/pcmcia/Makefile +++ b/drivers/char/pcmcia/Makefile @@ -4,8 +4,6 @@ # Makefile for the Linux PCMCIA char device drivers. # -obj-y += ipwireless/ - obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o -- cgit v1.2.3 From 000061245a6797d542854106463b6b20fbdcb12e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 22 Feb 2011 19:59:54 -0700 Subject: dt/powerpc: Eliminate users of of_platform_{,un}register_driver Get rid of old users of of_platform_driver in arch/powerpc. Most of_platform_driver users can be converted to use the platform_bus directly. Signed-off-by: Grant Likely --- arch/powerpc/kernel/of_platform.c | 7 +++---- arch/powerpc/platforms/52xx/mpc52xx_gpio.c | 14 ++++++-------- arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 10 +++------- arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c | 11 ++++------- arch/powerpc/platforms/82xx/ep8248e.c | 7 +++---- arch/powerpc/platforms/83xx/suspend.c | 14 +++++++++----- arch/powerpc/platforms/cell/axon_msi.c | 11 ++++------- arch/powerpc/platforms/pasemi/gpio_mdio.c | 9 ++++----- arch/powerpc/sysdev/axonram.c | 11 +++++------ arch/powerpc/sysdev/bestcomm/bestcomm.c | 9 ++++----- arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 9 ++++----- arch/powerpc/sysdev/fsl_msi.c | 13 ++++++++----- arch/powerpc/sysdev/fsl_pmc.c | 7 +++---- arch/powerpc/sysdev/fsl_rio.c | 7 +++---- arch/powerpc/sysdev/pmi.c | 9 ++++----- arch/powerpc/sysdev/qe_lib/qe.c | 7 +++---- drivers/char/hw_random/pasemi-rng.c | 9 ++++----- drivers/crypto/amcc/crypto4xx_core.c | 9 ++++----- drivers/dma/fsldma.c | 14 +++----------- drivers/dma/mpc512x_dma.c | 9 ++++----- drivers/dma/ppc4xx/adma.c | 11 +++++------ drivers/edac/mpc85xx_edac.c | 27 ++++++++++++--------------- drivers/edac/ppc4xx_edac.c | 23 +++++++---------------- drivers/macintosh/smu.c | 7 +++---- drivers/macintosh/therm_pm72.c | 8 ++++---- drivers/macintosh/therm_windtunnel.c | 9 ++++----- 26 files changed, 120 insertions(+), 161 deletions(-) (limited to 'drivers/char') diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 9bd951c67767..24582181b6ec 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -36,8 +36,7 @@ * lacking some bits needed here. */ -static int __devinit of_pci_phb_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit of_pci_phb_probe(struct platform_device *dev) { struct pci_controller *phb; @@ -104,7 +103,7 @@ static struct of_device_id of_pci_phb_ids[] = { {} }; -static struct of_platform_driver of_pci_phb_driver = { +static struct platform_driver of_pci_phb_driver = { .probe = of_pci_phb_probe, .driver = { .name = "of-pci", @@ -115,7 +114,7 @@ static struct of_platform_driver of_pci_phb_driver = { static __init int of_pci_phb_init(void) { - return of_register_platform_driver(&of_pci_phb_driver); + return platform_driver_register(&of_pci_phb_driver); } device_initcall(of_pci_phb_init); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c index 0dad9a935eb5..1757d1db4b51 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c @@ -147,8 +147,7 @@ mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) return 0; } -static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) { struct mpc52xx_gpiochip *chip; struct mpc52xx_gpio_wkup __iomem *regs; @@ -191,7 +190,7 @@ static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { {} }; -static struct of_platform_driver mpc52xx_wkup_gpiochip_driver = { +static struct platform_driver mpc52xx_wkup_gpiochip_driver = { .driver = { .name = "gpio_wkup", .owner = THIS_MODULE, @@ -310,8 +309,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) return 0; } -static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev) { struct mpc52xx_gpiochip *chip; struct gpio_chip *gc; @@ -349,7 +347,7 @@ static const struct of_device_id mpc52xx_simple_gpiochip_match[] = { {} }; -static struct of_platform_driver mpc52xx_simple_gpiochip_driver = { +static struct platform_driver mpc52xx_simple_gpiochip_driver = { .driver = { .name = "gpio", .owner = THIS_MODULE, @@ -361,10 +359,10 @@ static struct of_platform_driver mpc52xx_simple_gpiochip_driver = { static int __init mpc52xx_gpio_init(void) { - if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver)) + if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver)) printk(KERN_ERR "Unable to register wakeup GPIO driver\n"); - if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver)) + if (platform_driver_register(&mpc52xx_simple_gpiochip_driver)) printk(KERN_ERR "Unable to register simple GPIO driver\n"); return 0; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index e0d703c7fdf7..859abf1c6d4b 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -721,8 +721,7 @@ static inline int mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv *gpt, /* --------------------------------------------------------------------- * of_platform bus binding code */ -static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev) { struct mpc52xx_gpt_priv *gpt; @@ -781,7 +780,7 @@ static const struct of_device_id mpc52xx_gpt_match[] = { {} }; -static struct of_platform_driver mpc52xx_gpt_driver = { +static struct platform_driver mpc52xx_gpt_driver = { .driver = { .name = "mpc52xx-gpt", .owner = THIS_MODULE, @@ -793,10 +792,7 @@ static struct of_platform_driver mpc52xx_gpt_driver = { static int __init mpc52xx_gpt_init(void) { - if (of_register_platform_driver(&mpc52xx_gpt_driver)) - pr_err("error registering MPC52xx GPT driver\n"); - - return 0; + return platform_driver_register(&mpc52xx_gpt_driver); } /* Make sure GPIOs and IRQs get set up before anyone tries to use them */ diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c index f4ac213c89c0..6385d883cb8d 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c @@ -436,8 +436,7 @@ void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req) } EXPORT_SYMBOL(mpc52xx_lpbfifo_abort); -static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op) { struct resource res; int rc = -ENOMEM; @@ -536,7 +535,7 @@ static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = { {}, }; -static struct of_platform_driver mpc52xx_lpbfifo_driver = { +static struct platform_driver mpc52xx_lpbfifo_driver = { .driver = { .name = "mpc52xx-lpbfifo", .owner = THIS_MODULE, @@ -551,14 +550,12 @@ static struct of_platform_driver mpc52xx_lpbfifo_driver = { */ static int __init mpc52xx_lpbfifo_init(void) { - pr_debug("Registering LocalPlus bus FIFO driver\n"); - return of_register_platform_driver(&mpc52xx_lpbfifo_driver); + return platform_driver_register(&mpc52xx_lpbfifo_driver); } module_init(mpc52xx_lpbfifo_init); static void __exit mpc52xx_lpbfifo_exit(void) { - pr_debug("Unregistering LocalPlus bus FIFO driver\n"); - of_unregister_platform_driver(&mpc52xx_lpbfifo_driver); + platform_driver_unregister(&mpc52xx_lpbfifo_driver); } module_exit(mpc52xx_lpbfifo_exit); diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index 1565e0446dc8..10ff526cd046 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -111,8 +111,7 @@ static struct mdiobb_ctrl ep8248e_mdio_ctrl = { .ops = &ep8248e_mdio_ops, }; -static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev) { struct mii_bus *bus; struct resource res; @@ -167,7 +166,7 @@ static const struct of_device_id ep8248e_mdio_match[] = { {}, }; -static struct of_platform_driver ep8248e_mdio_driver = { +static struct platform_driver ep8248e_mdio_driver = { .driver = { .name = "ep8248e-mdio-bitbang", .owner = THIS_MODULE, @@ -308,7 +307,7 @@ static __initdata struct of_device_id of_bus_ids[] = { static int __init declare_of_platform_devices(void) { of_platform_bus_probe(NULL, of_bus_ids, NULL); - of_register_platform_driver(&ep8248e_mdio_driver); + platform_driver_register(&ep8248e_mdio_driver); return 0; } diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index fd4f2f2f19e6..188272934cfb 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c @@ -318,14 +318,18 @@ static const struct platform_suspend_ops mpc83xx_suspend_ops = { .end = mpc83xx_suspend_end, }; -static int pmc_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int pmc_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct resource res; - struct pmc_type *type = match->data; + struct pmc_type *type; int ret = 0; + if (!ofdev->dev.of_match) + return -EINVAL; + + type = ofdev->dev.of_match->data; + if (!of_device_is_available(np)) return -ENODEV; @@ -422,7 +426,7 @@ static struct of_device_id pmc_match[] = { {} }; -static struct of_platform_driver pmc_driver = { +static struct platform_driver pmc_driver = { .driver = { .name = "mpc83xx-pmc", .owner = THIS_MODULE, @@ -434,7 +438,7 @@ static struct of_platform_driver pmc_driver = { static int pmc_init(void) { - return of_register_platform_driver(&pmc_driver); + return platform_driver_register(&pmc_driver); } module_init(pmc_init); diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index e3e379c6caa7..c35099af340e 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -328,7 +328,7 @@ static struct irq_host_ops msic_host_ops = { .map = msic_host_map, }; -static int axon_msi_shutdown(struct platform_device *device) +static void axon_msi_shutdown(struct platform_device *device) { struct axon_msic *msic = dev_get_drvdata(&device->dev); u32 tmp; @@ -338,12 +338,9 @@ static int axon_msi_shutdown(struct platform_device *device) tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; msic_dcr_write(msic, MSIC_CTRL_REG, tmp); - - return 0; } -static int axon_msi_probe(struct platform_device *device, - const struct of_device_id *device_id) +static int axon_msi_probe(struct platform_device *device) { struct device_node *dn = device->dev.of_node; struct axon_msic *msic; @@ -446,7 +443,7 @@ static const struct of_device_id axon_msi_device_id[] = { {} }; -static struct of_platform_driver axon_msi_driver = { +static struct platform_driver axon_msi_driver = { .probe = axon_msi_probe, .shutdown = axon_msi_shutdown, .driver = { @@ -458,7 +455,7 @@ static struct of_platform_driver axon_msi_driver = { static int __init axon_msi_init(void) { - return of_register_platform_driver(&axon_msi_driver); + return platform_driver_register(&axon_msi_driver); } subsys_initcall(axon_msi_init); diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index a5d907b5a4c2..9886296e08da 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -216,8 +216,7 @@ static int gpio_mdio_reset(struct mii_bus *bus) } -static int __devinit gpio_mdio_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit gpio_mdio_probe(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; @@ -299,7 +298,7 @@ static struct of_device_id gpio_mdio_match[] = }; MODULE_DEVICE_TABLE(of, gpio_mdio_match); -static struct of_platform_driver gpio_mdio_driver = +static struct platform_driver gpio_mdio_driver = { .probe = gpio_mdio_probe, .remove = gpio_mdio_remove, @@ -326,13 +325,13 @@ int gpio_mdio_init(void) if (!gpio_regs) return -ENODEV; - return of_register_platform_driver(&gpio_mdio_driver); + return platform_driver_register(&gpio_mdio_driver); } module_init(gpio_mdio_init); void gpio_mdio_exit(void) { - of_unregister_platform_driver(&gpio_mdio_driver); + platform_driver_unregister(&gpio_mdio_driver); if (gpio_regs) iounmap(gpio_regs); } diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index 2659a60bd7b8..27402c7d309d 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -172,10 +172,9 @@ static const struct block_device_operations axon_ram_devops = { /** * axon_ram_probe - probe() method for platform driver - * @device, @device_id: see of_platform_driver method + * @device: see platform_driver method */ -static int axon_ram_probe(struct platform_device *device, - const struct of_device_id *device_id) +static int axon_ram_probe(struct platform_device *device) { static int axon_ram_bank_id = -1; struct axon_ram_bank *bank; @@ -326,7 +325,7 @@ static struct of_device_id axon_ram_device_id[] = { {} }; -static struct of_platform_driver axon_ram_driver = { +static struct platform_driver axon_ram_driver = { .probe = axon_ram_probe, .remove = axon_ram_remove, .driver = { @@ -350,7 +349,7 @@ axon_ram_init(void) } azfs_minor = 0; - return of_register_platform_driver(&axon_ram_driver); + return platform_driver_register(&axon_ram_driver); } /** @@ -359,7 +358,7 @@ axon_ram_init(void) static void __exit axon_ram_exit(void) { - of_unregister_platform_driver(&axon_ram_driver); + platform_driver_unregister(&axon_ram_driver); unregister_blkdev(azfs_major, AXON_RAM_DEVICE_NAME); } diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c index 650256115064..b3fbb271be87 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.c +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c @@ -365,8 +365,7 @@ bcom_engine_cleanup(void) /* OF platform driver */ /* ======================================================================== */ -static int __devinit mpc52xx_bcom_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit mpc52xx_bcom_probe(struct platform_device *op) { struct device_node *ofn_sram; struct resource res_bcom; @@ -492,7 +491,7 @@ static struct of_device_id mpc52xx_bcom_of_match[] = { MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match); -static struct of_platform_driver mpc52xx_bcom_of_platform_driver = { +static struct platform_driver mpc52xx_bcom_of_platform_driver = { .probe = mpc52xx_bcom_probe, .remove = mpc52xx_bcom_remove, .driver = { @@ -510,13 +509,13 @@ static struct of_platform_driver mpc52xx_bcom_of_platform_driver = { static int __init mpc52xx_bcom_init(void) { - return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver); + return platform_driver_register(&mpc52xx_bcom_of_platform_driver); } static void __exit mpc52xx_bcom_exit(void) { - of_unregister_platform_driver(&mpc52xx_bcom_of_platform_driver); + platform_driver_unregister(&mpc52xx_bcom_of_platform_driver); } /* If we're not a module, we must make sure everything is setup before */ diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c index cc8d6556d799..2b9f0c925326 100644 --- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c +++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c @@ -71,8 +71,7 @@ static int __init get_offset_from_cmdline(char *str) __setup("cache-sram-size=", get_size_from_cmdline); __setup("cache-sram-offset=", get_offset_from_cmdline); -static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev) { long rval; unsigned int rem; @@ -204,7 +203,7 @@ static struct of_device_id mpc85xx_l2ctlr_of_match[] = { {}, }; -static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = { +static struct platform_driver mpc85xx_l2ctlr_of_platform_driver = { .driver = { .name = "fsl-l2ctlr", .owner = THIS_MODULE, @@ -216,12 +215,12 @@ static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = { static __init int mpc85xx_l2ctlr_of_init(void) { - return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver); + return platform_driver_register(&mpc85xx_l2ctlr_of_platform_driver); } static void __exit mpc85xx_l2ctlr_of_exit(void) { - of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver); + platform_driver_unregister(&mpc85xx_l2ctlr_of_platform_driver); } subsys_initcall(mpc85xx_l2ctlr_of_init); diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 108d76fa8f1c..ee6a8a52ac71 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -273,8 +273,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev) return 0; } -static int __devinit fsl_of_msi_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit fsl_of_msi_probe(struct platform_device *dev) { struct fsl_msi *msi; struct resource res; @@ -282,11 +281,15 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev, int rc; int virt_msir; const u32 *p; - struct fsl_msi_feature *features = match->data; + struct fsl_msi_feature *features; struct fsl_msi_cascade_data *cascade_data = NULL; int len; u32 offset; + if (!dev->dev.of_match) + return -EINVAL; + features = dev->dev.of_match->data; + printk(KERN_DEBUG "Setting up Freescale MSI support\n"); msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); @@ -411,7 +414,7 @@ static const struct of_device_id fsl_of_msi_ids[] = { {} }; -static struct of_platform_driver fsl_of_msi_driver = { +static struct platform_driver fsl_of_msi_driver = { .driver = { .name = "fsl-msi", .owner = THIS_MODULE, @@ -423,7 +426,7 @@ static struct of_platform_driver fsl_of_msi_driver = { static __init int fsl_of_msi_init(void) { - return of_register_platform_driver(&fsl_of_msi_driver); + return platform_driver_register(&fsl_of_msi_driver); } subsys_initcall(fsl_of_msi_init); diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c index e9381bfefb21..f122e8961d32 100644 --- a/arch/powerpc/sysdev/fsl_pmc.c +++ b/arch/powerpc/sysdev/fsl_pmc.c @@ -58,8 +58,7 @@ static const struct platform_suspend_ops pmc_suspend_ops = { .enter = pmc_suspend_enter, }; -static int pmc_probe(struct platform_device *ofdev, - const struct of_device_id *id) +static int pmc_probe(struct platform_device *ofdev) { pmc_regs = of_iomap(ofdev->dev.of_node, 0); if (!pmc_regs) @@ -76,7 +75,7 @@ static const struct of_device_id pmc_ids[] = { { }, }; -static struct of_platform_driver pmc_driver = { +static struct platform_driver pmc_driver = { .driver = { .name = "fsl-pmc", .owner = THIS_MODULE, @@ -87,6 +86,6 @@ static struct of_platform_driver pmc_driver = { static int __init pmc_init(void) { - return of_register_platform_driver(&pmc_driver); + return platform_driver_register(&pmc_driver); } device_initcall(pmc_init); diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 8c6cab013278..3eff2c3a9ad5 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1570,8 +1570,7 @@ err_ops: /* The probe function for RapidIO peer-to-peer network. */ -static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev) { int rc; printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", @@ -1594,7 +1593,7 @@ static const struct of_device_id fsl_of_rio_rpn_ids[] = { {}, }; -static struct of_platform_driver fsl_of_rio_rpn_driver = { +static struct platform_driver fsl_of_rio_rpn_driver = { .driver = { .name = "fsl-of-rio", .owner = THIS_MODULE, @@ -1605,7 +1604,7 @@ static struct of_platform_driver fsl_of_rio_rpn_driver = { static __init int fsl_of_rio_rpn_init(void) { - return of_register_platform_driver(&fsl_of_rio_rpn_driver); + return platform_driver_register(&fsl_of_rio_rpn_driver); } subsys_initcall(fsl_of_rio_rpn_init); diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 4260f368db52..8ce4fc3d9828 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -121,8 +121,7 @@ static void pmi_notify_handlers(struct work_struct *work) spin_unlock(&data->handler_spinlock); } -static int pmi_of_probe(struct platform_device *dev, - const struct of_device_id *match) +static int pmi_of_probe(struct platform_device *dev) { struct device_node *np = dev->dev.of_node; int rc; @@ -205,7 +204,7 @@ static int pmi_of_remove(struct platform_device *dev) return 0; } -static struct of_platform_driver pmi_of_platform_driver = { +static struct platform_driver pmi_of_platform_driver = { .probe = pmi_of_probe, .remove = pmi_of_remove, .driver = { @@ -217,13 +216,13 @@ static struct of_platform_driver pmi_of_platform_driver = { static int __init pmi_module_init(void) { - return of_register_platform_driver(&pmi_of_platform_driver); + return platform_driver_register(&pmi_of_platform_driver); } module_init(pmi_module_init); static void __exit pmi_module_exit(void) { - of_unregister_platform_driver(&pmi_of_platform_driver); + platform_driver_unregister(&pmi_of_platform_driver); } module_exit(pmi_module_exit); diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 90020de4dcf2..904c6cbaf45b 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -659,8 +659,7 @@ static int qe_resume(struct platform_device *ofdev) return 0; } -static int qe_probe(struct platform_device *ofdev, - const struct of_device_id *id) +static int qe_probe(struct platform_device *ofdev) { return 0; } @@ -670,7 +669,7 @@ static const struct of_device_id qe_ids[] = { { }, }; -static struct of_platform_driver qe_driver = { +static struct platform_driver qe_driver = { .driver = { .name = "fsl-qe", .owner = THIS_MODULE, @@ -682,7 +681,7 @@ static struct of_platform_driver qe_driver = { static int __init qe_drv_init(void) { - return of_register_platform_driver(&qe_driver); + return platform_driver_register(&qe_driver); } device_initcall(qe_drv_init); #endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */ diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index a31c830ca8cd..1d504815e6db 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c @@ -94,8 +94,7 @@ static struct hwrng pasemi_rng = { .data_read = pasemi_rng_data_read, }; -static int __devinit rng_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit rng_probe(struct platform_device *ofdev) { void __iomem *rng_regs; struct device_node *rng_np = ofdev->dev.of_node; @@ -139,7 +138,7 @@ static struct of_device_id rng_match[] = { { }, }; -static struct of_platform_driver rng_driver = { +static struct platform_driver rng_driver = { .driver = { .name = "pasemi-rng", .owner = THIS_MODULE, @@ -151,13 +150,13 @@ static struct of_platform_driver rng_driver = { static int __init rng_init(void) { - return of_register_platform_driver(&rng_driver); + return platform_driver_register(&rng_driver); } module_init(rng_init); static void __exit rng_exit(void) { - of_unregister_platform_driver(&rng_driver); + platform_driver_unregister(&rng_driver); } module_exit(rng_exit); diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 2b1baee525bc..18912521a7a5 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1150,8 +1150,7 @@ struct crypto4xx_alg_common crypto4xx_alg[] = { /** * Module Initialization Routine */ -static int __init crypto4xx_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __init crypto4xx_probe(struct platform_device *ofdev) { int rc; struct resource res; @@ -1280,7 +1279,7 @@ static const struct of_device_id crypto4xx_match[] = { { }, }; -static struct of_platform_driver crypto4xx_driver = { +static struct platform_driver crypto4xx_driver = { .driver = { .name = "crypto4xx", .owner = THIS_MODULE, @@ -1292,12 +1291,12 @@ static struct of_platform_driver crypto4xx_driver = { static int __init crypto4xx_init(void) { - return of_register_platform_driver(&crypto4xx_driver); + return platform_driver_register(&crypto4xx_driver); } static void __exit crypto4xx_exit(void) { - of_unregister_platform_driver(&crypto4xx_driver); + platform_driver_unregister(&crypto4xx_driver); } module_init(crypto4xx_init); diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 4de947a450fc..e3854a8f0de0 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1281,8 +1281,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan) kfree(chan); } -static int __devinit fsldma_of_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit fsldma_of_probe(struct platform_device *op) { struct fsldma_device *fdev; struct device_node *child; @@ -1414,20 +1413,13 @@ static struct of_platform_driver fsldma_of_driver = { static __init int fsldma_init(void) { - int ret; - pr_info("Freescale Elo / Elo Plus DMA driver\n"); - - ret = of_register_platform_driver(&fsldma_of_driver); - if (ret) - pr_err("fsldma: failed to register platform driver\n"); - - return ret; + return platform_driver_register(&fsldma_of_driver); } static void __exit fsldma_exit(void) { - of_unregister_platform_driver(&fsldma_of_driver); + platform_driver_unregister(&fsldma_of_driver); } subsys_initcall(fsldma_init); diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 59c270192ccc..4f95d31f5a20 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -649,8 +649,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, return &mdesc->desc; } -static int __devinit mpc_dma_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit mpc_dma_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct device *dev = &op->dev; @@ -827,7 +826,7 @@ static struct of_device_id mpc_dma_match[] = { {}, }; -static struct of_platform_driver mpc_dma_driver = { +static struct platform_driver mpc_dma_driver = { .probe = mpc_dma_probe, .remove = __devexit_p(mpc_dma_remove), .driver = { @@ -839,13 +838,13 @@ static struct of_platform_driver mpc_dma_driver = { static int __init mpc_dma_init(void) { - return of_register_platform_driver(&mpc_dma_driver); + return platform_driver_register(&mpc_dma_driver); } module_init(mpc_dma_init); static void __exit mpc_dma_exit(void) { - of_unregister_platform_driver(&mpc_dma_driver); + platform_driver_unregister(&mpc_dma_driver); } module_exit(mpc_dma_exit); diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index cef584533ee8..3b0247e74cc4 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -4393,8 +4393,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev, /** * ppc440spe_adma_probe - probe the asynch device */ -static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct resource res; @@ -4944,7 +4943,7 @@ static const struct of_device_id ppc440spe_adma_of_match[] __devinitconst = { }; MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match); -static struct of_platform_driver ppc440spe_adma_driver = { +static struct platform_driver ppc440spe_adma_driver = { .probe = ppc440spe_adma_probe, .remove = __devexit_p(ppc440spe_adma_remove), .driver = { @@ -4962,7 +4961,7 @@ static __init int ppc440spe_adma_init(void) if (ret) return ret; - ret = of_register_platform_driver(&ppc440spe_adma_driver); + ret = platform_driver_register(&ppc440spe_adma_driver); if (ret) { pr_err("%s: failed to register platform driver\n", __func__); @@ -4996,7 +4995,7 @@ out_dev: /* User will not be able to enable h/w RAID-6 */ pr_err("%s: failed to create RAID-6 driver interface\n", __func__); - of_unregister_platform_driver(&ppc440spe_adma_driver); + platform_driver_unregister(&ppc440spe_adma_driver); out_reg: dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len); kfree(ppc440spe_dma_fifo_buf); @@ -5011,7 +5010,7 @@ static void __exit ppc440spe_adma_exit(void) &driver_attr_enable); driver_remove_file(&ppc440spe_adma_driver.driver, &driver_attr_devices); - of_unregister_platform_driver(&ppc440spe_adma_driver); + platform_driver_unregister(&ppc440spe_adma_driver); dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len); kfree(ppc440spe_dma_fifo_buf); } diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index b123bb308a4a..ffb5ad080bee 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -200,8 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_pci_err_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) { struct edac_pci_ctl_info *pci; struct mpc85xx_pci_pdata *pdata; @@ -338,7 +337,7 @@ static struct of_device_id mpc85xx_pci_err_of_match[] = { }; MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match); -static struct of_platform_driver mpc85xx_pci_err_driver = { +static struct platform_driver mpc85xx_pci_err_driver = { .probe = mpc85xx_pci_err_probe, .remove = __devexit_p(mpc85xx_pci_err_remove), .driver = { @@ -503,8 +502,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_l2_err_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) { struct edac_device_ctl_info *edac_dev; struct mpc85xx_l2_pdata *pdata; @@ -656,7 +654,7 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = { }; MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match); -static struct of_platform_driver mpc85xx_l2_err_driver = { +static struct platform_driver mpc85xx_l2_err_driver = { .probe = mpc85xx_l2_err_probe, .remove = mpc85xx_l2_err_remove, .driver = { @@ -956,8 +954,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) } } -static int __devinit mpc85xx_mc_err_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) { struct mem_ctl_info *mci; struct mpc85xx_mc_pdata *pdata; @@ -1136,7 +1133,7 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = { }; MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match); -static struct of_platform_driver mpc85xx_mc_err_driver = { +static struct platform_driver mpc85xx_mc_err_driver = { .probe = mpc85xx_mc_err_probe, .remove = mpc85xx_mc_err_remove, .driver = { @@ -1171,16 +1168,16 @@ static int __init mpc85xx_mc_init(void) break; } - res = of_register_platform_driver(&mpc85xx_mc_err_driver); + res = platform_driver_register(&mpc85xx_mc_err_driver); if (res) printk(KERN_WARNING EDAC_MOD_STR "MC fails to register\n"); - res = of_register_platform_driver(&mpc85xx_l2_err_driver); + res = platform_driver_register(&mpc85xx_l2_err_driver); if (res) printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n"); #ifdef CONFIG_PCI - res = of_register_platform_driver(&mpc85xx_pci_err_driver); + res = platform_driver_register(&mpc85xx_pci_err_driver); if (res) printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n"); #endif @@ -1212,10 +1209,10 @@ static void __exit mpc85xx_mc_exit(void) on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0); #endif #ifdef CONFIG_PCI - of_unregister_platform_driver(&mpc85xx_pci_err_driver); + platform_driver_unregister(&mpc85xx_pci_err_driver); #endif - of_unregister_platform_driver(&mpc85xx_l2_err_driver); - of_unregister_platform_driver(&mpc85xx_mc_err_driver); + platform_driver_unregister(&mpc85xx_l2_err_driver); + platform_driver_unregister(&mpc85xx_mc_err_driver); } module_exit(mpc85xx_mc_exit); diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index b9f0c20df1aa..c1f0045ceb8e 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -184,8 +184,7 @@ struct ppc4xx_ecc_status { /* Function Prototypes */ -static int ppc4xx_edac_probe(struct platform_device *device, - const struct of_device_id *device_id); +static int ppc4xx_edac_probe(struct platform_device *device) static int ppc4xx_edac_remove(struct platform_device *device); /* Global Variables */ @@ -201,7 +200,7 @@ static struct of_device_id ppc4xx_edac_match[] = { { } }; -static struct of_platform_driver ppc4xx_edac_driver = { +static struct platform_driver ppc4xx_edac_driver = { .probe = ppc4xx_edac_probe, .remove = ppc4xx_edac_remove, .driver = { @@ -997,9 +996,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) * initialized. * @op: A pointer to the OpenFirmware device tree node associated * with the controller this EDAC instance is bound to. - * @match: A pointer to the OpenFirmware device tree match - * information associated with the controller this EDAC instance - * is bound to. * @dcr_host: A pointer to the DCR data containing the DCR mapping * for this controller instance. * @mcopt1: The 32-bit Memory Controller Option 1 register value @@ -1015,7 +1011,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) static int __devinit ppc4xx_edac_mc_init(struct mem_ctl_info *mci, struct platform_device *op, - const struct of_device_id *match, const dcr_host_t *dcr_host, u32 mcopt1) { @@ -1024,7 +1019,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, struct ppc4xx_edac_pdata *pdata = NULL; const struct device_node *np = op->dev.of_node; - if (match == NULL) + if (op->dev.of_match == NULL) return -EINVAL; /* Initial driver pointers and private data */ @@ -1227,9 +1222,6 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) * ppc4xx_edac_probe - check controller and bind driver * @op: A pointer to the OpenFirmware device tree node associated * with the controller being probed for driver binding. - * @match: A pointer to the OpenFirmware device tree match - * information associated with the controller being probed - * for driver binding. * * This routine probes a specific ibm,sdram-4xx-ddr2 controller * instance for binding with the driver. @@ -1237,8 +1229,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) * Returns 0 if the controller instance was successfully bound to the * driver; otherwise, < 0 on error. */ -static int __devinit -ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit ppc4xx_edac_probe(struct platform_device *op) { int status = 0; u32 mcopt1, memcheck; @@ -1304,7 +1295,7 @@ ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match) goto done; } - status = ppc4xx_edac_mc_init(mci, op, match, &dcr_host, mcopt1); + status = ppc4xx_edac_mc_init(mci, op, &dcr_host, mcopt1); if (status) { ppc4xx_edac_mc_printk(KERN_ERR, mci, @@ -1421,7 +1412,7 @@ ppc4xx_edac_init(void) ppc4xx_edac_opstate_init(); - return of_register_platform_driver(&ppc4xx_edac_driver); + return platform_driver_register(&ppc4xx_edac_driver); } /** @@ -1434,7 +1425,7 @@ ppc4xx_edac_init(void) static void __exit ppc4xx_edac_exit(void) { - of_unregister_platform_driver(&ppc4xx_edac_driver); + platform_driver_unregister(&ppc4xx_edac_driver); } module_init(ppc4xx_edac_init); diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 290cb325a94c..116a49ce74b2 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -645,8 +645,7 @@ static void smu_expose_childs(struct work_struct *unused) static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); -static int smu_platform_probe(struct platform_device* dev, - const struct of_device_id *match) +static int smu_platform_probe(struct platform_device* dev) { if (!smu) return -ENODEV; @@ -669,7 +668,7 @@ static const struct of_device_id smu_platform_match[] = {}, }; -static struct of_platform_driver smu_of_platform_driver = +static struct platform_driver smu_of_platform_driver = { .driver = { .name = "smu", @@ -689,7 +688,7 @@ static int __init smu_init_sysfs(void) * I'm a bit too far from figuring out how that works with those * new chipsets, but that will come back and bite us */ - of_register_platform_driver(&smu_of_platform_driver); + platform_driver_register(&smu_of_platform_driver); return 0; } diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index f3a29f264db9..bca2af2e3760 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -2210,7 +2210,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node) } } -static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) +static int fcu_of_probe(struct platform_device* dev) { state = state_detached; of_dev = dev; @@ -2240,7 +2240,7 @@ static const struct of_device_id fcu_match[] = }; MODULE_DEVICE_TABLE(of, fcu_match); -static struct of_platform_driver fcu_of_platform_driver = +static struct platform_driver fcu_of_platform_driver = { .driver = { .name = "temperature", @@ -2263,12 +2263,12 @@ static int __init therm_pm72_init(void) !rackmac) return -ENODEV; - return of_register_platform_driver(&fcu_of_platform_driver); + return platform_driver_register(&fcu_of_platform_driver); } static void __exit therm_pm72_exit(void) { - of_unregister_platform_driver(&fcu_of_platform_driver); + platform_driver_unregister(&fcu_of_platform_driver); } module_init(therm_pm72_init); diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index c89f396e4c53..d37819fd5ad3 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -443,8 +443,7 @@ static struct i2c_driver g4fan_driver = { /* initialization / cleanup */ /************************************************************************/ -static int -therm_of_probe( struct platform_device *dev, const struct of_device_id *match ) +static int therm_of_probe(struct platform_device *dev) { return i2c_add_driver( &g4fan_driver ); } @@ -462,7 +461,7 @@ static const struct of_device_id therm_of_match[] = {{ }, {} }; -static struct of_platform_driver therm_of_driver = { +static struct platform_driver therm_of_driver = { .driver = { .name = "temperature", .owner = THIS_MODULE, @@ -509,14 +508,14 @@ g4fan_init( void ) return -ENODEV; } - of_register_platform_driver( &therm_of_driver ); + platform_driver_register( &therm_of_driver ); return 0; } static void __exit g4fan_exit( void ) { - of_unregister_platform_driver( &therm_of_driver ); + platform_driver_unregister( &therm_of_driver ); if( x.of_dev ) of_device_unregister( x.of_dev ); -- cgit v1.2.3 From 4ebb24f707187196937607c60810d42f7112d7aa Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 22 Feb 2011 20:01:33 -0700 Subject: dt/sparc: Eliminate users of of_platform_{,un}register_driver Get rid of old users of of_platform_driver in arch/sparc. Most of_platform_driver users can be converted to use the platform_bus directly. Signed-off-by: Grant Likely --- arch/sparc/include/asm/parport.h | 6 +++--- arch/sparc/kernel/apc.c | 7 +++---- arch/sparc/kernel/auxio_64.c | 7 +++---- arch/sparc/kernel/central.c | 14 ++++++-------- arch/sparc/kernel/chmc.c | 19 ++++++++----------- arch/sparc/kernel/pci_fire.c | 7 +++---- arch/sparc/kernel/pci_psycho.c | 7 +++---- arch/sparc/kernel/pci_sabre.c | 9 ++++----- arch/sparc/kernel/pci_schizo.c | 11 ++++++----- arch/sparc/kernel/pci_sun4v.c | 7 +++---- arch/sparc/kernel/pmc.c | 7 +++---- arch/sparc/kernel/power.c | 6 +++--- arch/sparc/kernel/time_32.c | 6 +++--- arch/sparc/kernel/time_64.c | 18 +++++++++--------- drivers/char/hw_random/n2-drv.c | 16 +++++++++------- drivers/crypto/n2_core.c | 20 +++++++++----------- drivers/hwmon/ultra45_env.c | 9 ++++----- drivers/input/misc/sparcspkr.c | 22 ++++++++++------------ drivers/input/serio/i8042-sparcio.h | 8 ++++---- drivers/parport/parport_sunbpp.c | 8 ++++---- drivers/sbus/char/bbc_i2c.c | 9 ++++----- drivers/sbus/char/display7seg.c | 9 ++++----- drivers/sbus/char/envctrl.c | 9 ++++----- drivers/sbus/char/flash.c | 9 ++++----- drivers/sbus/char/uctrl.c | 9 ++++----- drivers/scsi/qlogicpti.c | 14 +++++++++----- drivers/scsi/sun_esp.c | 8 ++++---- 27 files changed, 133 insertions(+), 148 deletions(-) (limited to 'drivers/char') diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index aa4c82648d88..cb33608cc68f 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -103,7 +103,7 @@ static inline unsigned int get_dma_residue(unsigned int dmanr) return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info); } -static int __devinit ecpp_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit ecpp_probe(struct platform_device *op) { unsigned long base = op->resource[0].start; unsigned long config = op->resource[1].start; @@ -235,7 +235,7 @@ static const struct of_device_id ecpp_match[] = { {}, }; -static struct of_platform_driver ecpp_driver = { +static struct platform_driver ecpp_driver = { .driver = { .name = "ecpp", .owner = THIS_MODULE, @@ -247,7 +247,7 @@ static struct of_platform_driver ecpp_driver = { static int parport_pc_find_nonpci_ports(int autoirq, int autodma) { - return of_register_platform_driver(&ecpp_driver); + return platform_driver_register(&ecpp_driver); } #endif /* !(_ASM_SPARC64_PARPORT_H */ diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 52de4a9424e8..f679c57644d5 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -137,8 +137,7 @@ static const struct file_operations apc_fops = { static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; -static int __devinit apc_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit apc_probe(struct platform_device *op) { int err; @@ -174,7 +173,7 @@ static struct of_device_id __initdata apc_match[] = { }; MODULE_DEVICE_TABLE(of, apc_match); -static struct of_platform_driver apc_driver = { +static struct platform_driver apc_driver = { .driver = { .name = "apc", .owner = THIS_MODULE, @@ -185,7 +184,7 @@ static struct of_platform_driver apc_driver = { static int __init apc_init(void) { - return of_register_platform_driver(&apc_driver); + return platform_driver_register(&apc_driver); } /* This driver is not critical to the boot process diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c index 3efd3c5af6a9..2abace076c7d 100644 --- a/arch/sparc/kernel/auxio_64.c +++ b/arch/sparc/kernel/auxio_64.c @@ -102,8 +102,7 @@ static struct of_device_id __initdata auxio_match[] = { MODULE_DEVICE_TABLE(of, auxio_match); -static int __devinit auxio_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit auxio_probe(struct platform_device *dev) { struct device_node *dp = dev->dev.of_node; unsigned long size; @@ -132,7 +131,7 @@ static int __devinit auxio_probe(struct platform_device *dev, return 0; } -static struct of_platform_driver auxio_driver = { +static struct platform_driver auxio_driver = { .probe = auxio_probe, .driver = { .name = "auxio", @@ -143,7 +142,7 @@ static struct of_platform_driver auxio_driver = { static int __init auxio_init(void) { - return of_register_platform_driver(&auxio_driver); + return platform_driver_register(&auxio_driver); } /* Must be after subsys_initcall() so that busses are probed. Must diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c index cfa2624c5332..136d3718a74a 100644 --- a/arch/sparc/kernel/central.c +++ b/arch/sparc/kernel/central.c @@ -59,8 +59,7 @@ static int __devinit clock_board_calc_nslots(struct clock_board *p) } } -static int __devinit clock_board_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit clock_board_probe(struct platform_device *op) { struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); int err = -ENOMEM; @@ -148,7 +147,7 @@ static struct of_device_id __initdata clock_board_match[] = { {}, }; -static struct of_platform_driver clock_board_driver = { +static struct platform_driver clock_board_driver = { .probe = clock_board_probe, .driver = { .name = "clock_board", @@ -157,8 +156,7 @@ static struct of_platform_driver clock_board_driver = { }, }; -static int __devinit fhc_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit fhc_probe(struct platform_device *op) { struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); int err = -ENOMEM; @@ -254,7 +252,7 @@ static struct of_device_id __initdata fhc_match[] = { {}, }; -static struct of_platform_driver fhc_driver = { +static struct platform_driver fhc_driver = { .probe = fhc_probe, .driver = { .name = "fhc", @@ -265,8 +263,8 @@ static struct of_platform_driver fhc_driver = { static int __init sunfire_init(void) { - (void) of_register_platform_driver(&fhc_driver); - (void) of_register_platform_driver(&clock_board_driver); + (void) platform_driver_register(&fhc_driver); + (void) platform_driver_register(&clock_board_driver); return 0; } diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c index 08c466ebb32b..668c7be5d365 100644 --- a/arch/sparc/kernel/chmc.c +++ b/arch/sparc/kernel/chmc.c @@ -392,8 +392,7 @@ static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p, } } -static int __devinit jbusmc_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit jbusmc_probe(struct platform_device *op) { const struct linux_prom64_registers *mem_regs; struct device_node *mem_node; @@ -690,8 +689,7 @@ static void chmc_fetch_decode_regs(struct chmc *p) chmc_read_mcreg(p, CHMCTRL_DECODE4)); } -static int __devinit chmc_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit chmc_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; unsigned long ver; @@ -765,13 +763,12 @@ out_free: goto out; } -static int __devinit us3mc_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit us3mc_probe(struct platform_device *op) { if (mc_type == MC_TYPE_SAFARI) - return chmc_probe(op, match); + return chmc_probe(op); else if (mc_type == MC_TYPE_JBUS) - return jbusmc_probe(op, match); + return jbusmc_probe(op); return -ENODEV; } @@ -810,7 +807,7 @@ static const struct of_device_id us3mc_match[] = { }; MODULE_DEVICE_TABLE(of, us3mc_match); -static struct of_platform_driver us3mc_driver = { +static struct platform_driver us3mc_driver = { .driver = { .name = "us3mc", .owner = THIS_MODULE, @@ -848,7 +845,7 @@ static int __init us3mc_init(void) ret = register_dimm_printer(us3mc_dimm_printer); if (!ret) { - ret = of_register_platform_driver(&us3mc_driver); + ret = platform_driver_register(&us3mc_driver); if (ret) unregister_dimm_printer(us3mc_dimm_printer); } @@ -859,7 +856,7 @@ static void __exit us3mc_cleanup(void) { if (us3mc_platform()) { unregister_dimm_printer(us3mc_dimm_printer); - of_unregister_platform_driver(&us3mc_driver); + platform_driver_unregister(&us3mc_driver); } } diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c index efb896d68754..be5e2441c6d7 100644 --- a/arch/sparc/kernel/pci_fire.c +++ b/arch/sparc/kernel/pci_fire.c @@ -455,8 +455,7 @@ static int __devinit pci_fire_pbm_init(struct pci_pbm_info *pbm, return 0; } -static int __devinit fire_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit fire_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; struct pci_pbm_info *pbm; @@ -507,7 +506,7 @@ static struct of_device_id __initdata fire_match[] = { {}, }; -static struct of_platform_driver fire_driver = { +static struct platform_driver fire_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -518,7 +517,7 @@ static struct of_platform_driver fire_driver = { static int __init fire_init(void) { - return of_register_platform_driver(&fire_driver); + return platform_driver_register(&fire_driver); } subsys_initcall(fire_init); diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index 22eab7cf3b11..56ee745064de 100644 --- a/arch/sparc/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c @@ -503,8 +503,7 @@ static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid) #define PSYCHO_CONFIGSPACE 0x001000000UL -static int __devinit psycho_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit psycho_probe(struct platform_device *op) { const struct linux_prom64_registers *pr_regs; struct device_node *dp = op->dev.of_node; @@ -601,7 +600,7 @@ static struct of_device_id __initdata psycho_match[] = { {}, }; -static struct of_platform_driver psycho_driver = { +static struct platform_driver psycho_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -612,7 +611,7 @@ static struct of_platform_driver psycho_driver = { static int __init psycho_init(void) { - return of_register_platform_driver(&psycho_driver); + return platform_driver_register(&psycho_driver); } subsys_initcall(psycho_init); diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 5c3f5ec4cabc..2857073342d2 100644 --- a/arch/sparc/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c @@ -452,8 +452,7 @@ static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm, sabre_scan_bus(pbm, &op->dev); } -static int __devinit sabre_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit sabre_probe(struct platform_device *op) { const struct linux_prom64_registers *pr_regs; struct device_node *dp = op->dev.of_node; @@ -464,7 +463,7 @@ static int __devinit sabre_probe(struct platform_device *op, const u32 *vdma; u64 clear_irq; - hummingbird_p = (match->data != NULL); + hummingbird_p = op->dev.of_match && (op->dev.of_match->data != NULL); if (!hummingbird_p) { struct device_node *cpu_dp; @@ -595,7 +594,7 @@ static struct of_device_id __initdata sabre_match[] = { {}, }; -static struct of_platform_driver sabre_driver = { +static struct platform_driver sabre_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -606,7 +605,7 @@ static struct of_platform_driver sabre_driver = { static int __init sabre_init(void) { - return of_register_platform_driver(&sabre_driver); + return platform_driver_register(&sabre_driver); } subsys_initcall(sabre_init); diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 445a47a2fb3d..6783410ceb02 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c @@ -1460,10 +1460,11 @@ out_err: return err; } -static int __devinit schizo_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit schizo_probe(struct platform_device *op) { - return __schizo_init(op, (unsigned long) match->data); + if (!op->dev.of_match) + return -EINVAL; + return __schizo_init(op, (unsigned long) op->dev.of_match->data); } /* The ordering of this table is very important. Some Tomatillo @@ -1490,7 +1491,7 @@ static struct of_device_id __initdata schizo_match[] = { {}, }; -static struct of_platform_driver schizo_driver = { +static struct platform_driver schizo_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -1501,7 +1502,7 @@ static struct of_platform_driver schizo_driver = { static int __init schizo_init(void) { - return of_register_platform_driver(&schizo_driver); + return platform_driver_register(&schizo_driver); } subsys_initcall(schizo_init); diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index 743344aa6d8a..158cd739b263 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c @@ -918,8 +918,7 @@ static int __devinit pci_sun4v_pbm_init(struct pci_pbm_info *pbm, return 0; } -static int __devinit pci_sun4v_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit pci_sun4v_probe(struct platform_device *op) { const struct linux_prom64_registers *regs; static int hvapi_negotiated = 0; @@ -1008,7 +1007,7 @@ static struct of_device_id __initdata pci_sun4v_match[] = { {}, }; -static struct of_platform_driver pci_sun4v_driver = { +static struct platform_driver pci_sun4v_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -1019,7 +1018,7 @@ static struct of_platform_driver pci_sun4v_driver = { static int __init pci_sun4v_init(void) { - return of_register_platform_driver(&pci_sun4v_driver); + return platform_driver_register(&pci_sun4v_driver); } subsys_initcall(pci_sun4v_init); diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 94536a85f161..93d7b4465f8d 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -51,8 +51,7 @@ static void pmc_swift_idle(void) #endif } -static int __devinit pmc_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit pmc_probe(struct platform_device *op) { regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), PMC_OBPNAME); @@ -78,7 +77,7 @@ static struct of_device_id __initdata pmc_match[] = { }; MODULE_DEVICE_TABLE(of, pmc_match); -static struct of_platform_driver pmc_driver = { +static struct platform_driver pmc_driver = { .driver = { .name = "pmc", .owner = THIS_MODULE, @@ -89,7 +88,7 @@ static struct of_platform_driver pmc_driver = { static int __init pmc_init(void) { - return of_register_platform_driver(&pmc_driver); + return platform_driver_register(&pmc_driver); } /* This driver is not critical to the boot process diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c index 2c59f4d387dd..cd725fe238b2 100644 --- a/arch/sparc/kernel/power.c +++ b/arch/sparc/kernel/power.c @@ -33,7 +33,7 @@ static int __devinit has_button_interrupt(unsigned int irq, struct device_node * return 1; } -static int __devinit power_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit power_probe(struct platform_device *op) { struct resource *res = &op->resource[0]; unsigned int irq = op->archdata.irqs[0]; @@ -59,7 +59,7 @@ static struct of_device_id __initdata power_match[] = { {}, }; -static struct of_platform_driver power_driver = { +static struct platform_driver power_driver = { .probe = power_probe, .driver = { .name = "power", @@ -70,7 +70,7 @@ static struct of_platform_driver power_driver = { static int __init power_init(void) { - return of_register_platform_driver(&power_driver); + return platform_driver_register(&power_driver); } device_initcall(power_init); diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 9c743b1886ff..23ccd737fc79 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -142,7 +142,7 @@ static struct platform_device m48t59_rtc = { }, }; -static int __devinit clock_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit clock_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; const char *model = of_get_property(dp, "model", NULL); @@ -176,7 +176,7 @@ static struct of_device_id __initdata clock_match[] = { {}, }; -static struct of_platform_driver clock_driver = { +static struct platform_driver clock_driver = { .probe = clock_probe, .driver = { .name = "rtc", @@ -189,7 +189,7 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ static int __init clock_init(void) { - return of_register_platform_driver(&clock_driver); + return platform_driver_register(&clock_driver); } /* Must be after subsys_initcall() so that busses are probed. Must * be before device_initcall() because things like the RTC driver diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 3bc9c9979b92..e1862793a61d 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -419,7 +419,7 @@ static struct platform_device rtc_cmos_device = { .num_resources = 1, }; -static int __devinit rtc_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit rtc_probe(struct platform_device *op) { struct resource *r; @@ -462,7 +462,7 @@ static struct of_device_id __initdata rtc_match[] = { {}, }; -static struct of_platform_driver rtc_driver = { +static struct platform_driver rtc_driver = { .probe = rtc_probe, .driver = { .name = "rtc", @@ -477,7 +477,7 @@ static struct platform_device rtc_bq4802_device = { .num_resources = 1, }; -static int __devinit bq4802_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit bq4802_probe(struct platform_device *op) { printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n", @@ -495,7 +495,7 @@ static struct of_device_id __initdata bq4802_match[] = { {}, }; -static struct of_platform_driver bq4802_driver = { +static struct platform_driver bq4802_driver = { .probe = bq4802_probe, .driver = { .name = "bq4802", @@ -534,7 +534,7 @@ static struct platform_device m48t59_rtc = { }, }; -static int __devinit mostek_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit mostek_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; @@ -559,7 +559,7 @@ static struct of_device_id __initdata mostek_match[] = { {}, }; -static struct of_platform_driver mostek_driver = { +static struct platform_driver mostek_driver = { .probe = mostek_probe, .driver = { .name = "mostek", @@ -586,9 +586,9 @@ static int __init clock_init(void) if (tlb_type == hypervisor) return platform_device_register(&rtc_sun4v_device); - (void) of_register_platform_driver(&rtc_driver); - (void) of_register_platform_driver(&mostek_driver); - (void) of_register_platform_driver(&bq4802_driver); + (void) platform_driver_register(&rtc_driver); + (void) platform_driver_register(&mostek_driver); + (void) platform_driver_register(&bq4802_driver); return 0; } diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index a3f5e381e746..43ac61978d8b 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -619,15 +619,17 @@ static void __devinit n2rng_driver_version(void) pr_info("%s", version); } -static int __devinit n2rng_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit n2rng_probe(struct platform_device *op) { - int victoria_falls = (match->data != NULL); + int victoria_falls; int err = -ENOMEM; struct n2rng *np; - n2rng_driver_version(); + if (!op->dev.of_match) + return -EINVAL; + victoria_falls = (op->dev.of_match->data != NULL); + n2rng_driver_version(); np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) goto out; @@ -750,7 +752,7 @@ static const struct of_device_id n2rng_match[] = { }; MODULE_DEVICE_TABLE(of, n2rng_match); -static struct of_platform_driver n2rng_driver = { +static struct platform_driver n2rng_driver = { .driver = { .name = "n2rng", .owner = THIS_MODULE, @@ -762,12 +764,12 @@ static struct of_platform_driver n2rng_driver = { static int __init n2rng_init(void) { - return of_register_platform_driver(&n2rng_driver); + return platform_driver_register(&n2rng_driver); } static void __exit n2rng_exit(void) { - of_unregister_platform_driver(&n2rng_driver); + platform_driver_unregister(&n2rng_driver); } module_init(n2rng_init); diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 80dc094e78c6..2e5b2044c96f 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -2004,8 +2004,7 @@ static void __devinit n2_spu_driver_version(void) pr_info("%s", version); } -static int __devinit n2_crypto_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit n2_crypto_probe(struct platform_device *dev) { struct mdesc_handle *mdesc; const char *full_name; @@ -2116,8 +2115,7 @@ static void free_ncp(struct n2_mau *mp) kfree(mp); } -static int __devinit n2_mau_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit n2_mau_probe(struct platform_device *dev) { struct mdesc_handle *mdesc; const char *full_name; @@ -2211,7 +2209,7 @@ static struct of_device_id n2_crypto_match[] = { MODULE_DEVICE_TABLE(of, n2_crypto_match); -static struct of_platform_driver n2_crypto_driver = { +static struct platform_driver n2_crypto_driver = { .driver = { .name = "n2cp", .owner = THIS_MODULE, @@ -2235,7 +2233,7 @@ static struct of_device_id n2_mau_match[] = { MODULE_DEVICE_TABLE(of, n2_mau_match); -static struct of_platform_driver n2_mau_driver = { +static struct platform_driver n2_mau_driver = { .driver = { .name = "ncp", .owner = THIS_MODULE, @@ -2247,20 +2245,20 @@ static struct of_platform_driver n2_mau_driver = { static int __init n2_init(void) { - int err = of_register_platform_driver(&n2_crypto_driver); + int err = platform_driver_register(&n2_crypto_driver); if (!err) { - err = of_register_platform_driver(&n2_mau_driver); + err = platform_driver_register(&n2_mau_driver); if (err) - of_unregister_platform_driver(&n2_crypto_driver); + platform_driver_unregister(&n2_crypto_driver); } return err; } static void __exit n2_exit(void) { - of_unregister_platform_driver(&n2_mau_driver); - of_unregister_platform_driver(&n2_crypto_driver); + platform_driver_unregister(&n2_mau_driver); + platform_driver_unregister(&n2_crypto_driver); } module_init(n2_init); diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index d863e13a50b8..1f36c635d933 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -234,8 +234,7 @@ static const struct attribute_group env_group = { .attrs = env_attributes, }; -static int __devinit env_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit env_probe(struct platform_device *op) { struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); int err = -ENOMEM; @@ -299,7 +298,7 @@ static const struct of_device_id env_match[] = { }; MODULE_DEVICE_TABLE(of, env_match); -static struct of_platform_driver env_driver = { +static struct platform_driver env_driver = { .driver = { .name = "ultra45_env", .owner = THIS_MODULE, @@ -311,12 +310,12 @@ static struct of_platform_driver env_driver = { static int __init env_init(void) { - return of_register_platform_driver(&env_driver); + return platform_driver_register(&env_driver); } static void __exit env_exit(void) { - of_unregister_platform_driver(&env_driver); + platform_driver_unregister(&env_driver); } module_init(env_init); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 8e130bf7d32b..0122f5351577 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -173,18 +173,16 @@ static int __devinit sparcspkr_probe(struct device *dev) return 0; } -static int sparcspkr_shutdown(struct platform_device *dev) +static void sparcspkr_shutdown(struct platform_device *dev) { struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); struct input_dev *input_dev = state->input_dev; /* turn off the speaker */ state->event(input_dev, EV_SND, SND_BELL, 0); - - return 0; } -static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit bbc_beep_probe(struct platform_device *op) { struct sparcspkr_state *state; struct bbc_beep_info *info; @@ -258,7 +256,7 @@ static const struct of_device_id bbc_beep_match[] = { {}, }; -static struct of_platform_driver bbc_beep_driver = { +static struct platform_driver bbc_beep_driver = { .driver = { .name = "bbcbeep", .owner = THIS_MODULE, @@ -269,7 +267,7 @@ static struct of_platform_driver bbc_beep_driver = { .shutdown = sparcspkr_shutdown, }; -static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit grover_beep_probe(struct platform_device *op) { struct sparcspkr_state *state; struct grover_beep_info *info; @@ -340,7 +338,7 @@ static const struct of_device_id grover_beep_match[] = { {}, }; -static struct of_platform_driver grover_beep_driver = { +static struct platform_driver grover_beep_driver = { .driver = { .name = "groverbeep", .owner = THIS_MODULE, @@ -353,12 +351,12 @@ static struct of_platform_driver grover_beep_driver = { static int __init sparcspkr_init(void) { - int err = of_register_platform_driver(&bbc_beep_driver); + int err = platform_driver_register(&bbc_beep_driver); if (!err) { - err = of_register_platform_driver(&grover_beep_driver); + err = platform_driver_register(&grover_beep_driver); if (err) - of_unregister_platform_driver(&bbc_beep_driver); + platform_driver_unregister(&bbc_beep_driver); } return err; @@ -366,8 +364,8 @@ static int __init sparcspkr_init(void) static void __exit sparcspkr_exit(void) { - of_unregister_platform_driver(&bbc_beep_driver); - of_unregister_platform_driver(&grover_beep_driver); + platform_driver_unregister(&bbc_beep_driver); + platform_driver_unregister(&grover_beep_driver); } module_init(sparcspkr_init); diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index c5cc4508d6df..395a9af3adcd 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) #define OBP_PS2MS_NAME1 "kdmouse" #define OBP_PS2MS_NAME2 "mouse" -static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit sparc_i8042_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; @@ -95,7 +95,7 @@ static const struct of_device_id sparc_i8042_match[] = { }; MODULE_DEVICE_TABLE(of, sparc_i8042_match); -static struct of_platform_driver sparc_i8042_driver = { +static struct platform_driver sparc_i8042_driver = { .driver = { .name = "i8042", .owner = THIS_MODULE, @@ -116,7 +116,7 @@ static int __init i8042_platform_init(void) if (!kbd_iobase) return -ENODEV; } else { - int err = of_register_platform_driver(&sparc_i8042_driver); + int err = platform_driver_register(&sparc_i8042_driver); if (err) return err; @@ -140,7 +140,7 @@ static inline void i8042_platform_exit(void) struct device_node *root = of_find_node_by_path("/"); if (strcmp(root->name, "SUNW,JavaStation-1")) - of_unregister_platform_driver(&sparc_i8042_driver); + platform_driver_unregister(&sparc_i8042_driver); } #else /* !CONFIG_PCI */ diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 55ba118f1cf1..910c5a26e347 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -286,7 +286,7 @@ static struct parport_operations parport_sunbpp_ops = .owner = THIS_MODULE, }; -static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit bpp_probe(struct platform_device *op) { struct parport_operations *ops; struct bpp_regs __iomem *regs; @@ -381,7 +381,7 @@ static const struct of_device_id bpp_match[] = { MODULE_DEVICE_TABLE(of, bpp_match); -static struct of_platform_driver bpp_sbus_driver = { +static struct platform_driver bpp_sbus_driver = { .driver = { .name = "bpp", .owner = THIS_MODULE, @@ -393,12 +393,12 @@ static struct of_platform_driver bpp_sbus_driver = { static int __init parport_sunbpp_init(void) { - return of_register_platform_driver(&bpp_sbus_driver); + return platform_driver_register(&bpp_sbus_driver); } static void __exit parport_sunbpp_exit(void) { - of_unregister_platform_driver(&bpp_sbus_driver); + platform_driver_unregister(&bpp_sbus_driver); } MODULE_AUTHOR("Derrick J Brashear"); diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 614a5e114a19..5f94d22c491e 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -361,8 +361,7 @@ fail: extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); -static int __devinit bbc_i2c_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit bbc_i2c_probe(struct platform_device *op) { struct bbc_i2c_bus *bp; int err, index = 0; @@ -413,7 +412,7 @@ static const struct of_device_id bbc_i2c_match[] = { }; MODULE_DEVICE_TABLE(of, bbc_i2c_match); -static struct of_platform_driver bbc_i2c_driver = { +static struct platform_driver bbc_i2c_driver = { .driver = { .name = "bbc_i2c", .owner = THIS_MODULE, @@ -425,12 +424,12 @@ static struct of_platform_driver bbc_i2c_driver = { static int __init bbc_i2c_init(void) { - return of_register_platform_driver(&bbc_i2c_driver); + return platform_driver_register(&bbc_i2c_driver); } static void __exit bbc_i2c_exit(void) { - of_unregister_platform_driver(&bbc_i2c_driver); + platform_driver_unregister(&bbc_i2c_driver); } module_init(bbc_i2c_init); diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 55f71ea9c418..740da4465447 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -171,8 +171,7 @@ static struct miscdevice d7s_miscdev = { .fops = &d7s_fops }; -static int __devinit d7s_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit d7s_probe(struct platform_device *op) { struct device_node *opts; int err = -EINVAL; @@ -266,7 +265,7 @@ static const struct of_device_id d7s_match[] = { }; MODULE_DEVICE_TABLE(of, d7s_match); -static struct of_platform_driver d7s_driver = { +static struct platform_driver d7s_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -278,12 +277,12 @@ static struct of_platform_driver d7s_driver = { static int __init d7s_init(void) { - return of_register_platform_driver(&d7s_driver); + return platform_driver_register(&d7s_driver); } static void __exit d7s_exit(void) { - of_unregister_platform_driver(&d7s_driver); + platform_driver_unregister(&d7s_driver); } module_init(d7s_init); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 8ce414e39489..be7b4e56154f 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1028,8 +1028,7 @@ static int kenvctrld(void *__unused) return 0; } -static int __devinit envctrl_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit envctrl_probe(struct platform_device *op) { struct device_node *dp; int index, err; @@ -1129,7 +1128,7 @@ static const struct of_device_id envctrl_match[] = { }; MODULE_DEVICE_TABLE(of, envctrl_match); -static struct of_platform_driver envctrl_driver = { +static struct platform_driver envctrl_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -1141,12 +1140,12 @@ static struct of_platform_driver envctrl_driver = { static int __init envctrl_init(void) { - return of_register_platform_driver(&envctrl_driver); + return platform_driver_register(&envctrl_driver); } static void __exit envctrl_exit(void) { - of_unregister_platform_driver(&envctrl_driver); + platform_driver_unregister(&envctrl_driver); } module_init(envctrl_init); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 2b4b4b613c48..73dd4e7afaaa 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -160,8 +160,7 @@ static const struct file_operations flash_fops = { static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; -static int __devinit flash_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit flash_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; struct device_node *parent; @@ -207,7 +206,7 @@ static const struct of_device_id flash_match[] = { }; MODULE_DEVICE_TABLE(of, flash_match); -static struct of_platform_driver flash_driver = { +static struct platform_driver flash_driver = { .driver = { .name = "flash", .owner = THIS_MODULE, @@ -219,12 +218,12 @@ static struct of_platform_driver flash_driver = { static int __init flash_init(void) { - return of_register_platform_driver(&flash_driver); + return platform_driver_register(&flash_driver); } static void __exit flash_cleanup(void) { - of_unregister_platform_driver(&flash_driver); + platform_driver_unregister(&flash_driver); } module_init(flash_init); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 1b345be5cc02..ebce9639a26a 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -348,8 +348,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver) } -static int __devinit uctrl_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit uctrl_probe(struct platform_device *op) { struct uctrl_driver *p; int err = -ENOMEM; @@ -425,7 +424,7 @@ static const struct of_device_id uctrl_match[] = { }; MODULE_DEVICE_TABLE(of, uctrl_match); -static struct of_platform_driver uctrl_driver = { +static struct platform_driver uctrl_driver = { .driver = { .name = "uctrl", .owner = THIS_MODULE, @@ -438,12 +437,12 @@ static struct of_platform_driver uctrl_driver = { static int __init uctrl_init(void) { - return of_register_platform_driver(&uctrl_driver); + return platform_driver_register(&uctrl_driver); } static void __exit uctrl_exit(void) { - of_unregister_platform_driver(&uctrl_driver); + platform_driver_unregister(&uctrl_driver); } module_init(uctrl_init); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 664c9572d0c9..e2d45c91b8e8 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1292,15 +1292,19 @@ static struct scsi_host_template qpti_template = { .use_clustering = ENABLE_CLUSTERING, }; -static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit qpti_sbus_probe(struct platform_device *op) { - struct scsi_host_template *tpnt = match->data; + struct scsi_host_template *tpnt; struct device_node *dp = op->dev.of_node; struct Scsi_Host *host; struct qlogicpti *qpti; static int nqptis; const char *fcode; + if (!op->dev.of_match) + return -EINVAL; + tpnt = op->dev.of_match->data; + /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. */ @@ -1457,7 +1461,7 @@ static const struct of_device_id qpti_match[] = { }; MODULE_DEVICE_TABLE(of, qpti_match); -static struct of_platform_driver qpti_sbus_driver = { +static struct platform_driver qpti_sbus_driver = { .driver = { .name = "qpti", .owner = THIS_MODULE, @@ -1469,12 +1473,12 @@ static struct of_platform_driver qpti_sbus_driver = { static int __init qpti_init(void) { - return of_register_platform_driver(&qpti_sbus_driver); + return platform_driver_register(&qpti_sbus_driver); } static void __exit qpti_exit(void) { - of_unregister_platform_driver(&qpti_sbus_driver); + platform_driver_unregister(&qpti_sbus_driver); } MODULE_DESCRIPTION("QlogicISP SBUS driver"); diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 193b37ba1834..676fe9ac7f61 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -562,7 +562,7 @@ fail: return err; } -static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit esp_sbus_probe(struct platform_device *op) { struct device_node *dma_node = NULL; struct device_node *dp = op->dev.of_node; @@ -632,7 +632,7 @@ static const struct of_device_id esp_match[] = { }; MODULE_DEVICE_TABLE(of, esp_match); -static struct of_platform_driver esp_sbus_driver = { +static struct platform_driver esp_sbus_driver = { .driver = { .name = "esp", .owner = THIS_MODULE, @@ -644,12 +644,12 @@ static struct of_platform_driver esp_sbus_driver = { static int __init sunesp_init(void) { - return of_register_platform_driver(&esp_sbus_driver); + return platform_driver_register(&esp_sbus_driver); } static void __exit sunesp_exit(void) { - of_unregister_platform_driver(&esp_sbus_driver); + platform_driver_unregister(&esp_sbus_driver); } MODULE_DESCRIPTION("Sun ESP SCSI driver"); -- cgit v1.2.3 From a1e9c9dd3383e6a1a762464ad604b1081774dbda Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 23 Feb 2011 15:37:59 -0600 Subject: ipmi: convert OF driver to platform driver of_bus is deprecated in favor of the plain platform bus. This patch merges the ipmi OF driver with the existing platform driver. CONFIG_PPC_OF occurrances are removed or replaced with CONFIG_OF. Compile tested with and without CONFIG_OF. Tested OF probe and default probe cases. Signed-off-by: Rob Herring Signed-off-by: Grant Likely --- drivers/char/ipmi/ipmi_si_intf.c | 70 +++++++++++++--------------------------- 1 file changed, 23 insertions(+), 47 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 7855f9f45b8e..dcfc39ca753e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -66,13 +66,10 @@ #include #include #include - -#ifdef CONFIG_PPC_OF #include #include #include #include -#endif #define PFX "ipmi_si: " @@ -116,13 +113,7 @@ static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", #define DEVICE_NAME "ipmi_si" -static struct platform_driver ipmi_driver = { - .driver = { - .name = DEVICE_NAME, - .bus = &platform_bus_type - } -}; - +static struct platform_driver ipmi_driver; /* * Indexes into stats[] in smi_info below. @@ -308,9 +299,6 @@ static int pci_registered; #ifdef CONFIG_ACPI static int pnp_registered; #endif -#ifdef CONFIG_PPC_OF -static int of_registered; -#endif static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; static int num_max_busy_us; @@ -1860,8 +1848,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) return rv; } -static void __devinit hardcode_find_bmc(void) +static int __devinit hardcode_find_bmc(void) { + int ret = -ENODEV; int i; struct smi_info *info; @@ -1871,7 +1860,7 @@ static void __devinit hardcode_find_bmc(void) info = smi_info_alloc(); if (!info) - return; + return -ENOMEM; info->addr_source = SI_HARDCODED; printk(KERN_INFO PFX "probing via hardcoded address\n"); @@ -1924,10 +1913,12 @@ static void __devinit hardcode_find_bmc(void) if (!add_smi(info)) { if (try_smi_init(info)) cleanup_one_si(info); + ret = 0; } else { kfree(info); } } + return ret; } #ifdef CONFIG_ACPI @@ -2555,11 +2546,9 @@ static struct pci_driver ipmi_pci_driver = { }; #endif /* CONFIG_PCI */ - -#ifdef CONFIG_PPC_OF -static int __devinit ipmi_of_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit ipmi_probe(struct platform_device *dev) { +#ifdef CONFIG_OF struct smi_info *info; struct resource resource; const __be32 *regsize, *regspacing, *regshift; @@ -2569,6 +2558,9 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, dev_info(&dev->dev, "probing via device tree\n"); + if (!dev->dev.of_match) + return -EINVAL; + ret = of_address_to_resource(np, 0, &resource); if (ret) { dev_warn(&dev->dev, PFX "invalid address from OF\n"); @@ -2601,7 +2593,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, return -ENOMEM; } - info->si_type = (enum si_type) match->data; + info->si_type = (enum si_type) dev->dev.of_match->data; info->addr_source = SI_DEVICETREE; info->irq_setup = std_irq_setup; @@ -2632,13 +2624,15 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, kfree(info); return -EBUSY; } - +#endif return 0; } -static int __devexit ipmi_of_remove(struct platform_device *dev) +static int __devexit ipmi_remove(struct platform_device *dev) { +#ifdef CONFIG_OF cleanup_one_si(dev_get_drvdata(&dev->dev)); +#endif return 0; } @@ -2653,16 +2647,15 @@ static struct of_device_id ipmi_match[] = {}, }; -static struct of_platform_driver ipmi_of_platform_driver = { +static struct platform_driver ipmi_driver = { .driver = { - .name = "ipmi", + .name = DEVICE_NAME, .owner = THIS_MODULE, .of_match_table = ipmi_match, }, - .probe = ipmi_of_probe, - .remove = __devexit_p(ipmi_of_remove), + .probe = ipmi_probe, + .remove = __devexit_p(ipmi_remove), }; -#endif /* CONFIG_PPC_OF */ static int wait_for_msg_done(struct smi_info *smi_info) { @@ -3340,8 +3333,7 @@ static int __devinit init_ipmi_si(void) return 0; initialized = 1; - /* Register the device drivers. */ - rv = driver_register(&ipmi_driver.driver); + rv = platform_driver_register(&ipmi_driver); if (rv) { printk(KERN_ERR PFX "Unable to register driver: %d\n", rv); return rv; @@ -3365,15 +3357,9 @@ static int __devinit init_ipmi_si(void) printk(KERN_INFO "IPMI System Interface driver.\n"); - hardcode_find_bmc(); - /* If the user gave us a device, they presumably want us to use it */ - mutex_lock(&smi_infos_lock); - if (!list_empty(&smi_infos)) { - mutex_unlock(&smi_infos_lock); + if (!hardcode_find_bmc()) return 0; - } - mutex_unlock(&smi_infos_lock); #ifdef CONFIG_PCI rv = pci_register_driver(&ipmi_pci_driver); @@ -3396,11 +3382,6 @@ static int __devinit init_ipmi_si(void) spmi_find_bmc(); #endif -#ifdef CONFIG_PPC_OF - of_register_platform_driver(&ipmi_of_platform_driver); - of_registered = 1; -#endif - /* We prefer devices with interrupts, but in the case of a machine with multiple BMCs we assume that there will be several instances of a given type so if we succeed in registering a type then also @@ -3548,17 +3529,12 @@ static void __exit cleanup_ipmi_si(void) pnp_unregister_driver(&ipmi_pnp_driver); #endif -#ifdef CONFIG_PPC_OF - if (of_registered) - of_unregister_platform_driver(&ipmi_of_platform_driver); -#endif + platform_driver_unregister(&ipmi_driver); mutex_lock(&smi_infos_lock); list_for_each_entry_safe(e, tmp_e, &smi_infos, link) cleanup_one_si(e); mutex_unlock(&smi_infos_lock); - - driver_unregister(&ipmi_driver.driver); } module_exit(cleanup_ipmi_si); -- cgit v1.2.3 From 55f19d56742a7b544e80b47339c17bfcfd0ff3b4 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 22 Feb 2011 20:13:26 -0700 Subject: dt: xilinx_hwicap: merge platform and of_platform driver bindings of_platform_driver is getting removed, and a single platform_driver can now support both devicetree and non-devicetree use cases. This patch merges the two driver registrations. Signed-off-by: Grant Likely Acked-by: Stephen Neuendorffer --- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 129 +++++++++++------------------ 1 file changed, 47 insertions(+), 82 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 9f2272e6de1c..d3c9d755ed98 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -714,20 +714,29 @@ static int __devexit hwicap_remove(struct device *dev) return 0; /* success */ } -static int __devinit hwicap_drv_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static int __devinit hwicap_of_probe(struct platform_device *op) { - struct resource *res; - const struct config_registers *regs; + struct resource res; + const unsigned int *id; const char *family; + int rc; + const struct hwicap_driver_config *config = op->dev.of_match->data; + const struct config_registers *regs; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; + + rc = of_address_to_resource(op->dev.of_node, 0, &res); + if (rc) { + dev_err(&op->dev, "invalid address\n"); + return rc; + } + + id = of_get_property(op->dev.of_node, "port-number", NULL); /* It's most likely that we're using V4, if the family is not specified */ regs = &v4_config_registers; - family = pdev->dev.platform_data; + family = of_get_property(op->dev.of_node, "xlnx,family", NULL); if (family) { if (!strcmp(family, "virtex2p")) { @@ -738,54 +747,33 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev) regs = &v5_config_registers; } } - - return hwicap_setup(&pdev->dev, pdev->id, res, - &buffer_icap_config, regs); + return hwicap_setup(&op->dev, id ? *id : -1, &res, config, + regs); } - -static int __devexit hwicap_drv_remove(struct platform_device *pdev) +#else +static inline int hwicap_of_probe(struct platform_device *op) { - return hwicap_remove(&pdev->dev); + return -EINVAL; } +#endif /* CONFIG_OF */ -static struct platform_driver hwicap_platform_driver = { - .probe = hwicap_drv_probe, - .remove = hwicap_drv_remove, - .driver = { - .owner = THIS_MODULE, - .name = DRIVER_NAME, - }, -}; - -/* --------------------------------------------------------------------- - * OF bus binding - */ - -#if defined(CONFIG_OF) -static int __devinit -hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) +static int __devinit hwicap_drv_probe(struct platform_device *pdev) { - struct resource res; - const unsigned int *id; - const char *family; - int rc; - const struct hwicap_driver_config *config = match->data; + struct resource *res; const struct config_registers *regs; + const char *family; - dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match); - - rc = of_address_to_resource(op->dev.of_node, 0, &res); - if (rc) { - dev_err(&op->dev, "invalid address\n"); - return rc; - } + if (pdev->dev.of_match) + return hwicap_of_probe(pdev); - id = of_get_property(op->dev.of_node, "port-number", NULL); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; /* It's most likely that we're using V4, if the family is not specified */ regs = &v4_config_registers; - family = of_get_property(op->dev.of_node, "xlnx,family", NULL); + family = pdev->dev.platform_data; if (family) { if (!strcmp(family, "virtex2p")) { @@ -796,50 +784,38 @@ hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) regs = &v5_config_registers; } } - return hwicap_setup(&op->dev, id ? *id : -1, &res, config, - regs); + + return hwicap_setup(&pdev->dev, pdev->id, res, + &buffer_icap_config, regs); } -static int __devexit hwicap_of_remove(struct platform_device *op) +static int __devexit hwicap_drv_remove(struct platform_device *pdev) { - return hwicap_remove(&op->dev); + return hwicap_remove(&pdev->dev); } -/* Match table for of_platform binding */ +#ifdef CONFIG_OF +/* Match table for device tree binding */ static const struct of_device_id __devinitconst hwicap_of_match[] = { { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config}, {}, }; MODULE_DEVICE_TABLE(of, hwicap_of_match); +#else +#define hwicap_of_match NULL +#endif -static struct of_platform_driver hwicap_of_driver = { - .probe = hwicap_of_probe, - .remove = __devexit_p(hwicap_of_remove), +static struct platform_driver hwicap_platform_driver = { + .probe = hwicap_drv_probe, + .remove = hwicap_drv_remove, .driver = { - .name = DRIVER_NAME, .owner = THIS_MODULE, + .name = DRIVER_NAME, .of_match_table = hwicap_of_match, }, }; -/* Registration helpers to keep the number of #ifdefs to a minimum */ -static inline int __init hwicap_of_register(void) -{ - pr_debug("hwicap: calling of_register_platform_driver()\n"); - return of_register_platform_driver(&hwicap_of_driver); -} - -static inline void __exit hwicap_of_unregister(void) -{ - of_unregister_platform_driver(&hwicap_of_driver); -} -#else /* CONFIG_OF */ -/* CONFIG_OF not enabled; do nothing helpers */ -static inline int __init hwicap_of_register(void) { return 0; } -static inline void __exit hwicap_of_unregister(void) { } -#endif /* CONFIG_OF */ - static int __init hwicap_module_init(void) { dev_t devt; @@ -856,21 +832,12 @@ static int __init hwicap_module_init(void) return retval; retval = platform_driver_register(&hwicap_platform_driver); - - if (retval) - goto failed1; - - retval = hwicap_of_register(); - if (retval) - goto failed2; + goto failed; return retval; - failed2: - platform_driver_unregister(&hwicap_platform_driver); - - failed1: + failed: unregister_chrdev_region(devt, HWICAP_DEVICES); return retval; @@ -884,8 +851,6 @@ static void __exit hwicap_module_cleanup(void) platform_driver_unregister(&hwicap_platform_driver); - hwicap_of_unregister(); - unregister_chrdev_region(devt, HWICAP_DEVICES); } -- cgit v1.2.3 From 751b3840d216f1ecd3b91ff5251bf7703b690cd8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 1 Mar 2011 13:12:47 +0800 Subject: pcmcia: synclink_cs: fix prototype for mgslpc_ioctl() The ioctl file pointer was removed in commit 6caa76 "tty: now phase out the ioctl file pointer for good". Thus fix the prototype for mgslpc_ioctl() and eliminate below warning: CC [M] drivers/char/pcmcia/synclink_cs.o drivers/char/pcmcia/synclink_cs.c:2787: warning: initialization from incompatible pointer type Signed-off-by: Axel Lin Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/synclink_cs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 02127cad0980..beca80bb9bdb 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2222,13 +2222,12 @@ static int mgslpc_get_icount(struct tty_struct *tty, * Arguments: * * tty pointer to tty instance data - * file pointer to associated file object for device * cmd IOCTL command code * arg command argument/context * * Return Value: 0 if success, otherwise error code */ -static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, +static int mgslpc_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; -- cgit v1.2.3 From 8d1dc20e8d689c7e6a0a4d2c94e36a99d5793ecb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 1 Mar 2011 13:23:27 -0800 Subject: Revert "TPM: Long default timeout fix" This reverts commit c4ff4b829ef9e6353c0b133b7adb564a68054979. Ted Ts'o reports: "TPM is working for me so I can log into employer's network in 2.6.37. It broke when I tried 2.6.38-rc6, with the following relevant lines from my dmesg: [ 11.081627] tpm_tis 00:0b: 1.2 TPM (device-id 0x0, rev-id 78) [ 25.734114] tpm_tis 00:0b: Operation Timed out [ 78.040949] tpm_tis 00:0b: Operation Timed out This caused me to get suspicious, especially since the _other_ TPM commit in 2.6.38 had already been reverted, so I tried reverting commit c4ff4b829e: "TPM: Long default timeout fix". With this commit reverted, my TPM on my Lenovo T410 is once again working." Requested-and-tested-by: Theodore Ts'o Acked-by: Rajiv Andrade Signed-off-by: Linus Torvalds --- drivers/char/tpm/tpm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 36e0fa161c2b..1f46f1cd9225 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -364,14 +364,12 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, tpm_protected_ordinal_duration[ordinal & TPM_PROTECTED_ORDINAL_MASK]; - if (duration_idx != TPM_UNDEFINED) { + if (duration_idx != TPM_UNDEFINED) duration = chip->vendor.duration[duration_idx]; - /* if duration is 0, it's because chip->vendor.duration wasn't */ - /* filled yet, so we set the lowest timeout just to give enough */ - /* time for tpm_get_timeouts() to succeed */ - return (duration <= 0 ? HZ : duration); - } else + if (duration <= 0) return 2 * 60 * HZ; + else + return duration; } EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); -- cgit v1.2.3 From d7a62cd0332115d4c7c4689abea0d889a30d8349 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Fri, 4 Mar 2011 14:04:33 +1030 Subject: virtio: console: Don't access vqs if device was unplugged If a virtio-console device gets unplugged while a port is open, a subsequent close() call on the port accesses vqs to free up buffers. This can lead to a crash. The buffers are already freed up as a result of the call to unplug_ports() from virtcons_remove(). The fix is to simply not access vq information if port->portdev is NULL. Reported-by: juzhang CC: stable@kernel.org Signed-off-by: Amit Shah Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds --- drivers/char/virtio_console.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 490393186338..84b164d1eb2b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -388,6 +388,10 @@ static void discard_port_data(struct port *port) unsigned int len; int ret; + if (!port->portdev) { + /* Device has been unplugged. vqs are already gone. */ + return; + } vq = port->in_vq; if (port->inbuf) buf = port->inbuf; @@ -470,6 +474,10 @@ static void reclaim_consumed_buffers(struct port *port) void *buf; unsigned int len; + if (!port->portdev) { + /* Device has been unplugged. vqs are already gone. */ + return; + } while ((buf = virtqueue_get_buf(port->out_vq, &len))) { kfree(buf); port->outvq_full = false; -- cgit v1.2.3 From 8d971e98a7be749445ac6eb9eb37b116f1a6d3c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Mar 2011 12:03:07 -0800 Subject: Staging: tty: fix build with epca.c driver I forgot to move the digi*.h files from drivers/char/ to drivers/staging/tty/ Thanks to Randy for pointing out the issue. Reported-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/char/digi1.h | 100 ------------------------------ drivers/char/digiFep1.h | 136 ----------------------------------------- drivers/char/digiPCI.h | 42 ------------- drivers/staging/tty/digi1.h | 100 ++++++++++++++++++++++++++++++ drivers/staging/tty/digiFep1.h | 136 +++++++++++++++++++++++++++++++++++++++++ drivers/staging/tty/digiPCI.h | 42 +++++++++++++ 6 files changed, 278 insertions(+), 278 deletions(-) delete mode 100644 drivers/char/digi1.h delete mode 100644 drivers/char/digiFep1.h delete mode 100644 drivers/char/digiPCI.h create mode 100644 drivers/staging/tty/digi1.h create mode 100644 drivers/staging/tty/digiFep1.h create mode 100644 drivers/staging/tty/digiPCI.h (limited to 'drivers/char') diff --git a/drivers/char/digi1.h b/drivers/char/digi1.h deleted file mode 100644 index 94d4eab5d3ca..000000000000 --- a/drivers/char/digi1.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Definitions for DigiBoard ditty(1) command. */ - -#if !defined(TIOCMODG) -#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ -#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ -#endif - -#if !defined(TIOCMSET) -#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ -#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ -#endif - -#if !defined(TIOCMBIC) -#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ -#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ -#endif - -#if !defined(TIOCSDTR) -#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ -#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ -#endif - -/************************************************************************ - * Ioctl command arguments for DIGI parameters. - ************************************************************************/ -#define DIGI_GETA (('e'<<8) | 94) /* Read params */ - -#define DIGI_SETA (('e'<<8) | 95) /* Set params */ -#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ -#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ - -#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ - /* control characters */ -#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ - /* control characters */ -#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ - /* flow control chars */ -#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ - /* flow control chars */ - -#define DIGI_GETINFO (('e'<<8) | 103) /* Fill in digi_info */ -#define DIGI_POLLER (('e'<<8) | 104) /* Turn on/off poller */ -#define DIGI_INIT (('e'<<8) | 105) /* Allow things to run. */ - -struct digiflow_struct -{ - unsigned char startc; /* flow cntl start char */ - unsigned char stopc; /* flow cntl stop char */ -}; - -typedef struct digiflow_struct digiflow_t; - - -/************************************************************************ - * Values for digi_flags - ************************************************************************/ -#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ -#define DIGI_FAST 0x0002 /* Fast baud rates */ -#define RTSPACE 0x0004 /* RTS input flow control */ -#define CTSPACE 0x0008 /* CTS output flow control */ -#define DSRPACE 0x0010 /* DSR output flow control */ -#define DCDPACE 0x0020 /* DCD output flow control */ -#define DTRPACE 0x0040 /* DTR input flow control */ -#define DIGI_FORCEDCD 0x0100 /* Force carrier */ -#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ -#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ - - -/************************************************************************ - * Values for digiDload - ************************************************************************/ -#define NORMAL 0 -#define PCI_CTL 1 - -#define SIZE8 0 -#define SIZE16 1 -#define SIZE32 2 - -/************************************************************************ - * Structure used with ioctl commands for DIGI parameters. - ************************************************************************/ -struct digi_struct -{ - unsigned short digi_flags; /* Flags (see above) */ -}; - -typedef struct digi_struct digi_t; - -struct digi_info -{ - unsigned long board; /* Which board is this ? */ - unsigned char status; /* Alive or dead */ - unsigned char type; /* see epca.h */ - unsigned char subtype; /* For future XEM, XR, etc ... */ - unsigned short numports; /* Number of ports configured */ - unsigned char *port; /* I/O Address */ - unsigned char *membase; /* DPR Address */ - unsigned char *version; /* For future ... */ - unsigned short windowData; /* For future ... */ -} ; diff --git a/drivers/char/digiFep1.h b/drivers/char/digiFep1.h deleted file mode 100644 index 3c1f1922c798..000000000000 --- a/drivers/char/digiFep1.h +++ /dev/null @@ -1,136 +0,0 @@ - -#define CSTART 0x400L -#define CMAX 0x800L -#define ISTART 0x800L -#define IMAX 0xC00L -#define CIN 0xD10L -#define GLOBAL 0xD10L -#define EIN 0xD18L -#define FEPSTAT 0xD20L -#define CHANSTRUCT 0x1000L -#define RXTXBUF 0x4000L - - -struct global_data -{ - u16 cin; - u16 cout; - u16 cstart; - u16 cmax; - u16 ein; - u16 eout; - u16 istart; - u16 imax; -}; - - -struct board_chan -{ - u32 filler1; - u32 filler2; - u16 tseg; - u16 tin; - u16 tout; - u16 tmax; - - u16 rseg; - u16 rin; - u16 rout; - u16 rmax; - - u16 tlow; - u16 rlow; - u16 rhigh; - u16 incr; - - u16 etime; - u16 edelay; - unchar *dev; - - u16 iflag; - u16 oflag; - u16 cflag; - u16 gmask; - - u16 col; - u16 delay; - u16 imask; - u16 tflush; - - u32 filler3; - u32 filler4; - u32 filler5; - u32 filler6; - - u8 num; - u8 ract; - u8 bstat; - u8 tbusy; - u8 iempty; - u8 ilow; - u8 idata; - u8 eflag; - - u8 tflag; - u8 rflag; - u8 xmask; - u8 xval; - u8 mstat; - u8 mchange; - u8 mint; - u8 lstat; - - u8 mtran; - u8 orun; - u8 startca; - u8 stopca; - u8 startc; - u8 stopc; - u8 vnext; - u8 hflow; - - u8 fillc; - u8 ochar; - u8 omask; - - u8 filler7; - u8 filler8[28]; -}; - - -#define SRXLWATER 0xE0 -#define SRXHWATER 0xE1 -#define STOUT 0xE2 -#define PAUSETX 0xE3 -#define RESUMETX 0xE4 -#define SAUXONOFFC 0xE6 -#define SENDBREAK 0xE8 -#define SETMODEM 0xE9 -#define SETIFLAGS 0xEA -#define SONOFFC 0xEB -#define STXLWATER 0xEC -#define PAUSERX 0xEE -#define RESUMERX 0xEF -#define SETBUFFER 0xF2 -#define SETCOOKED 0xF3 -#define SETHFLOW 0xF4 -#define SETCTRLFLAGS 0xF5 -#define SETVNEXT 0xF6 - - - -#define BREAK_IND 0x01 -#define LOWTX_IND 0x02 -#define EMPTYTX_IND 0x04 -#define DATA_IND 0x08 -#define MODEMCHG_IND 0x20 - -#define FEP_HUPCL 0002000 -#if 0 -#define RTS 0x02 -#define CD 0x08 -#define DSR 0x10 -#define CTS 0x20 -#define RI 0x40 -#define DTR 0x80 -#endif diff --git a/drivers/char/digiPCI.h b/drivers/char/digiPCI.h deleted file mode 100644 index 6ca7819e5069..000000000000 --- a/drivers/char/digiPCI.h +++ /dev/null @@ -1,42 +0,0 @@ -/************************************************************************* - * Defines and structure definitions for PCI BIOS Interface - *************************************************************************/ -#define PCIMAX 32 /* maximum number of PCI boards */ - - -#define PCI_VENDOR_DIGI 0x114F -#define PCI_DEVICE_EPC 0x0002 -#define PCI_DEVICE_RIGHTSWITCH 0x0003 /* For testing */ -#define PCI_DEVICE_XEM 0x0004 -#define PCI_DEVICE_XR 0x0005 -#define PCI_DEVICE_CX 0x0006 -#define PCI_DEVICE_XRJ 0x0009 /* Jupiter boards with */ -#define PCI_DEVICE_EPCJ 0x000a /* PLX 9060 chip for PCI */ - - -/* - * On the PCI boards, there is no IO space allocated - * The I/O registers will be in the first 3 bytes of the - * upper 2MB of the 4MB memory space. The board memory - * will be mapped into the low 2MB of the 4MB memory space - */ - -/* Potential location of PCI Bios from E0000 to FFFFF*/ -#define PCI_BIOS_SIZE 0x00020000 - -/* Size of Memory and I/O for PCI (4MB) */ -#define PCI_RAM_SIZE 0x00400000 - -/* Size of Memory (2MB) */ -#define PCI_MEM_SIZE 0x00200000 - -/* Offset of I/0 in Memory (2MB) */ -#define PCI_IO_OFFSET 0x00200000 - -#define MEMOUTB(basemem, pnum, setmemval) *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval) -#define MEMINB(basemem, pnum) *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum )) /* for PCI I/O */ - - - - - diff --git a/drivers/staging/tty/digi1.h b/drivers/staging/tty/digi1.h new file mode 100644 index 000000000000..94d4eab5d3ca --- /dev/null +++ b/drivers/staging/tty/digi1.h @@ -0,0 +1,100 @@ +/* Definitions for DigiBoard ditty(1) command. */ + +#if !defined(TIOCMODG) +#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ +#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ +#endif + +#if !defined(TIOCMSET) +#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ +#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ +#endif + +#if !defined(TIOCMBIC) +#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ +#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ +#endif + +#if !defined(TIOCSDTR) +#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ +#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ +#endif + +/************************************************************************ + * Ioctl command arguments for DIGI parameters. + ************************************************************************/ +#define DIGI_GETA (('e'<<8) | 94) /* Read params */ + +#define DIGI_SETA (('e'<<8) | 95) /* Set params */ +#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ +#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ + +#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ + /* control characters */ +#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ + /* control characters */ +#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ + /* flow control chars */ +#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ + /* flow control chars */ + +#define DIGI_GETINFO (('e'<<8) | 103) /* Fill in digi_info */ +#define DIGI_POLLER (('e'<<8) | 104) /* Turn on/off poller */ +#define DIGI_INIT (('e'<<8) | 105) /* Allow things to run. */ + +struct digiflow_struct +{ + unsigned char startc; /* flow cntl start char */ + unsigned char stopc; /* flow cntl stop char */ +}; + +typedef struct digiflow_struct digiflow_t; + + +/************************************************************************ + * Values for digi_flags + ************************************************************************/ +#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ +#define DIGI_FAST 0x0002 /* Fast baud rates */ +#define RTSPACE 0x0004 /* RTS input flow control */ +#define CTSPACE 0x0008 /* CTS output flow control */ +#define DSRPACE 0x0010 /* DSR output flow control */ +#define DCDPACE 0x0020 /* DCD output flow control */ +#define DTRPACE 0x0040 /* DTR input flow control */ +#define DIGI_FORCEDCD 0x0100 /* Force carrier */ +#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ +#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ + + +/************************************************************************ + * Values for digiDload + ************************************************************************/ +#define NORMAL 0 +#define PCI_CTL 1 + +#define SIZE8 0 +#define SIZE16 1 +#define SIZE32 2 + +/************************************************************************ + * Structure used with ioctl commands for DIGI parameters. + ************************************************************************/ +struct digi_struct +{ + unsigned short digi_flags; /* Flags (see above) */ +}; + +typedef struct digi_struct digi_t; + +struct digi_info +{ + unsigned long board; /* Which board is this ? */ + unsigned char status; /* Alive or dead */ + unsigned char type; /* see epca.h */ + unsigned char subtype; /* For future XEM, XR, etc ... */ + unsigned short numports; /* Number of ports configured */ + unsigned char *port; /* I/O Address */ + unsigned char *membase; /* DPR Address */ + unsigned char *version; /* For future ... */ + unsigned short windowData; /* For future ... */ +} ; diff --git a/drivers/staging/tty/digiFep1.h b/drivers/staging/tty/digiFep1.h new file mode 100644 index 000000000000..3c1f1922c798 --- /dev/null +++ b/drivers/staging/tty/digiFep1.h @@ -0,0 +1,136 @@ + +#define CSTART 0x400L +#define CMAX 0x800L +#define ISTART 0x800L +#define IMAX 0xC00L +#define CIN 0xD10L +#define GLOBAL 0xD10L +#define EIN 0xD18L +#define FEPSTAT 0xD20L +#define CHANSTRUCT 0x1000L +#define RXTXBUF 0x4000L + + +struct global_data +{ + u16 cin; + u16 cout; + u16 cstart; + u16 cmax; + u16 ein; + u16 eout; + u16 istart; + u16 imax; +}; + + +struct board_chan +{ + u32 filler1; + u32 filler2; + u16 tseg; + u16 tin; + u16 tout; + u16 tmax; + + u16 rseg; + u16 rin; + u16 rout; + u16 rmax; + + u16 tlow; + u16 rlow; + u16 rhigh; + u16 incr; + + u16 etime; + u16 edelay; + unchar *dev; + + u16 iflag; + u16 oflag; + u16 cflag; + u16 gmask; + + u16 col; + u16 delay; + u16 imask; + u16 tflush; + + u32 filler3; + u32 filler4; + u32 filler5; + u32 filler6; + + u8 num; + u8 ract; + u8 bstat; + u8 tbusy; + u8 iempty; + u8 ilow; + u8 idata; + u8 eflag; + + u8 tflag; + u8 rflag; + u8 xmask; + u8 xval; + u8 mstat; + u8 mchange; + u8 mint; + u8 lstat; + + u8 mtran; + u8 orun; + u8 startca; + u8 stopca; + u8 startc; + u8 stopc; + u8 vnext; + u8 hflow; + + u8 fillc; + u8 ochar; + u8 omask; + + u8 filler7; + u8 filler8[28]; +}; + + +#define SRXLWATER 0xE0 +#define SRXHWATER 0xE1 +#define STOUT 0xE2 +#define PAUSETX 0xE3 +#define RESUMETX 0xE4 +#define SAUXONOFFC 0xE6 +#define SENDBREAK 0xE8 +#define SETMODEM 0xE9 +#define SETIFLAGS 0xEA +#define SONOFFC 0xEB +#define STXLWATER 0xEC +#define PAUSERX 0xEE +#define RESUMERX 0xEF +#define SETBUFFER 0xF2 +#define SETCOOKED 0xF3 +#define SETHFLOW 0xF4 +#define SETCTRLFLAGS 0xF5 +#define SETVNEXT 0xF6 + + + +#define BREAK_IND 0x01 +#define LOWTX_IND 0x02 +#define EMPTYTX_IND 0x04 +#define DATA_IND 0x08 +#define MODEMCHG_IND 0x20 + +#define FEP_HUPCL 0002000 +#if 0 +#define RTS 0x02 +#define CD 0x08 +#define DSR 0x10 +#define CTS 0x20 +#define RI 0x40 +#define DTR 0x80 +#endif diff --git a/drivers/staging/tty/digiPCI.h b/drivers/staging/tty/digiPCI.h new file mode 100644 index 000000000000..6ca7819e5069 --- /dev/null +++ b/drivers/staging/tty/digiPCI.h @@ -0,0 +1,42 @@ +/************************************************************************* + * Defines and structure definitions for PCI BIOS Interface + *************************************************************************/ +#define PCIMAX 32 /* maximum number of PCI boards */ + + +#define PCI_VENDOR_DIGI 0x114F +#define PCI_DEVICE_EPC 0x0002 +#define PCI_DEVICE_RIGHTSWITCH 0x0003 /* For testing */ +#define PCI_DEVICE_XEM 0x0004 +#define PCI_DEVICE_XR 0x0005 +#define PCI_DEVICE_CX 0x0006 +#define PCI_DEVICE_XRJ 0x0009 /* Jupiter boards with */ +#define PCI_DEVICE_EPCJ 0x000a /* PLX 9060 chip for PCI */ + + +/* + * On the PCI boards, there is no IO space allocated + * The I/O registers will be in the first 3 bytes of the + * upper 2MB of the 4MB memory space. The board memory + * will be mapped into the low 2MB of the 4MB memory space + */ + +/* Potential location of PCI Bios from E0000 to FFFFF*/ +#define PCI_BIOS_SIZE 0x00020000 + +/* Size of Memory and I/O for PCI (4MB) */ +#define PCI_RAM_SIZE 0x00400000 + +/* Size of Memory (2MB) */ +#define PCI_MEM_SIZE 0x00200000 + +/* Offset of I/0 in Memory (2MB) */ +#define PCI_IO_OFFSET 0x00200000 + +#define MEMOUTB(basemem, pnum, setmemval) *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval) +#define MEMINB(basemem, pnum) *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum )) /* for PCI I/O */ + + + + + -- cgit v1.2.3 From b71dc8873427bb5bf0ce31b968c3f219a1d6d014 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 3 Mar 2011 18:38:22 +0100 Subject: tty: move cd1865.h to drivers/staging/tty/ The file is required by the specialix driver, which was moved to drivers/staging/. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/cd1865.h | 263 ------------------------------------------- drivers/staging/tty/cd1865.h | 263 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 263 insertions(+), 263 deletions(-) delete mode 100644 drivers/char/cd1865.h create mode 100644 drivers/staging/tty/cd1865.h (limited to 'drivers/char') diff --git a/drivers/char/cd1865.h b/drivers/char/cd1865.h deleted file mode 100644 index 9940966e7a1d..000000000000 --- a/drivers/char/cd1865.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * linux/drivers/char/cd1865.h -- Definitions relating to the CD1865 - * for the Specialix IO8+ multiport serial driver. - * - * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) - * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) - * - * Specialix pays for the development and support of this driver. - * Please DO contact io8-linux@specialix.co.uk if you require - * support. - * - * This driver was developped in the BitWizard linux device - * driver service. If you require a linux device driver for your - * product, please contact devices@BitWizard.nl for a quote. - * - */ - -/* - * Definitions for Driving CD180/CD1864/CD1865 based eightport serial cards. - */ - - -/* Values of choice for Interrupt ACKs */ -/* These values are "obligatory" if you use the register based - * interrupt acknowledgements. See page 99-101 of V2.0 of the CD1865 - * databook */ -#define SX_ACK_MINT 0x75 /* goes to PILR1 */ -#define SX_ACK_TINT 0x76 /* goes to PILR2 */ -#define SX_ACK_RINT 0x77 /* goes to PILR3 */ - -/* Chip ID (is used when chips ar daisy chained.) */ -#define SX_ID 0x10 - -/* Definitions for Cirrus Logic CL-CD186x 8-port async mux chip */ - -#define CD186x_NCH 8 /* Total number of channels */ -#define CD186x_TPC 16 /* Ticks per character */ -#define CD186x_NFIFO 8 /* TX FIFO size */ - - -/* Global registers */ - -#define CD186x_GIVR 0x40 /* Global Interrupt Vector Register */ -#define CD186x_GICR 0x41 /* Global Interrupting Channel Register */ -#define CD186x_PILR1 0x61 /* Priority Interrupt Level Register 1 */ -#define CD186x_PILR2 0x62 /* Priority Interrupt Level Register 2 */ -#define CD186x_PILR3 0x63 /* Priority Interrupt Level Register 3 */ -#define CD186x_CAR 0x64 /* Channel Access Register */ -#define CD186x_SRSR 0x65 /* Channel Access Register */ -#define CD186x_GFRCR 0x6b /* Global Firmware Revision Code Register */ -#define CD186x_PPRH 0x70 /* Prescaler Period Register High */ -#define CD186x_PPRL 0x71 /* Prescaler Period Register Low */ -#define CD186x_RDR 0x78 /* Receiver Data Register */ -#define CD186x_RCSR 0x7a /* Receiver Character Status Register */ -#define CD186x_TDR 0x7b /* Transmit Data Register */ -#define CD186x_EOIR 0x7f /* End of Interrupt Register */ -#define CD186x_MRAR 0x75 /* Modem Request Acknowledge register */ -#define CD186x_TRAR 0x76 /* Transmit Request Acknowledge register */ -#define CD186x_RRAR 0x77 /* Receive Request Acknowledge register */ -#define CD186x_SRCR 0x66 /* Service Request Configuration register */ - -/* Channel Registers */ - -#define CD186x_CCR 0x01 /* Channel Command Register */ -#define CD186x_IER 0x02 /* Interrupt Enable Register */ -#define CD186x_COR1 0x03 /* Channel Option Register 1 */ -#define CD186x_COR2 0x04 /* Channel Option Register 2 */ -#define CD186x_COR3 0x05 /* Channel Option Register 3 */ -#define CD186x_CCSR 0x06 /* Channel Control Status Register */ -#define CD186x_RDCR 0x07 /* Receive Data Count Register */ -#define CD186x_SCHR1 0x09 /* Special Character Register 1 */ -#define CD186x_SCHR2 0x0a /* Special Character Register 2 */ -#define CD186x_SCHR3 0x0b /* Special Character Register 3 */ -#define CD186x_SCHR4 0x0c /* Special Character Register 4 */ -#define CD186x_MCOR1 0x10 /* Modem Change Option 1 Register */ -#define CD186x_MCOR2 0x11 /* Modem Change Option 2 Register */ -#define CD186x_MCR 0x12 /* Modem Change Register */ -#define CD186x_RTPR 0x18 /* Receive Timeout Period Register */ -#define CD186x_MSVR 0x28 /* Modem Signal Value Register */ -#define CD186x_MSVRTS 0x29 /* Modem Signal Value Register */ -#define CD186x_MSVDTR 0x2a /* Modem Signal Value Register */ -#define CD186x_RBPRH 0x31 /* Receive Baud Rate Period Register High */ -#define CD186x_RBPRL 0x32 /* Receive Baud Rate Period Register Low */ -#define CD186x_TBPRH 0x39 /* Transmit Baud Rate Period Register High */ -#define CD186x_TBPRL 0x3a /* Transmit Baud Rate Period Register Low */ - - -/* Global Interrupt Vector Register (R/W) */ - -#define GIVR_ITMASK 0x07 /* Interrupt type mask */ -#define GIVR_IT_MODEM 0x01 /* Modem Signal Change Interrupt */ -#define GIVR_IT_TX 0x02 /* Transmit Data Interrupt */ -#define GIVR_IT_RCV 0x03 /* Receive Good Data Interrupt */ -#define GIVR_IT_REXC 0x07 /* Receive Exception Interrupt */ - - -/* Global Interrupt Channel Register (R/W) */ - -#define GICR_CHAN 0x1c /* Channel Number Mask */ -#define GICR_CHAN_OFF 2 /* Channel Number shift */ - - -/* Channel Address Register (R/W) */ - -#define CAR_CHAN 0x07 /* Channel Number Mask */ -#define CAR_A7 0x08 /* A7 Address Extension (unused) */ - - -/* Receive Character Status Register (R/O) */ - -#define RCSR_TOUT 0x80 /* Rx Timeout */ -#define RCSR_SCDET 0x70 /* Special Character Detected Mask */ -#define RCSR_NO_SC 0x00 /* No Special Characters Detected */ -#define RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected */ -#define RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected */ -#define RCSR_SC_3 0x30 /* Special Char 3 Detected */ -#define RCSR_SC_4 0x40 /* Special Char 4 Detected */ -#define RCSR_BREAK 0x08 /* Break has been detected */ -#define RCSR_PE 0x04 /* Parity Error */ -#define RCSR_FE 0x02 /* Frame Error */ -#define RCSR_OE 0x01 /* Overrun Error */ - - -/* Channel Command Register (R/W) (commands in groups can be OR-ed) */ - -#define CCR_HARDRESET 0x81 /* Reset the chip */ - -#define CCR_SOFTRESET 0x80 /* Soft Channel Reset */ - -#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */ -#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */ -#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */ - -#define CCR_SSCH1 0x21 /* Send Special Character 1 */ - -#define CCR_SSCH2 0x22 /* Send Special Character 2 */ - -#define CCR_SSCH3 0x23 /* Send Special Character 3 */ - -#define CCR_SSCH4 0x24 /* Send Special Character 4 */ - -#define CCR_TXEN 0x18 /* Enable Transmitter */ -#define CCR_RXEN 0x12 /* Enable Receiver */ - -#define CCR_TXDIS 0x14 /* Disable Transmitter */ -#define CCR_RXDIS 0x11 /* Disable Receiver */ - - -/* Interrupt Enable Register (R/W) */ - -#define IER_DSR 0x80 /* Enable interrupt on DSR change */ -#define IER_CD 0x40 /* Enable interrupt on CD change */ -#define IER_CTS 0x20 /* Enable interrupt on CTS change */ -#define IER_RXD 0x10 /* Enable interrupt on Receive Data */ -#define IER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */ -#define IER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */ -#define IER_TXEMPTY 0x02 /* Enable interrupt on TX completely empty */ -#define IER_RET 0x01 /* Enable interrupt on RX Exc. Timeout */ - - -/* Channel Option Register 1 (R/W) */ - -#define COR1_ODDP 0x80 /* Odd Parity */ -#define COR1_PARMODE 0x60 /* Parity Mode mask */ -#define COR1_NOPAR 0x00 /* No Parity */ -#define COR1_FORCEPAR 0x20 /* Force Parity */ -#define COR1_NORMPAR 0x40 /* Normal Parity */ -#define COR1_IGNORE 0x10 /* Ignore Parity on RX */ -#define COR1_STOPBITS 0x0c /* Number of Stop Bits */ -#define COR1_1SB 0x00 /* 1 Stop Bit */ -#define COR1_15SB 0x04 /* 1.5 Stop Bits */ -#define COR1_2SB 0x08 /* 2 Stop Bits */ -#define COR1_CHARLEN 0x03 /* Character Length */ -#define COR1_5BITS 0x00 /* 5 bits */ -#define COR1_6BITS 0x01 /* 6 bits */ -#define COR1_7BITS 0x02 /* 7 bits */ -#define COR1_8BITS 0x03 /* 8 bits */ - - -/* Channel Option Register 2 (R/W) */ - -#define COR2_IXM 0x80 /* Implied XON mode */ -#define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */ -#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */ -#define COR2_LLM 0x10 /* Local Loopback Mode */ -#define COR2_RLM 0x08 /* Remote Loopback Mode */ -#define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */ -#define COR2_CTSAE 0x02 /* CTS Automatic Enable */ -#define COR2_DSRAE 0x01 /* DSR Automatic Enable */ - - -/* Channel Option Register 3 (R/W) */ - -#define COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3) */ -#define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4) */ -#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */ -#define COR3_SCDE 0x10 /* Special Character Detection Enable */ -#define COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8) */ - - -/* Channel Control Status Register (R/O) */ - -#define CCSR_RXEN 0x80 /* Receiver Enabled */ -#define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent) */ -#define CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent) */ -#define CCSR_TXEN 0x08 /* Transmitter Enabled */ -#define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */ -#define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */ - - -/* Modem Change Option Register 1 (R/W) */ - -#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */ -#define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */ -#define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */ -#define MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8) */ -#define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */ - - -/* Modem Change Option Register 2 (R/W) */ - -#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */ -#define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */ -#define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */ - -/* Modem Change Register (R/W) */ - -#define MCR_DSRCHG 0x80 /* DSR Changed */ -#define MCR_CDCHG 0x40 /* CD Changed */ -#define MCR_CTSCHG 0x20 /* CTS Changed */ - - -/* Modem Signal Value Register (R/W) */ - -#define MSVR_DSR 0x80 /* Current state of DSR input */ -#define MSVR_CD 0x40 /* Current state of CD input */ -#define MSVR_CTS 0x20 /* Current state of CTS input */ -#define MSVR_DTR 0x02 /* Current state of DTR output */ -#define MSVR_RTS 0x01 /* Current state of RTS output */ - - -/* Escape characters */ - -#define CD186x_C_ESC 0x00 /* Escape character */ -#define CD186x_C_SBRK 0x81 /* Start sending BREAK */ -#define CD186x_C_DELAY 0x82 /* Delay output */ -#define CD186x_C_EBRK 0x83 /* Stop sending BREAK */ - -#define SRSR_RREQint 0x10 /* This chip wants "rec" serviced */ -#define SRSR_TREQint 0x04 /* This chip wants "transmit" serviced */ -#define SRSR_MREQint 0x01 /* This chip wants "mdm change" serviced */ - - - -#define SRCR_PKGTYPE 0x80 -#define SRCR_REGACKEN 0x40 -#define SRCR_DAISYEN 0x20 -#define SRCR_GLOBPRI 0x10 -#define SRCR_UNFAIR 0x08 -#define SRCR_AUTOPRI 0x02 -#define SRCR_PRISEL 0x01 - - diff --git a/drivers/staging/tty/cd1865.h b/drivers/staging/tty/cd1865.h new file mode 100644 index 000000000000..9940966e7a1d --- /dev/null +++ b/drivers/staging/tty/cd1865.h @@ -0,0 +1,263 @@ +/* + * linux/drivers/char/cd1865.h -- Definitions relating to the CD1865 + * for the Specialix IO8+ multiport serial driver. + * + * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) + * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com) + * + * Specialix pays for the development and support of this driver. + * Please DO contact io8-linux@specialix.co.uk if you require + * support. + * + * This driver was developped in the BitWizard linux device + * driver service. If you require a linux device driver for your + * product, please contact devices@BitWizard.nl for a quote. + * + */ + +/* + * Definitions for Driving CD180/CD1864/CD1865 based eightport serial cards. + */ + + +/* Values of choice for Interrupt ACKs */ +/* These values are "obligatory" if you use the register based + * interrupt acknowledgements. See page 99-101 of V2.0 of the CD1865 + * databook */ +#define SX_ACK_MINT 0x75 /* goes to PILR1 */ +#define SX_ACK_TINT 0x76 /* goes to PILR2 */ +#define SX_ACK_RINT 0x77 /* goes to PILR3 */ + +/* Chip ID (is used when chips ar daisy chained.) */ +#define SX_ID 0x10 + +/* Definitions for Cirrus Logic CL-CD186x 8-port async mux chip */ + +#define CD186x_NCH 8 /* Total number of channels */ +#define CD186x_TPC 16 /* Ticks per character */ +#define CD186x_NFIFO 8 /* TX FIFO size */ + + +/* Global registers */ + +#define CD186x_GIVR 0x40 /* Global Interrupt Vector Register */ +#define CD186x_GICR 0x41 /* Global Interrupting Channel Register */ +#define CD186x_PILR1 0x61 /* Priority Interrupt Level Register 1 */ +#define CD186x_PILR2 0x62 /* Priority Interrupt Level Register 2 */ +#define CD186x_PILR3 0x63 /* Priority Interrupt Level Register 3 */ +#define CD186x_CAR 0x64 /* Channel Access Register */ +#define CD186x_SRSR 0x65 /* Channel Access Register */ +#define CD186x_GFRCR 0x6b /* Global Firmware Revision Code Register */ +#define CD186x_PPRH 0x70 /* Prescaler Period Register High */ +#define CD186x_PPRL 0x71 /* Prescaler Period Register Low */ +#define CD186x_RDR 0x78 /* Receiver Data Register */ +#define CD186x_RCSR 0x7a /* Receiver Character Status Register */ +#define CD186x_TDR 0x7b /* Transmit Data Register */ +#define CD186x_EOIR 0x7f /* End of Interrupt Register */ +#define CD186x_MRAR 0x75 /* Modem Request Acknowledge register */ +#define CD186x_TRAR 0x76 /* Transmit Request Acknowledge register */ +#define CD186x_RRAR 0x77 /* Receive Request Acknowledge register */ +#define CD186x_SRCR 0x66 /* Service Request Configuration register */ + +/* Channel Registers */ + +#define CD186x_CCR 0x01 /* Channel Command Register */ +#define CD186x_IER 0x02 /* Interrupt Enable Register */ +#define CD186x_COR1 0x03 /* Channel Option Register 1 */ +#define CD186x_COR2 0x04 /* Channel Option Register 2 */ +#define CD186x_COR3 0x05 /* Channel Option Register 3 */ +#define CD186x_CCSR 0x06 /* Channel Control Status Register */ +#define CD186x_RDCR 0x07 /* Receive Data Count Register */ +#define CD186x_SCHR1 0x09 /* Special Character Register 1 */ +#define CD186x_SCHR2 0x0a /* Special Character Register 2 */ +#define CD186x_SCHR3 0x0b /* Special Character Register 3 */ +#define CD186x_SCHR4 0x0c /* Special Character Register 4 */ +#define CD186x_MCOR1 0x10 /* Modem Change Option 1 Register */ +#define CD186x_MCOR2 0x11 /* Modem Change Option 2 Register */ +#define CD186x_MCR 0x12 /* Modem Change Register */ +#define CD186x_RTPR 0x18 /* Receive Timeout Period Register */ +#define CD186x_MSVR 0x28 /* Modem Signal Value Register */ +#define CD186x_MSVRTS 0x29 /* Modem Signal Value Register */ +#define CD186x_MSVDTR 0x2a /* Modem Signal Value Register */ +#define CD186x_RBPRH 0x31 /* Receive Baud Rate Period Register High */ +#define CD186x_RBPRL 0x32 /* Receive Baud Rate Period Register Low */ +#define CD186x_TBPRH 0x39 /* Transmit Baud Rate Period Register High */ +#define CD186x_TBPRL 0x3a /* Transmit Baud Rate Period Register Low */ + + +/* Global Interrupt Vector Register (R/W) */ + +#define GIVR_ITMASK 0x07 /* Interrupt type mask */ +#define GIVR_IT_MODEM 0x01 /* Modem Signal Change Interrupt */ +#define GIVR_IT_TX 0x02 /* Transmit Data Interrupt */ +#define GIVR_IT_RCV 0x03 /* Receive Good Data Interrupt */ +#define GIVR_IT_REXC 0x07 /* Receive Exception Interrupt */ + + +/* Global Interrupt Channel Register (R/W) */ + +#define GICR_CHAN 0x1c /* Channel Number Mask */ +#define GICR_CHAN_OFF 2 /* Channel Number shift */ + + +/* Channel Address Register (R/W) */ + +#define CAR_CHAN 0x07 /* Channel Number Mask */ +#define CAR_A7 0x08 /* A7 Address Extension (unused) */ + + +/* Receive Character Status Register (R/O) */ + +#define RCSR_TOUT 0x80 /* Rx Timeout */ +#define RCSR_SCDET 0x70 /* Special Character Detected Mask */ +#define RCSR_NO_SC 0x00 /* No Special Characters Detected */ +#define RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected */ +#define RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected */ +#define RCSR_SC_3 0x30 /* Special Char 3 Detected */ +#define RCSR_SC_4 0x40 /* Special Char 4 Detected */ +#define RCSR_BREAK 0x08 /* Break has been detected */ +#define RCSR_PE 0x04 /* Parity Error */ +#define RCSR_FE 0x02 /* Frame Error */ +#define RCSR_OE 0x01 /* Overrun Error */ + + +/* Channel Command Register (R/W) (commands in groups can be OR-ed) */ + +#define CCR_HARDRESET 0x81 /* Reset the chip */ + +#define CCR_SOFTRESET 0x80 /* Soft Channel Reset */ + +#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */ +#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */ +#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */ + +#define CCR_SSCH1 0x21 /* Send Special Character 1 */ + +#define CCR_SSCH2 0x22 /* Send Special Character 2 */ + +#define CCR_SSCH3 0x23 /* Send Special Character 3 */ + +#define CCR_SSCH4 0x24 /* Send Special Character 4 */ + +#define CCR_TXEN 0x18 /* Enable Transmitter */ +#define CCR_RXEN 0x12 /* Enable Receiver */ + +#define CCR_TXDIS 0x14 /* Disable Transmitter */ +#define CCR_RXDIS 0x11 /* Disable Receiver */ + + +/* Interrupt Enable Register (R/W) */ + +#define IER_DSR 0x80 /* Enable interrupt on DSR change */ +#define IER_CD 0x40 /* Enable interrupt on CD change */ +#define IER_CTS 0x20 /* Enable interrupt on CTS change */ +#define IER_RXD 0x10 /* Enable interrupt on Receive Data */ +#define IER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */ +#define IER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */ +#define IER_TXEMPTY 0x02 /* Enable interrupt on TX completely empty */ +#define IER_RET 0x01 /* Enable interrupt on RX Exc. Timeout */ + + +/* Channel Option Register 1 (R/W) */ + +#define COR1_ODDP 0x80 /* Odd Parity */ +#define COR1_PARMODE 0x60 /* Parity Mode mask */ +#define COR1_NOPAR 0x00 /* No Parity */ +#define COR1_FORCEPAR 0x20 /* Force Parity */ +#define COR1_NORMPAR 0x40 /* Normal Parity */ +#define COR1_IGNORE 0x10 /* Ignore Parity on RX */ +#define COR1_STOPBITS 0x0c /* Number of Stop Bits */ +#define COR1_1SB 0x00 /* 1 Stop Bit */ +#define COR1_15SB 0x04 /* 1.5 Stop Bits */ +#define COR1_2SB 0x08 /* 2 Stop Bits */ +#define COR1_CHARLEN 0x03 /* Character Length */ +#define COR1_5BITS 0x00 /* 5 bits */ +#define COR1_6BITS 0x01 /* 6 bits */ +#define COR1_7BITS 0x02 /* 7 bits */ +#define COR1_8BITS 0x03 /* 8 bits */ + + +/* Channel Option Register 2 (R/W) */ + +#define COR2_IXM 0x80 /* Implied XON mode */ +#define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */ +#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */ +#define COR2_LLM 0x10 /* Local Loopback Mode */ +#define COR2_RLM 0x08 /* Remote Loopback Mode */ +#define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */ +#define COR2_CTSAE 0x02 /* CTS Automatic Enable */ +#define COR2_DSRAE 0x01 /* DSR Automatic Enable */ + + +/* Channel Option Register 3 (R/W) */ + +#define COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3) */ +#define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4) */ +#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */ +#define COR3_SCDE 0x10 /* Special Character Detection Enable */ +#define COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8) */ + + +/* Channel Control Status Register (R/O) */ + +#define CCSR_RXEN 0x80 /* Receiver Enabled */ +#define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent) */ +#define CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent) */ +#define CCSR_TXEN 0x08 /* Transmitter Enabled */ +#define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */ +#define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */ + + +/* Modem Change Option Register 1 (R/W) */ + +#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */ +#define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */ +#define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */ +#define MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8) */ +#define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */ + + +/* Modem Change Option Register 2 (R/W) */ + +#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */ +#define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */ +#define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */ + +/* Modem Change Register (R/W) */ + +#define MCR_DSRCHG 0x80 /* DSR Changed */ +#define MCR_CDCHG 0x40 /* CD Changed */ +#define MCR_CTSCHG 0x20 /* CTS Changed */ + + +/* Modem Signal Value Register (R/W) */ + +#define MSVR_DSR 0x80 /* Current state of DSR input */ +#define MSVR_CD 0x40 /* Current state of CD input */ +#define MSVR_CTS 0x20 /* Current state of CTS input */ +#define MSVR_DTR 0x02 /* Current state of DTR output */ +#define MSVR_RTS 0x01 /* Current state of RTS output */ + + +/* Escape characters */ + +#define CD186x_C_ESC 0x00 /* Escape character */ +#define CD186x_C_SBRK 0x81 /* Start sending BREAK */ +#define CD186x_C_DELAY 0x82 /* Delay output */ +#define CD186x_C_EBRK 0x83 /* Stop sending BREAK */ + +#define SRSR_RREQint 0x10 /* This chip wants "rec" serviced */ +#define SRSR_TREQint 0x04 /* This chip wants "transmit" serviced */ +#define SRSR_MREQint 0x01 /* This chip wants "mdm change" serviced */ + + + +#define SRCR_PKGTYPE 0x80 +#define SRCR_REGACKEN 0x40 +#define SRCR_DAISYEN 0x20 +#define SRCR_GLOBPRI 0x10 +#define SRCR_UNFAIR 0x08 +#define SRCR_AUTOPRI 0x02 +#define SRCR_PRISEL 0x01 + + -- cgit v1.2.3 From 4c418ba9695a24917a1fcfa48f7db3fd76337eb7 Mon Sep 17 00:00:00 2001 From: "Doe, YiCheng" Date: Thu, 10 Mar 2011 14:00:21 -0600 Subject: ipmi: Fix IPMI errors due to timing problems This patch fixes an issue in OpenIPMI module where sometimes an ABORT command is sent after sending an IPMI request to BMC causing the IPMI request to fail. Signed-off-by: YiCheng Doe Signed-off-by: Corey Minyard Acked-by: Tom Mingarelli Tested-by: Andy Cress Tested-by: Mika Lansirine Tested-by: Brian De Wolf Cc: Jean Michel Audet Cc: Jozef Sudelsky Acked-by: Matthew Garrett Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 7855f9f45b8e..62787e30d508 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -900,6 +900,14 @@ static void sender(void *send_info, printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif + /* + * last_timeout_jiffies is updated here to avoid + * smi_timeout() handler passing very large time_diff + * value to smi_event_handler() that causes + * the send command to abort. + */ + smi_info->last_timeout_jiffies = jiffies; + mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); if (smi_info->thread) -- cgit v1.2.3 From 8ec3b8432e4fe8d452f88f1ed9a3450e715bb797 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:36 -0800 Subject: char: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- drivers/char/mwave/Makefile | 4 ++-- drivers/char/mwave/README | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mwave/Makefile b/drivers/char/mwave/Makefile index 26b4fce217b6..efa6a82e543d 100644 --- a/drivers/char/mwave/Makefile +++ b/drivers/char/mwave/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_MWAVE) += mwave.o mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o # To have the mwave driver disable other uarts if necessary -# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES +# ccflags-y := -DMWAVE_FUTZ_WITH_OTHER_DEVICES # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: -ccflags-y := -DMW_TRACE +ccflags-y += -DMW_TRACE diff --git a/drivers/char/mwave/README b/drivers/char/mwave/README index 480251fc78e2..c2a58f428bc8 100644 --- a/drivers/char/mwave/README +++ b/drivers/char/mwave/README @@ -11,7 +11,7 @@ are not saved by the BIOS and so do not persist after unload and reload. 0x0008 tp3780i tracing Tracing only occurs if the driver has been compiled with the - MW_TRACE macro #defined (i.e. let EXTRA_CFLAGS += -DMW_TRACE + MW_TRACE macro #defined (i.e. let ccflags-y := -DMW_TRACE in the Makefile). mwave_3780i_irq=5/7/10/11/15 -- cgit v1.2.3 From 0dcf334c44d99cd08515f4fc5cc9075abd92b2ff Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 23 Mar 2011 16:42:54 -0700 Subject: drivers/char/ipmi/ipmi_si_intf.c: fix cleanup_one_si section mismatch commit d2478521afc2022 ("char/ipmi: fix OOPS caused by pnp_unregister_driver on unregistered driver") introduced a section mismatch by calling __exit cleanup_ipmi_si from __devinit init_ipmi_si. Remove __exit annotation from cleanup_ipmi_si. Signed-off-by: Sergey Senozhatsky Acked-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index c86d43b88e1e..d28b484aee45 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -3521,7 +3521,7 @@ static void cleanup_one_si(struct smi_info *to_clean) kfree(to_clean); } -static void __exit cleanup_ipmi_si(void) +static void cleanup_ipmi_si(void) { struct smi_info *e, *tmp_e; -- cgit v1.2.3 From 73210a135b9dd53ba59beb4ced5a55633ae65b2f Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Wed, 23 Mar 2011 16:42:55 -0700 Subject: drivers/char: add MSM smd_pkt driver Add smd_pkt driver which provides device interface to smd packet ports. Signed-off-by: Niranjana Vishwanathapura Cc: Brian Swetland Cc: Greg KH Cc: Alan Cox Cc: David Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 8 + drivers/char/Makefile | 1 + drivers/char/msm_smd_pkt.c | 466 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+) create mode 100644 drivers/char/msm_smd_pkt.c (limited to 'drivers/char') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 04f8b2d083c6..ad59b4e0a9b5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -608,5 +608,13 @@ config RAMOOPS This enables panic and oops messages to be logged to a circular buffer in RAM where it can be read back at some later point. +config MSM_SMD_PKT + bool "Enable device interface for some SMD packet ports" + default n + depends on MSM_SMD + help + Enables userspace clients to read and write to some packet SMD + ports via device interface for MSM chipset. + endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 057f65452e7b..7a00672bd85d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o +obj-$(CONFIG_MSM_SMD_PKT) += msm_smd_pkt.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_MMTIMER) += mmtimer.o obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o diff --git a/drivers/char/msm_smd_pkt.c b/drivers/char/msm_smd_pkt.c new file mode 100644 index 000000000000..b6f8a65c9960 --- /dev/null +++ b/drivers/char/msm_smd_pkt.c @@ -0,0 +1,466 @@ +/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + */ +/* + * SMD Packet Driver -- Provides userspace interface to SMD packet ports. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NUM_SMD_PKT_PORTS 9 +#define DEVICE_NAME "smdpkt" +#define MAX_BUF_SIZE 2048 + +struct smd_pkt_dev { + struct cdev cdev; + struct device *devicep; + + struct smd_channel *ch; + int open_count; + struct mutex ch_lock; + struct mutex rx_lock; + struct mutex tx_lock; + wait_queue_head_t ch_read_wait_queue; + wait_queue_head_t ch_opened_wait_queue; + + int i; + + unsigned char tx_buf[MAX_BUF_SIZE]; + unsigned char rx_buf[MAX_BUF_SIZE]; + int remote_open; + +} *smd_pkt_devp[NUM_SMD_PKT_PORTS]; + +struct class *smd_pkt_classp; +static dev_t smd_pkt_number; + +static int msm_smd_pkt_debug_enable; +module_param_named(debug_enable, msm_smd_pkt_debug_enable, + int, S_IRUGO | S_IWUSR | S_IWGRP); + +#ifdef DEBUG +#define D_DUMP_BUFFER(prestr, cnt, buf) do { \ + int i; \ + if (msm_smd_pkt_debug_enable) { \ + pr_debug("%s", prestr); \ + for (i = 0; i < cnt; i++) \ + pr_debug("%.2x", buf[i]); \ + pr_debug("\n"); \ + } \ + } while (0) +#else +#define D_DUMP_BUFFER(prestr, cnt, buf) do {} while (0) +#endif + +#ifdef DEBUG +#define DBG(x...) do { \ + if (msm_smd_pkt_debug_enable) \ + pr_debug(x); \ + } while (0) +#else +#define DBG(x...) do {} while (0) +#endif + +static void check_and_wakeup_reader(struct smd_pkt_dev *smd_pkt_devp) +{ + int sz; + + if (!smd_pkt_devp || !smd_pkt_devp->ch) + return; + + sz = smd_cur_packet_size(smd_pkt_devp->ch); + if (sz == 0) { + DBG("no packet\n"); + return; + } + if (sz > smd_read_avail(smd_pkt_devp->ch)) { + DBG("incomplete packet\n"); + return; + } + + DBG("waking up reader\n"); + wake_up_interruptible(&smd_pkt_devp->ch_read_wait_queue); +} + +static int smd_pkt_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int r, bytes_read; + struct smd_pkt_dev *smd_pkt_devp; + struct smd_channel *chl; + + DBG("read %d bytes\n", count); + if (count > MAX_BUF_SIZE) + return -EINVAL; + + smd_pkt_devp = file->private_data; + if (!smd_pkt_devp || !smd_pkt_devp->ch) + return -EINVAL; + + chl = smd_pkt_devp->ch; +wait_for_packet: + r = wait_event_interruptible(smd_pkt_devp->ch_read_wait_queue, + (smd_cur_packet_size(chl) > 0 && + smd_read_avail(chl) >= + smd_cur_packet_size(chl))); + + if (r < 0) { + if (r != -ERESTARTSYS) + pr_err("wait returned %d\n", r); + return r; + } + + mutex_lock(&smd_pkt_devp->rx_lock); + + bytes_read = smd_cur_packet_size(smd_pkt_devp->ch); + if (bytes_read == 0 || + bytes_read < smd_read_avail(smd_pkt_devp->ch)) { + mutex_unlock(&smd_pkt_devp->rx_lock); + DBG("Nothing to read\n"); + goto wait_for_packet; + } + + if (bytes_read > count) { + mutex_unlock(&smd_pkt_devp->rx_lock); + pr_info("packet size %d > buffer size %d", bytes_read, count); + return -EINVAL; + } + + r = smd_read(smd_pkt_devp->ch, smd_pkt_devp->rx_buf, bytes_read); + if (r != bytes_read) { + mutex_unlock(&smd_pkt_devp->rx_lock); + pr_err("smd_read failed to read %d bytes: %d\n", bytes_read, r); + return -EIO; + } + + D_DUMP_BUFFER("read: ", bytes_read, smd_pkt_devp->rx_buf); + r = copy_to_user(buf, smd_pkt_devp->rx_buf, bytes_read); + mutex_unlock(&smd_pkt_devp->rx_lock); + if (r) { + pr_err("copy_to_user failed %d\n", r); + return -EFAULT; + } + + DBG("read complete %d bytes\n", bytes_read); + check_and_wakeup_reader(smd_pkt_devp); + + return bytes_read; +} + +static int smd_pkt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int r; + struct smd_pkt_dev *smd_pkt_devp; + + if (count > MAX_BUF_SIZE) + return -EINVAL; + + DBG("writting %d bytes\n", count); + + smd_pkt_devp = file->private_data; + if (!smd_pkt_devp || !smd_pkt_devp->ch) + return -EINVAL; + + mutex_lock(&smd_pkt_devp->tx_lock); + if (smd_write_avail(smd_pkt_devp->ch) < count) { + mutex_unlock(&smd_pkt_devp->tx_lock); + DBG("Not enough space to write\n"); + return -ENOMEM; + } + + D_DUMP_BUFFER("write: ", count, buf); + r = copy_from_user(smd_pkt_devp->tx_buf, buf, count); + if (r) { + mutex_unlock(&smd_pkt_devp->tx_lock); + pr_err("copy_from_user failed %d\n", r); + return -EFAULT; + } + + r = smd_write(smd_pkt_devp->ch, smd_pkt_devp->tx_buf, count); + if (r != count) { + mutex_unlock(&smd_pkt_devp->tx_lock); + pr_err("smd_write failed to write %d bytes: %d.\n", count, r); + return -EIO; + } + mutex_unlock(&smd_pkt_devp->tx_lock); + + DBG("wrote %d bytes\n", count); + return count; +} + +static unsigned int smd_pkt_poll(struct file *file, poll_table *wait) +{ + struct smd_pkt_dev *smd_pkt_devp; + unsigned int mask = 0; + + smd_pkt_devp = file->private_data; + if (!smd_pkt_devp) + return POLLERR; + + DBG("poll waiting\n"); + poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait); + if (smd_read_avail(smd_pkt_devp->ch)) + mask |= POLLIN | POLLRDNORM; + + DBG("poll return\n"); + return mask; +} + +static void smd_pkt_ch_notify(void *priv, unsigned event) +{ + struct smd_pkt_dev *smd_pkt_devp = priv; + + if (smd_pkt_devp->ch == 0) + return; + + switch (event) { + case SMD_EVENT_DATA: + DBG("data\n"); + check_and_wakeup_reader(smd_pkt_devp); + break; + + case SMD_EVENT_OPEN: + DBG("remote open\n"); + smd_pkt_devp->remote_open = 1; + wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue); + break; + + case SMD_EVENT_CLOSE: + smd_pkt_devp->remote_open = 0; + pr_info("remote closed\n"); + break; + + default: + pr_err("unknown event %d\n", event); + break; + } +} + +static char *smd_pkt_dev_name[] = { + "smdcntl0", + "smdcntl1", + "smdcntl2", + "smdcntl3", + "smdcntl4", + "smdcntl5", + "smdcntl6", + "smdcntl7", + "smd22", +}; + +static char *smd_ch_name[] = { + "DATA5_CNTL", + "DATA6_CNTL", + "DATA7_CNTL", + "DATA8_CNTL", + "DATA9_CNTL", + "DATA12_CNTL", + "DATA13_CNTL", + "DATA14_CNTL", + "DATA22", +}; + +static int smd_pkt_open(struct inode *inode, struct file *file) +{ + int r = 0; + struct smd_pkt_dev *smd_pkt_devp; + + smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev); + if (!smd_pkt_devp) + return -EINVAL; + + file->private_data = smd_pkt_devp; + + mutex_lock(&smd_pkt_devp->ch_lock); + if (smd_pkt_devp->open_count == 0) { + r = smd_open(smd_ch_name[smd_pkt_devp->i], + &smd_pkt_devp->ch, smd_pkt_devp, + smd_pkt_ch_notify); + if (r < 0) { + pr_err("smd_open failed for %s, %d\n", + smd_ch_name[smd_pkt_devp->i], r); + goto out; + } + + r = wait_event_interruptible_timeout( + smd_pkt_devp->ch_opened_wait_queue, + smd_pkt_devp->remote_open, + msecs_to_jiffies(2 * HZ)); + if (r == 0) + r = -ETIMEDOUT; + + if (r < 0) { + pr_err("wait returned %d\n", r); + smd_close(smd_pkt_devp->ch); + smd_pkt_devp->ch = 0; + } else { + smd_pkt_devp->open_count++; + r = 0; + } + } +out: + mutex_unlock(&smd_pkt_devp->ch_lock); + return r; +} + +static int smd_pkt_release(struct inode *inode, struct file *file) +{ + int r = 0; + struct smd_pkt_dev *smd_pkt_devp = file->private_data; + + if (!smd_pkt_devp) + return -EINVAL; + + mutex_lock(&smd_pkt_devp->ch_lock); + if (--smd_pkt_devp->open_count == 0) { + r = smd_close(smd_pkt_devp->ch); + smd_pkt_devp->ch = 0; + } + mutex_unlock(&smd_pkt_devp->ch_lock); + + return r; +} + +static const struct file_operations smd_pkt_fops = { + .owner = THIS_MODULE, + .open = smd_pkt_open, + .release = smd_pkt_release, + .read = smd_pkt_read, + .write = smd_pkt_write, + .poll = smd_pkt_poll, +}; + +static int __init smd_pkt_init(void) +{ + int i; + int r; + + r = alloc_chrdev_region(&smd_pkt_number, 0, + NUM_SMD_PKT_PORTS, DEVICE_NAME); + if (r) { + pr_err("alloc_chrdev_region() failed %d\n", r); + return r; + } + + smd_pkt_classp = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(smd_pkt_classp)) { + r = PTR_ERR(smd_pkt_classp); + pr_err("class_create() failed %d\n", r); + goto unreg_chardev; + } + + for (i = 0; i < NUM_SMD_PKT_PORTS; ++i) { + smd_pkt_devp[i] = kzalloc(sizeof(struct smd_pkt_dev), + GFP_KERNEL); + if (IS_ERR(smd_pkt_devp[i])) { + r = PTR_ERR(smd_pkt_devp[i]); + pr_err("kmalloc() failed %d\n", r); + goto clean_cdevs; + } + + smd_pkt_devp[i]->i = i; + + init_waitqueue_head(&smd_pkt_devp[i]->ch_read_wait_queue); + smd_pkt_devp[i]->remote_open = 0; + init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue); + + mutex_init(&smd_pkt_devp[i]->ch_lock); + mutex_init(&smd_pkt_devp[i]->rx_lock); + mutex_init(&smd_pkt_devp[i]->tx_lock); + + cdev_init(&smd_pkt_devp[i]->cdev, &smd_pkt_fops); + smd_pkt_devp[i]->cdev.owner = THIS_MODULE; + + r = cdev_add(&smd_pkt_devp[i]->cdev, + (smd_pkt_number + i), 1); + if (r) { + pr_err("cdev_add() failed %d\n", r); + kfree(smd_pkt_devp[i]); + goto clean_cdevs; + } + + smd_pkt_devp[i]->devicep = + device_create(smd_pkt_classp, NULL, + (smd_pkt_number + i), NULL, + smd_pkt_dev_name[i]); + if (IS_ERR(smd_pkt_devp[i]->devicep)) { + r = PTR_ERR(smd_pkt_devp[i]->devicep); + pr_err("device_create() failed %d\n", r); + cdev_del(&smd_pkt_devp[i]->cdev); + kfree(smd_pkt_devp[i]); + goto clean_cdevs; + } + + } + + pr_info("SMD Packet Port Driver Initialized.\n"); + return 0; + +clean_cdevs: + if (i > 0) { + while (--i >= 0) { + mutex_destroy(&smd_pkt_devp[i]->ch_lock); + mutex_destroy(&smd_pkt_devp[i]->rx_lock); + mutex_destroy(&smd_pkt_devp[i]->tx_lock); + cdev_del(&smd_pkt_devp[i]->cdev); + kfree(smd_pkt_devp[i]); + device_destroy(smd_pkt_classp, + MKDEV(MAJOR(smd_pkt_number), i)); + } + } + + class_destroy(smd_pkt_classp); +unreg_chardev: + unregister_chrdev_region(MAJOR(smd_pkt_number), NUM_SMD_PKT_PORTS); + return r; +} +module_init(smd_pkt_init); + +static void __exit smd_pkt_cleanup(void) +{ + int i; + + for (i = 0; i < NUM_SMD_PKT_PORTS; ++i) { + mutex_destroy(&smd_pkt_devp[i]->ch_lock); + mutex_destroy(&smd_pkt_devp[i]->rx_lock); + mutex_destroy(&smd_pkt_devp[i]->tx_lock); + cdev_del(&smd_pkt_devp[i]->cdev); + kfree(smd_pkt_devp[i]); + device_destroy(smd_pkt_classp, + MKDEV(MAJOR(smd_pkt_number), i)); + } + + class_destroy(smd_pkt_classp); + unregister_chrdev_region(MAJOR(smd_pkt_number), NUM_SMD_PKT_PORTS); +} +module_exit(smd_pkt_cleanup); + +MODULE_DESCRIPTION("MSM Shared Memory Packet Port"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From cfaf346cb2741ca648d83527df173b759381e607 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Wed, 23 Mar 2011 16:42:58 -0700 Subject: drivers/char/mem.c: clean up the code Reduce the lines of code and simplify the logic. Signed-off-by: Changli Gao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mem.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 1256454b2d43..436a99017998 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -47,10 +47,7 @@ static inline unsigned long size_inside_page(unsigned long start, #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE static inline int valid_phys_addr_range(unsigned long addr, size_t count) { - if (addr + count > __pa(high_memory)) - return 0; - - return 1; + return addr + count <= __pa(high_memory); } static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) -- cgit v1.2.3 From 1309d7afbed112f0e8e90be9af975550caa0076b Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 29 Mar 2011 13:31:25 +0200 Subject: char/tpm: Fix unitialized usage of data buffer This patch fixes information leakage to the userspace by initializing the data buffer to zero. Reported-by: Peter Huewe Signed-off-by: Peter Huewe Signed-off-by: Marcel Selhorst [ Also removed the silly "* sizeof(u8)". If that isn't 1, we have way deeper problems than a simple multiplication can fix. - Linus ] Signed-off-by: Linus Torvalds --- drivers/char/tpm/tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 1f46f1cd9225..7beb0e25f1e1 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -980,7 +980,7 @@ int tpm_open(struct inode *inode, struct file *file) return -EBUSY; } - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); + chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL); if (chip->data_buffer == NULL) { clear_bit(0, &chip->is_open); put_device(chip->dev); -- cgit v1.2.3 From 25985edcedea6396277003854657b5f3cb31a628 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 30 Mar 2011 22:57:33 -0300 Subject: Fix common misspellings Fixes generated by 'codespell' and manually reviewed. Signed-off-by: Lucas De Marchi --- CREDITS | 6 +-- Documentation/ABI/testing/sysfs-bus-css | 2 +- Documentation/ABI/testing/sysfs-class-led | 2 +- Documentation/DocBook/dvb/dvbproperty.xml | 2 +- Documentation/DocBook/dvb/frontend.xml | 2 +- Documentation/DocBook/kernel-locking.tmpl | 2 +- Documentation/DocBook/libata.tmpl | 10 ++-- Documentation/DocBook/mtdnand.tmpl | 12 ++--- Documentation/DocBook/regulator.tmpl | 4 +- Documentation/DocBook/uio-howto.tmpl | 2 +- Documentation/DocBook/usb.tmpl | 2 +- Documentation/DocBook/v4l/common.xml | 2 +- Documentation/DocBook/v4l/controls.xml | 2 +- Documentation/DocBook/v4l/dev-subdev.xml | 2 +- Documentation/DocBook/v4l/libv4l.xml | 2 +- Documentation/DocBook/v4l/remote_controllers.xml | 2 +- Documentation/DocBook/writing-an-alsa-driver.tmpl | 2 +- Documentation/PCI/MSI-HOWTO.txt | 4 +- Documentation/SecurityBugs | 2 +- Documentation/SubmittingDrivers | 2 +- Documentation/SubmittingPatches | 2 +- Documentation/arm/IXP4xx | 4 +- Documentation/arm/Samsung-S3C24XX/Suspend.txt | 2 +- Documentation/arm/Samsung/GPIO.txt | 2 +- Documentation/block/biodoc.txt | 4 +- Documentation/cpu-hotplug.txt | 2 +- Documentation/dell_rbu.txt | 2 +- Documentation/device-mapper/dm-service-time.txt | 2 +- Documentation/devicetree/bindings/fb/sm501fb.txt | 4 +- .../devicetree/bindings/mtd/fsl-upm-nand.txt | 2 +- .../devicetree/bindings/net/can/sja1000.txt | 2 +- .../devicetree/bindings/powerpc/fsl/mpic.txt | 2 +- Documentation/dvb/README.dvb-usb | 2 +- Documentation/dvb/ci.txt | 2 +- Documentation/dvb/faq.txt | 2 +- Documentation/edac.txt | 2 +- Documentation/eisa.txt | 2 +- Documentation/fb/viafb.txt | 4 +- .../filesystems/autofs4-mount-control.txt | 2 +- Documentation/filesystems/caching/netfs-api.txt | 18 ++++---- Documentation/filesystems/configfs/configfs.txt | 2 +- Documentation/filesystems/ext4.txt | 4 +- Documentation/filesystems/gfs2-uevents.txt | 2 +- Documentation/filesystems/gfs2.txt | 2 +- Documentation/filesystems/ntfs.txt | 2 +- Documentation/filesystems/ocfs2.txt | 2 +- Documentation/filesystems/path-lookup.txt | 4 +- .../filesystems/pohmelfs/network_protocol.txt | 2 +- Documentation/filesystems/proc.txt | 6 +-- Documentation/filesystems/squashfs.txt | 2 +- Documentation/filesystems/sysfs.txt | 2 +- Documentation/filesystems/vfs.txt | 2 +- .../filesystems/xfs-delayed-logging-design.txt | 8 ++-- Documentation/hwmon/abituguru | 2 +- Documentation/hwmon/abituguru-datasheet | 8 ++-- Documentation/hwmon/abituguru3 | 2 +- Documentation/hwmon/pmbus | 6 +-- Documentation/hwmon/sysfs-interface | 2 +- Documentation/hwmon/w83781d | 2 +- Documentation/hwmon/w83791d | 2 +- Documentation/i2c/busses/i2c-parport-light | 2 +- Documentation/i2c/busses/i2c-sis96x | 2 +- Documentation/i2c/busses/i2c-taos-evm | 2 +- Documentation/i2o/README | 2 +- Documentation/ia64/aliasing-test.c | 2 +- Documentation/input/joystick-parport.txt | 2 +- Documentation/input/rotary-encoder.txt | 2 +- Documentation/input/walkera0701.txt | 2 +- Documentation/irqflags-tracing.txt | 2 +- Documentation/isdn/INTERFACE.CAPI | 2 +- Documentation/kbuild/kbuild.txt | 8 ++-- Documentation/kernel-parameters.txt | 2 +- Documentation/kvm/mmu.txt | 2 +- Documentation/kvm/ppc-pv.txt | 2 +- Documentation/kvm/timekeeping.txt | 2 +- Documentation/media-framework.txt | 4 +- Documentation/mips/AU1xxx_IDE.README | 4 +- Documentation/misc-devices/ics932s401 | 2 +- Documentation/networking/3c359.txt | 2 +- Documentation/networking/README.ipw2200 | 2 +- Documentation/networking/bonding.txt | 2 +- Documentation/networking/caif/Linux-CAIF.txt | 2 +- Documentation/networking/caif/spi_porting.txt | 2 +- Documentation/networking/can.txt | 2 +- Documentation/networking/ieee802154.txt | 2 +- Documentation/networking/olympic.txt | 2 +- Documentation/networking/packet_mmap.txt | 2 +- Documentation/networking/s2io.txt | 4 +- Documentation/networking/tc-actions-env-rules.txt | 4 +- Documentation/power/devices.txt | 2 +- Documentation/power/notifiers.txt | 4 +- Documentation/power/opp.txt | 2 +- Documentation/power/swsusp.txt | 4 +- Documentation/power/userland-swsusp.txt | 6 +-- Documentation/powerpc/hvcs.txt | 2 +- Documentation/scsi/ChangeLog.lpfc | 18 ++++---- Documentation/scsi/ChangeLog.megaraid | 2 +- Documentation/scsi/ChangeLog.ncr53c8xx | 2 +- Documentation/scsi/ChangeLog.sym53c8xx | 2 +- Documentation/scsi/aha152x.txt | 2 +- Documentation/scsi/aic79xx.txt | 12 ++--- Documentation/scsi/ibmmca.txt | 4 +- Documentation/scsi/scsi-changer.txt | 2 +- Documentation/scsi/scsi_eh.txt | 2 +- Documentation/scsi/scsi_fc_transport.txt | 2 +- Documentation/serial/moxa-smartio | 2 +- Documentation/serial/n_gsm.txt | 2 +- Documentation/sound/alsa/ALSA-Configuration.txt | 4 +- Documentation/sound/oss/README.OSS | 2 +- Documentation/spi/pxa2xx | 2 +- Documentation/spi/spi-lm70llp | 2 +- Documentation/telephony/ixj.txt | 2 +- Documentation/trace/ring-buffer-design.txt | 2 +- Documentation/video4linux/README.pvrusb2 | 2 +- Documentation/video4linux/bttv/README | 2 +- Documentation/video4linux/bttv/README.freeze | 2 +- Documentation/video4linux/bttv/Sound-FAQ | 2 +- Documentation/video4linux/pxa_camera.txt | 8 ++-- Documentation/video4linux/v4l2-framework.txt | 2 +- Documentation/vm/active_mm.txt | 2 +- Documentation/vm/hugetlbpage.txt | 2 +- Documentation/vm/overcommit-accounting | 2 +- Documentation/w1/slaves/w1_ds2423 | 6 +-- Documentation/w1/w1.netlink | 2 +- Documentation/watchdog/hpwdt.txt | 2 +- arch/alpha/include/asm/elf.h | 2 +- arch/alpha/kernel/core_lca.c | 4 +- arch/alpha/kernel/err_marvel.c | 2 +- arch/alpha/lib/ev67-strrchr.S | 2 +- arch/alpha/lib/fls.c | 2 +- arch/alpha/lib/strrchr.S | 2 +- arch/alpha/oprofile/op_model_ev67.c | 2 +- arch/arm/Kconfig | 2 +- arch/arm/Kconfig-nommu | 2 +- arch/arm/common/pl330.c | 4 +- arch/arm/include/asm/fpstate.h | 2 +- arch/arm/include/asm/glue-cache.h | 2 +- arch/arm/include/asm/glue.h | 4 +- arch/arm/include/asm/hardware/pl080.h | 2 +- arch/arm/include/asm/system.h | 2 +- arch/arm/include/asm/ucontext.h | 2 +- arch/arm/kernel/swp_emulate.c | 2 +- arch/arm/mach-at91/board-carmeva.c | 2 +- arch/arm/mach-at91/include/mach/at91_mci.h | 2 +- arch/arm/mach-at91/include/mach/gpio.h | 2 +- arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c | 6 +-- arch/arm/mach-bcmring/dma.c | 4 +- arch/arm/mach-bcmring/include/csp/dmacHw.h | 6 +-- .../mach-bcmring/include/mach/csp/chipcHw_def.h | 2 +- .../mach-bcmring/include/mach/csp/chipcHw_inline.h | 2 +- .../arm/mach-bcmring/include/mach/csp/intcHw_reg.h | 4 +- arch/arm/mach-bcmring/include/mach/reg_umi.h | 2 +- arch/arm/mach-davinci/board-neuros-osd2.c | 2 +- arch/arm/mach-davinci/cpufreq.c | 2 +- arch/arm/mach-davinci/da850.c | 2 +- arch/arm/mach-davinci/dm355.c | 2 +- arch/arm/mach-davinci/dm644x.c | 2 +- arch/arm/mach-davinci/include/mach/cputype.h | 2 +- arch/arm/mach-ep93xx/gpio.c | 2 +- arch/arm/mach-exynos4/include/mach/gpio.h | 2 +- arch/arm/mach-exynos4/mct.c | 2 +- arch/arm/mach-exynos4/setup-sdhci-gpio.c | 4 +- arch/arm/mach-exynos4/setup-sdhci.c | 2 +- arch/arm/mach-iop13xx/pci.c | 4 +- arch/arm/mach-kirkwood/tsx1x-common.c | 2 +- arch/arm/mach-lpc32xx/pm.c | 2 +- arch/arm/mach-mmp/time.c | 2 +- arch/arm/mach-msm/acpuclock-arm11.c | 2 +- arch/arm/mach-msm/scm.c | 2 +- arch/arm/mach-omap1/ams-delta-fiq-handler.S | 2 +- arch/arm/mach-omap1/board-sx1.c | 2 +- arch/arm/mach-omap1/devices.c | 2 +- arch/arm/mach-omap1/include/mach/ams-delta-fiq.h | 2 +- arch/arm/mach-omap2/board-igep0020.c | 2 +- arch/arm/mach-omap2/board-igep0030.c | 2 +- arch/arm/mach-omap2/clockdomain.c | 2 +- arch/arm/mach-omap2/clockdomain.h | 2 +- arch/arm/mach-omap2/cpuidle34xx.c | 4 +- arch/arm/mach-omap2/devices.c | 6 +-- arch/arm/mach-omap2/dma.c | 2 +- arch/arm/mach-omap2/gpio.c | 2 +- arch/arm/mach-omap2/hsmmc.c | 2 +- arch/arm/mach-omap2/mcbsp.c | 2 +- arch/arm/mach-omap2/mux.c | 2 +- arch/arm/mach-omap2/mux2430.h | 2 +- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 2 +- arch/arm/mach-omap2/omap_phy_internal.c | 4 +- arch/arm/mach-omap2/omap_twl.c | 2 +- arch/arm/mach-omap2/powerdomain.c | 2 +- arch/arm/mach-omap2/powerdomain.h | 2 +- arch/arm/mach-omap2/powerdomains3xxx_data.c | 2 +- arch/arm/mach-omap2/smartreflex.c | 2 +- arch/arm/mach-omap2/voltage.c | 4 +- arch/arm/mach-orion5x/addr-map.c | 2 +- arch/arm/mach-orion5x/net2big-setup.c | 2 +- arch/arm/mach-orion5x/ts209-setup.c | 2 +- arch/arm/mach-orion5x/ts409-setup.c | 2 +- arch/arm/mach-pxa/include/mach/pxa3xx-regs.h | 2 +- arch/arm/mach-pxa/include/mach/zeus.h | 2 +- arch/arm/mach-pxa/mioa701.c | 2 +- arch/arm/mach-s3c2410/include/mach/dma.h | 2 +- arch/arm/mach-s3c2410/include/mach/regs-mem.h | 2 +- arch/arm/mach-s3c2410/mach-n30.c | 2 +- arch/arm/mach-s3c2440/mach-mini2440.c | 2 +- arch/arm/mach-s3c64xx/dma.c | 2 +- arch/arm/mach-s5pc100/include/mach/regs-fb.h | 2 +- arch/arm/mach-s5pc100/setup-sdhci.c | 2 +- arch/arm/mach-s5pv210/include/mach/gpio.h | 2 +- arch/arm/mach-s5pv210/setup-sdhci-gpio.c | 4 +- arch/arm/mach-s5pv210/setup-sdhci.c | 2 +- arch/arm/mach-sa1100/Makefile | 2 +- arch/arm/mach-sa1100/cpu-sa1100.c | 2 +- arch/arm/mach-sa1100/include/mach/SA-1100.h | 2 +- arch/arm/mach-sa1100/jornada720_ssp.c | 4 +- arch/arm/mach-tegra/dma.c | 4 +- arch/arm/mach-tegra/include/mach/dma.h | 4 +- arch/arm/mach-u300/clock.c | 6 +-- arch/arm/mach-ux500/board-mop500.c | 2 +- arch/arm/mach-ux500/include/mach/db8500-regs.h | 10 ++-- arch/arm/mm/cache-v4wb.S | 2 +- arch/arm/mm/cache-v4wt.S | 2 +- arch/arm/mm/cache-v7.S | 2 +- arch/arm/mm/proc-arm1020.S | 2 +- arch/arm/mm/proc-arm1020e.S | 2 +- arch/arm/mm/proc-arm1022.S | 2 +- arch/arm/mm/proc-arm1026.S | 2 +- arch/arm/mm/proc-arm720.S | 2 +- arch/arm/mm/proc-arm920.S | 2 +- arch/arm/mm/proc-arm922.S | 2 +- arch/arm/mm/proc-arm925.S | 2 +- arch/arm/mm/proc-macros.S | 2 +- arch/arm/mm/proc-v6.S | 4 +- arch/arm/mm/proc-v7.S | 2 +- arch/arm/plat-mxc/cpufreq.c | 2 +- arch/arm/plat-mxc/include/mach/entry-macro.S | 4 +- arch/arm/plat-mxc/include/mach/mxc_nand.h | 2 +- arch/arm/plat-omap/devices.c | 2 +- arch/arm/plat-omap/dma.c | 4 +- arch/arm/plat-omap/include/plat/gpio.h | 2 +- arch/arm/plat-omap/include/plat/gpmc.h | 2 +- arch/arm/plat-omap/mcbsp.c | 2 +- arch/arm/plat-pxa/include/plat/mfp.h | 2 +- arch/arm/plat-s3c24xx/Makefile | 2 +- arch/arm/plat-s3c24xx/cpu-freq.c | 2 +- arch/arm/plat-s3c24xx/dma.c | 2 +- arch/arm/plat-s5p/irq-gpioint.c | 2 +- arch/arm/plat-samsung/include/plat/clock.h | 2 +- .../plat-samsung/include/plat/gpio-cfg-helpers.h | 2 +- arch/arm/plat-samsung/include/plat/gpio-cfg.h | 6 +-- arch/arm/plat-samsung/include/plat/gpio-core.h | 2 +- arch/arm/plat-samsung/include/plat/sdhci.h | 4 +- arch/arm/plat-samsung/s3c-pl330.c | 2 +- arch/arm/plat-spear/include/plat/clock.h | 2 +- arch/blackfin/Kconfig.debug | 2 +- arch/blackfin/include/asm/traps.h | 2 +- arch/blackfin/kernel/kgdb.c | 2 +- arch/blackfin/kernel/traps.c | 2 +- arch/blackfin/lib/ins.S | 2 +- arch/blackfin/lib/memmove.S | 2 +- arch/blackfin/mach-bf537/boards/stamp.c | 2 +- arch/blackfin/mach-common/entry.S | 4 +- arch/blackfin/mach-common/head.S | 2 +- arch/cris/arch-v10/README.mm | 2 +- arch/cris/arch-v10/drivers/sync_serial.c | 2 +- arch/cris/arch-v32/drivers/axisflashmap.c | 2 +- arch/cris/arch-v32/drivers/mach-a3/nandflash.c | 2 +- arch/cris/arch-v32/drivers/mach-fs/nandflash.c | 2 +- arch/cris/arch-v32/drivers/sync_serial.c | 2 +- arch/cris/arch-v32/kernel/entry.S | 2 +- arch/cris/arch-v32/kernel/irq.c | 2 +- arch/cris/arch-v32/kernel/kgdb.c | 2 +- arch/cris/arch-v32/kernel/process.c | 2 +- arch/cris/arch-v32/kernel/signal.c | 2 +- arch/cris/arch-v32/mach-a3/arbiter.c | 4 +- arch/cris/arch-v32/mach-fs/arbiter.c | 2 +- arch/cris/boot/rescue/head_v10.S | 2 +- arch/cris/include/arch-v32/arch/hwregs/Makefile | 2 +- .../cris/include/arch-v32/arch/hwregs/iop/Makefile | 2 +- arch/cris/include/asm/pgtable.h | 2 +- arch/cris/kernel/traps.c | 2 +- arch/frv/include/asm/pci.h | 2 +- arch/frv/include/asm/spr-regs.h | 2 +- arch/frv/include/asm/virtconvert.h | 2 +- arch/frv/kernel/entry-table.S | 4 +- arch/ia64/Kconfig | 4 +- arch/ia64/include/asm/pal.h | 2 +- arch/ia64/include/asm/perfmon_default_smpl.h | 4 +- arch/ia64/include/asm/sn/bte.h | 2 +- arch/ia64/include/asm/sn/shub_mmr.h | 2 +- arch/ia64/include/asm/sn/shubio.h | 4 +- arch/ia64/kernel/cyclone.c | 2 +- arch/ia64/kernel/perfmon_default_smpl.c | 2 +- arch/ia64/kernel/smpboot.c | 2 +- arch/ia64/kernel/topology.c | 2 +- arch/ia64/kvm/process.c | 2 +- arch/ia64/lib/do_csum.S | 2 +- arch/ia64/sn/kernel/irq.c | 4 +- arch/ia64/sn/pci/pcibr/pcibr_dma.c | 2 +- arch/m32r/include/asm/m32104ut/m32104ut_pld.h | 2 +- arch/m32r/include/asm/m32700ut/m32700ut_pld.h | 2 +- arch/m32r/include/asm/opsput/opsput_pld.h | 2 +- arch/m32r/include/asm/pgtable-2level.h | 2 +- arch/m32r/mm/fault.c | 4 +- arch/m68k/atari/atakeyb.c | 2 +- arch/m68k/fpsp040/bindec.S | 2 +- arch/m68k/ifpsp060/src/fpsp.S | 10 ++-- arch/m68k/ifpsp060/src/pfpsp.S | 8 ++-- arch/m68k/include/asm/atariints.h | 2 +- arch/m68k/include/asm/bootstd.h | 2 +- arch/m68k/include/asm/commproc.h | 4 +- arch/m68k/include/asm/delay_no.h | 2 +- arch/m68k/include/asm/gpio.h | 2 +- arch/m68k/include/asm/m520xsim.h | 2 +- arch/m68k/include/asm/m523xsim.h | 2 +- arch/m68k/include/asm/m527xsim.h | 2 +- arch/m68k/include/asm/m5307sim.h | 2 +- arch/m68k/include/asm/m5407sim.h | 2 +- arch/m68k/include/asm/m68360_quicc.h | 2 +- arch/m68k/include/asm/mac_oss.h | 2 +- arch/m68k/include/asm/mac_via.h | 2 +- arch/m68k/include/asm/macintosh.h | 2 +- arch/m68k/include/asm/mcftimer.h | 2 +- arch/m68k/kernel/head.S | 12 ++--- arch/m68k/kernel/vmlinux.lds_no.S | 2 +- arch/m68k/platform/523x/config.c | 2 +- arch/m68k/platform/5272/intc.c | 2 +- arch/m68k/platform/527x/config.c | 2 +- arch/m68k/platform/528x/config.c | 2 +- arch/m68k/platform/coldfire/cache.c | 2 +- arch/m68k/platform/coldfire/entry.S | 2 +- arch/m68k/platform/coldfire/head.S | 2 +- arch/m68k/platform/coldfire/intc.c | 2 +- arch/m68k/platform/coldfire/sltimers.c | 2 +- arch/m68k/q40/README | 2 +- arch/microblaze/Makefile | 2 +- arch/microblaze/include/asm/io.h | 2 +- arch/microblaze/include/asm/pci-bridge.h | 2 +- arch/microblaze/include/asm/pci.h | 2 +- arch/microblaze/kernel/cpu/cache.c | 2 +- arch/microblaze/lib/memcpy.c | 8 ++-- arch/microblaze/lib/memmove.c | 6 +-- arch/microblaze/lib/memset.c | 2 +- arch/microblaze/pci/indirect_pci.c | 2 +- arch/microblaze/platform/generic/Kconfig.auto | 2 +- arch/mips/Kconfig | 2 +- arch/mips/Makefile | 4 +- arch/mips/alchemy/common/clocks.c | 2 +- arch/mips/cavium-octeon/executive/octeon-model.c | 2 +- arch/mips/cavium-octeon/octeon-platform.c | 2 +- arch/mips/cavium-octeon/setup.c | 2 +- arch/mips/fw/arc/promlib.c | 2 +- arch/mips/include/asm/dec/prom.h | 2 +- arch/mips/include/asm/floppy.h | 2 +- arch/mips/include/asm/hw_irq.h | 2 +- arch/mips/include/asm/io.h | 2 +- arch/mips/include/asm/irqflags.h | 2 +- arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h | 2 +- arch/mips/include/asm/mach-ip32/mc146818rtc.h | 2 +- .../mips/include/asm/mach-loongson/cs5536/cs5536.h | 2 +- arch/mips/include/asm/mach-pb1x00/pb1000.h | 2 +- arch/mips/include/asm/mach-pb1x00/pb1200.h | 2 +- arch/mips/include/asm/mach-pb1x00/pb1550.h | 2 +- arch/mips/include/asm/mach-powertv/dma-coherence.h | 2 +- arch/mips/include/asm/mipsregs.h | 4 +- arch/mips/include/asm/octeon/cvmx-bootinfo.h | 2 +- arch/mips/include/asm/octeon/cvmx-bootmem.h | 2 +- arch/mips/include/asm/octeon/cvmx-l2c.h | 2 +- arch/mips/include/asm/octeon/cvmx.h | 2 +- arch/mips/include/asm/paccess.h | 2 +- arch/mips/include/asm/pci/bridge.h | 2 +- .../include/asm/pmc-sierra/msp71xx/msp_regops.h | 2 +- arch/mips/include/asm/processor.h | 2 +- arch/mips/include/asm/sgi/ioc.h | 2 +- arch/mips/include/asm/sibyte/sb1250_mac.h | 4 +- arch/mips/include/asm/siginfo.h | 2 +- arch/mips/include/asm/sn/klconfig.h | 4 +- arch/mips/include/asm/sn/sn0/hubio.h | 2 +- arch/mips/include/asm/stackframe.h | 2 +- arch/mips/include/asm/war.h | 2 +- arch/mips/jz4740/board-qi_lb60.c | 4 +- arch/mips/kernel/cpu-bugs64.c | 2 +- arch/mips/kernel/perf_event_mipsxx.c | 2 +- arch/mips/kernel/process.c | 2 +- arch/mips/kernel/smp-mt.c | 2 +- arch/mips/kernel/time.c | 2 +- arch/mips/kernel/vpe.c | 2 +- arch/mips/lib/strnlen_user.S | 2 +- arch/mips/math-emu/dp_fsp.c | 2 +- arch/mips/math-emu/dp_mul.c | 2 +- arch/mips/math-emu/dsemul.c | 2 +- arch/mips/math-emu/sp_mul.c | 2 +- arch/mips/mm/cex-sb1.S | 2 +- arch/mips/mm/tlbex.c | 2 +- arch/mips/mti-malta/malta-smtc.c | 2 +- arch/mips/pci/ops-pmcmsp.c | 4 +- arch/mips/pci/pci-bcm1480.c | 2 +- arch/mips/pci/pci-octeon.c | 4 +- arch/mips/pci/pci.c | 2 +- arch/mips/pmc-sierra/msp71xx/msp_setup.c | 2 +- arch/mips/pnx833x/common/platform.c | 2 +- arch/mips/sgi-ip27/Kconfig | 2 +- arch/mips/sgi-ip27/TODO | 2 +- arch/mips/sgi-ip27/ip27-init.c | 2 +- arch/mips/sgi-ip27/ip27-irq.c | 2 +- arch/mn10300/include/asm/cpu-regs.h | 2 +- arch/parisc/include/asm/eisa_eeprom.h | 2 +- arch/parisc/kernel/entry.S | 10 ++-- arch/parisc/kernel/head.S | 2 +- arch/parisc/kernel/inventory.c | 2 +- arch/parisc/kernel/signal.c | 2 +- arch/parisc/kernel/syscall.S | 2 +- arch/parisc/kernel/syscall_table.S | 2 +- arch/parisc/math-emu/dfadd.c | 2 +- arch/parisc/math-emu/dfsub.c | 2 +- arch/parisc/math-emu/fmpyfadd.c | 8 ++-- arch/parisc/math-emu/sfadd.c | 2 +- arch/parisc/math-emu/sfsub.c | 2 +- arch/powerpc/include/asm/bitops.h | 4 +- arch/powerpc/include/asm/compat.h | 2 +- arch/powerpc/include/asm/cpm.h | 2 +- arch/powerpc/include/asm/cpm1.h | 2 +- arch/powerpc/include/asm/hvcall.h | 2 +- arch/powerpc/include/asm/kprobes.h | 2 +- arch/powerpc/include/asm/lppaca.h | 2 +- arch/powerpc/include/asm/page_64.h | 2 +- arch/powerpc/include/asm/pasemi_dma.h | 2 +- arch/powerpc/include/asm/pci-bridge.h | 2 +- arch/powerpc/include/asm/pmac_feature.h | 4 +- arch/powerpc/include/asm/pte-common.h | 4 +- arch/powerpc/include/asm/reg_booke.h | 2 +- arch/powerpc/include/asm/spu_priv1.h | 2 +- arch/powerpc/include/asm/uninorth.h | 2 +- arch/powerpc/include/asm/vdso_datapage.h | 2 +- arch/powerpc/kernel/btext.c | 2 +- arch/powerpc/kernel/exceptions-64e.S | 2 +- arch/powerpc/kernel/exceptions-64s.S | 2 +- arch/powerpc/kernel/head_40x.S | 2 +- arch/powerpc/kernel/head_44x.S | 2 +- arch/powerpc/kernel/head_64.S | 2 +- arch/powerpc/kernel/head_fsl_booke.S | 2 +- arch/powerpc/kernel/l2cr_6xx.S | 2 +- arch/powerpc/kernel/lparcfg.c | 2 +- arch/powerpc/kernel/perf_event.c | 2 +- arch/powerpc/kernel/ppc_save_regs.S | 2 +- arch/powerpc/kernel/prom.c | 4 +- arch/powerpc/kernel/ptrace.c | 2 +- arch/powerpc/kernel/rtasd.c | 2 +- arch/powerpc/kernel/swsusp_32.S | 2 +- arch/powerpc/kernel/traps.c | 2 +- arch/powerpc/kernel/udbg_16550.c | 2 +- arch/powerpc/kernel/vdso32/sigtramp.S | 2 +- arch/powerpc/kernel/vdso64/sigtramp.S | 2 +- arch/powerpc/mm/hash_low_64.S | 24 +++++----- arch/powerpc/mm/hash_utils_64.c | 2 +- arch/powerpc/mm/mem.c | 2 +- arch/powerpc/mm/numa.c | 10 ++-- arch/powerpc/mm/tlb_low_64e.S | 4 +- arch/powerpc/oprofile/op_model_cell.c | 6 +-- arch/powerpc/oprofile/op_model_power4.c | 2 +- arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c | 6 +-- arch/powerpc/platforms/52xx/mpc52xx_pic.c | 2 +- arch/powerpc/platforms/cell/spufs/lscsa_alloc.c | 2 +- arch/powerpc/platforms/cell/spufs/sched.c | 2 +- arch/powerpc/platforms/cell/spufs/spu_restore.c | 2 +- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/viopath.c | 8 ++-- arch/powerpc/platforms/pasemi/dma_lib.c | 4 +- arch/powerpc/platforms/powermac/Makefile | 2 +- arch/powerpc/platforms/powermac/low_i2c.c | 2 +- arch/powerpc/platforms/powermac/pci.c | 2 +- arch/powerpc/platforms/pseries/dlpar.c | 2 +- arch/powerpc/platforms/pseries/eeh.c | 2 +- arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +- arch/powerpc/platforms/pseries/iommu.c | 6 +-- arch/powerpc/platforms/pseries/xics.c | 2 +- arch/powerpc/sysdev/axonram.c | 2 +- arch/powerpc/sysdev/bestcomm/bestcomm.h | 2 +- arch/powerpc/sysdev/bestcomm/bestcomm_priv.h | 2 +- arch/powerpc/sysdev/cpm1.c | 2 +- arch/powerpc/sysdev/indirect_pci.c | 2 +- arch/powerpc/sysdev/ppc4xx_pci.h | 2 +- arch/s390/include/asm/atomic.h | 2 +- arch/s390/include/asm/cio.h | 2 +- arch/s390/kernel/reipl64.S | 2 +- arch/s390/kernel/setup.c | 2 +- arch/s390/kernel/time.c | 6 +-- arch/s390/kernel/vtime.c | 2 +- arch/s390/kvm/kvm-s390.c | 2 +- arch/s390/kvm/priv.c | 2 +- arch/s390/mm/fault.c | 2 +- arch/score/Makefile | 2 +- arch/sh/Kconfig.debug | 2 +- arch/sh/boards/mach-dreamcast/irq.c | 2 +- arch/sh/boards/mach-ecovec24/setup.c | 2 +- arch/sh/drivers/pci/pci-sh7751.h | 2 +- arch/sh/drivers/pci/pci.c | 2 +- arch/sh/include/asm/page.h | 2 +- arch/sh/include/asm/pgtable_32.h | 2 +- arch/sh/include/asm/unaligned-sh4a.h | 2 +- arch/sh/include/mach-common/mach/highlander.h | 4 +- arch/sh/include/mach-common/mach/r2d.h | 6 +-- arch/sh/kernel/cpu/clock-cpg.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 2 +- arch/sh/kernel/irq.c | 2 +- arch/sh/kernel/setup.c | 2 +- arch/sh/lib64/copy_user_memcpy.S | 2 +- arch/sh/lib64/memcpy.S | 2 +- arch/sparc/include/asm/hypervisor.h | 20 ++++---- arch/sparc/include/asm/ns87303.h | 2 +- arch/sparc/include/asm/pcr.h | 2 +- arch/sparc/include/asm/ptrace.h | 2 +- arch/sparc/kernel/entry.S | 4 +- arch/sparc/kernel/head_64.S | 2 +- arch/sparc/kernel/init_task.c | 2 +- arch/sparc/kernel/of_device_64.c | 2 +- arch/sparc/kernel/perf_event.c | 2 +- arch/sparc/math-emu/Makefile | 2 +- arch/tile/Kconfig | 2 +- arch/tile/include/hv/drv_xgbe_intf.h | 2 +- arch/tile/include/hv/hypervisor.h | 4 +- arch/tile/kernel/pci.c | 4 +- arch/tile/mm/fault.c | 2 +- arch/tile/mm/hugetlbpage.c | 2 +- arch/um/Kconfig.net | 2 +- arch/unicore32/include/mach/regs-umal.h | 4 +- arch/unicore32/kernel/head.S | 2 +- arch/xtensa/include/asm/dma.h | 2 +- arch/xtensa/kernel/entry.S | 2 +- block/blk-cgroup.c | 4 +- block/blk-core.c | 2 +- block/blk-throttle.c | 2 +- block/blk.h | 2 +- block/cfq-iosched.c | 2 +- block/genhd.c | 2 +- crypto/ansi_cprng.c | 2 +- crypto/async_tx/async_xor.c | 2 +- crypto/gf128mul.c | 2 +- crypto/vmac.c | 2 +- crypto/xts.c | 2 +- drivers/acpi/apei/ghes.c | 2 +- drivers/acpi/processor_throttling.c | 2 +- drivers/acpi/video.c | 4 +- drivers/amba/bus.c | 2 +- drivers/ata/ahci.c | 2 +- drivers/ata/ahci.h | 4 +- drivers/ata/ata_piix.c | 10 ++-- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-eh.c | 10 ++-- drivers/ata/libata-scsi.c | 2 +- drivers/ata/libata-sff.c | 4 +- drivers/ata/pata_amd.c | 2 +- drivers/ata/pata_arasan_cf.c | 8 ++-- drivers/ata/pata_bf54x.c | 2 +- drivers/ata/pata_cs5520.c | 2 +- drivers/ata/pata_mpiix.c | 2 +- drivers/ata/pata_rz1000.c | 2 +- drivers/ata/pata_sil680.c | 4 +- drivers/ata/pata_sis.c | 4 +- drivers/ata/pata_triflex.c | 2 +- drivers/ata/sata_fsl.c | 4 +- drivers/ata/sata_mv.c | 4 +- drivers/ata/sata_nv.c | 2 +- drivers/ata/sata_via.c | 2 +- drivers/atm/ambassador.c | 2 +- drivers/atm/firestream.c | 2 +- drivers/atm/fore200e.h | 4 +- drivers/atm/horizon.c | 10 ++-- drivers/atm/idt77252.c | 2 +- drivers/atm/idt77252.h | 2 +- drivers/atm/iphase.c | 6 +-- drivers/atm/lanai.c | 4 +- drivers/auxdisplay/cfag12864b.c | 4 +- drivers/base/power/runtime.c | 2 +- drivers/base/sys.c | 14 +++--- drivers/block/DAC960.c | 2 +- drivers/block/drbd/drbd_actlog.c | 2 +- drivers/block/drbd/drbd_int.h | 10 ++-- drivers/block/drbd/drbd_main.c | 4 +- drivers/block/drbd/drbd_receiver.c | 2 +- drivers/block/drbd/drbd_vli.h | 2 +- drivers/block/hd.c | 2 +- drivers/block/viodasd.c | 2 +- drivers/block/xsysace.c | 8 ++-- drivers/bluetooth/hci_ll.c | 2 +- drivers/cdrom/cdrom.c | 4 +- drivers/char/agp/agp.h | 2 +- drivers/char/agp/amd-k7-agp.c | 2 +- drivers/char/agp/sworks-agp.c | 2 +- drivers/char/agp/via-agp.c | 2 +- drivers/char/ipmi/ipmi_poweroff.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 4 +- drivers/char/mbcs.h | 4 +- drivers/char/mwave/3780i.h | 2 +- drivers/char/nwbutton.c | 2 +- drivers/char/pcmcia/cm4000_cs.c | 2 +- drivers/char/pcmcia/synclink_cs.c | 4 +- drivers/char/random.c | 2 +- drivers/char/sonypi.c | 4 +- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 2 +- drivers/cpufreq/cpufreq.c | 2 +- drivers/crypto/amcc/crypto4xx_sa.c | 2 +- drivers/crypto/amcc/crypto4xx_sa.h | 2 +- drivers/crypto/ixp4xx_crypto.c | 2 +- drivers/dma/at_hdmac.c | 2 +- drivers/dma/coh901318.c | 2 +- drivers/dma/intel_mid_dma.c | 8 ++-- drivers/dma/intel_mid_dma_regs.h | 4 +- drivers/dma/mpc512x_dma.c | 2 +- drivers/dma/ste_dma40.c | 4 +- drivers/edac/Kconfig | 2 +- drivers/edac/cpc925_edac.c | 2 +- drivers/edac/edac_core.h | 8 ++-- drivers/edac/edac_device.c | 4 +- drivers/edac/edac_device_sysfs.c | 4 +- drivers/edac/edac_mc.c | 2 +- drivers/edac/edac_mc_sysfs.c | 2 +- drivers/edac/edac_pci_sysfs.c | 4 +- drivers/edac/i5000_edac.c | 2 +- drivers/edac/i5100_edac.c | 2 +- drivers/edac/i5400_edac.c | 4 +- drivers/edac/i7300_edac.c | 2 +- drivers/edac/i7core_edac.c | 2 +- drivers/edac/i82443bxgx_edac.c | 4 +- drivers/edac/mce_amd_inj.c | 2 +- drivers/edac/r82600_edac.c | 6 +-- drivers/firewire/net.c | 2 +- drivers/gpio/mc33880.c | 2 +- drivers/gpu/drm/drm_crtc.c | 4 +- drivers/gpu/drm/drm_mm.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 +- drivers/gpu/drm/mga/mga_dma.c | 2 +- drivers/gpu/drm/nouveau/nouveau_channel.c | 4 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +- drivers/gpu/drm/nouveau/nouveau_state.c | 2 +- drivers/gpu/drm/nouveau/nv04_crtc.c | 4 +- drivers/gpu/drm/nouveau/nv40_graph.c | 2 +- drivers/gpu/drm/radeon/atombios.h | 34 +++++++------- drivers/gpu/drm/radeon/evergreen_cs.c | 2 +- drivers/gpu/drm/radeon/r300.c | 2 +- drivers/gpu/drm/radeon/r300_reg.h | 4 +- drivers/gpu/drm/radeon/r600_cs.c | 2 +- drivers/gpu/drm/radeon/r600_hdmi.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 4 +- drivers/gpu/drm/radeon/radeon_cp.c | 2 +- drivers/gpu/drm/radeon/radeon_cursor.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 2 +- drivers/gpu/drm/radeon/radeon_display.c | 2 +- drivers/gpu/drm/radeon/radeon_drv.h | 2 +- drivers/gpu/drm/radeon/radeon_object.h | 2 +- drivers/gpu/drm/radeon/radeon_state.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- drivers/gpu/vga/vgaarb.c | 4 +- drivers/hid/hid-core.c | 4 +- drivers/hid/hid-debug.c | 2 +- drivers/hid/hid-magicmouse.c | 2 +- drivers/hid/hid-picolcd.c | 4 +- drivers/hid/hid-roccat-kone.h | 2 +- drivers/hwmon/abituguru.c | 2 +- drivers/hwmon/abituguru3.c | 2 +- drivers/hwmon/adm1026.c | 2 +- drivers/hwmon/lm85.c | 2 +- drivers/hwmon/lm90.c | 2 +- drivers/hwmon/sht15.c | 6 +-- drivers/hwmon/tmp102.c | 2 +- drivers/hwmon/w83791d.c | 2 +- drivers/hwmon/w83792d.c | 2 +- drivers/hwmon/w83793.c | 2 +- drivers/i2c/algos/i2c-algo-pca.c | 2 +- drivers/i2c/busses/i2c-ali1535.c | 2 +- drivers/i2c/busses/i2c-ali15x3.c | 2 +- drivers/i2c/busses/i2c-davinci.c | 2 +- drivers/i2c/busses/i2c-designware.c | 2 +- drivers/i2c/busses/i2c-elektor.c | 2 +- drivers/i2c/busses/i2c-i801.c | 2 +- drivers/i2c/busses/i2c-ibm_iic.c | 4 +- drivers/i2c/busses/i2c-intel-mid.c | 14 +++--- drivers/i2c/busses/i2c-isch.c | 2 +- drivers/i2c/busses/i2c-mxs.c | 2 +- drivers/i2c/busses/i2c-nomadik.c | 8 ++-- drivers/i2c/busses/i2c-s6000.c | 2 +- drivers/i2c/busses/i2c-stu300.c | 4 +- drivers/i2c/busses/i2c-tegra.c | 2 +- drivers/i2c/busses/i2c-xiic.c | 2 +- drivers/i2c/i2c-core.c | 2 +- drivers/ide/cy82c693.c | 2 +- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-taskfile.c | 2 +- drivers/ide/piix.c | 4 +- drivers/ide/sis5513.c | 4 +- drivers/ide/triflex.c | 2 +- drivers/ide/via82cxxx.c | 2 +- drivers/infiniband/hw/amso1100/c2_ae.c | 2 +- drivers/infiniband/hw/amso1100/c2_qp.c | 2 +- drivers/infiniband/hw/amso1100/c2_wr.h | 4 +- drivers/infiniband/hw/ipath/ipath_driver.c | 2 +- drivers/infiniband/hw/ipath/ipath_file_ops.c | 2 +- drivers/infiniband/hw/ipath/ipath_init_chip.c | 2 +- drivers/infiniband/hw/ipath/ipath_ud.c | 4 +- drivers/infiniband/hw/ipath/ipath_user_sdma.c | 2 +- drivers/infiniband/hw/nes/nes_cm.c | 2 +- drivers/infiniband/hw/nes/nes_hw.c | 4 +- drivers/infiniband/hw/nes/nes_nic.c | 2 +- drivers/infiniband/hw/qib/qib.h | 2 +- drivers/infiniband/hw/qib/qib_file_ops.c | 4 +- drivers/infiniband/hw/qib/qib_iba6120.c | 4 +- drivers/infiniband/hw/qib/qib_iba7220.c | 6 +-- drivers/infiniband/hw/qib/qib_iba7322.c | 8 ++-- drivers/infiniband/hw/qib/qib_init.c | 2 +- drivers/infiniband/hw/qib/qib_mad.h | 2 +- drivers/infiniband/hw/qib/qib_twsi.c | 2 +- drivers/infiniband/hw/qib/qib_ud.c | 4 +- drivers/infiniband/hw/qib/qib_user_sdma.c | 2 +- drivers/infiniband/ulp/iser/iscsi_iser.h | 2 +- drivers/input/joydev.c | 4 +- drivers/input/joystick/a3d.c | 4 +- drivers/input/keyboard/davinci_keyscan.c | 2 +- drivers/input/misc/adxl34x.c | 2 +- drivers/input/misc/keyspan_remote.c | 2 +- drivers/input/misc/wistron_btns.c | 2 +- drivers/input/mouse/bcm5974.c | 2 +- drivers/input/mouse/synaptics_i2c.c | 2 +- drivers/input/mouse/vsxxxaa.c | 2 +- drivers/input/serio/hp_sdc.c | 2 +- drivers/input/serio/xilinx_ps2.c | 2 +- drivers/input/touchscreen/intel-mid-touch.c | 2 +- drivers/input/touchscreen/ucb1400_ts.c | 2 +- drivers/input/touchscreen/wm9705.c | 2 +- drivers/input/touchscreen/wm9712.c | 2 +- drivers/input/touchscreen/wm9713.c | 2 +- drivers/input/touchscreen/wm97xx-core.c | 4 +- drivers/isdn/hardware/eicon/divacapi.h | 2 +- drivers/isdn/hardware/eicon/io.h | 2 +- drivers/isdn/hardware/eicon/message.c | 4 +- drivers/isdn/hardware/eicon/pc.h | 2 +- drivers/isdn/hardware/eicon/um_idi.c | 2 +- drivers/isdn/hardware/mISDN/hfcmulti.c | 4 +- drivers/isdn/hardware/mISDN/hfcpci.c | 2 +- drivers/isdn/hisax/hfc_pci.c | 2 +- drivers/isdn/hisax/hfc_sx.c | 2 +- drivers/isdn/hisax/hfc_usb.h | 2 +- drivers/isdn/hisax/l3dss1.c | 4 +- drivers/isdn/hisax/l3ni1.c | 4 +- drivers/isdn/hisax/nj_s.c | 2 +- drivers/isdn/hisax/st5481_b.c | 2 +- drivers/isdn/hisax/st5481_usb.c | 2 +- drivers/isdn/hisax/teles_cs.c | 2 +- drivers/isdn/hysdn/hysdn_sched.c | 2 +- drivers/isdn/i4l/isdn_net.c | 4 +- drivers/isdn/i4l/isdn_ppp.c | 4 +- drivers/isdn/i4l/isdn_tty.c | 2 +- drivers/isdn/isdnloop/isdnloop.c | 2 +- drivers/isdn/mISDN/dsp.h | 2 +- drivers/isdn/mISDN/dsp_cmx.c | 4 +- drivers/isdn/mISDN/dsp_core.c | 8 ++-- drivers/isdn/mISDN/dsp_dtmf.c | 4 +- drivers/isdn/mISDN/dsp_tones.c | 2 +- drivers/isdn/mISDN/l1oip_core.c | 6 +-- drivers/isdn/mISDN/layer2.c | 4 +- drivers/leds/leds-pca9532.c | 2 +- drivers/leds/leds-wm8350.c | 4 +- drivers/lguest/lguest_user.c | 2 +- drivers/macintosh/adbhid.c | 2 +- drivers/macintosh/macio-adb.c | 2 +- drivers/macintosh/therm_adt746x.c | 2 +- drivers/macintosh/therm_pm72.c | 6 +-- drivers/macintosh/therm_windtunnel.c | 2 +- drivers/md/bitmap.h | 2 +- drivers/md/dm-region-hash.c | 2 +- drivers/md/faulty.c | 2 +- drivers/md/md.c | 2 +- drivers/md/md.h | 2 +- drivers/md/raid10.c | 6 +-- drivers/md/raid10.h | 4 +- drivers/media/common/saa7146_i2c.c | 8 ++-- drivers/media/common/tuners/mxl5005s.c | 2 +- drivers/media/common/tuners/tda18271.h | 2 +- drivers/media/dvb/b2c2/flexcop-pci.c | 2 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 4 +- drivers/media/dvb/dvb-core/dvb_frontend.c | 4 +- drivers/media/dvb/dvb-usb/af9005-fe.c | 8 ++-- drivers/media/dvb/dvb-usb/friio.h | 2 +- drivers/media/dvb/dvb-usb/lmedm04.c | 12 ++--- drivers/media/dvb/frontends/atbm8830.h | 2 +- drivers/media/dvb/frontends/au8522_dig.c | 6 +-- drivers/media/dvb/frontends/bcm3510.c | 6 +-- drivers/media/dvb/frontends/cx22700.c | 2 +- drivers/media/dvb/frontends/cx22702.c | 6 +-- drivers/media/dvb/frontends/cx24110.c | 2 +- drivers/media/dvb/frontends/cx24113.h | 2 +- drivers/media/dvb/frontends/cx24123.c | 2 +- drivers/media/dvb/frontends/drx397xD.c | 2 +- drivers/media/dvb/frontends/mb86a16.c | 2 +- drivers/media/dvb/frontends/mb86a20s.c | 2 +- drivers/media/dvb/frontends/mt312.c | 2 +- drivers/media/dvb/frontends/s5h1420.c | 2 +- drivers/media/dvb/frontends/stb6100.c | 2 +- drivers/media/dvb/frontends/stv0297.c | 2 +- drivers/media/dvb/frontends/stv0367.c | 2 +- drivers/media/dvb/frontends/stv0900_priv.h | 2 +- drivers/media/dvb/frontends/stv090x.c | 12 ++--- drivers/media/dvb/mantis/mantis_uart.c | 2 +- drivers/media/dvb/ngene/ngene-core.c | 4 +- drivers/media/dvb/pluto2/pluto2.c | 10 ++-- drivers/media/dvb/siano/smsdvb.c | 2 +- drivers/media/dvb/ttpci/av7110.c | 2 +- drivers/media/dvb/ttpci/budget-patch.c | 2 +- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 2 +- drivers/media/radio/radio-mr800.c | 2 +- drivers/media/radio/si4713-i2c.c | 2 +- drivers/media/radio/wl128x/fmdrv_common.c | 6 +-- drivers/media/radio/wl128x/fmdrv_common.h | 2 +- drivers/media/rc/ene_ir.c | 4 +- drivers/media/rc/imon.c | 2 +- drivers/media/rc/ir-raw.c | 2 +- drivers/media/rc/keymaps/rc-lme2510.c | 4 +- drivers/media/rc/keymaps/rc-msi-tvanywhere.c | 2 +- drivers/media/rc/keymaps/rc-norwood.c | 2 +- drivers/media/rc/rc-main.c | 4 +- drivers/media/video/au0828/au0828-video.c | 2 +- drivers/media/video/bt8xx/bttv-cards.c | 6 +-- drivers/media/video/bt8xx/bttv-gpio.c | 2 +- drivers/media/video/cafe_ccic.c | 2 +- drivers/media/video/cx18/cx18-av-core.h | 2 +- drivers/media/video/cx18/cx18-ioctl.c | 2 +- drivers/media/video/cx18/cx18-vbi.c | 2 +- drivers/media/video/cx231xx/cx231xx-avcore.c | 2 +- drivers/media/video/cx231xx/cx231xx-vbi.c | 2 +- drivers/media/video/cx231xx/cx231xx-video.c | 2 +- drivers/media/video/cx23885/cimax2.c | 2 +- drivers/media/video/cx23885/cx23885.h | 2 +- drivers/media/video/cx25840/cx25840-core.c | 10 ++-- drivers/media/video/davinci/dm644x_ccdc.c | 4 +- drivers/media/video/davinci/vpfe_capture.c | 2 +- drivers/media/video/em28xx/em28xx-video.c | 4 +- drivers/media/video/gspca/gl860/gl860-mi1320.c | 2 +- drivers/media/video/gspca/gspca.c | 4 +- drivers/media/video/gspca/mars.c | 2 +- drivers/media/video/gspca/mr97310a.c | 2 +- drivers/media/video/gspca/ov519.c | 4 +- drivers/media/video/gspca/sonixb.c | 2 +- drivers/media/video/gspca/spca500.c | 4 +- drivers/media/video/gspca/spca508.c | 2 +- drivers/media/video/gspca/sq905.c | 2 +- drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 2 +- drivers/media/video/hexium_gemini.c | 2 +- drivers/media/video/ivtv/ivtv-firmware.c | 4 +- drivers/media/video/ivtv/ivtvfb.c | 2 +- drivers/media/video/msp3400-driver.c | 4 +- drivers/media/video/msp3400-kthreads.c | 2 +- drivers/media/video/omap/omap_vout.c | 4 +- drivers/media/video/omap/omap_voutlib.c | 6 +-- drivers/media/video/omap1_camera.c | 4 +- drivers/media/video/omap3isp/isp.c | 8 ++-- drivers/media/video/omap3isp/ispccdc.h | 4 +- drivers/media/video/omap3isp/ispccp2.c | 2 +- drivers/media/video/omap3isp/ispcsi2.c | 2 +- drivers/media/video/omap3isp/isppreview.c | 20 ++++---- drivers/media/video/omap3isp/isppreview.h | 2 +- drivers/media/video/omap3isp/ispqueue.h | 4 +- drivers/media/video/omap3isp/ispresizer.c | 4 +- drivers/media/video/omap3isp/ispvideo.c | 6 +-- drivers/media/video/ov6650.c | 2 +- drivers/media/video/ov9640.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-eeprom.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 2 +- drivers/media/video/pxa_camera.c | 2 +- drivers/media/video/s5p-fimc/fimc-reg.c | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 4 +- drivers/media/video/saa7164/saa7164-cmd.c | 2 +- drivers/media/video/saa7164/saa7164-fw.c | 2 +- drivers/media/video/saa7164/saa7164-types.h | 2 +- drivers/media/video/sn9c102/sn9c102_core.c | 2 +- drivers/media/video/sn9c102/sn9c102_sensor.h | 2 +- drivers/media/video/tcm825x.c | 4 +- drivers/media/video/tvaudio.c | 10 ++-- drivers/media/video/uvc/uvc_video.c | 8 ++-- drivers/media/video/v4l2-ioctl.c | 2 +- drivers/media/video/vpx3220.c | 2 +- drivers/media/video/zoran/videocodec.h | 2 +- drivers/media/video/zoran/zoran.h | 2 +- drivers/media/video/zoran/zoran_driver.c | 2 +- drivers/memstick/core/mspro_block.c | 2 +- drivers/memstick/host/r592.c | 2 +- drivers/memstick/host/r592.h | 6 +-- drivers/message/fusion/lsi/mpi_log_fc.h | 4 +- drivers/message/fusion/lsi/mpi_log_sas.h | 14 +++--- drivers/message/fusion/mptbase.c | 6 +-- drivers/message/fusion/mptctl.c | 4 +- drivers/message/fusion/mptsas.c | 8 ++-- drivers/message/i2o/README | 2 +- drivers/message/i2o/device.c | 8 ++-- drivers/message/i2o/i2o_block.c | 4 +- drivers/message/i2o/i2o_block.h | 2 +- drivers/message/i2o/i2o_scsi.c | 2 +- drivers/mfd/Kconfig | 2 +- drivers/mfd/ab8500-gpadc.c | 2 +- drivers/mfd/ezx-pcap.c | 4 +- drivers/mfd/omap-usb-host.c | 2 +- drivers/mfd/pcf50633-core.c | 4 +- drivers/mfd/twl6030-irq.c | 4 +- drivers/mfd/ucb1400_core.c | 2 +- drivers/misc/bmp085.c | 4 +- drivers/misc/c2port/c2port-duramar2150.c | 2 +- drivers/misc/ibmasm/remote.h | 2 +- drivers/misc/iwmc3200top/main.c | 2 +- drivers/misc/kgdbts.c | 2 +- drivers/misc/sgi-gru/grukservices.c | 2 +- drivers/misc/sgi-gru/grutables.h | 2 +- drivers/misc/ti-st/st_kim.c | 2 +- drivers/mmc/card/mmc_test.c | 2 +- drivers/mmc/core/mmc.c | 2 +- drivers/mmc/core/mmc_ops.c | 2 +- drivers/mmc/core/sdio_irq.c | 2 +- drivers/mmc/host/atmel-mci.c | 4 +- drivers/mmc/host/mmc_spi.c | 2 +- drivers/mmc/host/s3cmci.c | 6 +-- drivers/mmc/host/tmio_mmc_pio.c | 2 +- drivers/mmc/host/wbsd.c | 6 +-- drivers/mtd/chips/Kconfig | 2 +- drivers/mtd/chips/cfi_cmdset_0001.c | 4 +- drivers/mtd/chips/cfi_cmdset_0002.c | 10 ++-- drivers/mtd/chips/cfi_util.c | 2 +- drivers/mtd/chips/jedec_probe.c | 2 +- drivers/mtd/devices/block2mtd.c | 2 +- drivers/mtd/devices/doc2001plus.c | 2 +- drivers/mtd/devices/docecc.c | 4 +- drivers/mtd/devices/lart.c | 4 +- drivers/mtd/devices/pmc551.c | 4 +- drivers/mtd/lpddr/lpddr_cmds.c | 4 +- drivers/mtd/maps/ceiva.c | 4 +- drivers/mtd/maps/cfi_flagadm.c | 2 +- drivers/mtd/maps/pcmciamtd.c | 2 +- drivers/mtd/maps/pmcmsp-flash.c | 2 +- drivers/mtd/maps/sc520cdp.c | 2 +- drivers/mtd/maps/tqm8xxl.c | 2 +- drivers/mtd/mtdblock.c | 2 +- drivers/mtd/mtdchar.c | 2 +- drivers/mtd/nand/Kconfig | 2 +- drivers/mtd/nand/ams-delta.c | 2 +- drivers/mtd/nand/autcpu12.c | 2 +- drivers/mtd/nand/cs553x_nand.c | 2 +- drivers/mtd/nand/denali.c | 6 +-- drivers/mtd/nand/diskonchip.c | 8 ++-- drivers/mtd/nand/fsl_elbc_nand.c | 2 +- drivers/mtd/nand/fsmc_nand.c | 10 ++-- drivers/mtd/nand/nand_base.c | 2 +- drivers/mtd/nand/nand_bbt.c | 2 +- drivers/mtd/nand/nandsim.c | 2 +- drivers/mtd/nand/nomadik_nand.c | 2 +- drivers/mtd/nand/pasemi_nand.c | 2 +- drivers/mtd/nand/plat_nand.c | 2 +- drivers/mtd/nand/pxa3xx_nand.c | 2 +- drivers/mtd/nand/r852.c | 10 ++-- drivers/mtd/nand/sh_flctl.c | 2 +- drivers/mtd/nand/sm_common.c | 2 +- drivers/mtd/nand/tmio_nand.c | 2 +- drivers/mtd/onenand/omap2.c | 4 +- drivers/mtd/onenand/onenand_sim.c | 4 +- drivers/mtd/sm_ftl.c | 4 +- drivers/mtd/ubi/scan.c | 2 +- drivers/net/3c501.c | 6 +-- drivers/net/3c523.c | 2 +- drivers/net/3c527.c | 4 +- drivers/net/3c59x.c | 2 +- drivers/net/acenic.c | 4 +- drivers/net/amd8111e.c | 2 +- drivers/net/at1700.c | 2 +- drivers/net/atl1e/atl1e_main.c | 2 +- drivers/net/atlx/atl2.c | 2 +- drivers/net/bcm63xx_enet.c | 2 +- drivers/net/benet/be_cmds.c | 2 +- drivers/net/benet/be_main.c | 2 +- drivers/net/bna/bna_hw.h | 2 +- drivers/net/bnx2x/bnx2x.h | 2 +- drivers/net/bnx2x/bnx2x_hsi.h | 2 +- drivers/net/bnx2x/bnx2x_link.c | 14 +++--- drivers/net/bnx2x/bnx2x_main.c | 10 ++-- drivers/net/bnx2x/bnx2x_reg.h | 44 +++++++++--------- drivers/net/bonding/bond_alb.h | 2 +- drivers/net/caif/caif_shmcore.c | 2 +- drivers/net/caif/caif_spi.c | 2 +- drivers/net/caif/caif_spi_slave.c | 4 +- drivers/net/can/at91_can.c | 4 +- drivers/net/can/c_can/c_can.c | 4 +- drivers/net/can/janz-ican3.c | 8 ++-- drivers/net/can/mscan/mscan.c | 2 +- drivers/net/can/sja1000/sja1000.c | 2 +- drivers/net/can/softing/softing.h | 2 +- drivers/net/can/softing/softing_main.c | 2 +- drivers/net/can/ti_hecc.c | 2 +- drivers/net/can/usb/ems_usb.c | 2 +- drivers/net/can/usb/esd_usb2.c | 2 +- drivers/net/cassini.c | 4 +- drivers/net/cassini.h | 2 +- drivers/net/chelsio/mv88e1xxx.c | 2 +- drivers/net/chelsio/pm3393.c | 2 +- drivers/net/chelsio/sge.c | 2 +- drivers/net/chelsio/vsc7326.c | 2 +- drivers/net/cris/eth_v10.c | 2 +- drivers/net/cxgb3/sge.c | 2 +- drivers/net/cxgb3/t3_hw.c | 6 +-- drivers/net/cxgb4/t4_hw.c | 2 +- drivers/net/cxgb4vf/cxgb4vf_main.c | 2 +- drivers/net/cxgb4vf/sge.c | 8 ++-- drivers/net/davinci_emac.c | 8 ++-- drivers/net/e1000/e1000_ethtool.c | 2 +- drivers/net/e1000/e1000_hw.h | 2 +- drivers/net/e1000/e1000_main.c | 2 +- drivers/net/e1000e/netdev.c | 2 +- drivers/net/enc28j60_hw.h | 2 +- drivers/net/eth16i.c | 2 +- drivers/net/ethoc.c | 2 +- drivers/net/fec.h | 4 +- drivers/net/forcedeth.c | 14 +++--- drivers/net/gianfar.h | 2 +- drivers/net/hamradio/Makefile | 2 +- drivers/net/hamradio/yam.c | 2 +- drivers/net/hp100.c | 16 +++---- drivers/net/hp100.h | 2 +- drivers/net/ibm_newemac/tah.c | 2 +- drivers/net/ibmlana.c | 4 +- drivers/net/ibmlana.h | 2 +- drivers/net/igb/e1000_mac.c | 4 +- drivers/net/igb/e1000_phy.c | 2 +- drivers/net/igb/igb_main.c | 14 +++--- drivers/net/igbvf/netdev.c | 2 +- drivers/net/ipg.c | 28 +++++------ drivers/net/irda/ali-ircc.c | 4 +- drivers/net/irda/donauboe.c | 2 +- drivers/net/irda/donauboe.h | 2 +- drivers/net/irda/girbil-sir.c | 2 +- drivers/net/irda/irda-usb.c | 4 +- drivers/net/irda/mcs7780.c | 6 +-- drivers/net/irda/nsc-ircc.c | 2 +- drivers/net/irda/nsc-ircc.h | 2 +- drivers/net/irda/pxaficp_ir.c | 4 +- drivers/net/irda/smsc-ircc2.c | 2 +- drivers/net/irda/via-ircc.c | 4 +- drivers/net/irda/vlsi_ir.h | 4 +- drivers/net/ixgbe/ixgbe_dcb.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_nl.c | 4 +- drivers/net/ixgbe/ixgbe_main.c | 8 ++-- drivers/net/ixgbe/ixgbe_phy.c | 2 +- drivers/net/ixgbe/ixgbe_x540.c | 2 +- drivers/net/ixgbevf/ixgbevf_main.c | 2 +- drivers/net/ks8842.c | 2 +- drivers/net/ks8851.c | 8 ++-- drivers/net/ks8851_mll.c | 4 +- drivers/net/lib8390.c | 4 +- drivers/net/lp486e.c | 2 +- drivers/net/meth.h | 4 +- drivers/net/mlx4/en_main.c | 2 +- drivers/net/mlx4/en_netdev.c | 10 ++-- drivers/net/mlx4/en_rx.c | 2 +- drivers/net/mlx4/en_selftest.c | 2 +- drivers/net/mlx4/en_tx.c | 2 +- drivers/net/mlx4/mcg.c | 2 +- drivers/net/mlx4/port.c | 4 +- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/myri_sbus.c | 2 +- drivers/net/natsemi.c | 6 +-- drivers/net/netxen/netxen_nic_hdr.h | 2 +- drivers/net/ns83820.c | 4 +- drivers/net/pch_gbe/pch_gbe.h | 14 +++--- drivers/net/pch_gbe/pch_gbe_ethtool.c | 2 +- drivers/net/pch_gbe/pch_gbe_main.c | 4 +- drivers/net/pci-skeleton.c | 2 +- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/axnet_cs.c | 4 +- drivers/net/pcmcia/smc91c92_cs.c | 2 +- drivers/net/pcnet32.c | 2 +- drivers/net/phy/phy_device.c | 4 +- drivers/net/ppp_generic.c | 2 +- drivers/net/ppp_synctty.c | 2 +- drivers/net/pppoe.c | 2 +- drivers/net/ps3_gelic_net.c | 4 +- drivers/net/ps3_gelic_net.h | 2 +- drivers/net/ps3_gelic_wireless.c | 2 +- drivers/net/pxa168_eth.c | 2 +- drivers/net/qla3xxx.h | 2 +- drivers/net/qlge/qlge_main.c | 10 ++-- drivers/net/r6040.c | 2 +- drivers/net/s2io.c | 6 +-- drivers/net/s2io.h | 2 +- drivers/net/sfc/falcon.c | 4 +- drivers/net/sfc/mcdi.c | 2 +- drivers/net/sfc/mcdi_pcol.h | 6 +-- drivers/net/sfc/mcdi_phy.c | 2 +- drivers/net/sfc/net_driver.h | 2 +- drivers/net/sgiseeq.c | 4 +- drivers/net/sh_eth.c | 2 +- drivers/net/sis190.c | 4 +- drivers/net/sis900.c | 6 +-- drivers/net/skfp/ess.c | 8 ++-- drivers/net/skfp/fplustm.c | 6 +-- drivers/net/skfp/h/cmtdef.h | 4 +- drivers/net/skfp/h/fplustm.h | 4 +- drivers/net/skfp/h/smc.h | 2 +- drivers/net/skfp/h/smt.h | 2 +- drivers/net/skfp/h/supern_2.h | 4 +- drivers/net/skfp/hwmtm.c | 2 +- drivers/net/skfp/pcmplc.c | 6 +-- drivers/net/skfp/smt.c | 2 +- drivers/net/skge.h | 8 ++-- drivers/net/sky2.c | 4 +- drivers/net/sky2.h | 6 +-- drivers/net/smc91x.h | 2 +- drivers/net/smsc911x.c | 2 +- drivers/net/smsc9420.c | 2 +- drivers/net/stmmac/norm_desc.c | 2 +- drivers/net/sunbmac.h | 2 +- drivers/net/sungem.c | 2 +- drivers/net/sunhme.h | 2 +- drivers/net/tc35815.c | 38 +++++++-------- drivers/net/tehuti.c | 12 ++--- drivers/net/tehuti.h | 2 +- drivers/net/tg3.c | 2 +- drivers/net/tg3.h | 4 +- drivers/net/tokenring/3c359.c | 2 +- drivers/net/tokenring/madgemc.c | 6 +-- drivers/net/tokenring/smctr.c | 12 ++--- drivers/net/tokenring/tms380tr.h | 2 +- drivers/net/tsi108_eth.h | 8 ++-- drivers/net/tulip/de4x5.c | 6 +-- drivers/net/tulip/dmfe.c | 2 +- drivers/net/tulip/eeprom.c | 2 +- drivers/net/typhoon.c | 2 +- drivers/net/ucc_geth.h | 4 +- drivers/net/usb/cdc_eem.c | 2 +- drivers/net/usb/kaweth.c | 2 +- drivers/net/via-rhine.c | 4 +- drivers/net/via-velocity.c | 4 +- drivers/net/vmxnet3/vmxnet3_drv.c | 4 +- drivers/net/vxge/vxge-config.c | 2 +- drivers/net/vxge/vxge-main.c | 8 ++-- drivers/net/vxge/vxge-traffic.c | 4 +- drivers/net/vxge/vxge-traffic.h | 2 +- drivers/net/wan/cosa.c | 2 +- drivers/net/wan/dscc4.c | 8 ++-- drivers/net/wan/hostess_sv11.c | 2 +- drivers/net/wan/ixp4xx_hss.c | 4 +- drivers/net/wan/lmc/lmc_main.c | 2 +- drivers/net/wan/lmc/lmc_var.h | 6 +-- drivers/net/wan/z85230.c | 8 ++-- drivers/net/wimax/i2400m/control.c | 4 +- drivers/net/wimax/i2400m/driver.c | 4 +- drivers/net/wimax/i2400m/fw.c | 4 +- drivers/net/wimax/i2400m/i2400m-usb.h | 6 +-- drivers/net/wimax/i2400m/i2400m.h | 4 +- drivers/net/wimax/i2400m/netdev.c | 2 +- drivers/net/wimax/i2400m/op-rfkill.c | 4 +- drivers/net/wimax/i2400m/rx.c | 4 +- drivers/net/wimax/i2400m/tx.c | 4 +- drivers/net/wimax/i2400m/usb-fw.c | 2 +- drivers/net/wimax/i2400m/usb-rx.c | 2 +- drivers/net/wimax/i2400m/usb-tx.c | 2 +- drivers/net/wireless/airo.c | 14 +++--- drivers/net/wireless/ath/ar9170/main.c | 2 +- drivers/net/wireless/ath/ar9170/phy.c | 2 +- drivers/net/wireless/ath/ath5k/ani.h | 2 +- drivers/net/wireless/ath/ath5k/base.c | 6 +-- drivers/net/wireless/ath/ath5k/desc.c | 14 +++--- drivers/net/wireless/ath/ath5k/eeprom.c | 4 +- drivers/net/wireless/ath/ath5k/pci.c | 2 +- drivers/net/wireless/ath/ath5k/pcu.c | 6 +-- drivers/net/wireless/ath/ath5k/phy.c | 22 ++++----- drivers/net/wireless/ath/ath5k/reg.h | 12 ++--- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 2 +- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- drivers/net/wireless/ath/ath9k/htc_hst.c | 2 +- drivers/net/wireless/ath/ath9k/pci.c | 2 +- drivers/net/wireless/ath/ath9k/rc.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 4 +- drivers/net/wireless/ath/carl9170/carl9170.h | 2 +- drivers/net/wireless/ath/carl9170/phy.c | 2 +- drivers/net/wireless/ath/carl9170/rx.c | 2 +- drivers/net/wireless/ath/carl9170/usb.c | 2 +- drivers/net/wireless/ath/hw.c | 2 +- drivers/net/wireless/ath/regd.c | 4 +- drivers/net/wireless/atmel.c | 4 +- drivers/net/wireless/atmel_cs.c | 2 +- drivers/net/wireless/b43/b43.h | 2 +- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43/phy_g.h | 2 +- drivers/net/wireless/b43/phy_n.h | 2 +- drivers/net/wireless/b43legacy/b43legacy.h | 2 +- drivers/net/wireless/hostap/hostap_ap.c | 2 +- drivers/net/wireless/hostap/hostap_ap.h | 2 +- drivers/net/wireless/hostap/hostap_ioctl.c | 4 +- drivers/net/wireless/hostap/hostap_wlan.h | 2 +- drivers/net/wireless/ipw2x00/ipw2100.c | 2 +- drivers/net/wireless/ipw2x00/ipw2200.c | 18 ++++---- drivers/net/wireless/ipw2x00/libipw_rx.c | 2 +- drivers/net/wireless/iwlegacy/iwl-core.c | 2 +- drivers/net/wireless/iwlegacy/iwl-fh.h | 2 +- drivers/net/wireless/iwlegacy/iwl-scan.c | 2 +- drivers/net/wireless/iwlegacy/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-ict.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-fh.h | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwmc3200wifi/hal.c | 4 +- drivers/net/wireless/iwmc3200wifi/tx.c | 2 +- drivers/net/wireless/libertas/README | 4 +- drivers/net/wireless/libertas/cfg.c | 2 +- drivers/net/wireless/libertas/if_cs.c | 2 +- drivers/net/wireless/libertas/if_spi.h | 2 +- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/orinoco/hw.c | 2 +- drivers/net/wireless/p54/main.c | 2 +- drivers/net/wireless/p54/p54spi.c | 2 +- drivers/net/wireless/prism54/islpci_eth.c | 4 +- drivers/net/wireless/rayctl.h | 2 +- drivers/net/wireless/rt2x00/rt2800.h | 2 +- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 8 ++-- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 2 +- drivers/net/wireless/rt2x00/rt2x00dump.h | 2 +- drivers/net/wireless/rt2x00/rt2x00link.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 +-- drivers/net/wireless/rt2x00/rt2x00queue.h | 12 ++--- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.h | 2 +- drivers/net/wireless/rtlwifi/base.c | 2 +- drivers/net/wireless/rtlwifi/pci.c | 2 +- drivers/net/wireless/rtlwifi/regd.c | 2 +- drivers/net/wireless/rtlwifi/wifi.h | 2 +- drivers/net/wireless/wl1251/cmd.c | 2 +- drivers/net/wireless/wl1251/rx.c | 2 +- drivers/net/wireless/wl12xx/cmd.c | 2 +- drivers/net/wireless/wl12xx/conf.h | 8 ++-- drivers/net/wireless/wl12xx/io.h | 2 +- drivers/net/wireless/wl3501_cs.c | 4 +- drivers/net/wireless/zd1211rw/zd_rf_rf2959.c | 2 +- drivers/net/wireless/zd1211rw/zd_rf_uw2453.c | 2 +- drivers/net/xilinx_emaclite.c | 2 +- drivers/net/znet.c | 2 +- drivers/of/fdt.c | 2 +- drivers/of/of_mdio.c | 2 +- drivers/parisc/pdc_stable.c | 4 +- drivers/parport/Kconfig | 2 +- drivers/parport/ieee1284.c | 2 +- drivers/parport/parport_pc.c | 6 +-- drivers/pci/hotplug/acpi_pcihp.c | 2 +- drivers/pci/hotplug/acpiphp_glue.c | 2 +- drivers/pci/hotplug/rpaphp_core.c | 2 +- drivers/pci/intel-iommu.c | 2 +- drivers/pci/intr_remapping.c | 2 +- drivers/pci/iova.c | 2 +- drivers/pci/pci-sysfs.c | 2 +- drivers/pci/quirks.c | 4 +- drivers/pcmcia/i82092.c | 2 +- drivers/pcmcia/pcmcia_resource.c | 2 +- drivers/pcmcia/pxa2xx_lubbock.c | 2 +- drivers/pcmcia/ti113x.h | 2 +- drivers/platform/x86/intel_mid_thermal.c | 2 +- drivers/pnp/card.c | 4 +- drivers/pnp/pnpbios/bioscalls.c | 2 +- drivers/pps/Kconfig | 2 +- drivers/ps3/ps3-lpm.c | 6 +-- drivers/ps3/ps3-sys-manager.c | 2 +- drivers/rapidio/rio-scan.c | 2 +- drivers/regulator/core.c | 2 +- drivers/regulator/max8952.c | 2 +- drivers/rtc/interface.c | 2 +- drivers/rtc/rtc-at91rm9200.c | 2 +- drivers/rtc/rtc-bfin.c | 4 +- drivers/rtc/rtc-lpc32xx.c | 2 +- drivers/rtc/rtc-x1205.c | 2 +- drivers/s390/block/dasd_3990_erp.c | 6 +-- drivers/s390/block/dasd_devmap.c | 2 +- drivers/s390/block/dasd_eckd.c | 2 +- drivers/s390/char/raw3270.c | 2 +- drivers/s390/char/tape_char.c | 2 +- drivers/s390/char/tty3270.c | 2 +- drivers/s390/cio/device_fsm.c | 4 +- drivers/s390/crypto/zcrypt_api.h | 2 +- drivers/s390/net/claw.c | 2 +- drivers/s390/net/ctcm_fsms.c | 2 +- drivers/s390/net/lcs.c | 2 +- drivers/s390/net/qeth_core_main.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 2 +- drivers/s390/scsi/zfcp_qdio.c | 2 +- drivers/sbus/char/jsflash.c | 2 +- drivers/sbus/char/max1617.h | 2 +- drivers/scsi/3w-9xxx.h | 2 +- drivers/scsi/3w-xxxx.h | 2 +- drivers/scsi/53c700.scr | 2 +- drivers/scsi/53c700_d.h_shipped | 2 +- drivers/scsi/FlashPoint.c | 4 +- drivers/scsi/NCR5380.c | 8 ++-- drivers/scsi/aacraid/aachba.c | 4 +- drivers/scsi/aacraid/aacraid.h | 2 +- drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/advansys.c | 2 +- drivers/scsi/aha1740.c | 2 +- drivers/scsi/aic7xxx/aic79xx.h | 4 +- drivers/scsi/aic7xxx/aic79xx.reg | 24 +++++----- drivers/scsi/aic7xxx/aic79xx.seq | 18 ++++---- drivers/scsi/aic7xxx/aic79xx_core.c | 24 +++++----- drivers/scsi/aic7xxx/aic79xx_osm.c | 2 +- drivers/scsi/aic7xxx/aic7xxx.h | 4 +- drivers/scsi/aic7xxx/aic7xxx.reg | 2 +- drivers/scsi/aic7xxx/aic7xxx.seq | 10 ++-- drivers/scsi/aic7xxx/aic7xxx_core.c | 18 ++++---- drivers/scsi/aic7xxx/aic7xxx_osm.c | 4 +- drivers/scsi/aic7xxx/aic7xxx_pci.c | 6 +-- drivers/scsi/aic7xxx/aicasm/aicasm_gram.y | 8 ++-- drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y | 2 +- drivers/scsi/aic7xxx_old.c | 12 ++--- drivers/scsi/aic7xxx_old/aic7xxx.seq | 8 ++-- drivers/scsi/aic94xx/aic94xx_reg_def.h | 2 +- drivers/scsi/arm/acornscsi.c | 4 +- drivers/scsi/arm/acornscsi.h | 6 +-- drivers/scsi/arm/arxescsi.c | 2 +- drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c | 2 +- drivers/scsi/arm/fas216.c | 4 +- drivers/scsi/arm/fas216.h | 10 ++-- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/atari_NCR5380.c | 6 +-- drivers/scsi/atp870u.c | 2 +- drivers/scsi/be2iscsi/be_cmds.h | 18 ++++---- drivers/scsi/bfa/bfa_core.c | 2 +- drivers/scsi/bfa/bfa_defs_svc.h | 6 +-- drivers/scsi/bfa/bfa_fc.h | 2 +- drivers/scsi/bfa/bfa_fcs.c | 2 +- drivers/scsi/bfa/bfa_fcs.h | 2 +- drivers/scsi/bfa/bfa_fcs_lport.c | 2 +- drivers/scsi/bfa/bfa_svc.c | 4 +- drivers/scsi/bfa/bfa_svc.h | 2 +- drivers/scsi/bfa/bfad.c | 2 +- drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h | 2 +- drivers/scsi/bnx2fc/bnx2fc_els.c | 2 +- drivers/scsi/bnx2fc/bnx2fc_io.c | 4 +- drivers/scsi/bnx2fc/bnx2fc_tgt.c | 2 +- drivers/scsi/bnx2i/bnx2i_hwi.c | 2 +- drivers/scsi/cxgbi/libcxgbi.h | 6 +-- drivers/scsi/dc395x.c | 14 +++--- drivers/scsi/dc395x.h | 2 +- drivers/scsi/device_handler/scsi_dh_alua.c | 4 +- drivers/scsi/dpt/sys_info.h | 6 +-- drivers/scsi/eata.c | 2 +- drivers/scsi/fcoe/fcoe_ctlr.c | 4 +- drivers/scsi/fdomain.c | 2 +- drivers/scsi/fnic/fnic_fcs.c | 2 +- drivers/scsi/fnic/fnic_scsi.c | 4 +- drivers/scsi/g_NCR5380.c | 4 +- drivers/scsi/gdth.h | 2 +- drivers/scsi/gvp11.c | 2 +- drivers/scsi/imm.c | 2 +- drivers/scsi/initio.c | 4 +- drivers/scsi/initio.h | 4 +- drivers/scsi/ips.c | 4 +- drivers/scsi/ips.h | 2 +- drivers/scsi/iscsi_tcp.c | 2 +- drivers/scsi/libfc/fc_exch.c | 4 +- drivers/scsi/libfc/fc_fcp.c | 4 +- drivers/scsi/libfc/fc_lport.c | 18 ++++---- drivers/scsi/libsas/sas_expander.c | 2 +- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_bsg.c | 2 +- drivers/scsi/lpfc/lpfc_debugfs.c | 8 ++-- drivers/scsi/lpfc/lpfc_els.c | 4 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 16 +++---- drivers/scsi/lpfc/lpfc_init.c | 20 ++++---- drivers/scsi/lpfc/lpfc_mbox.c | 2 +- drivers/scsi/lpfc/lpfc_nl.h | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 10 ++-- drivers/scsi/lpfc/lpfc_scsi.h | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 26 +++++------ drivers/scsi/megaraid.c | 4 +- drivers/scsi/megaraid.h | 6 +-- drivers/scsi/megaraid/mbox_defs.h | 8 ++-- drivers/scsi/megaraid/megaraid_mbox.c | 6 +-- drivers/scsi/megaraid/megaraid_sas.h | 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- drivers/scsi/mpt2sas/mpi/mpi2_init.h | 2 +- drivers/scsi/mpt2sas/mpt2sas_base.c | 12 ++--- drivers/scsi/mpt2sas/mpt2sas_config.c | 2 +- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 2 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 20 ++++---- drivers/scsi/ncr53c8xx.c | 2 +- drivers/scsi/nsp32.c | 6 +-- drivers/scsi/nsp32.h | 2 +- drivers/scsi/osst.c | 6 +-- drivers/scsi/osst.h | 2 +- drivers/scsi/pcmcia/nsp_cs.c | 2 +- drivers/scsi/pm8001/pm8001_hwi.c | 2 +- drivers/scsi/pm8001/pm8001_hwi.h | 4 +- drivers/scsi/pm8001/pm8001_sas.h | 2 +- drivers/scsi/pmcraid.c | 10 ++-- drivers/scsi/pmcraid.h | 2 +- drivers/scsi/qla1280.c | 2 +- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/scsi/qla2xxx/qla_fw.h | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 6 +-- drivers/scsi/qla2xxx/qla_nx.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 6 +-- drivers/scsi/qla4xxx/ql4_def.h | 2 +- drivers/scsi/qla4xxx/ql4_init.c | 2 +- drivers/scsi/qla4xxx/ql4_nvram.h | 2 +- drivers/scsi/qla4xxx/ql4_os.c | 8 ++-- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_netlink.c | 2 +- drivers/scsi/scsi_tgt_lib.c | 2 +- drivers/scsi/scsi_transport_fc.c | 4 +- drivers/scsi/sd.c | 2 +- drivers/scsi/sr.c | 2 +- drivers/scsi/sun3_NCR5380.c | 6 +-- drivers/scsi/sym53c416.c | 2 +- drivers/scsi/sym53c8xx_2/sym_fw1.h | 2 +- drivers/scsi/sym53c8xx_2/sym_fw2.h | 2 +- drivers/scsi/sym53c8xx_2/sym_hipd.c | 4 +- drivers/scsi/sym53c8xx_2/sym_malloc.c | 2 +- drivers/scsi/wd33c93.c | 2 +- drivers/scsi/wd7000.c | 2 +- drivers/sfi/sfi_core.c | 2 +- drivers/spi/amba-pl022.c | 16 +++---- drivers/spi/au1550_spi.c | 2 +- drivers/spi/dw_spi.c | 2 +- drivers/spi/dw_spi.h | 2 +- drivers/spi/ep93xx_spi.c | 2 +- drivers/spi/pxa2xx_spi.c | 4 +- drivers/spi/spi.c | 2 +- drivers/spi/spi_bfin5xx.c | 2 +- drivers/spi/spi_fsl_espi.c | 2 +- drivers/ssb/pci.c | 2 +- drivers/ssb/sprom.c | 2 +- .../ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c | 6 +-- drivers/staging/ath6kl/include/aggr_recv_api.h | 2 +- drivers/staging/ath6kl/include/common/a_hci.h | 4 +- drivers/staging/ath6kl/include/common/dbglog.h | 2 +- .../staging/ath6kl/include/common/epping_test.h | 2 +- drivers/staging/ath6kl/include/common/ini_dset.h | 2 +- drivers/staging/ath6kl/include/common/testcmd.h | 4 +- drivers/staging/ath6kl/include/common/wmi.h | 8 ++-- drivers/staging/ath6kl/include/common/wmix.h | 2 +- drivers/staging/ath6kl/include/htc_api.h | 6 +-- drivers/staging/ath6kl/miscdrv/credit_dist.c | 6 +-- drivers/staging/ath6kl/os/linux/ar6000_android.c | 2 +- drivers/staging/ath6kl/os/linux/ar6000_drv.c | 8 ++-- drivers/staging/ath6kl/wmi/wmi.c | 2 +- drivers/staging/bcm/Adapter.h | 10 ++-- drivers/staging/bcm/CmHost.c | 16 +++---- drivers/staging/bcm/HostMIBSInterface.h | 2 +- drivers/staging/bcm/IPv6Protocol.c | 4 +- drivers/staging/bcm/InterfaceIdleMode.c | 4 +- drivers/staging/bcm/InterfaceIsr.c | 4 +- drivers/staging/bcm/InterfaceRx.c | 10 ++-- drivers/staging/bcm/Ioctl.h | 2 +- drivers/staging/bcm/LeakyBucket.c | 2 +- drivers/staging/bcm/Misc.c | 6 +-- drivers/staging/bcm/Qos.c | 2 +- drivers/staging/bcm/cntrl_SignalingInterface.h | 6 +-- drivers/staging/bcm/nvm.c | 54 +++++++++++----------- drivers/staging/brcm80211/README | 2 +- drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 2 +- .../staging/brcm80211/brcmfmac/dhd_custom_gpio.c | 2 +- drivers/staging/brcm80211/brcmfmac/dhd_linux.c | 2 +- drivers/staging/brcm80211/brcmfmac/dhd_sdio.c | 4 +- drivers/staging/brcm80211/brcmsmac/wl_mac80211.c | 2 +- drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c | 6 +-- drivers/staging/brcm80211/brcmsmac/wlc_bmac.c | 2 +- drivers/staging/brcm80211/brcmsmac/wlc_main.c | 4 +- drivers/staging/brcm80211/brcmsmac/wlc_rate.c | 2 +- drivers/staging/brcm80211/include/bcmsrom_fmt.h | 2 +- drivers/staging/brcm80211/include/hndsoc.h | 2 +- drivers/staging/brcm80211/util/bcmotp.c | 4 +- drivers/staging/brcm80211/util/bcmsrom.c | 2 +- drivers/staging/brcm80211/util/hnddma.c | 6 +-- drivers/staging/brcm80211/util/sbpcmcia.h | 2 +- drivers/staging/brcm80211/util/siutils.c | 2 +- drivers/staging/comedi/comedi_fops.c | 2 +- .../comedi/drivers/addi-data/APCI1710_Chrono.c | 8 ++-- .../comedi/drivers/addi-data/addi_amcc_S5920.c | 2 +- .../comedi/drivers/addi-data/hwdrv_apci2032.c | 2 +- .../comedi/drivers/addi-data/hwdrv_apci3120.c | 18 ++++---- .../comedi/drivers/addi-data/hwdrv_apci3120.h | 2 +- .../comedi/drivers/addi-data/hwdrv_apci3200.c | 4 +- drivers/staging/comedi/drivers/adl_pci9118.c | 6 +-- drivers/staging/comedi/drivers/adq12b.c | 4 +- drivers/staging/comedi/drivers/adv_pci1710.c | 8 ++-- drivers/staging/comedi/drivers/cb_pcidas.c | 6 +-- drivers/staging/comedi/drivers/cb_pcidas64.c | 14 +++--- drivers/staging/comedi/drivers/comedi_test.c | 2 +- drivers/staging/comedi/drivers/das1800.c | 2 +- drivers/staging/comedi/drivers/das800.c | 2 +- drivers/staging/comedi/drivers/dmm32at.c | 2 +- drivers/staging/comedi/drivers/dt2811.c | 2 +- drivers/staging/comedi/drivers/dt9812.c | 2 +- drivers/staging/comedi/drivers/gsc_hpdi.c | 4 +- drivers/staging/comedi/drivers/icp_multi.c | 6 +-- drivers/staging/comedi/drivers/me4000.c | 4 +- drivers/staging/comedi/drivers/mpc624.c | 14 +++--- drivers/staging/comedi/drivers/ni_at_a2150.c | 12 ++--- drivers/staging/comedi/drivers/ni_labpc.c | 14 +++--- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- drivers/staging/comedi/drivers/pcl812.c | 2 +- drivers/staging/comedi/drivers/pcl816.c | 6 +-- drivers/staging/comedi/drivers/pcl818.c | 6 +-- drivers/staging/comedi/drivers/pcmmio.c | 4 +- drivers/staging/comedi/drivers/pcmuio.c | 2 +- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 4 +- drivers/staging/comedi/drivers/rtd520.c | 12 ++--- drivers/staging/comedi/drivers/s626.c | 18 ++++---- drivers/staging/comedi/drivers/usbdux.c | 22 ++++----- drivers/staging/comedi/drivers/usbduxfast.c | 8 ++-- drivers/staging/cptm1217/clearpad_tm1217.c | 2 +- drivers/staging/crystalhd/crystalhd_cmds.c | 2 +- drivers/staging/crystalhd/crystalhd_hw.c | 6 +-- drivers/staging/cxt1e1/musycc.c | 2 +- drivers/staging/cxt1e1/musycc.h | 4 +- drivers/staging/cxt1e1/pmcc4_defs.h | 4 +- drivers/staging/cxt1e1/sbecrc.c | 2 +- drivers/staging/cxt1e1/sbeproc.c | 2 +- drivers/staging/et131x/et1310_address_map.h | 4 +- drivers/staging/et131x/et1310_phy.h | 2 +- drivers/staging/et131x/et1310_rx.c | 2 +- drivers/staging/et131x/et131x_isr.c | 2 +- drivers/staging/et131x/et131x_netdev.c | 2 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h | 4 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 44 +++++++++--------- .../staging/ft1000/ft1000-usb/ft1000_download.c | 8 ++-- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 16 +++---- drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h | 2 +- drivers/staging/ft1000/ft1000-usb/ft1000_usb.h | 2 +- drivers/staging/generic_serial/generic_serial.c | 2 +- drivers/staging/generic_serial/rio/map.h | 2 +- drivers/staging/generic_serial/rio/rioboot.c | 8 ++-- drivers/staging/generic_serial/rio/riocmd.c | 2 +- drivers/staging/generic_serial/rio/rioroute.c | 4 +- drivers/staging/generic_serial/rio/riotty.c | 4 +- drivers/staging/generic_serial/sx.c | 8 ++-- drivers/staging/gma500/psb_drm.h | 2 +- drivers/staging/gma500/psb_drv.c | 2 +- drivers/staging/gma500/psb_intel_bios.c | 2 +- drivers/staging/gma500/psb_intel_sdvo.c | 2 +- drivers/staging/gma500/psb_intel_sdvo_regs.h | 2 +- drivers/staging/gma500/psb_ttm_fence_user.h | 2 +- drivers/staging/go7007/go7007.txt | 2 +- drivers/staging/hv/blkvsc_drv.c | 2 +- drivers/staging/hv/channel_mgmt.c | 2 +- drivers/staging/hv/hv.c | 2 +- drivers/staging/hv/hv_api.h | 4 +- drivers/staging/hv/hv_kvp.h | 2 +- drivers/staging/hv/hv_util.c | 2 +- drivers/staging/hv/rndis_filter.c | 2 +- drivers/staging/hv/tools/hv_kvp_daemon.c | 2 +- drivers/staging/iio/Documentation/iio_utils.h | 2 +- drivers/staging/iio/accel/adis16201.h | 2 +- drivers/staging/iio/accel/adis16203.h | 2 +- drivers/staging/iio/accel/adis16204.h | 2 +- drivers/staging/iio/accel/adis16209.h | 2 +- drivers/staging/iio/accel/adis16220.h | 2 +- drivers/staging/iio/accel/adis16240.h | 2 +- drivers/staging/iio/accel/lis3l02dq.h | 26 +++++------ drivers/staging/iio/accel/lis3l02dq_core.c | 2 +- drivers/staging/iio/accel/lis3l02dq_ring.c | 4 +- drivers/staging/iio/accel/sca3000.h | 4 +- drivers/staging/iio/accel/sca3000_ring.c | 2 +- drivers/staging/iio/adc/ad7298_ring.c | 2 +- drivers/staging/iio/adc/ad7476_ring.c | 2 +- drivers/staging/iio/adc/ad7887_ring.c | 2 +- drivers/staging/iio/adc/ad799x_core.c | 2 +- drivers/staging/iio/adc/ad799x_ring.c | 2 +- drivers/staging/iio/adc/max1363_core.c | 4 +- drivers/staging/iio/adc/max1363_ring.c | 2 +- drivers/staging/iio/chrdev.h | 6 +-- drivers/staging/iio/gyro/adis16060_core.c | 2 +- drivers/staging/iio/gyro/adis16080_core.c | 2 +- drivers/staging/iio/gyro/adis16260.h | 2 +- drivers/staging/iio/iio.h | 2 +- drivers/staging/iio/imu/adis16300.h | 2 +- drivers/staging/iio/imu/adis16350.h | 2 +- drivers/staging/iio/imu/adis16400.h | 2 +- drivers/staging/iio/industrialio-core.c | 2 +- drivers/staging/iio/meter/ade7753.h | 2 +- drivers/staging/iio/meter/ade7754.h | 2 +- drivers/staging/iio/meter/ade7758.h | 2 +- drivers/staging/iio/meter/ade7759.h | 2 +- drivers/staging/iio/meter/ade7854.h | 2 +- drivers/staging/iio/ring_generic.h | 2 +- drivers/staging/intel_sst/TODO | 2 +- drivers/staging/intel_sst/intel_sst.c | 4 +- .../staging/intel_sst/intel_sst_app_interface.c | 16 +++---- .../staging/intel_sst/intel_sst_drv_interface.c | 2 +- drivers/staging/intel_sst/intel_sst_dsp.c | 4 +- drivers/staging/intel_sst/intel_sst_fw_ipc.h | 2 +- drivers/staging/intel_sst/intel_sst_stream.c | 2 +- .../staging/intel_sst/intel_sst_stream_encoded.c | 2 +- drivers/staging/intel_sst/intelmid.c | 2 +- drivers/staging/intel_sst/intelmid.h | 2 +- drivers/staging/keucr/init.c | 4 +- drivers/staging/keucr/smilmain.c | 8 ++-- drivers/staging/keucr/smilsub.c | 6 +-- drivers/staging/lirc/lirc_ene0100.h | 4 +- drivers/staging/memrar/memrar_handler.c | 2 +- drivers/staging/msm/mdp4_overlay.c | 2 +- drivers/staging/msm/mdp_ppp_dq.c | 2 +- drivers/staging/msm/msm_fb.c | 6 +-- drivers/staging/octeon/cvmx-cmd-queue.h | 2 +- drivers/staging/octeon/cvmx-fpa.h | 2 +- drivers/staging/octeon/cvmx-helper-board.h | 2 +- drivers/staging/octeon/cvmx-helper-util.c | 2 +- drivers/staging/octeon/cvmx-helper.c | 2 +- drivers/staging/octeon/cvmx-mdio.h | 2 +- drivers/staging/octeon/cvmx-pko.h | 4 +- drivers/staging/octeon/cvmx-pow.h | 12 ++--- drivers/staging/octeon/ethernet-util.h | 2 +- drivers/staging/olpc_dcon/olpc_dcon_xo_1.c | 2 +- drivers/staging/pohmelfs/crypto.c | 2 +- drivers/staging/quatech_usb2/quatech_usb2.c | 12 ++--- drivers/staging/rt2860/chip/rtmp_phy.h | 2 +- drivers/staging/rt2860/common/ba_action.c | 4 +- drivers/staging/rt2860/common/cmm_aes.c | 2 +- drivers/staging/rt2860/common/cmm_cfg.c | 2 +- drivers/staging/rt2860/common/cmm_data.c | 4 +- drivers/staging/rt2860/common/cmm_data_pci.c | 6 +-- drivers/staging/rt2860/common/cmm_data_usb.c | 6 +-- drivers/staging/rt2860/common/cmm_mac_pci.c | 2 +- drivers/staging/rt2860/common/cmm_sanity.c | 4 +- drivers/staging/rt2860/common/cmm_sync.c | 2 +- drivers/staging/rt2860/common/cmm_wpa.c | 4 +- drivers/staging/rt2860/common/mlme.c | 16 +++---- drivers/staging/rt2860/common/rtmp_init.c | 14 +++--- drivers/staging/rt2860/common/spectrum.c | 12 ++--- drivers/staging/rt2860/mlme.h | 8 ++-- drivers/staging/rt2860/rt_linux.c | 2 +- drivers/staging/rt2860/rt_pci_rbus.c | 2 +- drivers/staging/rt2860/rtmp.h | 4 +- drivers/staging/rt2860/sta_ioctl.c | 2 +- drivers/staging/rt2870/common/rtusb_bulk.c | 6 +-- drivers/staging/rt2870/common/rtusb_data.c | 2 +- drivers/staging/rtl8187se/ieee80211/ieee80211.h | 6 +-- .../rtl8187se/ieee80211/ieee80211_softmac.c | 2 +- drivers/staging/rtl8187se/r8180_core.c | 4 +- drivers/staging/rtl8187se/r8180_dm.c | 4 +- drivers/staging/rtl8187se/r8180_rtl8225z2.c | 2 +- drivers/staging/rtl8187se/r8185b_init.c | 2 +- drivers/staging/rtl8192e/ieee80211/ieee80211.h | 8 ++-- drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c | 2 +- .../staging/rtl8192e/ieee80211/ieee80211_softmac.c | 4 +- drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h | 2 +- .../staging/rtl8192e/ieee80211/rtl819x_HTProc.c | 8 ++-- drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h | 2 +- .../staging/rtl8192e/ieee80211/rtl819x_TSProc.c | 2 +- drivers/staging/rtl8192e/r819xE_phy.c | 6 +-- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 8 ++-- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +- .../staging/rtl8192u/ieee80211/ieee80211_softmac.c | 4 +- drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h | 2 +- .../staging/rtl8192u/ieee80211/rtl819x_HTProc.c | 8 ++-- drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h | 2 +- .../staging/rtl8192u/ieee80211/rtl819x_TSProc.c | 2 +- drivers/staging/rtl8192u/ieee80211/scatterwalk.c | 2 +- drivers/staging/rtl8192u/r8192U_core.c | 6 +-- drivers/staging/rtl8192u/r819xU_HTType.h | 2 +- drivers/staging/rtl8192u/r819xU_phy.c | 6 +-- drivers/staging/rtl8712/rtl871x_cmd.h | 2 +- drivers/staging/rtl8712/rtl871x_led.h | 4 +- drivers/staging/rtl8712/rtl871x_mlme.c | 6 +-- drivers/staging/rtl8712/rtl871x_mlme.h | 2 +- drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h | 2 +- drivers/staging/rtl8712/usb_halinit.c | 2 +- drivers/staging/rts_pstor/rtsx_chip.h | 10 ++-- drivers/staging/rts_pstor/rtsx_scsi.h | 2 +- drivers/staging/rts_pstor/sd.c | 2 +- drivers/staging/sep/sep_driver.c | 10 ++-- drivers/staging/sep/sep_driver_config.h | 4 +- drivers/staging/slicoss/README | 2 +- drivers/staging/sm7xx/smtcfb.c | 4 +- drivers/staging/speakup/keyhelp.c | 2 +- drivers/staging/speakup/spkguide.txt | 2 +- drivers/staging/spectra/ffsport.c | 4 +- drivers/staging/spectra/flash.c | 6 +-- drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c | 20 ++++---- drivers/staging/tidspbridge/core/_tiomap.h | 2 +- drivers/staging/tidspbridge/core/chnl_sm.c | 2 +- drivers/staging/tidspbridge/dynload/cload.c | 2 +- drivers/staging/tidspbridge/hw/hw_mmu.c | 6 +-- .../tidspbridge/include/dspbridge/_chnl_sm.h | 4 +- .../staging/tidspbridge/include/dspbridge/clk.h | 6 +-- .../staging/tidspbridge/include/dspbridge/cmm.h | 2 +- .../staging/tidspbridge/include/dspbridge/cod.h | 2 +- .../staging/tidspbridge/include/dspbridge/dev.h | 2 +- .../staging/tidspbridge/include/dspbridge/drv.h | 6 +-- .../tidspbridge/include/dspbridge/dspdefs.h | 14 +++--- .../staging/tidspbridge/include/dspbridge/mgr.h | 4 +- .../staging/tidspbridge/include/dspbridge/node.h | 2 +- .../staging/tidspbridge/include/dspbridge/proc.h | 6 +-- .../staging/tidspbridge/include/dspbridge/pwr.h | 8 ++-- drivers/staging/tidspbridge/pmgr/dev.c | 6 +-- drivers/staging/tidspbridge/rmgr/drv.c | 2 +- drivers/staging/tidspbridge/rmgr/nldr.c | 6 +-- drivers/staging/tidspbridge/rmgr/proc.c | 4 +- drivers/staging/tm6000/tm6000-video.c | 2 +- drivers/staging/tty/cd1865.h | 2 +- drivers/staging/tty/epca.c | 16 +++---- drivers/staging/tty/ip2/i2hw.h | 4 +- drivers/staging/tty/ip2/i2lib.c | 8 ++-- drivers/staging/tty/ip2/ip2main.c | 2 +- drivers/staging/tty/specialix.c | 4 +- drivers/staging/tty/specialix_io8.h | 4 +- drivers/staging/usbip/vhci_hcd.c | 2 +- drivers/staging/vme/bridges/vme_ca91cx42.c | 6 +-- drivers/staging/vme/bridges/vme_tsi148.c | 4 +- drivers/staging/vme/bridges/vme_tsi148.h | 8 ++-- drivers/staging/vme/vme_api.txt | 6 +-- drivers/staging/vt6655/card.c | 2 +- drivers/staging/vt6655/device_main.c | 2 +- drivers/staging/vt6655/wcmd.c | 2 +- drivers/staging/vt6655/wmgr.h | 4 +- drivers/staging/vt6656/rxtx.c | 2 +- drivers/staging/vt6656/wcmd.c | 4 +- drivers/staging/vt6656/wmgr.h | 4 +- .../staging/westbridge/astoria/api/src/cyasdma.c | 2 +- .../westbridge/astoria/api/src/cyaslep2pep.c | 2 +- .../westbridge/astoria/api/src/cyaslowlevel.c | 2 +- .../staging/westbridge/astoria/api/src/cyasmisc.c | 6 +-- .../staging/westbridge/astoria/api/src/cyasmtp.c | 4 +- .../westbridge/astoria/api/src/cyasstorage.c | 6 +-- .../staging/westbridge/astoria/api/src/cyasusb.c | 4 +- .../arch/arm/mach-omap2/cyashalomap_kernel.c | 12 ++--- .../cyashalomap_kernel.h | 2 +- .../westbridge-omap3-pnand-hal/cyasmemmap.h | 4 +- .../westbridge/astoria/block/cyasblkdev_queue.c | 2 +- .../astoria/include/linux/westbridge/cyasdevice.h | 6 +-- .../astoria/include/linux/westbridge/cyasdma.h | 10 ++-- .../astoria/include/linux/westbridge/cyaserr.h | 4 +- .../astoria/include/linux/westbridge/cyashaldoc.h | 2 +- .../astoria/include/linux/westbridge/cyasintr.h | 2 +- .../astoria/include/linux/westbridge/cyasmisc.h | 8 ++-- .../include/linux/westbridge/cyasprotocol.h | 4 +- .../astoria/include/linux/westbridge/cyasstorage.h | 34 +++++++------- .../astoria/include/linux/westbridge/cyasusb.h | 40 ++++++++-------- drivers/staging/winbond/mds.c | 2 +- drivers/staging/wlags49_h2/README.ubuntu | 2 +- drivers/staging/wlags49_h2/TODO | 4 +- drivers/staging/wlags49_h2/hcf.c | 24 +++++----- drivers/staging/wlags49_h2/hcfdef.h | 2 +- drivers/staging/wlags49_h2/wl_wext.c | 6 +-- drivers/staging/wlags49_h25/TODO | 4 +- drivers/staging/wlan-ng/prism2sta.c | 2 +- drivers/staging/xgifb/vb_setmode.c | 2 +- drivers/staging/xgifb/vgatypes.h | 2 +- drivers/target/target_core_alua.c | 10 ++-- drivers/target/target_core_device.c | 2 +- drivers/target/target_core_fabric_lib.c | 2 +- drivers/target/target_core_file.c | 2 +- drivers/target/target_core_pr.c | 6 +-- drivers/target/target_core_transport.c | 14 +++--- drivers/target/target_core_ua.c | 4 +- drivers/telephony/ixj.c | 8 ++-- drivers/telephony/ixj.h | 2 +- drivers/tty/hvc/hvc_iucv.c | 4 +- drivers/tty/hvc/hvc_vio.c | 2 +- drivers/tty/hvc/hvcs.c | 8 ++-- drivers/tty/mxser.h | 2 +- drivers/tty/n_gsm.c | 10 ++-- drivers/tty/nozomi.c | 2 +- drivers/tty/rocket.c | 4 +- drivers/tty/serial/8250.c | 2 +- drivers/tty/serial/8250_pci.c | 2 +- drivers/tty/serial/amba-pl011.c | 2 +- drivers/tty/serial/icom.c | 2 +- drivers/tty/serial/imx.c | 2 +- drivers/tty/serial/ip22zilog.c | 2 +- drivers/tty/serial/jsm/jsm.h | 2 +- drivers/tty/serial/jsm/jsm_neo.c | 4 +- drivers/tty/serial/max3107.h | 2 +- drivers/tty/serial/mrst_max3110.c | 2 +- drivers/tty/serial/mrst_max3110.h | 2 +- drivers/tty/serial/msm_serial_hs.c | 4 +- drivers/tty/serial/omap-serial.c | 2 +- drivers/tty/serial/pmac_zilog.c | 6 +-- drivers/tty/serial/samsung.c | 4 +- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/sn_console.c | 4 +- drivers/tty/serial/sunzilog.c | 2 +- drivers/tty/synclink.c | 10 ++-- drivers/tty/synclink_gt.c | 2 +- drivers/tty/synclinkmp.c | 10 ++-- drivers/tty/tty_io.c | 8 ++-- drivers/tty/tty_ioctl.c | 6 +-- drivers/tty/vt/vt.c | 2 +- drivers/uio/uio_pruss.c | 2 +- drivers/usb/atm/ueagle-atm.c | 8 ++-- drivers/usb/c67x00/c67x00-drv.c | 2 +- drivers/usb/c67x00/c67x00-hcd.h | 2 +- drivers/usb/c67x00/c67x00-sched.c | 2 +- drivers/usb/class/cdc-acm.h | 2 +- drivers/usb/class/usbtmc.c | 2 +- drivers/usb/core/hcd.c | 2 +- drivers/usb/core/hub.c | 2 +- drivers/usb/early/ehci-dbgp.c | 2 +- drivers/usb/gadget/amd5536udc.c | 14 +++--- drivers/usb/gadget/amd5536udc.h | 2 +- drivers/usb/gadget/at91_udc.c | 2 +- drivers/usb/gadget/composite.c | 6 +-- drivers/usb/gadget/f_audio.c | 2 +- drivers/usb/gadget/f_ncm.c | 2 +- drivers/usb/gadget/fsl_qe_udc.h | 6 +-- drivers/usb/gadget/fsl_udc_core.c | 6 +-- drivers/usb/gadget/fsl_usb2_udc.h | 4 +- drivers/usb/gadget/gmidi.c | 2 +- drivers/usb/gadget/langwell_udc.c | 2 +- drivers/usb/gadget/mv_udc_core.c | 6 +-- drivers/usb/gadget/net2280.c | 2 +- drivers/usb/gadget/nokia.c | 2 +- drivers/usb/gadget/printer.c | 2 +- drivers/usb/gadget/pxa27x_udc.c | 12 ++--- drivers/usb/gadget/s3c-hsotg.c | 18 ++++---- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci.h | 2 +- drivers/usb/host/fhci-hcd.c | 2 +- drivers/usb/host/fhci-tds.c | 8 ++-- drivers/usb/host/fhci.h | 4 +- drivers/usb/host/imx21-hcd.c | 2 +- drivers/usb/host/isp116x.h | 2 +- drivers/usb/host/isp1362-hcd.c | 2 +- drivers/usb/host/ohci-hcd.c | 2 +- drivers/usb/host/oxu210hp-hcd.c | 4 +- drivers/usb/host/whci/qset.c | 2 +- drivers/usb/host/xhci.c | 4 +- drivers/usb/host/xhci.h | 2 +- drivers/usb/image/microtek.c | 8 ++-- drivers/usb/misc/iowarrior.c | 2 +- drivers/usb/otg/isp1301_omap.c | 2 +- drivers/usb/otg/langwell_otg.c | 4 +- drivers/usb/serial/aircable.c | 4 +- drivers/usb/serial/cp210x.c | 2 +- drivers/usb/serial/cypress_m8.c | 2 +- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/io_edgeport.c | 2 +- drivers/usb/serial/io_edgeport.h | 2 +- drivers/usb/serial/io_ti.c | 2 +- drivers/usb/serial/opticon.c | 2 +- drivers/usb/storage/ene_ub6250.c | 4 +- drivers/usb/storage/isd200.c | 2 +- drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/shuttle_usbat.c | 2 +- drivers/usb/wusbcore/crypto.c | 4 +- drivers/usb/wusbcore/reservation.c | 2 +- drivers/usb/wusbcore/rh.c | 2 +- drivers/usb/wusbcore/wa-rpipe.c | 2 +- drivers/usb/wusbcore/wa-xfer.c | 8 ++-- drivers/usb/wusbcore/wusbhc.h | 2 +- drivers/uwb/driver.c | 2 +- drivers/uwb/drp.c | 6 +-- drivers/uwb/lc-rc.c | 2 +- drivers/uwb/reset.c | 2 +- drivers/uwb/umc-dev.c | 2 +- drivers/video/atmel_lcdfb.c | 2 +- drivers/video/aty/atyfb_base.c | 4 +- drivers/video/aty/mach64_cursor.c | 2 +- drivers/video/au1200fb.c | 2 +- drivers/video/backlight/corgi_lcd.c | 2 +- drivers/video/backlight/locomolcd.c | 2 +- drivers/video/bfin_adv7393fb.h | 24 +++++----- drivers/video/console/font_mini_4x6.c | 2 +- drivers/video/da8xx-fb.c | 2 +- drivers/video/display/display-sysfs.c | 2 +- drivers/video/ep93xx-fb.c | 2 +- drivers/video/fbsysfs.c | 2 +- drivers/video/fm2fb.c | 2 +- drivers/video/fsl-diu-fb.c | 2 +- drivers/video/gbefb.c | 2 +- drivers/video/geode/lxfb.h | 2 +- drivers/video/i810/i810_accel.c | 2 +- drivers/video/kyro/STG4000OverlayDevice.c | 2 +- drivers/video/kyro/STG4000Reg.h | 2 +- drivers/video/matrox/matroxfb_DAC1064.h | 2 +- drivers/video/matrox/matroxfb_Ti3026.c | 4 +- drivers/video/matrox/matroxfb_base.c | 2 +- drivers/video/matrox/matroxfb_base.h | 2 +- drivers/video/nuc900fb.h | 2 +- drivers/video/omap/Kconfig | 2 +- drivers/video/omap2/dss/hdmi.c | 2 +- drivers/video/pxa3xx-gcu.c | 2 +- drivers/video/savage/savagefb.h | 2 +- drivers/video/savage/savagefb_driver.c | 4 +- drivers/video/sm501fb.c | 4 +- drivers/video/sstfb.c | 8 ++-- drivers/video/sticore.h | 2 +- drivers/video/tdfxfb.c | 18 ++++---- drivers/video/tmiofb.c | 2 +- drivers/video/udlfb.c | 2 +- drivers/video/vga16fb.c | 2 +- drivers/video/via/via_utility.c | 2 +- drivers/video/via/via_utility.h | 2 +- drivers/video/via/viafbdev.c | 2 +- drivers/video/w100fb.c | 2 +- drivers/w1/masters/omap_hdq.c | 2 +- drivers/watchdog/Kconfig | 2 +- drivers/watchdog/Makefile | 4 +- drivers/watchdog/acquirewdt.c | 2 +- drivers/watchdog/pc87413_wdt.c | 2 +- drivers/watchdog/sbc7240_wdt.c | 2 +- drivers/watchdog/sch311x_wdt.c | 2 +- drivers/watchdog/shwdt.c | 2 +- drivers/watchdog/smsc37b787_wdt.c | 2 +- drivers/watchdog/sp805_wdt.c | 2 +- drivers/xen/events.c | 4 +- fs/adfs/map.c | 2 +- fs/afs/cache.c | 12 ++--- fs/afs/cell.c | 2 +- fs/attr.c | 2 +- fs/autofs4/root.c | 2 +- fs/befs/ChangeLog | 10 ++-- fs/befs/befs_fs_types.h | 2 +- fs/befs/btree.c | 2 +- fs/befs/linuxvfs.c | 2 +- fs/binfmt_flat.c | 2 +- fs/bio.c | 2 +- fs/block_dev.c | 2 +- fs/btrfs/extent_map.c | 2 +- fs/btrfs/inode.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/cachefiles/interface.c | 2 +- fs/ceph/addr.c | 2 +- fs/ceph/caps.c | 2 +- fs/ceph/snap.c | 2 +- fs/cifs/AUTHORS | 2 +- fs/cifs/cifs_dfs_ref.c | 2 +- fs/cifs/cifssmb.c | 2 +- fs/cifs/connect.c | 4 +- fs/cifs/dir.c | 2 +- fs/configfs/dir.c | 2 +- fs/dlm/lock.c | 2 +- fs/dlm/lowcomms.c | 2 +- fs/dlm/recover.c | 2 +- fs/ecryptfs/main.c | 4 +- fs/eventpoll.c | 8 ++-- fs/exofs/common.h | 4 +- fs/ext2/balloc.c | 6 +-- fs/ext2/inode.c | 8 ++-- fs/ext2/super.c | 2 +- fs/ext2/xattr.c | 2 +- fs/ext3/balloc.c | 10 ++-- fs/ext3/inode.c | 6 +-- fs/ext3/resize.c | 2 +- fs/ext3/super.c | 2 +- fs/ext4/balloc.c | 2 +- fs/ext4/extents.c | 10 ++-- fs/ext4/fsync.c | 2 +- fs/ext4/inode.c | 20 ++++---- fs/ext4/mballoc.c | 2 +- fs/ext4/migrate.c | 2 +- fs/ext4/super.c | 4 +- fs/freevxfs/vxfs_fshead.c | 2 +- fs/freevxfs/vxfs_lookup.c | 2 +- fs/freevxfs/vxfs_olt.h | 2 +- fs/fs-writeback.c | 2 +- fs/fuse/file.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/gfs2/glock.c | 2 +- fs/gfs2/super.c | 2 +- fs/jbd/commit.c | 2 +- fs/jbd/journal.c | 4 +- fs/jbd/revoke.c | 2 +- fs/jbd/transaction.c | 2 +- fs/jbd2/commit.c | 2 +- fs/jbd2/journal.c | 4 +- fs/jbd2/revoke.c | 2 +- fs/jbd2/transaction.c | 2 +- fs/jffs2/TODO | 2 +- fs/jffs2/readinode.c | 2 +- fs/jffs2/summary.c | 4 +- fs/jffs2/wbuf.c | 2 +- fs/jfs/jfs_dmap.c | 4 +- fs/jfs/jfs_extent.c | 6 +-- fs/jfs/jfs_imap.c | 14 +++--- fs/jfs/jfs_logmgr.h | 2 +- fs/jfs/jfs_metapage.h | 2 +- fs/jfs/jfs_txnmgr.c | 2 +- fs/jfs/resize.c | 4 +- fs/jfs/super.c | 2 +- fs/logfs/dev_mtd.c | 2 +- fs/logfs/dir.c | 2 +- fs/logfs/readwrite.c | 2 +- fs/mbcache.c | 2 +- fs/namei.c | 2 +- fs/ncpfs/inode.c | 2 +- fs/nfs/callback_xdr.c | 2 +- fs/nfs/file.c | 2 +- fs/nfs/nfs4filelayout.h | 2 +- fs/nfs_common/nfsacl.c | 2 +- fs/nfsd/nfs3xdr.c | 2 +- fs/nfsd/nfs4state.c | 4 +- fs/nfsd/nfsxdr.c | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/notify/inotify/inotify_fsnotify.c | 2 +- fs/notify/mark.c | 2 +- fs/ntfs/attrib.c | 4 +- fs/ntfs/compress.c | 2 +- fs/ntfs/inode.c | 4 +- fs/ntfs/layout.h | 12 ++--- fs/ntfs/logfile.c | 2 +- fs/ntfs/logfile.h | 2 +- fs/ntfs/mft.c | 8 ++-- fs/ntfs/runlist.c | 2 +- fs/ntfs/super.c | 14 +++--- fs/ocfs2/alloc.c | 2 +- fs/ocfs2/aops.h | 2 +- fs/ocfs2/cluster/heartbeat.c | 2 +- fs/ocfs2/cluster/quorum.c | 4 +- fs/ocfs2/cluster/tcp.c | 2 +- fs/ocfs2/dlm/dlmmaster.c | 4 +- fs/ocfs2/inode.c | 4 +- fs/ocfs2/journal.c | 2 +- fs/ocfs2/journal.h | 2 +- fs/ocfs2/namei.c | 2 +- fs/ocfs2/ocfs2_fs.h | 4 +- fs/ocfs2/quota_global.c | 2 +- fs/ocfs2/reservations.h | 2 +- fs/ocfs2/stackglue.h | 2 +- fs/ocfs2/suballoc.c | 4 +- fs/ocfs2/super.c | 2 +- fs/ocfs2/xattr.c | 4 +- fs/partitions/check.c | 4 +- fs/proc/base.c | 2 +- fs/pstore/Kconfig | 2 +- fs/quota/dquot.c | 2 +- fs/reiserfs/journal.c | 4 +- fs/reiserfs/lock.c | 2 +- fs/reiserfs/super.c | 4 +- fs/reiserfs/xattr.c | 2 +- fs/squashfs/cache.c | 4 +- fs/ubifs/budget.c | 2 +- fs/ufs/inode.c | 2 +- fs/ufs/super.c | 6 +-- fs/xfs/linux-2.6/xfs_aops.c | 2 +- fs/xfs/linux-2.6/xfs_buf.c | 4 +- fs/xfs/linux-2.6/xfs_file.c | 2 +- fs/xfs/linux-2.6/xfs_iops.c | 2 +- fs/xfs/linux-2.6/xfs_sync.c | 2 +- fs/xfs/quota/xfs_dquot.c | 2 +- fs/xfs/quota/xfs_qm_bhv.c | 2 +- fs/xfs/quota/xfs_qm_syscalls.c | 4 +- fs/xfs/xfs_buf_item.c | 2 +- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode.h | 4 +- fs/xfs/xfs_log_priv.h | 2 +- fs/xfs/xfs_log_recover.c | 4 +- fs/xfs/xfs_trans_inode.c | 2 +- fs/xfs/xfs_vnodeops.c | 4 +- include/acpi/actbl.h | 2 +- include/asm-generic/siginfo.h | 2 +- include/asm-generic/vmlinux.lds.h | 2 +- include/drm/drmP.h | 4 +- include/drm/drm_crtc.h | 4 +- include/drm/drm_mm.h | 2 +- include/drm/drm_mode.h | 2 +- include/drm/mga_drm.h | 2 +- include/drm/radeon_drm.h | 2 +- include/drm/savage_drm.h | 2 +- include/drm/ttm/ttm_bo_api.h | 14 +++--- include/drm/ttm/ttm_bo_driver.h | 6 +-- include/drm/vmwgfx_drm.h | 2 +- include/linux/amba/clcd.h | 2 +- include/linux/amba/mmci.h | 6 +-- include/linux/can/error.h | 2 +- include/linux/can/netlink.h | 2 +- include/linux/cdk.h | 2 +- include/linux/cfag12864b.h | 2 +- include/linux/cgroup.h | 2 +- include/linux/cm4000_cs.h | 2 +- include/linux/configfs.h | 2 +- include/linux/cper.h | 2 +- include/linux/decompress/mm.h | 2 +- include/linux/dmaengine.h | 2 +- include/linux/drbd.h | 4 +- include/linux/drbd_limits.h | 6 +-- include/linux/ethtool.h | 2 +- include/linux/eventpoll.h | 2 +- include/linux/exportfs.h | 2 +- include/linux/fb.h | 8 ++-- include/linux/firewire-cdev.h | 2 +- include/linux/fs.h | 4 +- include/linux/fscache-cache.h | 2 +- include/linux/fscache.h | 6 +-- include/linux/hid.h | 2 +- include/linux/hp_sdc.h | 2 +- include/linux/i2o.h | 2 +- include/linux/interrupt.h | 4 +- include/linux/ipmi.h | 4 +- include/linux/isdn/hdlc.h | 2 +- include/linux/ixjuser.h | 2 +- include/linux/jiffies.h | 2 +- include/linux/ktime.h | 4 +- include/linux/led-lm3530.h | 2 +- include/linux/libata.h | 2 +- include/linux/lru_cache.h | 2 +- include/linux/mfd/wm8350/pmic.h | 2 +- include/linux/mm.h | 2 +- include/linux/mmc/dw_mmc.h | 4 +- include/linux/mroute6.h | 2 +- include/linux/mtd/cfi.h | 2 +- include/linux/mtd/nand.h | 6 +-- include/linux/mtd/xip.h | 2 +- include/linux/netfilter/nf_conntrack_proto_gre.h | 2 +- include/linux/netfilter_bridge/ebtables.h | 2 +- include/linux/nfs4.h | 2 +- include/linux/nfsd/export.h | 2 +- include/linux/nfsd/nfsfh.h | 2 +- include/linux/nl80211.h | 10 ++-- include/linux/notifier.h | 2 +- include/linux/omap3isp.h | 2 +- include/linux/page_cgroup.h | 2 +- include/linux/pci_regs.h | 4 +- include/linux/perf_event.h | 2 +- include/linux/pid.h | 2 +- include/linux/pkt_sched.h | 2 +- include/linux/poll.h | 2 +- include/linux/prefetch.h | 2 +- include/linux/pxa2xx_ssp.h | 2 +- include/linux/raid/md_p.h | 2 +- include/linux/reiserfs_fs.h | 2 +- include/linux/sched.h | 2 +- include/linux/skbuff.h | 2 +- include/linux/smc91x.h | 2 +- include/linux/socket.h | 2 +- include/linux/soundcard.h | 2 +- include/linux/spi/spidev.h | 2 +- include/linux/spinlock.h | 2 +- include/linux/stmmac.h | 2 +- include/linux/stop_machine.h | 2 +- include/linux/sunrpc/cache.h | 4 +- include/linux/sunrpc/svcauth_gss.h | 2 +- include/linux/sysdev.h | 6 +-- include/linux/timerqueue.h | 2 +- include/linux/tracehook.h | 4 +- include/linux/ucb1400.h | 2 +- include/linux/usb.h | 4 +- include/linux/usb/composite.h | 2 +- include/linux/usb/ehci_def.h | 2 +- include/linux/usb/functionfs.h | 4 +- include/linux/usb/gadget.h | 4 +- include/linux/usb/midi.h | 2 +- include/linux/usb/wusb.h | 2 +- include/linux/uwb.h | 6 +-- include/linux/uwb/umc.h | 2 +- include/linux/vgaarb.h | 4 +- include/linux/wimax.h | 2 +- include/linux/xilinxfb.h | 2 +- include/media/davinci/dm355_ccdc.h | 2 +- include/media/davinci/isif.h | 2 +- include/media/lirc.h | 2 +- include/net/9p/9p.h | 8 ++-- include/net/9p/client.h | 2 +- include/net/9p/transport.h | 2 +- include/net/caif/cfcnfg.h | 2 +- include/net/gen_stats.h | 2 +- include/net/ip_vs.h | 2 +- include/net/irda/irlap.h | 2 +- include/net/irda/wrapper.h | 2 +- include/net/iucv/iucv.h | 2 +- include/net/iw_handler.h | 4 +- include/net/mac80211.h | 2 +- include/net/pkt_sched.h | 2 +- include/net/sock.h | 2 +- include/net/transp_v6.h | 2 +- include/net/wimax.h | 2 +- include/net/wpan-phy.h | 2 +- include/rxrpc/packet.h | 2 +- include/scsi/fc/fc_fcp.h | 2 +- include/scsi/iscsi_if.h | 2 +- include/scsi/libfc.h | 8 ++-- include/scsi/libiscsi_tcp.h | 2 +- include/scsi/osd_initiator.h | 2 +- include/scsi/scsi_host.h | 2 +- include/scsi/scsi_transport_fc.h | 6 +-- include/sound/ac97_codec.h | 2 +- include/sound/control.h | 2 +- include/sound/cs46xx_dsp_spos.h | 2 +- include/sound/hdspm.h | 2 +- include/sound/soc-dapm.h | 2 +- include/target/target_core_base.h | 6 +-- include/target/target_core_fabric_ops.h | 2 +- include/video/kyro.h | 2 +- include/video/neomagic.h | 2 +- include/video/newport.h | 2 +- include/video/sisfb.h | 2 +- include/video/sstfb.h | 6 +-- include/xen/interface/elfnote.h | 2 +- init/do_mounts.c | 2 +- ipc/msg.c | 4 +- ipc/sem.c | 2 +- ipc/shm.c | 2 +- kernel/audit_tree.c | 2 +- kernel/auditsc.c | 2 +- kernel/cgroup.c | 2 +- kernel/cpu.c | 2 +- kernel/debug/debug_core.c | 2 +- kernel/debug/kdb/kdb_main.c | 6 +-- kernel/debug/kdb/kdb_support.c | 2 +- kernel/exit.c | 2 +- kernel/irq/chip.c | 2 +- kernel/irq/migration.c | 2 +- kernel/kexec.c | 6 +-- kernel/kthread.c | 2 +- kernel/latencytop.c | 2 +- kernel/lockdep.c | 4 +- kernel/module.c | 6 +-- kernel/mutex.c | 2 +- kernel/padata.c | 8 ++-- kernel/params.c | 2 +- kernel/posix-cpu-timers.c | 2 +- kernel/posix-timers.c | 2 +- kernel/power/main.c | 2 +- kernel/sched.c | 6 +-- kernel/sched_autogroup.c | 2 +- kernel/sched_fair.c | 2 +- kernel/sched_rt.c | 4 +- kernel/signal.c | 2 +- kernel/softirq.c | 2 +- kernel/time/jiffies.c | 2 +- kernel/time/timer_stats.c | 2 +- kernel/trace/ftrace.c | 4 +- kernel/trace/ring_buffer.c | 4 +- kernel/trace/trace.c | 2 +- kernel/trace/trace_clock.c | 2 +- kernel/trace/trace_entries.h | 2 +- kernel/trace/trace_functions_graph.c | 2 +- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_kprobe.c | 2 +- kernel/user-return-notifier.c | 2 +- kernel/wait.c | 2 +- kernel/workqueue.c | 2 +- lib/bitmap.c | 2 +- lib/btree.c | 4 +- lib/decompress_unxz.c | 2 +- lib/parser.c | 2 +- lib/timerqueue.c | 2 +- mm/backing-dev.c | 2 +- mm/hugetlb.c | 10 ++-- mm/hwpoison-inject.c | 2 +- mm/internal.h | 2 +- mm/kmemleak.c | 6 +-- mm/ksm.c | 2 +- mm/memcontrol.c | 8 ++-- mm/memory-failure.c | 6 +-- mm/memory_hotplug.c | 2 +- mm/migrate.c | 2 +- mm/nobootmem.c | 2 +- mm/page_alloc.c | 4 +- mm/page_cgroup.c | 2 +- mm/percpu.c | 10 ++-- mm/slab.c | 4 +- mm/slub.c | 8 ++-- mm/sparse.c | 2 +- mm/util.c | 2 +- mm/vmscan.c | 4 +- net/8021q/vlanproc.c | 2 +- net/9p/client.c | 2 +- net/9p/trans_common.c | 4 +- net/9p/util.c | 2 +- net/atm/br2684.c | 2 +- net/atm/lec.h | 2 +- net/batman-adv/soft-interface.c | 2 +- net/bluetooth/hci_core.c | 2 +- net/bluetooth/l2cap_sock.c | 2 +- net/bridge/br_fdb.c | 2 +- net/bridge/br_ioctl.c | 2 +- net/caif/caif_socket.c | 2 +- net/can/bcm.c | 2 +- net/ceph/osd_client.c | 2 +- net/core/dev.c | 12 ++--- net/core/filter.c | 2 +- net/core/link_watch.c | 2 +- net/core/rtnetlink.c | 4 +- net/core/skbuff.c | 2 +- net/core/sock.c | 10 ++-- net/dccp/output.c | 2 +- net/dsa/mv88e6131.c | 2 +- net/ipv4/cipso_ipv4.c | 8 ++-- net/ipv4/fib_trie.c | 2 +- net/ipv4/icmp.c | 2 +- net/ipv4/ip_output.c | 2 +- net/ipv4/ipconfig.c | 2 +- net/ipv4/netfilter/arp_tables.c | 4 +- net/ipv4/netfilter/ip_tables.c | 2 +- net/ipv4/netfilter/nf_nat_core.c | 4 +- net/ipv4/raw.c | 2 +- net/ipv4/route.c | 4 +- net/ipv4/tcp_lp.c | 2 +- net/ipv4/tcp_output.c | 2 +- net/ipv4/tcp_yeah.c | 2 +- net/ipv4/udp.c | 2 +- net/ipv6/addrconf.c | 4 +- net/ipv6/af_inet6.c | 2 +- net/ipv6/ip6_output.c | 2 +- net/ipv6/netfilter/ip6_tables.c | 2 +- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 2 +- net/irda/irlap.c | 2 +- net/irda/irlap_event.c | 8 ++-- net/irda/irlap_frame.c | 2 +- net/irda/irlmp_event.c | 2 +- net/irda/irnet/irnet.h | 2 +- net/irda/irqueue.c | 2 +- net/irda/irttp.c | 2 +- net/irda/qos.c | 8 ++-- net/irda/timer.c | 2 +- net/iucv/af_iucv.c | 2 +- net/iucv/iucv.c | 4 +- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/mesh_pathtbl.c | 2 +- net/mac80211/rc80211_minstrel_ht.c | 2 +- net/mac80211/rc80211_pid.h | 2 +- net/mac80211/rx.c | 2 +- net/mac80211/sta_info.c | 4 +- net/mac80211/sta_info.h | 2 +- net/netfilter/ipset/ip_set_core.c | 2 +- net/netfilter/ipvs/ip_vs_conn.c | 4 +- net/netfilter/ipvs/ip_vs_lblc.c | 2 +- net/netfilter/ipvs/ip_vs_lblcr.c | 2 +- net/netfilter/ipvs/ip_vs_proto_sctp.c | 8 ++-- net/netfilter/nf_conntrack_core.c | 4 +- net/netfilter/nf_conntrack_proto_dccp.c | 2 +- net/netfilter/nf_conntrack_proto_sctp.c | 6 +-- net/netfilter/nf_conntrack_sip.c | 2 +- net/netfilter/nf_queue.c | 2 +- net/netlabel/netlabel_domainhash.c | 10 ++-- net/netlabel/netlabel_mgmt.c | 2 +- net/rds/ib_send.c | 2 +- net/rds/iw_cm.c | 2 +- net/rds/iw_rdma.c | 2 +- net/rds/iw_send.c | 2 +- net/rds/send.c | 2 +- net/rose/rose_route.c | 2 +- net/sched/act_api.c | 2 +- net/sched/act_pedit.c | 2 +- net/sched/em_meta.c | 2 +- net/sched/sch_htb.c | 2 +- net/sched/sch_netem.c | 6 +-- net/sctp/associola.c | 2 +- net/sctp/auth.c | 6 +-- net/sctp/input.c | 2 +- net/sctp/output.c | 2 +- net/sctp/outqueue.c | 6 +-- net/sctp/sm_sideeffect.c | 2 +- net/sctp/sm_statefuns.c | 20 ++++---- net/sctp/socket.c | 2 +- net/sctp/ulpevent.c | 2 +- net/sctp/ulpqueue.c | 2 +- net/socket.c | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/xprtsock.c | 4 +- net/tipc/link.c | 2 +- net/tipc/name_distr.c | 2 +- net/unix/af_unix.c | 2 +- net/wanrouter/wanproc.c | 2 +- net/wireless/reg.c | 4 +- net/x25/x25_facilities.c | 2 +- net/x25/x25_forward.c | 4 +- net/xfrm/xfrm_user.c | 6 +-- samples/Kconfig | 2 +- samples/hw_breakpoint/data_breakpoint.c | 2 +- scripts/Makefile.modpost | 4 +- scripts/checkpatch.pl | 6 +-- scripts/dtc/libfdt/libfdt.h | 2 +- scripts/dtc/livetree.c | 2 +- scripts/gen_initramfs_list.sh | 2 +- scripts/kernel-doc | 2 +- scripts/package/buildtar | 2 +- scripts/rt-tester/rt-tester.py | 2 +- security/apparmor/match.c | 2 +- security/apparmor/policy_unpack.c | 2 +- security/selinux/netlabel.c | 2 +- security/selinux/ss/services.c | 4 +- security/smack/smack_access.c | 2 +- security/smack/smack_lsm.c | 6 +-- security/smack/smackfs.c | 6 +-- security/tomoyo/load_policy.c | 2 +- sound/aoa/codecs/tas.c | 2 +- sound/core/pcm_memory.c | 6 +-- sound/core/pcm_native.c | 2 +- sound/core/seq/seq_dummy.c | 2 +- sound/core/vmaster.c | 2 +- sound/drivers/pcm-indirect2.c | 4 +- sound/drivers/vx/vx_pcm.c | 2 +- sound/isa/sb/emu8000.c | 2 +- sound/isa/wavefront/wavefront_midi.c | 2 +- sound/isa/wss/wss_lib.c | 2 +- sound/oss/ac97_codec.c | 6 +-- sound/oss/audio.c | 4 +- sound/oss/dmasound/dmasound_core.c | 2 +- sound/oss/midibuf.c | 2 +- sound/oss/sb_card.c | 2 +- sound/oss/sb_ess.c | 2 +- sound/oss/swarm_cs4297a.c | 2 +- sound/oss/vidc.c | 2 +- sound/pci/ad1889.c | 2 +- sound/pci/asihpi/asihpi.c | 2 +- sound/pci/asihpi/hpi.h | 2 +- sound/pci/asihpi/hpi6000.c | 2 +- sound/pci/asihpi/hpi6205.c | 2 +- sound/pci/asihpi/hpi_internal.h | 2 +- sound/pci/asihpi/hpimsgx.c | 2 +- sound/pci/au88x0/au88x0.h | 2 +- sound/pci/au88x0/au88x0_a3d.c | 4 +- sound/pci/au88x0/au88x0_pcm.c | 2 +- sound/pci/azt3328.c | 2 +- sound/pci/ca0106/ca0106.h | 6 +-- sound/pci/ca0106/ca0106_main.c | 2 +- sound/pci/ca0106/ca0106_mixer.c | 2 +- sound/pci/ca0106/ca0106_proc.c | 2 +- sound/pci/cmipci.c | 8 ++-- sound/pci/ctxfi/ctatc.c | 2 +- sound/pci/ctxfi/cthw20k1.c | 2 +- sound/pci/emu10k1/memory.c | 2 +- sound/pci/emu10k1/p16v.c | 2 +- sound/pci/emu10k1/p16v.h | 4 +- sound/pci/hda/hda_codec.c | 4 +- sound/pci/hda/patch_realtek.c | 4 +- sound/pci/hda/patch_sigmatel.c | 2 +- sound/pci/ice1712/aureon.c | 4 +- sound/pci/ice1712/ice1712.c | 4 +- sound/pci/ice1712/pontis.c | 2 +- sound/pci/ice1712/prodigy_hifi.c | 4 +- sound/pci/intel8x0.c | 2 +- sound/pci/intel8x0m.c | 2 +- sound/pci/mixart/mixart_core.c | 4 +- sound/pci/pcxhr/pcxhr_core.c | 12 ++--- sound/pci/rme96.c | 2 +- sound/pci/rme9652/hdspm.c | 4 +- sound/pci/sis7019.c | 6 +-- sound/ppc/snd_ps3.c | 2 +- sound/ppc/snd_ps3_reg.h | 14 +++--- sound/soc/atmel/atmel_ssc_dai.c | 2 +- sound/soc/codecs/alc5623.c | 2 +- sound/soc/codecs/lm4857.c | 2 +- sound/soc/codecs/tlv320aic26.h | 4 +- sound/soc/codecs/tlv320aic3x.c | 2 +- sound/soc/codecs/tlv320dac33.c | 2 +- sound/soc/codecs/twl4030.c | 6 +-- sound/soc/codecs/wm8580.c | 2 +- sound/soc/codecs/wm8753.c | 2 +- sound/soc/codecs/wm8904.c | 2 +- sound/soc/codecs/wm8955.c | 2 +- sound/soc/codecs/wm8962.c | 2 +- sound/soc/codecs/wm8991.c | 2 +- sound/soc/codecs/wm8993.c | 2 +- sound/soc/codecs/wm8994.c | 6 +-- sound/soc/codecs/wm9081.c | 4 +- sound/soc/imx/imx-ssi.c | 2 +- sound/soc/kirkwood/kirkwood-dma.c | 4 +- sound/soc/mid-x86/sst_platform.c | 4 +- sound/soc/omap/ams-delta.c | 6 +-- sound/soc/samsung/neo1973_wm8753.c | 4 +- sound/usb/6fire/firmware.c | 4 +- sound/usb/mixer.c | 2 +- sound/usb/quirks.c | 2 +- sound/usb/usx2y/usx2yhwdeppcm.c | 4 +- tools/perf/util/string.c | 2 +- .../x86_energy_perf_policy.c | 2 +- virt/kvm/eventfd.c | 2 +- 2463 files changed, 4252 insertions(+), 4252 deletions(-) (limited to 'drivers/char') diff --git a/CREDITS b/CREDITS index 1d39a6d0a510..dca6abcead6b 100644 --- a/CREDITS +++ b/CREDITS @@ -1677,7 +1677,7 @@ W: http://www.codemonkey.org.uk D: Assorted VIA x86 support. D: 2.5 AGPGART overhaul. D: CPUFREQ maintenance. -D: Fedora kernel maintainence. +D: Fedora kernel maintenance. D: Misc/Other. S: 314 Littleton Rd, Westford, MA 01886, USA @@ -3211,7 +3211,7 @@ N: James Simmons E: jsimmons@infradead.org E: jsimmons@users.sf.net D: Frame buffer device maintainer -D: input layer developement +D: input layer development D: tty/console layer D: various mipsel devices S: 115 Carmel Avenue @@ -3290,7 +3290,7 @@ S: USA N: Manfred Spraul E: manfred@colorfullife.com W: http://www.colorfullife.com/~manfred -D: Lots of tiny hacks. Larger improvments to SysV IPC msg, +D: Lots of tiny hacks. Larger improvements to SysV IPC msg, D: slab, pipe, select. S: 71701 Schwieberdingen S: Germany diff --git a/Documentation/ABI/testing/sysfs-bus-css b/Documentation/ABI/testing/sysfs-bus-css index b585ec258a08..2979c40c10e9 100644 --- a/Documentation/ABI/testing/sysfs-bus-css +++ b/Documentation/ABI/testing/sysfs-bus-css @@ -29,7 +29,7 @@ Contact: Cornelia Huck linux-s390@vger.kernel.org Description: Contains the PIM/PAM/POM values, as reported by the channel subsystem when last queried by the common I/O - layer (this implies that this attribute is not neccessarily + layer (this implies that this attribute is not necessarily in sync with the values current in the channel subsystem). Note: This is an I/O-subchannel specific attribute. Users: s390-tools, HAL diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led index edff6630c805..3646ec85d513 100644 --- a/Documentation/ABI/testing/sysfs-class-led +++ b/Documentation/ABI/testing/sysfs-class-led @@ -33,5 +33,5 @@ Contact: Richard Purdie Description: Invert the LED on/off state. This parameter is specific to gpio and backlight triggers. In case of the backlight trigger, - it is usefull when driving a LED which is intended to indicate + it is useful when driving a LED which is intended to indicate a device in a standby like state. diff --git a/Documentation/DocBook/dvb/dvbproperty.xml b/Documentation/DocBook/dvb/dvbproperty.xml index 5f57c7ccd4ba..97f397e2fb3a 100644 --- a/Documentation/DocBook/dvb/dvbproperty.xml +++ b/Documentation/DocBook/dvb/dvbproperty.xml @@ -40,7 +40,7 @@ Central frequency of the channel. - For ISDB-T the channels are usally transmitted with an offset of 143kHz. E.g. a + For ISDB-T the channels are usually transmitted with an offset of 143kHz. E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of the channel which is 6MHz. diff --git a/Documentation/DocBook/dvb/frontend.xml b/Documentation/DocBook/dvb/frontend.xml index 78d756de5906..60c6976fb311 100644 --- a/Documentation/DocBook/dvb/frontend.xml +++ b/Documentation/DocBook/dvb/frontend.xml @@ -139,7 +139,7 @@ consistently to the DiSEqC commands as described in the DiSEqC spec.
SEC continuous tone -The continous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the +The continuous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the high/low band of a dual-band LNB. When using DiSEqC epuipment this voltage has to be switched consistently to the DiSEqC commands as described in the DiSEqC spec. diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index f66f4df18690..67e7ab41c0a6 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -1763,7 +1763,7 @@ as it would be on UP. There is a furthur optimization possible here: remember our original cache code, where there were no reference counts and the caller simply held the lock whenever using the object? This is still possible: if -you hold the lock, noone can delete the object, so you don't need to +you hold the lock, no one can delete the object, so you don't need to get and put the reference count. diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index 8c5411cfeaf0..cdd1bb9aac0d 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -1032,7 +1032,7 @@ and other resources, etc. This is indicated by ICRC bit in the ERROR register and - means that corruption occurred during data transfer. Upto + means that corruption occurred during data transfer. Up to ATA/ATAPI-7, the standard specifies that this bit is only applicable to UDMA transfers but ATA/ATAPI-8 draft revision 1f says that the bit may be applicable to multiword DMA and @@ -1045,10 +1045,10 @@ and other resources, etc. ABRT error during data transfer or on completion - Upto ATA/ATAPI-7, the standard specifies that ABRT could be + Up to ATA/ATAPI-7, the standard specifies that ABRT could be set on ICRC errors and on cases where a device is not able to complete a command. Combined with the fact that MWDMA - and PIO transfer errors aren't allowed to use ICRC bit upto + and PIO transfer errors aren't allowed to use ICRC bit up to ATA/ATAPI-7, it seems to imply that ABRT bit alone could indicate tranfer errors. @@ -1122,7 +1122,7 @@ and other resources, etc. Depending on commands, not all STATUS/ERROR bits are applicable. These non-applicable bits are marked with - "na" in the output descriptions but upto ATA/ATAPI-7 + "na" in the output descriptions but up to ATA/ATAPI-7 no definition of "na" can be found. However, ATA/ATAPI-8 draft revision 1f describes "N/A" as follows. @@ -1507,7 +1507,7 @@ and other resources, etc. - CHS set up with INITIALIZE DEVICE PARAMETERS (seldomly used) + CHS set up with INITIALIZE DEVICE PARAMETERS (seldom used) diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl index 620eb3f6a90a..6f242d5dee9a 100644 --- a/Documentation/DocBook/mtdnand.tmpl +++ b/Documentation/DocBook/mtdnand.tmpl @@ -485,7 +485,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip) Reed-Solomon library. - The ECC bytes must be placed immidiately after the data + The ECC bytes must be placed immediately after the data bytes in order to make the syndrome generator work. This is contrary to the usual layout used by software ECC. The separation of data and out of band area is not longer @@ -629,7 +629,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip) holds the bad block table. Store a pointer to the pattern in the pattern field. Further the length of the pattern has to be stored in len and the offset in the spare area must be given - in the offs member of the nand_bbt_descr stucture. For mirrored + in the offs member of the nand_bbt_descr structure. For mirrored bad block tables different patterns are mandatory. Table creation Set the option NAND_BBT_CREATE to enable the table creation @@ -648,7 +648,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip) Table version control Set the option NAND_BBT_VERSION to enable the table version control. It's highly recommended to enable this for mirrored tables with write - support. It makes sure that the risk of loosing the bad block + support. It makes sure that the risk of losing the bad block table information is reduced to the loss of the information about the one worn out block which should be marked bad. The version is stored in 4 consecutive bytes in the spare area of the device. The position of @@ -1060,19 +1060,19 @@ data in this page 0x3D ECC byte 21 -Error correction code byte 0 of the eigth 256 Bytes of data +Error correction code byte 0 of the eighth 256 Bytes of data in this page 0x3E ECC byte 22 -Error correction code byte 1 of the eigth 256 Bytes of data +Error correction code byte 1 of the eighth 256 Bytes of data in this page 0x3F ECC byte 23 -Error correction code byte 2 of the eigth 256 Bytes of data +Error correction code byte 2 of the eighth 256 Bytes of data in this page diff --git a/Documentation/DocBook/regulator.tmpl b/Documentation/DocBook/regulator.tmpl index 53f4f8d3b810..346e552fa2cc 100644 --- a/Documentation/DocBook/regulator.tmpl +++ b/Documentation/DocBook/regulator.tmpl @@ -267,8 +267,8 @@ Constraints - As well as definining the connections the machine interface - also provides constraints definining the operations that + As well as defining the connections the machine interface + also provides constraints defining the operations that clients are allowed to perform and the parameters that may be set. This is required since generally regulator devices will offer more flexibility than it is safe to use on a given diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index b4665b9c40b0..7c4b514d62b1 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -797,7 +797,7 @@ framework to set up sysfs files for this region. Simply leave it alone. perform some initialization. After that, your hardware starts working and will generate an interrupt as soon as it's finished, has some data available, or needs your - attention because an error occured. + attention because an error occurred. /dev/uioX is a read-only file. A diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl index af293606fbe3..8d57c1888dca 100644 --- a/Documentation/DocBook/usb.tmpl +++ b/Documentation/DocBook/usb.tmpl @@ -690,7 +690,7 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param) This request lets kernel drivers talk to user mode code through filesystem operations even when they don't create - a charactor or block special device. + a character or block special device. It's also been used to do things like ask devices what device special file should be used. Two pre-defined ioctls are used diff --git a/Documentation/DocBook/v4l/common.xml b/Documentation/DocBook/v4l/common.xml index dbab79c215c1..9028721438dc 100644 --- a/Documentation/DocBook/v4l/common.xml +++ b/Documentation/DocBook/v4l/common.xml @@ -100,7 +100,7 @@ linux-kernel@vger.kernel.org, 2002-11-20. --> By convention system administrators create various character device special files with these major and minor numbers in -the /dev directory. The names recomended for the +the /dev directory. The names recommended for the different V4L2 device types are listed in . diff --git a/Documentation/DocBook/v4l/controls.xml b/Documentation/DocBook/v4l/controls.xml index 2fae3e87ce73..a920ee80f640 100644 --- a/Documentation/DocBook/v4l/controls.xml +++ b/Documentation/DocBook/v4l/controls.xml @@ -1243,7 +1243,7 @@ values are: Mutes the audio when capturing. This is not done by muting audio hardware, which can still produce a slight hiss, but in the encoder itself, guaranteeing a fixed -and reproducable audio bitstream. 0 = unmuted, 1 = muted. +and reproducible audio bitstream. 0 = unmuted, 1 = muted. diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml index 21caff6d159b..05c8fefcbcbe 100644 --- a/Documentation/DocBook/v4l/dev-subdev.xml +++ b/Documentation/DocBook/v4l/dev-subdev.xml @@ -90,7 +90,7 @@ processing hardware.
- Image Format Negotation on Pipelines + Image Format Negotiation on Pipelines diff --git a/Documentation/DocBook/v4l/libv4l.xml b/Documentation/DocBook/v4l/libv4l.xml index c14fc3db2a81..3cb10ec51929 100644 --- a/Documentation/DocBook/v4l/libv4l.xml +++ b/Documentation/DocBook/v4l/libv4l.xml @@ -140,7 +140,7 @@ and is not locked sets the cid to the scaled value. int v4l2_get_control(int fd, int cid) - This function returns a value of 0 - 65535, scaled to from the actual range of the given v4l control id. when the cid does not exist, could not be -accessed for some reason, or some error occured 0 is returned. +accessed for some reason, or some error occurred 0 is returned.
diff --git a/Documentation/DocBook/v4l/remote_controllers.xml b/Documentation/DocBook/v4l/remote_controllers.xml index 3c3b667b28e7..160e464d44b7 100644 --- a/Documentation/DocBook/v4l/remote_controllers.xml +++ b/Documentation/DocBook/v4l/remote_controllers.xml @@ -133,7 +133,7 @@ different IR's. Due to that, V4L2 API now specifies a standard for mapping Media KEY_LEFTLeft keyLEFT KEY_RIGHTRight keyRIGHT -Miscelaneous keys +Miscellaneous keys KEY_DOTReturn a dot. KEY_FNSelect a functionFUNCTION diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl index 0ba149de2608..58ced2346e67 100644 --- a/Documentation/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl @@ -4784,7 +4784,7 @@ struct _snd_pcm_runtime { FM registers can be directly accessed through the direct-FM API, defined in <sound/asound_fm.h>. In ALSA native mode, FM registers are accessed through - the Hardware-Dependant Device direct-FM extension API, whereas in + the Hardware-Dependent Device direct-FM extension API, whereas in OSS compatible mode, FM registers can be accessed with the OSS direct-FM compatible API in /dev/dmfmX device. diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index dcf7acc720e1..3f5e0b09bed5 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -253,8 +253,8 @@ In constrast, MSI is restricted to a maximum of 32 interrupts (and must be a power of two). In addition, the MSI interrupt vectors must be allocated consecutively, so the system may not be able to allocate as many vectors for MSI as it could for MSI-X. On some platforms, MSI -interrupts must all be targetted at the same set of CPUs whereas MSI-X -interrupts can all be targetted at different CPUs. +interrupts must all be targeted at the same set of CPUs whereas MSI-X +interrupts can all be targeted at different CPUs. 4.5.2 Spinlocks diff --git a/Documentation/SecurityBugs b/Documentation/SecurityBugs index 26c3b3635d9f..a660d494c8ed 100644 --- a/Documentation/SecurityBugs +++ b/Documentation/SecurityBugs @@ -28,7 +28,7 @@ expect these delays to be short, measurable in days, not weeks or months. A disclosure date is negotiated by the security team working with the bug submitter as well as vendors. However, the kernel security team holds the final say when setting a disclosure date. The timeframe for -disclosure is from immediate (esp. if it's already publically known) +disclosure is from immediate (esp. if it's already publicly known) to a few weeks. As a basic default policy, we expect report date to disclosure date to be on the order of 7 days. diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers index 38d2aab59cac..319baa8b60dd 100644 --- a/Documentation/SubmittingDrivers +++ b/Documentation/SubmittingDrivers @@ -101,7 +101,7 @@ PM support: Since Linux is used on many portable and desktop systems, your complete overview of the power management issues related to drivers see Documentation/power/devices.txt . -Control: In general if there is active maintainance of a driver by +Control: In general if there is active maintenance of a driver by the author then patches will be redirected to them unless they are totally obvious and without need of checking. If you want to be the contact and update point for the diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 689e2371095c..e439cd0d3375 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -729,7 +729,7 @@ Linus Torvalds's mail on the canonical patch format: Andi Kleen, "On submitting kernel patches" - Some strategies to get difficult or controversal changes in. + Some strategies to get difficult or controversial changes in. http://halobates.de/on-submitting-patches.pdf -- diff --git a/Documentation/arm/IXP4xx b/Documentation/arm/IXP4xx index 133c5fa6c7a1..7b9351f2f555 100644 --- a/Documentation/arm/IXP4xx +++ b/Documentation/arm/IXP4xx @@ -36,7 +36,7 @@ Linux currently supports the following features on the IXP4xx chips: - Timers (watchdog, OS) The following components of the chips are not supported by Linux and -require the use of Intel's propietary CSR softare: +require the use of Intel's proprietary CSR softare: - USB device interface - Network interfaces (HSS, Utopia, NPEs, etc) @@ -47,7 +47,7 @@ software from: http://developer.intel.com/design/network/products/npfamily/ixp425.htm -DO NOT POST QUESTIONS TO THE LINUX MAILING LISTS REGARDING THE PROPIETARY +DO NOT POST QUESTIONS TO THE LINUX MAILING LISTS REGARDING THE PROPRIETARY SOFTWARE. There are several websites that provide directions/pointers on using diff --git a/Documentation/arm/Samsung-S3C24XX/Suspend.txt b/Documentation/arm/Samsung-S3C24XX/Suspend.txt index 7edd0e2e6c5b..1ca63b3e5635 100644 --- a/Documentation/arm/Samsung-S3C24XX/Suspend.txt +++ b/Documentation/arm/Samsung-S3C24XX/Suspend.txt @@ -116,7 +116,7 @@ Configuration Allows the entire memory to be checksummed before and after the suspend to see if there has been any corruption of the contents. - Note, the time to calculate the CRC is dependant on the CPU speed + Note, the time to calculate the CRC is dependent on the CPU speed and the size of memory. For an 64Mbyte RAM area on an 200MHz S3C2410, this can take approximately 4 seconds to complete. diff --git a/Documentation/arm/Samsung/GPIO.txt b/Documentation/arm/Samsung/GPIO.txt index 05850c62abeb..513f2562c1a3 100644 --- a/Documentation/arm/Samsung/GPIO.txt +++ b/Documentation/arm/Samsung/GPIO.txt @@ -5,7 +5,7 @@ Introduction ------------ This outlines the Samsung GPIO implementation and the architecture -specfic calls provided alongisde the drivers/gpio core. +specific calls provided alongisde the drivers/gpio core. S3C24XX (Legacy) diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 2a7b38c832c7..c6d84cfd2f56 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -497,7 +497,7 @@ The scatter gather list is in the form of an array of entries with their corresponding dma address mappings filled in at the appropriate time. As an optimization, contiguous physical pages can be covered by a single entry where refers to the first page and -covers the range of pages (upto 16 contiguous pages could be covered this +covers the range of pages (up to 16 contiguous pages could be covered this way). There is a helper routine (blk_rq_map_sg) which drivers can use to build the sg list. @@ -565,7 +565,7 @@ struct request { . int tag; /* command tag associated with request */ void *special; /* same as before */ - char *buffer; /* valid only for low memory buffers upto + char *buffer; /* valid only for low memory buffers up to current_nr_sectors */ . . diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index 45d5a217484f..a20bfd415e41 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt @@ -196,7 +196,7 @@ the state as 0 when a cpu if offline and 1 when its online. #To display the current cpu state. #cat /sys/devices/system/cpu/cpuX/online -Q: Why cant i remove CPU0 on some systems? +Q: Why can't i remove CPU0 on some systems? A: Some architectures may have some special dependency on a certain CPU. For e.g in IA64 platforms we have ability to sent platform interrupts to the diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt index 15174985ad08..d262e22bddec 100644 --- a/Documentation/dell_rbu.txt +++ b/Documentation/dell_rbu.txt @@ -62,7 +62,7 @@ image file and then arrange all these packets back to back in to one single file. This file is then copied to /sys/class/firmware/dell_rbu/data. Once this file gets to the driver, the driver extracts packet_size data from -the file and spreads it accross the physical memory in contiguous packet_sized +the file and spreads it across the physical memory in contiguous packet_sized space. This method makes sure that all the packets get to the driver in a single operation. diff --git a/Documentation/device-mapper/dm-service-time.txt b/Documentation/device-mapper/dm-service-time.txt index 7d00668e97bb..fb1d4a0cf122 100644 --- a/Documentation/device-mapper/dm-service-time.txt +++ b/Documentation/device-mapper/dm-service-time.txt @@ -37,7 +37,7 @@ Algorithm ========= dm-service-time adds the I/O size to 'in-flight-size' when the I/O is -dispatched and substracts when completed. +dispatched and subtracts when completed. Basically, dm-service-time selects a path having minimum service time which is calculated by: diff --git a/Documentation/devicetree/bindings/fb/sm501fb.txt b/Documentation/devicetree/bindings/fb/sm501fb.txt index 7d319fba9b5b..9d9f0098092b 100644 --- a/Documentation/devicetree/bindings/fb/sm501fb.txt +++ b/Documentation/devicetree/bindings/fb/sm501fb.txt @@ -18,9 +18,9 @@ Optional properties: - edid : verbatim EDID data block describing attached display. Data from the detailed timing descriptor will be used to program the display controller. -- little-endian: availiable on big endian systems, to +- little-endian: available on big endian systems, to set different foreign endian. -- big-endian: availiable on little endian systems, to +- big-endian: available on little endian systems, to set different foreign endian. Example for MPC5200: diff --git a/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt b/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt index a48b2cadc7f0..00f1f546b32e 100644 --- a/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt +++ b/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt @@ -15,7 +15,7 @@ Optional properties: - gpios : may specify optional GPIOs connected to the Ready-Not-Busy pins (R/B#). For multi-chip devices, "n" GPIO definitions are required according to the number of chips. -- chip-delay : chip dependent delay for transfering data from array to +- chip-delay : chip dependent delay for transferring data from array to read registers (tR). Required if property "gpios" is not used (R/B# pins not connected). diff --git a/Documentation/devicetree/bindings/net/can/sja1000.txt b/Documentation/devicetree/bindings/net/can/sja1000.txt index d6d209ded937..c2dbcec0ee31 100644 --- a/Documentation/devicetree/bindings/net/can/sja1000.txt +++ b/Documentation/devicetree/bindings/net/can/sja1000.txt @@ -39,7 +39,7 @@ Optional properties: - nxp,no-comparator-bypass : Allows to disable the CAN input comperator. -For futher information, please have a look to the SJA1000 data sheet. +For further information, please have a look to the SJA1000 data sheet. Examples: diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt index 8aa10f45ebe6..4f6145859aab 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt +++ b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt @@ -199,7 +199,7 @@ EXAMPLE 4 EXAMPLE 5 /* - * Definition of an error interrupt (interupt type 1). + * Definition of an error interrupt (interrupt type 1). * SoC interrupt number is 16 and the specific error * interrupt bit in the error interrupt summary register * is 23. diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb index c8238e44ed6b..c4d963a67d6f 100644 --- a/Documentation/dvb/README.dvb-usb +++ b/Documentation/dvb/README.dvb-usb @@ -138,7 +138,7 @@ Hotplug is able to load the driver, when it is needed (because you plugged in the device). If you want to enable debug output, you have to load the driver manually and -from withing the dvb-kernel cvs repository. +from within the dvb-kernel cvs repository. first have a look, which debug level are available: diff --git a/Documentation/dvb/ci.txt b/Documentation/dvb/ci.txt index 4a0c2b56e690..6c3bda50f7dc 100644 --- a/Documentation/dvb/ci.txt +++ b/Documentation/dvb/ci.txt @@ -47,7 +47,7 @@ so on. * CI modules that are supported ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The CI module support is largely dependant upon the firmware on the cards +The CI module support is largely dependent upon the firmware on the cards Some cards do support almost all of the available CI modules. There is nothing much that can be done in order to make additional CI modules working with these cards. diff --git a/Documentation/dvb/faq.txt b/Documentation/dvb/faq.txt index 121832e5d899..97b1373f2428 100644 --- a/Documentation/dvb/faq.txt +++ b/Documentation/dvb/faq.txt @@ -106,7 +106,7 @@ Some very frequently asked questions about linuxtv-dvb 5. The dvb_net device doesn't give me any packets at all Run tcpdump on the dvb0_0 interface. This sets the interface - into promiscous mode so it accepts any packets from the PID + into promiscuous mode so it accepts any packets from the PID you have configured with the dvbnet utility. Check if there are any packets with the IP addr and MAC addr you have configured with ifconfig. diff --git a/Documentation/edac.txt b/Documentation/edac.txt index 9ee774de57cd..44364fa3598d 100644 --- a/Documentation/edac.txt +++ b/Documentation/edac.txt @@ -741,7 +741,7 @@ were done at i7core_edac driver. This chapter will cover those differences As EDAC API maps the minimum unity is csrows, the driver sequencially maps channel/dimm into different csrows. - For example, suposing the following layout: + For example, supposing the following layout: Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400 dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400 diff --git a/Documentation/eisa.txt b/Documentation/eisa.txt index f297fc1202ae..38cf0c7b559f 100644 --- a/Documentation/eisa.txt +++ b/Documentation/eisa.txt @@ -84,7 +84,7 @@ struct eisa_driver { id_table : an array of NULL terminated EISA id strings, followed by an empty string. Each string can - optionally be paired with a driver-dependant value + optionally be paired with a driver-dependent value (driver_data). driver : a generic driver, such as described in diff --git a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt index 1a2e8aa3fbb1..444e34b52ae1 100644 --- a/Documentation/fb/viafb.txt +++ b/Documentation/fb/viafb.txt @@ -204,7 +204,7 @@ Notes: supported_output_devices - This read-only file contains a full ',' seperated list containing all + This read-only file contains a full ',' separated list containing all output devices that could be available on your platform. It is likely that not all of those have a connector on your hardware but it should provide a good starting point to figure out which of those names match @@ -225,7 +225,7 @@ Notes: This can happen for example if only one (the other) iga is used. Writing to these files allows adjusting the output devices during runtime. One can add new devices, remove existing ones or switch - between igas. Essentially you can write a ',' seperated list of device + between igas. Essentially you can write a ',' separated list of device names (or a single one) in the same format as the output to those files. You can add a '+' or '-' as a prefix allowing simple addition and removal of devices. So a prefix '+' adds the devices from your list diff --git a/Documentation/filesystems/autofs4-mount-control.txt b/Documentation/filesystems/autofs4-mount-control.txt index 51986bf08a4d..4c95935cbcf4 100644 --- a/Documentation/filesystems/autofs4-mount-control.txt +++ b/Documentation/filesystems/autofs4-mount-control.txt @@ -309,7 +309,7 @@ ioctlfd field set to the descriptor obtained from the open call. AUTOFS_DEV_IOCTL_TIMEOUT_CMD ---------------------------- -Set the expire timeout for mounts withing an autofs mount point. +Set the expire timeout for mounts within an autofs mount point. The call requires an initialized struct autofs_dev_ioctl with the ioctlfd field set to the descriptor obtained from the open call. diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt index 1902c57b72ef..a167ab876c35 100644 --- a/Documentation/filesystems/caching/netfs-api.txt +++ b/Documentation/filesystems/caching/netfs-api.txt @@ -95,7 +95,7 @@ restraints as possible on how an index is structured and where it is placed in the tree. The netfs can even mix indices and data files at the same level, but it's not recommended. -Each index entry consists of a key of indeterminate length plus some auxilliary +Each index entry consists of a key of indeterminate length plus some auxiliary data, also of indeterminate length. There are some limits on indices: @@ -203,23 +203,23 @@ This has the following fields: If the function is absent, a file size of 0 is assumed. - (6) A function to retrieve auxilliary data from the netfs [optional]. + (6) A function to retrieve auxiliary data from the netfs [optional]. This function will be called with the netfs data that was passed to the - cookie acquisition function and the maximum length of auxilliary data that - it may provide. It should write the auxilliary data into the given buffer + cookie acquisition function and the maximum length of auxiliary data that + it may provide. It should write the auxiliary data into the given buffer and return the quantity it wrote. - If this function is absent, the auxilliary data length will be set to 0. + If this function is absent, the auxiliary data length will be set to 0. - The length of the auxilliary data buffer may be dependent on the key + The length of the auxiliary data buffer may be dependent on the key length. A netfs mustn't rely on being able to provide more than 400 bytes for both. - (7) A function to check the auxilliary data [optional]. + (7) A function to check the auxiliary data [optional]. This function will be called to check that a match found in the cache for - this object is valid. For instance with AFS it could check the auxilliary + this object is valid. For instance with AFS it could check the auxiliary data against the data version number returned by the server to determine whether the index entry in a cache is still valid. @@ -232,7 +232,7 @@ This has the following fields: (*) FSCACHE_CHECKAUX_NEEDS_UPDATE - the entry requires update (*) FSCACHE_CHECKAUX_OBSOLETE - the entry should be deleted - This function can also be used to extract data from the auxilliary data in + This function can also be used to extract data from the auxiliary data in the cache and copy it into the netfs's structures. (8) A pair of functions to manage contexts for the completion callback diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt index fabcb0e00f25..dd57bb6bb390 100644 --- a/Documentation/filesystems/configfs/configfs.txt +++ b/Documentation/filesystems/configfs/configfs.txt @@ -409,7 +409,7 @@ As a consequence of this, default_groups cannot be removed directly via rmdir(2). They also are not considered when rmdir(2) on the parent group is checking for children. -[Dependant Subsystems] +[Dependent Subsystems] Sometimes other drivers depend on particular configfs items. For example, ocfs2 mounts depend on a heartbeat region item. If that diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 6b050464a90d..c79ec58fd7f6 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -97,7 +97,7 @@ Note: More extensive information for getting started with ext4 can be * Inode allocation using large virtual block groups via flex_bg * delayed allocation * large block (up to pagesize) support -* efficent new ordered mode in JBD2 and ext4(avoid using buffer head to force +* efficient new ordered mode in JBD2 and ext4(avoid using buffer head to force the ordering) [1] Filesystems with a block size of 1k may see a limit imposed by the @@ -106,7 +106,7 @@ directory hash tree having a maximum depth of two. 2.2 Candidate features for future inclusion * Online defrag (patches available but not well tested) -* reduced mke2fs time via lazy itable initialization in conjuction with +* reduced mke2fs time via lazy itable initialization in conjunction with the uninit_bg feature (capability to do this is available in e2fsprogs but a kernel thread to do lazy zeroing of unused inode table blocks after filesystem is first mounted is required for safety) diff --git a/Documentation/filesystems/gfs2-uevents.txt b/Documentation/filesystems/gfs2-uevents.txt index fd966dc9979a..d81889669293 100644 --- a/Documentation/filesystems/gfs2-uevents.txt +++ b/Documentation/filesystems/gfs2-uevents.txt @@ -62,7 +62,7 @@ be fixed. The REMOVE uevent is generated at the end of an unsuccessful mount or at the end of a umount of the filesystem. All REMOVE uevents will -have been preceeded by at least an ADD uevent for the same fileystem, +have been preceded by at least an ADD uevent for the same fileystem, and unlike the other uevents is generated automatically by the kernel's kobject subsystem. diff --git a/Documentation/filesystems/gfs2.txt b/Documentation/filesystems/gfs2.txt index 0b59c0200912..4cda926628aa 100644 --- a/Documentation/filesystems/gfs2.txt +++ b/Documentation/filesystems/gfs2.txt @@ -11,7 +11,7 @@ their I/O so file system consistency is maintained. One of the nifty features of GFS is perfect consistency -- changes made to the file system on one machine show up immediately on all other machines in the cluster. -GFS uses interchangable inter-node locking mechanisms, the currently +GFS uses interchangeable inter-node locking mechanisms, the currently supported mechanisms are: lock_nolock -- allows gfs to be used as a local file system diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 933bc66ccff1..791af8dac065 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -350,7 +350,7 @@ Note the "Should sync?" parameter "nosync" means that the two mirrors are already in sync which will be the case on a clean shutdown of Windows. If the mirrors are not clean, you can specify the "sync" option instead of "nosync" and the Device-Mapper driver will then copy the entirety of the "Source Device" -to the "Target Device" or if you specified multipled target devices to all of +to the "Target Device" or if you specified multiple target devices to all of them. Once you have your table, save it in a file somewhere (e.g. /etc/ntfsvolume1), diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt index 5393e6611691..9ed920a8cd79 100644 --- a/Documentation/filesystems/ocfs2.txt +++ b/Documentation/filesystems/ocfs2.txt @@ -80,7 +80,7 @@ user_xattr (*) Enables Extended User Attributes. nouser_xattr Disables Extended User Attributes. acl Enables POSIX Access Control Lists support. noacl (*) Disables POSIX Access Control Lists support. -resv_level=2 (*) Set how agressive allocation reservations will be. +resv_level=2 (*) Set how aggressive allocation reservations will be. Valid values are between 0 (reservations off) to 8 (maximum space for reservations). dir_resv_level= (*) By default, directory reservations will scale with file diff --git a/Documentation/filesystems/path-lookup.txt b/Documentation/filesystems/path-lookup.txt index eb59c8b44be9..3571667c7105 100644 --- a/Documentation/filesystems/path-lookup.txt +++ b/Documentation/filesystems/path-lookup.txt @@ -42,7 +42,7 @@ Path walking overview A name string specifies a start (root directory, cwd, fd-relative) and a sequence of elements (directory entry names), which together refer to a path in the namespace. A path is represented as a (dentry, vfsmount) tuple. The name -elements are sub-strings, seperated by '/'. +elements are sub-strings, separated by '/'. Name lookups will want to find a particular path that a name string refers to (usually the final element, or parent of final element). This is done by taking @@ -354,7 +354,7 @@ vfstest 24185492 4945 708725(2.9%) 1076136(4.4%) 0 2651 What this shows is that failed rcu-walk lookups, ie. ones that are restarted entirely with ref-walk, are quite rare. Even the "vfstest" case which -specifically has concurrent renames/mkdir/rmdir/ creat/unlink/etc to excercise +specifically has concurrent renames/mkdir/rmdir/ creat/unlink/etc to exercise such races is not showing a huge amount of restarts. Dropping from rcu-walk to ref-walk mean that we have encountered a dentry where diff --git a/Documentation/filesystems/pohmelfs/network_protocol.txt b/Documentation/filesystems/pohmelfs/network_protocol.txt index 40ea6c295afb..65e03dd44823 100644 --- a/Documentation/filesystems/pohmelfs/network_protocol.txt +++ b/Documentation/filesystems/pohmelfs/network_protocol.txt @@ -20,7 +20,7 @@ Commands can be embedded into transaction command (which in turn has own command so one can extend protocol as needed without breaking backward compatibility as long as old commands are supported. All string lengths include tail 0 byte. -All commans are transfered over the network in big-endian. CPU endianess is used at the end peers. +All commands are transferred over the network in big-endian. CPU endianess is used at the end peers. @cmd - command number, which specifies command to be processed. Following commands are used currently: diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 23cae6548d3a..b0b814d75ca1 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -543,7 +543,7 @@ just those considered 'most important'. The new vectors are: their statistics are used by kernel developers and interested users to determine the occurrence of interrupts of the given type. -The above IRQ vectors are displayed only when relevent. For example, +The above IRQ vectors are displayed only when relevant. For example, the threshold vector does not exist on x86_64 platforms. Others are suppressed when the system is a uniprocessor. As of this writing, only i386 and x86_64 platforms support the new IRQ vector displays. @@ -1202,7 +1202,7 @@ The columns are: W = can do write operations U = can do unblank flags E = it is enabled - C = it is prefered console + C = it is preferred console B = it is primary boot console p = it is used for printk buffer b = it is not a TTY but a Braille device @@ -1331,7 +1331,7 @@ NOTICE: /proc//oom_adj is deprecated and will be removed, please see Documentation/feature-removal-schedule.txt. Caveat: when a parent task is selected, the oom killer will sacrifice any first -generation children with seperate address spaces instead, if possible. This +generation children with separate address spaces instead, if possible. This avoids servers and important system daemons from being killed and loses the minimal amount of work. diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt index 2d78f1911844..d4d41465a0b1 100644 --- a/Documentation/filesystems/squashfs.txt +++ b/Documentation/filesystems/squashfs.txt @@ -219,7 +219,7 @@ or if it is stored out of line (in which case the value field stores a reference to where the actual value is stored). This allows large values to be stored out of line improving scanning and lookup performance and it also allows values to be de-duplicated, the value being stored once, and -all other occurences holding an out of line reference to that value. +all other occurrences holding an out of line reference to that value. The xattr lists are packed into compressed 8K metadata blocks. To reduce overhead in inodes, rather than storing the on-disk diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index f806e50aaa63..597f728e7b4e 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -62,7 +62,7 @@ values of the same type. Mixing types, expressing multiple lines of data, and doing fancy formatting of data is heavily frowned upon. Doing these things may get -you publically humiliated and your code rewritten without notice. +you publicly humiliated and your code rewritten without notice. An attribute definition is simply: diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 80815ed654cb..21a7dc467bba 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -97,7 +97,7 @@ functions: The passed struct file_system_type describes your filesystem. When a request is made to mount a filesystem onto a directory in your namespace, the VFS will call the appropriate mount() method for the specific -filesystem. New vfsmount refering to the tree returned by ->mount() +filesystem. New vfsmount referring to the tree returned by ->mount() will be attached to the mountpoint, so that when pathname resolution reaches the mountpoint it will jump into the root of that vfsmount. diff --git a/Documentation/filesystems/xfs-delayed-logging-design.txt b/Documentation/filesystems/xfs-delayed-logging-design.txt index 5282e3e51413..2ce36439c09f 100644 --- a/Documentation/filesystems/xfs-delayed-logging-design.txt +++ b/Documentation/filesystems/xfs-delayed-logging-design.txt @@ -42,7 +42,7 @@ the aggregation of all the previous changes currently held only in the log. This relogging technique also allows objects to be moved forward in the log so that an object being relogged does not prevent the tail of the log from ever moving forward. This can be seen in the table above by the changing -(increasing) LSN of each subsquent transaction - the LSN is effectively a +(increasing) LSN of each subsequent transaction - the LSN is effectively a direct encoding of the location in the log of the transaction. This relogging is also used to implement long-running, multiple-commit @@ -338,7 +338,7 @@ the same time another transaction modifies the item and inserts the log item into the new CIL, then checkpoint transaction commit code cannot use log items to store the list of log vectors that need to be written into the transaction. Hence log vectors need to be able to be chained together to allow them to be -detatched from the log items. That is, when the CIL is flushed the memory +detached from the log items. That is, when the CIL is flushed the memory buffer and log vector attached to each log item needs to be attached to the checkpoint context so that the log item can be released. In diagrammatic form, the CIL would look like this before the flush: @@ -577,7 +577,7 @@ only becomes unpinned when all the transactions complete and there are no pending transactions. Thus the pinning and unpinning of a log item is symmetric as there is a 1:1 relationship with transaction commit and log item completion. -For delayed logging, however, we have an assymetric transaction commit to +For delayed logging, however, we have an asymmetric transaction commit to completion relationship. Every time an object is relogged in the CIL it goes through the commit process without a corresponding completion being registered. That is, we now have a many-to-one relationship between transaction commit and @@ -780,7 +780,7 @@ With delayed logging, there are new steps inserted into the life cycle: From this, it can be seen that the only life cycle differences between the two logging methods are in the middle of the life cycle - they still have the same beginning and end and execution constraints. The only differences are in the -commiting of the log items to the log itself and the completion processing. +committing of the log items to the log itself and the completion processing. Hence delayed logging should not introduce any constraints on log item behaviour, allocation or freeing that don't already exist. diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru index 5eb3b9d5f0d5..915f32063a26 100644 --- a/Documentation/hwmon/abituguru +++ b/Documentation/hwmon/abituguru @@ -78,7 +78,7 @@ motherboards (most modern Abit motherboards). The first and second revision of the uGuru chip in reality is a Winbond W83L950D in disguise (despite Abit claiming it is "a new microprocessor -designed by the ABIT Engineers"). Unfortunatly this doesn't help since the +designed by the ABIT Engineers"). Unfortunately this doesn't help since the W83L950D is a generic microcontroller with a custom Abit application running on it. diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet index d9251efdcec7..8d2be8a0b1e3 100644 --- a/Documentation/hwmon/abituguru-datasheet +++ b/Documentation/hwmon/abituguru-datasheet @@ -5,9 +5,9 @@ First of all, what I know about uGuru is no fact based on any help, hints or datasheet from Abit. The data I have got on uGuru have I assembled through my weak knowledge in "backwards engineering". And just for the record, you may have noticed uGuru isn't a chip developed by -Abit, as they claim it to be. It's realy just an microprocessor (uC) created by +Abit, as they claim it to be. It's really just an microprocessor (uC) created by Winbond (W83L950D). And no, reading the manual for this specific uC or -mailing Windbond for help won't give any usefull data about uGuru, as it is +mailing Windbond for help won't give any useful data about uGuru, as it is the program inside the uC that is responding to calls. Olle Sandberg , 2005-05-25 @@ -41,7 +41,7 @@ later on attached again data-port will hold 0x08, more about this later. After wider testing of the Linux kernel driver some variants of the uGuru have turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also -have to test CMD for two different values. On these uGuru's DATA will initally +have to test CMD for two different values. On these uGuru's DATA will initially hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read first! @@ -308,5 +308,5 @@ the voltage / clock programming out, I tried reading and only reading banks resulted in a _permanent_ reprogramming of the voltages, luckily I had the sensors part configured so that it would shutdown my system on any out of spec voltages which proprably safed my computer (after a reboot I managed to -immediatly enter the bios and reload the defaults). This probably means that +immediately enter the bios and reload the defaults). This probably means that the read/write cycle for the non sensor part is different from the sensor part. diff --git a/Documentation/hwmon/abituguru3 b/Documentation/hwmon/abituguru3 index fa598aac22fa..a6ccfe4bb6aa 100644 --- a/Documentation/hwmon/abituguru3 +++ b/Documentation/hwmon/abituguru3 @@ -47,7 +47,7 @@ This driver supports the hardware monitoring features of the third revision of the Abit uGuru chip, found on recent Abit uGuru featuring motherboards. The 3rd revision of the uGuru chip in reality is a Winbond W83L951G. -Unfortunatly this doesn't help since the W83L951G is a generic microcontroller +Unfortunately this doesn't help since the W83L951G is a generic microcontroller with a custom Abit application running on it. Despite Abit not releasing any information regarding the uGuru revision 3, diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus index f2d42e8bdf48..dc4933e96344 100644 --- a/Documentation/hwmon/pmbus +++ b/Documentation/hwmon/pmbus @@ -150,11 +150,11 @@ The following attributes are supported. Limits are read-write; all other attributes are read-only. inX_input Measured voltage. From READ_VIN or READ_VOUT register. -inX_min Minumum Voltage. +inX_min Minimum Voltage. From VIN_UV_WARN_LIMIT or VOUT_UV_WARN_LIMIT register. inX_max Maximum voltage. From VIN_OV_WARN_LIMIT or VOUT_OV_WARN_LIMIT register. -inX_lcrit Critical minumum Voltage. +inX_lcrit Critical minimum Voltage. From VIN_UV_FAULT_LIMIT or VOUT_UV_FAULT_LIMIT register. inX_crit Critical maximum voltage. From VIN_OV_FAULT_LIMIT or VOUT_OV_FAULT_LIMIT register. @@ -169,7 +169,7 @@ inX_label "vin", "vcap", or "voutY" currX_input Measured current. From READ_IIN or READ_IOUT register. currX_max Maximum current. From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT register. -currX_lcrit Critical minumum output current. +currX_lcrit Critical minimum output current. From IOUT_UC_FAULT_LIMIT register. currX_crit Critical maximum current. From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register. diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index 83a698773ade..8f63c244f1aa 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -579,7 +579,7 @@ channel should not be trusted. fan[1-*]_fault temp[1-*]_fault Input fault condition - 0: no fault occured + 0: no fault occurred 1: fault condition RO diff --git a/Documentation/hwmon/w83781d b/Documentation/hwmon/w83781d index ecbc1e4574b4..129b0a3b555b 100644 --- a/Documentation/hwmon/w83781d +++ b/Documentation/hwmon/w83781d @@ -403,7 +403,7 @@ found out the following values do work as a form of coarse pwm: 0x80 - seems to turn fans off after some time(1-2 minutes)... might be some form of auto-fan-control based on temp? hmm (Qfan? this mobo is an -old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attemp at Qfan +old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attempt at Qfan that was dropped at the BIOS) 0x81 - off 0x82 - slightly "on-ner" than off, but my fans do not get to move. I can diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d index 5663e491655c..90387c3540f7 100644 --- a/Documentation/hwmon/w83791d +++ b/Documentation/hwmon/w83791d @@ -93,7 +93,7 @@ The sysfs interface to the beep bitmask has migrated from the original legacy method of a single sysfs beep_mask file to a newer method using multiple *_beep files as described in .../Documentation/hwmon/sysfs-interface. -A similar change has occured for the bitmap corresponding to the alarms. The +A similar change has occurred for the bitmap corresponding to the alarms. The original legacy method used a single sysfs alarms file containing a bitmap of triggered alarms. The newer method uses multiple sysfs *_alarm files (again following the pattern described in sysfs-interface). diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light index bdc9cbb2e0f2..c22ee063e1e5 100644 --- a/Documentation/i2c/busses/i2c-parport-light +++ b/Documentation/i2c/busses/i2c-parport-light @@ -4,7 +4,7 @@ Author: Jean Delvare This driver is a light version of i2c-parport. It doesn't depend on the parport driver, and uses direct I/O access instead. This might be -prefered on embedded systems where wasting memory for the clean but heavy +preferred on embedded systems where wasting memory for the clean but heavy parport handling is not an option. The drawback is a reduced portability and the impossibility to daisy-chain other parallel port devices. diff --git a/Documentation/i2c/busses/i2c-sis96x b/Documentation/i2c/busses/i2c-sis96x index 70e6a0cc1e15..0b979f3252a4 100644 --- a/Documentation/i2c/busses/i2c-sis96x +++ b/Documentation/i2c/busses/i2c-sis96x @@ -35,7 +35,7 @@ or perhaps this... (kernel versions later than 2.4.18 may fill in the "Unknown"s) -If you cant see it please look on quirk_sis_96x_smbus +If you can't see it please look on quirk_sis_96x_smbus (drivers/pci/quirks.c) (also if southbridge detection fails) I suspect that this driver could be made to work for the following SiS diff --git a/Documentation/i2c/busses/i2c-taos-evm b/Documentation/i2c/busses/i2c-taos-evm index 9146e33be6dd..63f62bcbf592 100644 --- a/Documentation/i2c/busses/i2c-taos-evm +++ b/Documentation/i2c/busses/i2c-taos-evm @@ -13,7 +13,7 @@ Currently supported devices are: * TAOS TSL2550 EVM -For addtional information on TAOS products, please see +For additional information on TAOS products, please see http://www.taosinc.com/ diff --git a/Documentation/i2o/README b/Documentation/i2o/README index 0ebf58c73f54..ee91e2626ff0 100644 --- a/Documentation/i2o/README +++ b/Documentation/i2o/README @@ -53,7 +53,7 @@ Symbios Logic (Now LSI) BoxHill Corporation Loan of initial FibreChannel disk array used for development work. -European Comission +European Commission Funding the work done by the University of Helsinki SysKonnect diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c index 3dfb76ca6931..5caa2af33207 100644 --- a/Documentation/ia64/aliasing-test.c +++ b/Documentation/ia64/aliasing-test.c @@ -177,7 +177,7 @@ static int scan_rom(char *path, char *file) /* * It's OK if the ROM is unreadable. Maybe there - * is no ROM, or some other error ocurred. The + * is no ROM, or some other error occurred. The * important thing is that no MCA happened. */ if (rc > 0) diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt index 1c856f32ff2c..56870c70a796 100644 --- a/Documentation/input/joystick-parport.txt +++ b/Documentation/input/joystick-parport.txt @@ -272,7 +272,7 @@ if you want to use gamecon.c. Also, the connection is a bit more complex. You'll need a bunch of diodes, and one pullup resistor. First, you connect the Directions and the button -the same as for db9, however with the diodes inbetween. +the same as for db9, however with the diodes between. Diodes (pin 2) -----|<|----> Up diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt index 8b4129de1d2d..943e8f6f2b15 100644 --- a/Documentation/input/rotary-encoder.txt +++ b/Documentation/input/rotary-encoder.txt @@ -46,7 +46,7 @@ c) Falling edge on channel A, channel B in high state d) Falling edge on channel B, channel A in low state Parking position. If the encoder enters this state, a full transition - should have happend, unless it flipped back on half the way. The + should have happened, unless it flipped back on half the way. The 'armed' state tells us about that. 2. Platform requirements diff --git a/Documentation/input/walkera0701.txt b/Documentation/input/walkera0701.txt index 8f4289efc5c4..561385d38482 100644 --- a/Documentation/input/walkera0701.txt +++ b/Documentation/input/walkera0701.txt @@ -77,7 +77,7 @@ pulse length: 24 bin+oct values + 1 bin value = 24*4+1 bits = 97 bits -(Warning, pulses on ACK ar inverted by transistor, irq is rised up on sync +(Warning, pulses on ACK are inverted by transistor, irq is raised up on sync to bin change or octal value to bin change). Binary data representations: diff --git a/Documentation/irqflags-tracing.txt b/Documentation/irqflags-tracing.txt index 6a444877ee0b..67aa71e73035 100644 --- a/Documentation/irqflags-tracing.txt +++ b/Documentation/irqflags-tracing.txt @@ -53,5 +53,5 @@ implementation in an architecture: lockdep will detect that and will turn itself off. I.e. the lock validator will still be reliable. There should be no crashes due to irq-tracing bugs. (except if the assembly changes break other code by modifying conditions or registers that -shouldnt be) +shouldn't be) diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/INTERFACE.CAPI index 309eb5ed942b..1688b5a1fd77 100644 --- a/Documentation/isdn/INTERFACE.CAPI +++ b/Documentation/isdn/INTERFACE.CAPI @@ -240,7 +240,7 @@ Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert messages between their transport encoding described in the CAPI 2.0 standard and their _cmsg structure representation. Note that capi_cmsg2message() does not know or check the size of its destination buffer. The caller must make -sure it is big enough to accomodate the resulting CAPI message. +sure it is big enough to accommodate the resulting CAPI message. 5. Lower Layer Interface Functions diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt index f1431d099fce..7c2a89ba674c 100644 --- a/Documentation/kbuild/kbuild.txt +++ b/Documentation/kbuild/kbuild.txt @@ -26,11 +26,11 @@ Additional options to the assembler (for built-in and modules). AFLAGS_MODULE -------------------------------------------------- -Addtional module specific options to use for $(AS). +Additional module specific options to use for $(AS). AFLAGS_KERNEL -------------------------------------------------- -Addtional options for $(AS) when used for assembler +Additional options for $(AS) when used for assembler code for code that is compiled as built-in. KCFLAGS @@ -39,12 +39,12 @@ Additional options to the C compiler (for built-in and modules). CFLAGS_KERNEL -------------------------------------------------- -Addtional options for $(CC) when used to compile +Additional options for $(CC) when used to compile code that is compiled as built-in. CFLAGS_MODULE -------------------------------------------------- -Addtional module specific options to use for $(CC). +Additional module specific options to use for $(CC). LDFLAGS_MODULE -------------------------------------------------- diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c357a31411cd..49e9796a86a5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -699,7 +699,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ekgdboc= [X86,KGDB] Allow early kernel console debugging ekgdboc=kbd - This is desgined to be used in conjunction with + This is designed to be used in conjunction with the boot argument: earlyprintk=vga edd= [EDD] diff --git a/Documentation/kvm/mmu.txt b/Documentation/kvm/mmu.txt index 142cc5136650..f46aa58389ca 100644 --- a/Documentation/kvm/mmu.txt +++ b/Documentation/kvm/mmu.txt @@ -23,7 +23,7 @@ The mmu code attempts to satisfy the following requirements: and framebuffer-based displays - footprint: keep the amount of pinned kernel memory low (most memory should be shrinkable) -- reliablity: avoid multipage or GFP_ATOMIC allocations +- reliability: avoid multipage or GFP_ATOMIC allocations Acronyms ======== diff --git a/Documentation/kvm/ppc-pv.txt b/Documentation/kvm/ppc-pv.txt index a7f2244b3be9..3ab969c59046 100644 --- a/Documentation/kvm/ppc-pv.txt +++ b/Documentation/kvm/ppc-pv.txt @@ -136,7 +136,7 @@ Patched instructions ==================== The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions -respectively on 32 bit systems with an added offset of 4 to accomodate for big +respectively on 32 bit systems with an added offset of 4 to accommodate for big endianness. The following is a list of mapping the Linux kernel performs when running as diff --git a/Documentation/kvm/timekeeping.txt b/Documentation/kvm/timekeeping.txt index 0c5033a58c9e..df8946377cb6 100644 --- a/Documentation/kvm/timekeeping.txt +++ b/Documentation/kvm/timekeeping.txt @@ -81,7 +81,7 @@ Mode 0: Single Timeout. This is a one-shot software timeout that counts down when the gate is high (always true for timers 0 and 1). When the count reaches zero, the output goes high. -Mode 1: Triggered One-shot. The output is intially set high. When the gate +Mode 1: Triggered One-shot. The output is initially set high. When the gate line is set high, a countdown is initiated (which does not stop if the gate is lowered), during which the output is set low. When the count reaches zero, the output goes high. diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index fd48add02cb0..76a2087db205 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -194,7 +194,7 @@ each pad. Links are represented by a struct media_link instance, defined in include/media/media-entity.h. Each entity stores all links originating at or -targetting any of its pads in a links array. A given link is thus stored +targeting any of its pads in a links array. A given link is thus stored twice, once in the source entity and once in the target entity. The array is pre-allocated and grows dynamically as needed. @@ -348,6 +348,6 @@ a streaming entity. Links that can be modified while streaming must be marked with the MEDIA_LNK_FL_DYNAMIC flag. If other operations need to be disallowed on streaming entities (such as -changing entities configuration parameters) drivers can explictly check the +changing entities configuration parameters) drivers can explicitly check the media_entity stream_count field to find out if an entity is streaming. This operation must be done with the media_device graph_mutex held. diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/AU1xxx_IDE.README index 8ace35ebdcd5..cc887ecfd6eb 100644 --- a/Documentation/mips/AU1xxx_IDE.README +++ b/Documentation/mips/AU1xxx_IDE.README @@ -39,13 +39,13 @@ Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE Interface and Linux Device Driver" Application Note. -FILES, CONFIGS AND COMPATABILITY +FILES, CONFIGS AND COMPATIBILITY -------------------------------- Two files are introduced: a) 'arch/mips/include/asm/mach-au1x00/au1xxx_ide.h' - containes : struct _auide_hwif + contains : struct _auide_hwif timing parameters for PIO mode 0/1/2/3/4 timing parameters for MWDMA 0/1/2 diff --git a/Documentation/misc-devices/ics932s401 b/Documentation/misc-devices/ics932s401 index 07a739f406d8..bdac67ff6e3f 100644 --- a/Documentation/misc-devices/ics932s401 +++ b/Documentation/misc-devices/ics932s401 @@ -5,7 +5,7 @@ Supported chips: * IDT ICS932S401 Prefix: 'ics932s401' Addresses scanned: I2C 0x69 - Datasheet: Publically available at the IDT website + Datasheet: Publicly available at the IDT website Author: Darrick J. Wong diff --git a/Documentation/networking/3c359.txt b/Documentation/networking/3c359.txt index 4af8071a6d18..dadfe8147ab8 100644 --- a/Documentation/networking/3c359.txt +++ b/Documentation/networking/3c359.txt @@ -45,7 +45,7 @@ debugging messages on, that must be done by modified the source code. Variable MTU size: -The driver can handle a MTU size upto either 4500 or 18000 depending upon +The driver can handle a MTU size up to either 4500 or 18000 depending upon ring speed. The driver also changes the size of the receive buffers as part of the mtu re-sizing, so if you set mtu = 18000, you will need to be able to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index 616a8e540b0b..b7658bed4906 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 @@ -256,7 +256,7 @@ You can set the debug level via: Where $VALUE would be a number in the case of this sysfs entry. The input to sysfs files does not have to be a number. For example, the -firmware loader used by hotplug utilizes sysfs entries for transfering +firmware loader used by hotplug utilizes sysfs entries for transferring the firmware image from user space into the driver. The Intel(R) PRO/Wireless 2915ABG Driver for Linux exposes sysfs entries diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index b36e741e94db..e27202bb8d75 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -368,7 +368,7 @@ fail_over_mac gratuitous ARP is lost, communication may be disrupted. - When this policy is used in conjuction with the mii + When this policy is used in conjunction with the mii monitor, devices which assert link up prior to being able to actually transmit and receive are particularly susceptible to loss of the gratuitous ARP, and an diff --git a/Documentation/networking/caif/Linux-CAIF.txt b/Documentation/networking/caif/Linux-CAIF.txt index 7fe7a9a33a4f..e52fd62bef3a 100644 --- a/Documentation/networking/caif/Linux-CAIF.txt +++ b/Documentation/networking/caif/Linux-CAIF.txt @@ -136,7 +136,7 @@ The CAIF Protocol implementation contains: - CFMUX CAIF Mux layer. Handles multiplexing between multiple physical bearers and multiple channels such as VEI, Datagram, etc. The MUX keeps track of the existing CAIF Channels and - Physical Instances and selects the apropriate instance based + Physical Instances and selects the appropriate instance based on Channel-Id and Physical-ID. - CFFRML CAIF Framing layer. Handles Framing i.e. Frame length diff --git a/Documentation/networking/caif/spi_porting.txt b/Documentation/networking/caif/spi_porting.txt index 0cb8cb9098f4..9efd0687dc4c 100644 --- a/Documentation/networking/caif/spi_porting.txt +++ b/Documentation/networking/caif/spi_porting.txt @@ -150,7 +150,7 @@ static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev) void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev) { /* If xfer is true then you should assert the SPI_INT to indicate to - * the master that you are ready to recieve the data from the master + * the master that you are ready to receive the data from the master * SPI. If xfer is false then you should de-assert SPI_INT to indicate * that the transfer is done. */ diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt index 5b04b67ddca2..56ca3b75376e 100644 --- a/Documentation/networking/can.txt +++ b/Documentation/networking/can.txt @@ -240,7 +240,7 @@ solution for a couple of reasons: the user application using the common CAN filter mechanisms. Inside this filter definition the (interested) type of errors may be selected. The reception of error frames is disabled by default. - The format of the CAN error frame is briefly decribed in the Linux + The format of the CAN error frame is briefly described in the Linux header file "include/linux/can/error.h". 4. How to use Socket CAN diff --git a/Documentation/networking/ieee802154.txt b/Documentation/networking/ieee802154.txt index 23c995e64032..f41ea2405220 100644 --- a/Documentation/networking/ieee802154.txt +++ b/Documentation/networking/ieee802154.txt @@ -9,7 +9,7 @@ The Linux-ZigBee project goal is to provide complete implementation of IEEE 802.15.4 / ZigBee / 6LoWPAN protocols. IEEE 802.15.4 is a stack of protocols for organizing Low-Rate Wireless Personal Area Networks. -Currently only IEEE 802.15.4 layer is implemented. We have choosen +Currently only IEEE 802.15.4 layer is implemented. We have chosen to use plain Berkeley socket API, the generic Linux networking stack to transfer IEEE 802.15.4 messages and a special protocol over genetlink for configuration/management diff --git a/Documentation/networking/olympic.txt b/Documentation/networking/olympic.txt index c65a94010ea8..b95b5bf96751 100644 --- a/Documentation/networking/olympic.txt +++ b/Documentation/networking/olympic.txt @@ -65,7 +65,7 @@ together. Variable MTU size: -The driver can handle a MTU size upto either 4500 or 18000 depending upon +The driver can handle a MTU size up to either 4500 or 18000 depending upon ring speed. The driver also changes the size of the receive buffers as part of the mtu re-sizing, so if you set mtu = 18000, you will need to be able to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 073894d1c093..4acea6603720 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -223,7 +223,7 @@ we will get the following buffer structure: A frame can be of any size with the only condition it can fit in a block. A block can only hold an integer number of frames, or in other words, a frame cannot -be spawned accross two blocks, so there are some details you have to take into +be spawned across two blocks, so there are some details you have to take into account when choosing the frame_size. See "Mapping and use of the circular buffer (ring)". diff --git a/Documentation/networking/s2io.txt b/Documentation/networking/s2io.txt index 9d4e0f4df5a8..4be0c039edbc 100644 --- a/Documentation/networking/s2io.txt +++ b/Documentation/networking/s2io.txt @@ -37,7 +37,7 @@ To associate an interface with a physical adapter use "ethtool -p ". The corresponding adapter's LED will blink multiple times. 3. Features supported: -a. Jumbo frames. Xframe I/II supports MTU upto 9600 bytes, +a. Jumbo frames. Xframe I/II supports MTU up to 9600 bytes, modifiable using ifconfig command. b. Offloads. Supports checksum offload(TCP/UDP/IP) on transmit @@ -49,7 +49,7 @@ significant performance improvement on certain platforms(SGI Altix, IBM xSeries). d. MSI/MSI-X. Can be enabled on platforms which support this feature -(IA64, Xeon) resulting in noticeable performance improvement(upto 7% +(IA64, Xeon) resulting in noticeable performance improvement(up to 7% on certain platforms). e. Statistics. Comprehensive MAC-level and software statistics displayed diff --git a/Documentation/networking/tc-actions-env-rules.txt b/Documentation/networking/tc-actions-env-rules.txt index dcadf6f88e34..70d6cf608251 100644 --- a/Documentation/networking/tc-actions-env-rules.txt +++ b/Documentation/networking/tc-actions-env-rules.txt @@ -1,5 +1,5 @@ -The "enviromental" rules for authors of any new tc actions are: +The "environmental" rules for authors of any new tc actions are: 1) If you stealeth or borroweth any packet thou shalt be branching from the righteous path and thou shalt cloneth. @@ -20,7 +20,7 @@ this way any action downstream can stomp on the packet. 3) Dropping packets you don't own is a no-no. You simply return TC_ACT_SHOT to the caller and they will drop it. -The "enviromental" rules for callers of actions (qdiscs etc) are: +The "environmental" rules for callers of actions (qdiscs etc) are: *) Thou art responsible for freeing anything returned as being TC_ACT_SHOT/STOLEN/QUEUED. If none of TC_ACT_SHOT/STOLEN/QUEUED is diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index f023ba6bba62..1971bcf48a60 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -367,7 +367,7 @@ Drivers need to be able to handle hardware which has been reset since the suspend methods were called, for example by complete reinitialization. This may be the hardest part, and the one most protected by NDA'd documents and chip errata. It's simplest if the hardware state hasn't changed since -the suspend was carried out, but that can't be guaranteed (in fact, it ususally +the suspend was carried out, but that can't be guaranteed (in fact, it usually is not the case). Drivers must also be prepared to notice that the device has been removed diff --git a/Documentation/power/notifiers.txt b/Documentation/power/notifiers.txt index ae1b7ec07684..cf980709122a 100644 --- a/Documentation/power/notifiers.txt +++ b/Documentation/power/notifiers.txt @@ -24,7 +24,7 @@ PM_HIBERNATION_PREPARE The system is going to hibernate or suspend, tasks will be frozen immediately. PM_POST_HIBERNATION The system memory state has been restored from a - hibernation image or an error occured during the + hibernation image or an error occurred during the hibernation. Device drivers' .resume() callbacks have been executed and tasks have been thawed. @@ -38,7 +38,7 @@ PM_POST_RESTORE An error occurred during the hibernation restore. PM_SUSPEND_PREPARE The system is preparing for a suspend. -PM_POST_SUSPEND The system has just resumed or an error occured during +PM_POST_SUSPEND The system has just resumed or an error occurred during the suspend. Device drivers' .resume() callbacks have been executed and tasks have been thawed. diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index cd445582d1f8..5ae70a12c1e2 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt @@ -178,7 +178,7 @@ opp_find_freq_ceil - Search for an available OPP which is *at least* the if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); else - /* do something when we cant satisfy the req */ + /* do something when we can't satisfy the req */ /* do other stuff */ } diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index ea718891a665..ac190cf1963e 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -192,7 +192,7 @@ Q: There don't seem to be any generally useful behavioral distinctions between SUSPEND and FREEZE. A: Doing SUSPEND when you are asked to do FREEZE is always correct, -but it may be unneccessarily slow. If you want your driver to stay simple, +but it may be unnecessarily slow. If you want your driver to stay simple, slowness may not matter to you. It can always be fixed later. For devices like disk it does matter, you do not want to spindown for @@ -237,7 +237,7 @@ disk. Whole sequence goes like running system, user asks for suspend-to-disk - user processes are stopped (in common case there are none, but with resume-from-initrd, noone knows) + user processes are stopped (in common case there are none, but with resume-from-initrd, no one knows) read image from disk diff --git a/Documentation/power/userland-swsusp.txt b/Documentation/power/userland-swsusp.txt index 81680f9f5909..1101bee4e822 100644 --- a/Documentation/power/userland-swsusp.txt +++ b/Documentation/power/userland-swsusp.txt @@ -98,7 +98,7 @@ SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to The device's read() operation can be used to transfer the snapshot image from the kernel. It has the following limitations: - you cannot read() more than one virtual memory page at a time -- read()s accross page boundaries are impossible (ie. if ypu read() 1/2 of +- read()s across page boundaries are impossible (ie. if ypu read() 1/2 of a page in the previous call, you will only be able to read() _at_ _most_ 1/2 of the page in the next call) @@ -137,7 +137,7 @@ mechanism and the userland utilities using the interface SHOULD use additional means, such as checksums, to ensure the integrity of the snapshot image. The suspending and resuming utilities MUST lock themselves in memory, -preferrably using mlockall(), before calling SNAPSHOT_FREEZE. +preferably using mlockall(), before calling SNAPSHOT_FREEZE. The suspending utility MUST check the value stored by SNAPSHOT_CREATE_IMAGE in the memory location pointed to by the last argument of ioctl() and proceed @@ -147,7 +147,7 @@ in accordance with it: (a) The suspending utility MUST NOT close the snapshot device _unless_ the whole suspend procedure is to be cancelled, in which case, if the snapshot image has already been saved, the - suspending utility SHOULD destroy it, preferrably by zapping + suspending utility SHOULD destroy it, preferably by zapping its header. If the suspend is not to be cancelled, the system MUST be powered off or rebooted after the snapshot image has been saved. diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt index 6d8be3468d7d..a730ca5a07f8 100644 --- a/Documentation/powerpc/hvcs.txt +++ b/Documentation/powerpc/hvcs.txt @@ -528,7 +528,7 @@ this driver assignment of hotplug added vty-servers may be in a different order than how they would be exposed on module load. Rebooting or reloading the module after dynamic addition may result in the /dev/hvcs* and vty-server coupling changing if a vty-server adapter was added in a -slot inbetween two other vty-server adapters. Refer to the section above +slot between two other vty-server adapters. Refer to the section above on how to determine which vty-server goes with which /dev/hvcs* node. Hint; look at the sysfs "index" attribute for the vty-server. diff --git a/Documentation/scsi/ChangeLog.lpfc b/Documentation/scsi/ChangeLog.lpfc index 5e83769c6aa9..c56ec99d7b2f 100644 --- a/Documentation/scsi/ChangeLog.lpfc +++ b/Documentation/scsi/ChangeLog.lpfc @@ -352,7 +352,7 @@ Changes from 20041229 to 20050110 lpfc_scsiport.c * In remote port changes: no longer nulling target->pnode when removing from mapped list. Pnode get nulled when the node is - freed (after nodev tmo). This bug was causing i/o recieved in + freed (after nodev tmo). This bug was causing i/o received in the small window while the device was blocked to be errored w/ did_no_connect. With the fix, it returns host_busy (per the pre-remote port changes). @@ -530,7 +530,7 @@ Changes from 20041018 to 20041123 coherent mappings. Note: There are more consistent mappings that are using pci_dma_sync calls. Probably these should be removed as well. - * Modified lpfc_free_scsi_buf to accomodate all three scsi_buf + * Modified lpfc_free_scsi_buf to accommodate all three scsi_buf free types to alleviate miscellaneous panics with cable pull testing. * Set hotplug to default 0 and lpfc_target_remove to not remove @@ -583,7 +583,7 @@ Changes from 20041018 to 20041123 included more than once. * Replaced "set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(timeout)" with "msleep(timeout)". - * Fixnode was loosing starget when rediscovered. We saw messages + * Fixnode was losing starget when rediscovered. We saw messages like: lpfc 0000:04:02.0: 0:0263 Cannot block scsi target as a result. Moved starget field into struct lpfc_target which is referenced from the node. @@ -604,7 +604,7 @@ Changes from 20041018 to 20041123 * Make 3 functions static: lpfc_get_hba_sym_node_name, lpfc_intr_prep and lpfc_setup_slim_access. Move lpfc_intr_prep and lpfc_setup_slim_access so they're defined before being used. - * Remove an unecessary list_del() in lpfc_hbadisc.c. + * Remove an unnecessary list_del() in lpfc_hbadisc.c. * Set nlp_state before calling lpfc_nlp_list() since this will potentially call fc_target_unblock which may cause a race in queuecommand by releasing host_lock. @@ -753,7 +753,7 @@ Changes from 20040908 to 20040920 * Changed version number to 8.0.12 * Removed used #defines: DEFAULT_PCI_LATENCY_CLOCKS and PCI_LATENCY_VALUE from lpfc_hw.h. - * Changes to accomodate rnid. + * Changes to accommodate rnid. * Fix RSCN handling so RSCN NS queries only effect NPorts found in RSCN data. * If we rcv a plogi on a NPort queued up for discovery, clear the @@ -813,7 +813,7 @@ Changes from 20040908 to 20040920 counter instead, brd_no isn't reused anymore. Also some tiny whitespace cleanups in surrounding code. * Reorder functions in lpfc_els.c to remove need for prototypes. - * Removed unsed prototypes from lpfc_crtn.h - + * Removed unused prototypes from lpfc_crtn.h - lpfc_ip_timeout_handler, lpfc_read_pci and lpfc_revoke. * Removed some unused prototypes from lpfc_crtn.h - lpfc_scsi_hba_reset, lpfc_scsi_issue_inqsn, @@ -863,7 +863,7 @@ Changes from 20040823 to 20040908 * Minimal support for SCSI flat space addressing/volume set addressing. Use 16 bits of LUN address so that flat addressing/VSA will work. - * Changed 2 occurences of if( 1 != f(x)) to if(f(x) != 1) + * Changed 2 occurrences of if( 1 != f(x)) to if(f(x) != 1) * Drop include of lpfc_cfgparm.h. * Reduce stack usage of lpfc_fdmi_cmd in lpfc_ct.c. * Add minimum range checking property to /sys write/store @@ -1449,7 +1449,7 @@ Changes from 20040402 to 20040409 * Removed lpfc_els_chk_latt from the lpfc_config_post function. lpfc_els_chk_latt will enable the link event interrupts when flogi is pending which causes two discovery state machines - running parallely. + running parallelly. * Add pci_disable_device to unload path. * Move lpfc_sleep_event from lpfc_fcp.c to lpfc_util_ioctl.c * Call dma_map_single() & pci_map_single() directly instead of via @@ -1590,7 +1590,7 @@ Changes from 20040326 to 20040402 ELX_WRITE_HS ELX_WRITE_HA ELX_WRITE_CA ELX_READ_HC ELX_READ_HS ELX_READ_HA ELX_READ_CA ELX_READ_MB ELX_RESET ELX_READ_HBA ELX_INSTANCE ELX_LIP. Also introduced - attribute "set" to be used in conjuction with the above + attribute "set" to be used in conjunction with the above attributes. * Removed DLINK, enque and deque declarations now that clock doesn't use them anymore diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid index 5e07d320817d..d2052fdbedd2 100644 --- a/Documentation/scsi/ChangeLog.megaraid +++ b/Documentation/scsi/ChangeLog.megaraid @@ -168,7 +168,7 @@ Older Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module) 1. Sorted out PCI IDs to remove megaraid support overlaps. Based on the patch from Daniel, sorted out PCI IDs along with - charactor node name change from 'megadev' to 'megadev_legacy' to avoid + character node name change from 'megadev' to 'megadev_legacy' to avoid conflict. --- Hopefully we'll be getting the build restriction zapped much sooner, diff --git a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx index 8b278c10edfd..9288e3d8974a 100644 --- a/Documentation/scsi/ChangeLog.ncr53c8xx +++ b/Documentation/scsi/ChangeLog.ncr53c8xx @@ -200,7 +200,7 @@ Sun Feb 14:00 1999 Gerard Roudier (groudier@club-internet.fr) By default the driver uses both IRQF_SHARED and IRQF_DISABLED. Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by a 53C8XX adapter and a network board. - - Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately + - Tiny misspelling fixed (ABORT instead of ABRT). Was fortunately harmless. - Negotiate SYNC data transfers with CCS devices. diff --git a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx index 02ffbc1e8a84..c1933707d0bc 100644 --- a/Documentation/scsi/ChangeLog.sym53c8xx +++ b/Documentation/scsi/ChangeLog.sym53c8xx @@ -457,7 +457,7 @@ Fri Jan 1 20:00 1999 Gerard Roudier (groudier@club-internet.fr) Sat Dec 19 21:00 1998 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.0 - Define some new IO registers for the 896 (istat1, mbox0, mbox1) - - Revamp slighly the Symbios NVRAM lay-out based on the excerpt of + - Revamp slightly the Symbios NVRAM lay-out based on the excerpt of the header file I received from Symbios. - Check the PCI bus number for the boot order (Using a fast PCI controller behing a PCI-PCI bridge seems sub-optimal). diff --git a/Documentation/scsi/aha152x.txt b/Documentation/scsi/aha152x.txt index 29ce6d87e451..94848734ac66 100644 --- a/Documentation/scsi/aha152x.txt +++ b/Documentation/scsi/aha152x.txt @@ -124,7 +124,7 @@ in the partition table and therefore every operating system has to know the right geometry to be able to interpret it. Moreover there are certain limitations to the C/H/S addressing scheme, -namely the address space is limited to upto 255 heads, upto 63 sectors +namely the address space is limited to up to 255 heads, up to 63 sectors and a maximum of 1023 cylinders. The AHA-1522 BIOS calculates the geometry by fixing the number of heads diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt index 16e054c9c70b..64ac7093c872 100644 --- a/Documentation/scsi/aic79xx.txt +++ b/Documentation/scsi/aic79xx.txt @@ -267,7 +267,7 @@ The following information is available in this file: Option: tag_info:{{value[,value...]}[,{value[,value...]}...]} Definition: Set the per-target tagged queue depth on a per controller basis. Both controllers and targets - may be ommitted indicating that they should retain + may be omitted indicating that they should retain the default tag depth. Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} On Controller 0 @@ -291,7 +291,7 @@ The following information is available in this file: The rd_strm_bitmask is a 16 bit hex value in which each bit represents a target. Setting the target's bit to '1' enables read streaming for that - target. Controllers may be ommitted indicating that + target. Controllers may be omitted indicating that they should retain the default read streaming setting. Example: rd_strm:{0x0041} On Controller 0 @@ -313,7 +313,7 @@ The following information is available in this file: ----------------------------------------------------------------- Option: dv: {value[,value...]} Definition: Set Domain Validation Policy on a per-controller basis. - Controllers may be ommitted indicating that + Controllers may be omitted indicating that they should retain the default read streaming setting. Example: dv:{-1,0,,1,1,0} On Controller 0 leave DV at its default setting. @@ -340,7 +340,7 @@ The following information is available in this file: Option: precomp: {value[,value...]} Definition: Set IO Cell precompensation value on a per-controller basis. - Controllers may be ommitted indicating that + Controllers may be omitted indicating that they should retain the default precompensation setting. Example: precomp:{0x1} On Controller 0 set precompensation to 1. @@ -353,7 +353,7 @@ The following information is available in this file: ----------------------------------------------------------------- Option: slewrate: {value[,value...]} Definition: Set IO Cell slew rate on a per-controller basis. - Controllers may be ommitted indicating that + Controllers may be omitted indicating that they should retain the default slew rate setting. Example: slewrate:{0x1} On Controller 0 set slew rate to 1. @@ -366,7 +366,7 @@ The following information is available in this file: ----------------------------------------------------------------- Option: amplitude: {value[,value...]} Definition: Set IO Cell signal amplitude on a per-controller basis. - Controllers may be ommitted indicating that + Controllers may be omitted indicating that they should retain the default read streaming setting. Example: amplitude:{0x1} On Controller 0 set amplitude to 1. diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt index 45d61ad8c6f7..ac41a9fcac77 100644 --- a/Documentation/scsi/ibmmca.txt +++ b/Documentation/scsi/ibmmca.txt @@ -303,7 +303,7 @@ (scb) and calls a local function issue_cmd(), which writes a scb command into subsystem I/O ports. Once the scb command is carried out, the interrupt_handler() is invoked. If a device is determined to be - existant and it has not assigned any ldn, it gets one dynamically. + existent and it has not assigned any ldn, it gets one dynamically. For this, the whole stuff is done in ibmmca_queuecommand(). 2.6 Abort & Reset Commands @@ -741,7 +741,7 @@ some error appeared, else it is undefined. Now, this is fixed. Before any SCB command gets queued, the tsb.dev_status is set to 0, so the cmd->result won't screw up Linux higher level drivers. - 2) The reset-function has slightly improved. This is still planed for + 2) The reset-function has slightly improved. This is still planned for abort. During the abort and the reset function, no interrupts are allowed. This is however quite hard to cope with, so the INT-status register is read. When the interrupt gets queued, one can find its diff --git a/Documentation/scsi/scsi-changer.txt b/Documentation/scsi/scsi-changer.txt index 032399b16a53..ade046ea7c17 100644 --- a/Documentation/scsi/scsi-changer.txt +++ b/Documentation/scsi/scsi-changer.txt @@ -102,7 +102,7 @@ Trouble? If you insmod the driver with "insmod debug=1", it will be verbose and prints a lot of stuff to the syslog. Compiling the kernel with -CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot +CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages a lot because the kernel will translate the error codes into human-readable strings then. diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt index 7acbebb17fa6..6ff16b620d84 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.txt @@ -290,7 +290,7 @@ scmd->allowed. SCSI transports/LLDDs automatically acquire sense data on command failures (autosense). Autosense is recommended for performance reasons and as sense information could get out of - sync inbetween occurrence of CHECK CONDITION and this action. + sync between occurrence of CHECK CONDITION and this action. Note that if autosense is not supported, scmd->sense_buffer contains invalid sense data when error-completing the scmd diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt index e00192de4d1c..f79282fc48d7 100644 --- a/Documentation/scsi/scsi_fc_transport.txt +++ b/Documentation/scsi/scsi_fc_transport.txt @@ -291,7 +291,7 @@ Transport <-> LLDD Interfaces : Vport support by LLDD: The LLDD indicates support for vports by supplying a vport_create() - function in the transport template. The presense of this function will + function in the transport template. The presence of this function will cause the creation of the new attributes on the fc_host. As part of the physical port completing its initialization relative to the transport, it should set the max_npiv_vports attribute to indicate the diff --git a/Documentation/serial/moxa-smartio b/Documentation/serial/moxa-smartio index d10443918684..5d2a33be0bd8 100644 --- a/Documentation/serial/moxa-smartio +++ b/Documentation/serial/moxa-smartio @@ -473,7 +473,7 @@ Content spd_normal Use 38.4kb when the application requests 38.4kb. spd_cust Use the custom divisor to set the speed when the application requests 38.4kb. - divisor This option set the custom divison. + divisor This option set the custom division. baud_base This option set the base baud rate. ----------------------------------------------------------------------------- diff --git a/Documentation/serial/n_gsm.txt b/Documentation/serial/n_gsm.txt index 397f41a1f153..a5d91126a8f7 100644 --- a/Documentation/serial/n_gsm.txt +++ b/Documentation/serial/n_gsm.txt @@ -34,7 +34,7 @@ Major parts of the initialization program : /* configure the serial port : speed, flow control ... */ /* send the AT commands to switch the modem to CMUX mode - and check that it's succesful (should return OK) */ + and check that it's successful (should return OK) */ write(fd, "AT+CMUX=0\r", 10); /* experience showed that some modems need some time before diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 3c1eddd9fcc7..b9b7f30ab500 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -322,7 +322,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240) or the value stored in the card's EEPROM for cards that have an EEPROM and their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can - be choosen freely from the options enumerated above. + be chosen freely from the options enumerated above. If dma2 is specified and different from dma1, the card will operate in full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to @@ -356,7 +356,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240) or the value stored in the card's EEPROM for cards that have an EEPROM and their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can - be choosen freely from the options enumerated above. + be chosen freely from the options enumerated above. If dma2 is specified and different from dma1, the card will operate in full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to diff --git a/Documentation/sound/oss/README.OSS b/Documentation/sound/oss/README.OSS index c615debbf08d..4be259428a1c 100644 --- a/Documentation/sound/oss/README.OSS +++ b/Documentation/sound/oss/README.OSS @@ -1352,7 +1352,7 @@ OSS-mixer. The PCM20 contains a radio tuner, which is also controlled by ACI. This radio tuner is supported by the ACI driver together with the miropcm20.o module. Also the 7-band equalizer is integrated -(limited by the OSS-design). Developement has started and maybe +(limited by the OSS-design). Development has started and maybe finished for the RDS decoder on this card, too. You will be able to read RadioText, the Programme Service name, Programme TYpe and others. Even the v4l radio module benefits from it with a refined diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx index 68a4fe3818a1..493dada57372 100644 --- a/Documentation/spi/pxa2xx +++ b/Documentation/spi/pxa2xx @@ -143,7 +143,7 @@ configured to use SSPFRM instead. NOTE: the SPI driver cannot control the chip select if SSPFRM is used, so the chipselect is dropped after each spi_transfer. Most devices need chip select asserted around the complete message. Use SSPFRM as a GPIO (through cs_control) -to accomodate these chips. +to accommodate these chips. NSSP SLAVE SAMPLE diff --git a/Documentation/spi/spi-lm70llp b/Documentation/spi/spi-lm70llp index 34a9cfd746bd..463f6d01fa15 100644 --- a/Documentation/spi/spi-lm70llp +++ b/Documentation/spi/spi-lm70llp @@ -46,7 +46,7 @@ The hardware interfacing on the LM70 LLP eval board is as follows: Note that since the LM70 uses a "3-wire" variant of SPI, the SI/SO pin is connected to both pin D7 (as Master Out) and Select (as Master In) -using an arrangment that lets either the parport or the LM70 pull the +using an arrangement that lets either the parport or the LM70 pull the pin low. This can't be shared with true SPI devices, but other 3-wire devices might share the same SI/SO pin. diff --git a/Documentation/telephony/ixj.txt b/Documentation/telephony/ixj.txt index 4fb314d51702..db94fb6c5678 100644 --- a/Documentation/telephony/ixj.txt +++ b/Documentation/telephony/ixj.txt @@ -51,7 +51,7 @@ be removed to protect the rights of others. Specifically, very old Internet PhoneJACK cards have non-standard G.723.1 codecs (due to the early nature of the DSPs in those days). The auto-conversion code to bring those cards into compliance with -todays standards is available as a binary only module to those people +today's standards is available as a binary only module to those people needing it. If you bought your card after 1997 or so, you are OK - it's only the very old cards that are affected. diff --git a/Documentation/trace/ring-buffer-design.txt b/Documentation/trace/ring-buffer-design.txt index d299ff31df57..7d350b496585 100644 --- a/Documentation/trace/ring-buffer-design.txt +++ b/Documentation/trace/ring-buffer-design.txt @@ -237,7 +237,7 @@ with the previous write. |written | +---------+ |written | - +---------+ <--- next positon for write (current commit) + +---------+ <--- next position for write (current commit) | empty | +---------+ diff --git a/Documentation/video4linux/README.pvrusb2 b/Documentation/video4linux/README.pvrusb2 index a747200fe67c..2137b589276b 100644 --- a/Documentation/video4linux/README.pvrusb2 +++ b/Documentation/video4linux/README.pvrusb2 @@ -172,7 +172,7 @@ Source file list / functional overview: to provide a streaming API usable by a read() system call style of I/O. Right now this is the only layer on top of pvrusb2-io.[ch], however the underlying architecture here was intended to allow for - other styles of I/O to be implemented with additonal modules, like + other styles of I/O to be implemented with additional modules, like mmap()'ed buffers or something even more exotic. pvrusb2-main.c - This is the top level of the driver. Module level diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README index 3a367cdb664e..7cbf4fb6cf31 100644 --- a/Documentation/video4linux/bttv/README +++ b/Documentation/video4linux/bttv/README @@ -70,7 +70,7 @@ If you have trouble with some specific TV card, try to ask there instead of mailing me directly. The chance that someone with the same card listens there is much higher... -For problems with sound: There are alot of different systems used +For problems with sound: There are a lot of different systems used for TV sound all over the world. And there are also different chips which decode the audio signal. Reports about sound problems ("stereo does'nt work") are pretty useless unless you include some details diff --git a/Documentation/video4linux/bttv/README.freeze b/Documentation/video4linux/bttv/README.freeze index 4259dccc8287..5eddfa076cfb 100644 --- a/Documentation/video4linux/bttv/README.freeze +++ b/Documentation/video4linux/bttv/README.freeze @@ -33,7 +33,7 @@ state is stuck. I've seen reports that bttv 0.7.x crashes whereas 0.8.x works rock solid for some people. Thus probably a small buglet left somewhere in bttv -0.7.x. I have no idea where exactly, it works stable for me and alot of +0.7.x. I have no idea where exactly, it works stable for me and a lot of other people. But in case you have problems with the 0.7.x versions you can give 0.8.x a try ... diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ index 1e6328f91083..b6e6debbbc94 100644 --- a/Documentation/video4linux/bttv/Sound-FAQ +++ b/Documentation/video4linux/bttv/Sound-FAQ @@ -2,7 +2,7 @@ bttv and sound mini howto ========================= -There are alot of different bt848/849/878/879 based boards available. +There are a lot of different bt848/849/878/879 based boards available. Making video work often is not a big deal, because this is handled completely by the bt8xx chip, which is common on all boards. But sound is handled in slightly different ways on each board. diff --git a/Documentation/video4linux/pxa_camera.txt b/Documentation/video4linux/pxa_camera.txt index 4f6d0ca01956..51ed1578b0e8 100644 --- a/Documentation/video4linux/pxa_camera.txt +++ b/Documentation/video4linux/pxa_camera.txt @@ -84,12 +84,12 @@ DMA usage transfer is not started. On "End Of Frame" interrupt, the irq handler starts the DMA chain. - capture of one videobuffer - The DMA chain starts transfering data into videobuffer RAM pages. - When all pages are transfered, the DMA irq is raised on "ENDINTR" status + The DMA chain starts transferring data into videobuffer RAM pages. + When all pages are transferred, the DMA irq is raised on "ENDINTR" status - finishing one videobuffer The DMA irq handler marks the videobuffer as "done", and removes it from the active running queue - Meanwhile, the next videobuffer (if there is one), is transfered by DMA + Meanwhile, the next videobuffer (if there is one), is transferred by DMA - finishing the last videobuffer On the DMA irq of the last videobuffer, the QCI is stopped. @@ -101,7 +101,7 @@ DMA usage This structure is pointed by dma->sg_cpu. The descriptors are used as follows : - - desc-sg[i]: i-th descriptor, transfering the i-th sg + - desc-sg[i]: i-th descriptor, transferring the i-th sg element to the video buffer scatter gather - finisher: has ddadr=DADDR_STOP, dcmd=ENDIRQEN - linker: has ddadr= desc-sg[0] of next video buffer, dcmd=0 diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 3b15608ee070..cf21f7aae976 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -343,7 +343,7 @@ ignored. If you want to check for errors use this: err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); Any error except -ENOIOCTLCMD will exit the loop with that error. If no -errors (except -ENOIOCTLCMD) occured, then 0 is returned. +errors (except -ENOIOCTLCMD) occurred, then 0 is returned. The second argument to both calls is a group ID. If 0, then all subdevs are called. If non-zero, then only those whose group ID match that value will diff --git a/Documentation/vm/active_mm.txt b/Documentation/vm/active_mm.txt index 4ee1f643d897..dbf45817405f 100644 --- a/Documentation/vm/active_mm.txt +++ b/Documentation/vm/active_mm.txt @@ -74,7 +74,7 @@ we have a user context", and is generally done by the page fault handler and things like that). Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago, -because it slightly changes the interfaces to accomodate the alpha (who +because it slightly changes the interfaces to accommodate the alpha (who would have thought it, but the alpha actually ends up having one of the ugliest context switch codes - unlike the other architectures where the MM and register state is separate, the alpha PALcode joins the two, and you diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index 457634c1e03e..f8551b3879f8 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt @@ -72,7 +72,7 @@ number of huge pages requested. This is the most reliable method of allocating huge pages as memory has not yet become fragmented. Some platforms support multiple huge page sizes. To allocate huge pages -of a specific size, one must preceed the huge pages boot command parameters +of a specific size, one must precede the huge pages boot command parameters with a huge page size selection parameter "hugepagesz=". must be specified in bytes with optional scale suffix [kKmMgG]. The default huge page size may be selected with the "default_hugepagesz=" boot parameter. diff --git a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting index 21c7b1f8f32b..706d7ed9d8d2 100644 --- a/Documentation/vm/overcommit-accounting +++ b/Documentation/vm/overcommit-accounting @@ -4,7 +4,7 @@ The Linux kernel supports the following overcommit handling modes address space are refused. Used for a typical system. It ensures a seriously wild allocation fails while allowing overcommit to reduce swap usage. root is allowed to - allocate slighly more memory in this mode. This is the + allocate slightly more memory in this mode. This is the default. 1 - Always overcommit. Appropriate for some scientific diff --git a/Documentation/w1/slaves/w1_ds2423 b/Documentation/w1/slaves/w1_ds2423 index 90a65d23cf59..3f98b505a0ee 100644 --- a/Documentation/w1/slaves/w1_ds2423 +++ b/Documentation/w1/slaves/w1_ds2423 @@ -21,8 +21,8 @@ value and associated ram buffer is outpputed to own line. Each lines will contain the values of 42 bytes read from the counter and memory page along the crc=YES or NO for indicating whether the read operation -was successfull and CRC matched. -If the operation was successfull, there is also in the end of each line +was successful and CRC matched. +If the operation was successful, there is also in the end of each line a counter value expressed as an integer after c= Meaning of 42 bytes represented is following: @@ -34,7 +34,7 @@ Meaning of 42 bytes represented is following: - crc=YES/NO indicating whether read was ok and crc matched - c= current counter value -example from the successfull read: +example from the successful read: 00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 00 29 c6 5d 18 00 00 00 00 04 37 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408798761 diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink index 804445f745ed..f59a31965d50 100644 --- a/Documentation/w1/w1.netlink +++ b/Documentation/w1/w1.netlink @@ -81,7 +81,7 @@ which will contain list of all registered master ids in the following format: cn_msg (CN_W1_IDX.CN_W1_VAL as id, len is equal to sizeof(struct - w1_netlink_msg) plus number of masters multipled by 4) + w1_netlink_msg) plus number of masters multiplied by 4) w1_netlink_msg (type: W1_LIST_MASTERS, len is equal to number of masters multiplied by 4 (u32 size)) id0 ... idN diff --git a/Documentation/watchdog/hpwdt.txt b/Documentation/watchdog/hpwdt.txt index 9c24d5ffbb06..9488078900e0 100644 --- a/Documentation/watchdog/hpwdt.txt +++ b/Documentation/watchdog/hpwdt.txt @@ -8,7 +8,7 @@ Last reviewed: 06/02/2009 The HP iLO2 NMI Watchdog driver is a kernel module that provides basic watchdog functionality and the added benefit of NMI sourcing. Both the watchdog functionality and the NMI sourcing capability need to be enabled - by the user. Remember that the two modes are not dependant on one another. + by the user. Remember that the two modes are not dependent on one another. A user can have the NMI sourcing without the watchdog timer and vice-versa. Watchdog functionality is enabled like any other common watchdog driver. That diff --git a/arch/alpha/include/asm/elf.h b/arch/alpha/include/asm/elf.h index 9baae8afe8a3..da5449e22175 100644 --- a/arch/alpha/include/asm/elf.h +++ b/arch/alpha/include/asm/elf.h @@ -101,7 +101,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define ELF_PLAT_INIT(_r, load_addr) _r->r0 = 0 -/* The registers are layed out in pt_regs for PAL and syscall +/* The registers are laid out in pt_regs for PAL and syscall convenience. Re-order them for the linear elf_gregset_t. */ struct pt_regs; diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c index 4843f6ec9f3a..cb2801cfd3df 100644 --- a/arch/alpha/kernel/core_lca.c +++ b/arch/alpha/kernel/core_lca.c @@ -133,7 +133,7 @@ conf_read(unsigned long addr) local_irq_save(flags); - /* Reset status register to avoid loosing errors. */ + /* Reset status register to avoid losing errors. */ stat0 = *(vulp)LCA_IOC_STAT0; *(vulp)LCA_IOC_STAT0 = stat0; mb(); @@ -170,7 +170,7 @@ conf_write(unsigned long addr, unsigned int value) local_irq_save(flags); /* avoid getting hit by machine check */ - /* Reset status register to avoid loosing errors. */ + /* Reset status register to avoid losing errors. */ stat0 = *(vulp)LCA_IOC_STAT0; *(vulp)LCA_IOC_STAT0 = stat0; mb(); diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 648ae88aeb8a..ae54ad91e18f 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -1027,7 +1027,7 @@ marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print) * normal operation, dismiss them. * * Dismiss if: - * C_STAT = 0x14 (Error Reponse) + * C_STAT = 0x14 (Error Response) * C_STS<3> = 0 (C_ADDR valid) * C_ADDR<42> = 1 (I/O) * C_ADDR<31:22> = 111110xxb (PCI Config space) diff --git a/arch/alpha/lib/ev67-strrchr.S b/arch/alpha/lib/ev67-strrchr.S index 3fd8bf414c7b..dd0d8c6b9f59 100644 --- a/arch/alpha/lib/ev67-strrchr.S +++ b/arch/alpha/lib/ev67-strrchr.S @@ -82,7 +82,7 @@ $loop: $eos: negq t1, t4 # E : isolate first null byte match and t1, t4, t4 # E : - subq t4, 1, t5 # E : build a mask of the bytes upto... + subq t4, 1, t5 # E : build a mask of the bytes up to... or t4, t5, t4 # E : ... and including the null and t3, t4, t3 # E : mask out char matches after null diff --git a/arch/alpha/lib/fls.c b/arch/alpha/lib/fls.c index 32afaa3fa686..ddd048c0d825 100644 --- a/arch/alpha/lib/fls.c +++ b/arch/alpha/lib/fls.c @@ -6,7 +6,7 @@ #include /* This is fls(x)-1, except zero is held to zero. This allows most - efficent input into extbl, plus it allows easy handling of fls(0)=0. */ + efficient input into extbl, plus it allows easy handling of fls(0)=0. */ const unsigned char __flsm1_tab[256] = { diff --git a/arch/alpha/lib/strrchr.S b/arch/alpha/lib/strrchr.S index 82cfd0ac907b..1970dc07cfd1 100644 --- a/arch/alpha/lib/strrchr.S +++ b/arch/alpha/lib/strrchr.S @@ -54,7 +54,7 @@ $loop: $eos: negq t1, t4 # e0 : isolate first null byte match and t1, t4, t4 # e1 : - subq t4, 1, t5 # e0 : build a mask of the bytes upto... + subq t4, 1, t5 # e0 : build a mask of the bytes up to... or t4, t5, t4 # e1 : ... and including the null and t3, t4, t3 # e0 : mask out char matches after null diff --git a/arch/alpha/oprofile/op_model_ev67.c b/arch/alpha/oprofile/op_model_ev67.c index 70302086283c..5b9d178e0228 100644 --- a/arch/alpha/oprofile/op_model_ev67.c +++ b/arch/alpha/oprofile/op_model_ev67.c @@ -192,7 +192,7 @@ ev67_handle_interrupt(unsigned long which, struct pt_regs *regs, case TRAP_INVALID1: case TRAP_INVALID2: case TRAP_INVALID3: - /* Pipeline redirection ocurred. PMPC points + /* Pipeline redirection occurred. PMPC points to PALcode. Recognize ITB miss by PALcode offset address, and get actual PC from EXC_ADDR. */ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5b9f78b570e8..fdc9d4dbf85b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -694,7 +694,7 @@ config ARCH_S3C2410 the Samsung SMDK2410 development board (and derivatives). Note, the S3C2416 and the S3C2450 are so close that they even share - the same SoC ID code. This means that there is no seperate machine + the same SoC ID code. This means that there is no separate machine directory (no arch/arm/mach-s3c2450) as the S3C2416 was first. config ARCH_S3C64XX diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu index 901e6dff8437..2cef8e13f9f8 100644 --- a/arch/arm/Kconfig-nommu +++ b/arch/arm/Kconfig-nommu @@ -34,7 +34,7 @@ config PROCESSOR_ID used instead of the auto-probing which utilizes the register. config REMAP_VECTORS_TO_RAM - bool 'Install vectors to the begining of RAM' if DRAM_BASE + bool 'Install vectors to the beginning of RAM' if DRAM_BASE depends on DRAM_BASE help The kernel needs to change the hardware exception vectors. diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c index 8f0f86db3602..97912fa48782 100644 --- a/arch/arm/common/pl330.c +++ b/arch/arm/common/pl330.c @@ -1045,7 +1045,7 @@ static inline int _loop(unsigned dry_run, u8 buf[], unsigned lcnt0, lcnt1, ljmp0, ljmp1; struct _arg_LPEND lpend; - /* Max iterations possibile in DMALP is 256 */ + /* Max iterations possible in DMALP is 256 */ if (*bursts >= 256*256) { lcnt1 = 256; lcnt0 = 256; @@ -1446,7 +1446,7 @@ int pl330_update(const struct pl330_info *pi) } for (ev = 0; ev < pi->pcfg.num_events; ev++) { - if (val & (1 << ev)) { /* Event occured */ + if (val & (1 << ev)) { /* Event occurred */ struct pl330_thread *thrd; u32 inten = readl(regs + INTEN); int active; diff --git a/arch/arm/include/asm/fpstate.h b/arch/arm/include/asm/fpstate.h index ee5e03efc1bb..3ad4c10d0d84 100644 --- a/arch/arm/include/asm/fpstate.h +++ b/arch/arm/include/asm/fpstate.h @@ -18,7 +18,7 @@ * VFP storage area has: * - FPEXC, FPSCR, FPINST and FPINST2. * - 16 or 32 double precision data registers - * - an implementation-dependant word of state for FLDMX/FSTMX (pre-ARMv6) + * - an implementation-dependent word of state for FLDMX/FSTMX (pre-ARMv6) * * FPEXC will always be non-zero once the VFP has been used in this process. */ diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index c7afbc552c7f..7e30874377e6 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h @@ -126,7 +126,7 @@ #endif #if !defined(_CACHE) && !defined(MULTI_CACHE) -#error Unknown cache maintainence model +#error Unknown cache maintenance model #endif #ifndef MULTI_CACHE diff --git a/arch/arm/include/asm/glue.h b/arch/arm/include/asm/glue.h index 0ec35d1698aa..fbf71d75ec83 100644 --- a/arch/arm/include/asm/glue.h +++ b/arch/arm/include/asm/glue.h @@ -10,8 +10,8 @@ * * This file provides the glue to stick the processor-specific bits * into the kernel in an efficient manner. The idea is to use branches - * when we're only targetting one class of TLB, or indirect calls - * when we're targetting multiple classes of TLBs. + * when we're only targeting one class of TLB, or indirect calls + * when we're targeting multiple classes of TLBs. */ #ifdef __KERNEL__ diff --git a/arch/arm/include/asm/hardware/pl080.h b/arch/arm/include/asm/hardware/pl080.h index f35b86e68dd5..e4a04e4e5627 100644 --- a/arch/arm/include/asm/hardware/pl080.h +++ b/arch/arm/include/asm/hardware/pl080.h @@ -16,7 +16,7 @@ * make it not entierly compatible with the PL080 specification from * ARM. When in doubt, check the Samsung documentation first. * - * The Samsung defines are PL080S, and add an extra controll register, + * The Samsung defines are PL080S, and add an extra control register, * the ability to move more than 2^11 counts of data and some extra * OneNAND features. */ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 9a87823642d0..885be097769d 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -249,7 +249,7 @@ do { \ * cache totally. This means that the cache becomes inconsistent, and, * since we use normal loads/stores as well, this is really bad. * Typically, this causes oopsen in filp_close, but could have other, - * more disasterous effects. There are two work-arounds: + * more disastrous effects. There are two work-arounds: * 1. Disable interrupts and emulate the atomic swap * 2. Clean the cache, perform atomic swap, flush the cache * diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h index 47f023aa8495..14749aec94bf 100644 --- a/arch/arm/include/asm/ucontext.h +++ b/arch/arm/include/asm/ucontext.h @@ -47,7 +47,7 @@ struct crunch_sigframe { #endif #ifdef CONFIG_IWMMXT -/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ +/* iwmmxt_area is 0x98 bytes long, preceded by 8 bytes of signature */ #define IWMMXT_MAGIC 0x12ef842a #define IWMMXT_STORAGE_SIZE (IWMMXT_SIZE + 8) diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 7a5760922914..40ee7e5045e4 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c @@ -158,7 +158,7 @@ static int emulate_swpX(unsigned int address, unsigned int *data, if (res == 0) { /* - * Barrier also required between aquiring a lock for a + * Barrier also required between acquiring a lock for a * protected resource and accessing the resource. Inserted for * same reason as above. */ diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c index 2e74a19874d1..295e1e77fa60 100644 --- a/arch/arm/mach-at91/board-carmeva.c +++ b/arch/arm/mach-at91/board-carmeva.c @@ -76,7 +76,7 @@ static struct at91_udc_data __initdata carmeva_udc_data = { .pullup_pin = AT91_PIN_PD9, }; -/* FIXME: user dependant */ +/* FIXME: user dependent */ // static struct at91_cf_data __initdata carmeva_cf_data = { // .det_pin = AT91_PIN_PB0, // .rst_pin = AT91_PIN_PC5, diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h index 27ac6f550fe3..02182c16a022 100644 --- a/arch/arm/mach-at91/include/mach/at91_mci.h +++ b/arch/arm/mach-at91/include/mach/at91_mci.h @@ -102,7 +102,7 @@ #define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */ #define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */ #define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */ -#define AT91_MCI_RTOE (1 << 20) /* Reponse Time-out Error */ +#define AT91_MCI_RTOE (1 << 20) /* Response Time-out Error */ #define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */ #define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */ #define AT91_MCI_OVRE (1 << 30) /* Overrun */ diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index ddeb64536756..056dc6674b6b 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -208,7 +208,7 @@ extern void at91_gpio_resume(void); /*-------------------------------------------------------------------------*/ -/* wrappers for "new style" GPIO calls. the old AT91-specfic ones should +/* wrappers for "new style" GPIO calls. the old AT91-specific ones should * eventually be removed (along with this errno.h inclusion), and the * gpio request/free calls should probably be implemented. */ diff --git a/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c b/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c index 77f84b40dda9..a1f328357aa4 100644 --- a/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c +++ b/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c @@ -551,7 +551,7 @@ int dmacHw_calculateDescriptorCount(dmacHw_CONFIG_t *pConfig, /* [ IN ] Config /****************************************************************************/ /** -* @brief Check the existance of pending descriptor +* @brief Check the existence of pending descriptor * * This function confirmes if there is any pending descriptor in the chain * to program the channel @@ -775,7 +775,7 @@ int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle, /* [ IN ] DMA Cha /** * @brief Read data DMAed to memory * -* This function will read data that has been DMAed to memory while transfering from: +* This function will read data that has been DMAed to memory while transferring from: * - Memory to memory * - Peripheral to memory * @@ -941,7 +941,7 @@ int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configurat /** * @brief Sets channel specific user data * -* This function associates user data to a specif DMA channel +* This function associates user data to a specific DMA channel * */ /****************************************************************************/ diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c index 8d1baf3f4683..d87ad30dda35 100644 --- a/arch/arm/mach-bcmring/dma.c +++ b/arch/arm/mach-bcmring/dma.c @@ -629,7 +629,7 @@ EXPORT_SYMBOL(dma_get_device_descriptor_ring); * Configures a DMA channel. * * @return -* >= 0 - Initialization was successfull. +* >= 0 - Initialization was successful. * * -EBUSY - Device is currently being used. * -ENODEV - Device handed in is invalid. @@ -673,7 +673,7 @@ static int ConfigChannel(DMA_Handle_t handle) /** * Initializes all of the data structures associated with the DMA. * @return -* >= 0 - Initialization was successfull. +* >= 0 - Initialization was successful. * * -EBUSY - Device is currently being used. * -ENODEV - Device handed in is invalid. diff --git a/arch/arm/mach-bcmring/include/csp/dmacHw.h b/arch/arm/mach-bcmring/include/csp/dmacHw.h index 6c8da2b9fc1f..e6a1dc484ca7 100644 --- a/arch/arm/mach-bcmring/include/csp/dmacHw.h +++ b/arch/arm/mach-bcmring/include/csp/dmacHw.h @@ -362,7 +362,7 @@ int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configurati /** * @brief Read data DMA transferred to memory * -* This function will read data that has been DMAed to memory while transfering from: +* This function will read data that has been DMAed to memory while transferring from: * - Memory to memory * - Peripheral to memory * @@ -446,7 +446,7 @@ void dmacHw_stopTransfer(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle * /****************************************************************************/ /** -* @brief Check the existance of pending descriptor +* @brief Check the existence of pending descriptor * * This function confirmes if there is any pending descriptor in the chain * to program the channel @@ -542,7 +542,7 @@ dmacHw_HANDLE_t dmacHw_getInterruptSource(void); /** * @brief Sets channel specific user data * -* This function associates user data to a specif DMA channel +* This function associates user data to a specific DMA channel * */ /****************************************************************************/ diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h index 70eaea866cfe..161973385faf 100644 --- a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h +++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h @@ -180,7 +180,7 @@ typedef enum { #define chipcHw_XTAL_FREQ_Hz 25000000 /* Reference clock frequency in Hz */ -/* Programable pin defines */ +/* Programmable pin defines */ #define chipcHw_PIN_GPIO(n) ((((n) >= 0) && ((n) < (chipcHw_GPIO_COUNT))) ? (n) : 0xFFFFFFFF) /* GPIO pin 0 - 60 */ #define chipcHw_PIN_UARTTXD (chipcHw_GPIO_COUNT + 0) /* UART Transmit */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h index c78833acb37a..03238c299001 100644 --- a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h +++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h @@ -832,7 +832,7 @@ static inline void chipcHw_setUsbDevice(void) /****************************************************************************/ /** -* @brief Lower layer funtion to enable/disable a clock of a certain device +* @brief Lower layer function to enable/disable a clock of a certain device * * This function enables/disables a core clock * diff --git a/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h index e01fc4607c91..0aeb6a6fe7f8 100644 --- a/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h +++ b/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h @@ -109,9 +109,9 @@ #define INTCHW_INTC0_DMA0C0 (1<cpuinfo.transition_latency = 2000 * 1000; diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 68fe4c289d77..b95b9196deed 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1123,7 +1123,7 @@ void __init da850_init(void) * This helps keeping the peripherals on this domain insulated * from CPU frequency changes caused by DVFS. The firmware sets * both PLL0 and PLL1 to the same frequency so, there should not - * be any noticible change even in non-DVFS use cases. + * be any noticeable change even in non-DVFS use cases. */ da850_set_async3_src(1); diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 76364d1345df..f68012239641 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -314,7 +314,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = 1, /* REVISIT: why can't' this be disabled? */ }; static struct clk timer3_clk = { diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 9a2376b3137c..5f8a65424184 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -274,7 +274,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = 1, /* REVISIT: why can't' this be disabled? */ }; static struct clk_lookup dm644x_clks[] = { diff --git a/arch/arm/mach-davinci/include/mach/cputype.h b/arch/arm/mach-davinci/include/mach/cputype.h index cea6b8972043..957fb87e832e 100644 --- a/arch/arm/mach-davinci/include/mach/cputype.h +++ b/arch/arm/mach-davinci/include/mach/cputype.h @@ -4,7 +4,7 @@ * Author: Kevin Hilman, Deep Root Systems, LLC * * Defines the cpu_is_*() macros for runtime detection of DaVinci - * device type. In addtion, if support for a given device is not + * device type. In addition, if support for a given device is not * compiled in to the kernel, the macros return 0 so that * resulting code can be optimized out. * diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index 180b8a9d0d21..a5a9ff70b198 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -101,7 +101,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) { /* - * map discontiguous hw irq range to continous sw irq range: + * map discontiguous hw irq range to continuous sw irq range: * * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) */ diff --git a/arch/arm/mach-exynos4/include/mach/gpio.h b/arch/arm/mach-exynos4/include/mach/gpio.h index 939728b38d48..be9266b10fdb 100644 --- a/arch/arm/mach-exynos4/include/mach/gpio.h +++ b/arch/arm/mach-exynos4/include/mach/gpio.h @@ -18,7 +18,7 @@ #define gpio_cansleep __gpio_cansleep #define gpio_to_irq __gpio_to_irq -/* Practically, GPIO banks upto GPZ are the configurable gpio banks */ +/* Practically, GPIO banks up to GPZ are the configurable gpio banks */ /* GPIO bank sizes */ #define EXYNOS4_GPIO_A0_NR (8) diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c index af82a8fbb68b..14ac10b7ec02 100644 --- a/arch/arm/mach-exynos4/mct.c +++ b/arch/arm/mach-exynos4/mct.c @@ -276,7 +276,7 @@ static void exynos4_mct_tick_start(unsigned long cycles, /* update interrupt count buffer */ exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET); - /* enable MCT tick interupt */ + /* enable MCT tick interrupt */ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET); tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET); diff --git a/arch/arm/mach-exynos4/setup-sdhci-gpio.c b/arch/arm/mach-exynos4/setup-sdhci-gpio.c index 1b3d3a2de95c..e8d08bf8965a 100644 --- a/arch/arm/mach-exynos4/setup-sdhci-gpio.c +++ b/arch/arm/mach-exynos4/setup-sdhci-gpio.c @@ -38,14 +38,14 @@ void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) switch (width) { case 8: for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) { - /* Data pin GPK1[3:6] to special-funtion 3 */ + /* Data pin GPK1[3:6] to special-function 3 */ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); } case 4: for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6); gpio++) { - /* Data pin GPK0[3:6] to special-funtion 2 */ + /* Data pin GPK0[3:6] to special-function 2 */ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); diff --git a/arch/arm/mach-exynos4/setup-sdhci.c b/arch/arm/mach-exynos4/setup-sdhci.c index 85f9433d4836..1e83f8cf236d 100644 --- a/arch/arm/mach-exynos4/setup-sdhci.c +++ b/arch/arm/mach-exynos4/setup-sdhci.c @@ -35,7 +35,7 @@ void exynos4_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r, { u32 ctrl2, ctrl3; - /* don't need to alter anything acording to card-type */ + /* don't need to alter anything according to card-type */ ctrl2 = readl(r + S3C_SDHCI_CONTROL2); diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 773ea0c95b9f..ba3dae352a2d 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c @@ -225,7 +225,7 @@ static u32 iop13xx_atue_cfg_address(struct pci_bus *bus, int devfn, int where) /* This routine checks the status of the last configuration cycle. If an error * was detected it returns >0, else it returns a 0. The errors being checked * are parity, master abort, target abort (master and target). These types of - * errors occure during a config cycle where there is no device, like during + * errors occur during a config cycle where there is no device, like during * the discovery stage. */ static int iop13xx_atux_pci_status(int clear) @@ -332,7 +332,7 @@ static struct pci_ops iop13xx_atux_ops = { /* This routine checks the status of the last configuration cycle. If an error * was detected it returns >0, else it returns a 0. The errors being checked * are parity, master abort, target abort (master and target). These types of - * errors occure during a config cycle where there is no device, like during + * errors occur during a config cycle where there is no device, like during * the discovery stage. */ static int iop13xx_atue_pci_status(int clear) diff --git a/arch/arm/mach-kirkwood/tsx1x-common.c b/arch/arm/mach-kirkwood/tsx1x-common.c index f781164e623f..24294b2bc469 100644 --- a/arch/arm/mach-kirkwood/tsx1x-common.c +++ b/arch/arm/mach-kirkwood/tsx1x-common.c @@ -15,7 +15,7 @@ /**************************************************************************** * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the - * partitions on the device because we want to keep compatability with + * partitions on the device because we want to keep compatibility with * the QNAP firmware. * Layout as used by QNAP: * 0x00000000-0x00080000 : "U-Boot" diff --git a/arch/arm/mach-lpc32xx/pm.c b/arch/arm/mach-lpc32xx/pm.c index e76d41bb7056..b9c80597b7bf 100644 --- a/arch/arm/mach-lpc32xx/pm.c +++ b/arch/arm/mach-lpc32xx/pm.c @@ -41,7 +41,7 @@ * DRAM clocking and refresh are slightly different for systems with DDR * DRAM or regular SDRAM devices. If SDRAM is used in the system, the * SDRAM will still be accessible in direct-run mode. In DDR based systems, - * a transistion to direct-run mode will stop all DDR accesses (no clocks). + * a transition to direct-run mode will stop all DDR accesses (no clocks). * Because of this, the code to switch power modes and the code to enter * and exit DRAM self-refresh modes must not be executed in DRAM. A small * section of IRAM is used instead for this. diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index aeb9ae23e6ce..99833b9485cf 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -9,7 +9,7 @@ * 2008-04-11: Jason Chagas * 2008-10-08: Bin Yang * - * The timers module actually includes three timers, each timer with upto + * The timers module actually includes three timers, each timer with up to * three match comparators. Timer #0 is used here in free-running mode as * the clock source, and match comparator #1 used as clock event device. * diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c index 7ffbd987eb5d..805d4ee53f7e 100644 --- a/arch/arm/mach-msm/acpuclock-arm11.c +++ b/arch/arm/mach-msm/acpuclock-arm11.c @@ -343,7 +343,7 @@ int acpuclk_set_rate(unsigned long rate, int for_power_collapse) } } - /* Set wait states for CPU inbetween frequency changes */ + /* Set wait states for CPU between frequency changes */ reg_clkctl = readl(A11S_CLK_CNTL_ADDR); reg_clkctl |= (100 << 16); /* set WT_ST_CNT */ writel(reg_clkctl, A11S_CLK_CNTL_ADDR); diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c index cfa808dd4897..232f97a04504 100644 --- a/arch/arm/mach-msm/scm.c +++ b/arch/arm/mach-msm/scm.c @@ -46,7 +46,7 @@ static DEFINE_MUTEX(scm_lock); * @id: command to be executed * @buf: buffer returned from scm_get_command_buffer() * - * An SCM command is layed out in memory as follows: + * An SCM command is laid out in memory as follows: * * ------------------- <--- struct scm_command * | command header | diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S index 927d5a181760..c1c5fb6a5b4c 100644 --- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S +++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S @@ -79,7 +79,7 @@ /* - * Register useage + * Register usage * r8 - temporary * r9 - the driver buffer * r10 - temporary diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index d41fe2d0616a..0ad781db4e66 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -399,7 +399,7 @@ static void __init omap_sx1_init(void) sx1_mmc_init(); /* turn on USB power */ - /* sx1_setusbpower(1); cant do it here because i2c is not ready */ + /* sx1_setusbpower(1); can't do it here because i2c is not ready */ gpio_request(1, "A_IRDA_OFF"); gpio_request(11, "A_SWITCH"); gpio_request(15, "A_USB_ON"); diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index b0f4c231595f..36f26c3fa25e 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -281,7 +281,7 @@ static inline void omap_init_audio(void) {} * Claiming GPIOs, and setting their direction and initial values, is the * responsibility of the device drivers. So is responding to probe(). * - * Board-specific knowlege like creating devices or pin setup is to be + * Board-specific knowledge like creating devices or pin setup is to be * kept out of drivers as much as possible. In particular, pin setup * may be handled by the boot loader, and drivers should expect it will * normally have been done by the time they're probed. diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h index 7a2df29400ca..23eed0035ed8 100644 --- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h +++ b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h @@ -31,7 +31,7 @@ #endif /* - * These are the offsets from the begining of the fiq_buffer. They are put here + * These are the offsets from the beginning of the fiq_buffer. They are put here * since the buffer and header need to be accessed by drivers servicing devices * which generate GPIO interrupts - e.g. keyboard, modem, hook switch. */ diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 5f8a2fd06337..34cf982b9679 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -696,7 +696,7 @@ static void __init igep2_init(void) igep2_init_smsc911x(); /* - * WLAN-BT combo module from MuRata wich has a Marvell WLAN + * WLAN-BT combo module from MuRata which has a Marvell WLAN * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface. */ igep2_wlan_bt_init(); diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c index b10db0e6ee62..2cf86c3cb1a3 100644 --- a/arch/arm/mach-omap2/board-igep0030.c +++ b/arch/arm/mach-omap2/board-igep0030.c @@ -440,7 +440,7 @@ static void __init igep3_init(void) igep3_leds_init(); /* - * WLAN-BT combo module from MuRata wich has a Marvell WLAN + * WLAN-BT combo module from MuRata which has a Marvell WLAN * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface. */ igep3_wifi_bt_init(); diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index ab878545bd9b..6cb6c03293df 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -258,7 +258,7 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm, * clkdm_init - set up the clockdomain layer * @clkdms: optional pointer to an array of clockdomains to register * @init_autodeps: optional pointer to an array of autodeps to register - * @custom_funcs: func pointers for arch specfic implementations + * @custom_funcs: func pointers for arch specific implementations * * Set up internal state. If a pointer to an array of clockdomains * @clkdms was supplied, loop through the list of clockdomains, diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 85b3dce65640..5823584d9cd7 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -125,7 +125,7 @@ struct clockdomain { }; /** - * struct clkdm_ops - Arch specfic function implementations + * struct clkdm_ops - Arch specific function implementations * @clkdm_add_wkdep: Add a wakeup dependency between clk domains * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains * @clkdm_read_wkdep: Read wakeup dependency state between clk domains diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index a44c52303405..1c240eff3918 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -297,8 +297,8 @@ DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); /** * omap3_cpuidle_update_states() - Update the cpuidle states - * @mpu_deepest_state: Enable states upto and including this for mpu domain - * @core_deepest_state: Enable states upto and including this for core domain + * @mpu_deepest_state: Enable states up to and including this for mpu domain + * @core_deepest_state: Enable states up to and including this for core domain * * This goes through the list of states available and enables and disables the * validity of C states based on deepest state that can be achieved for the diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 84d1b735fe80..7b8558564591 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -253,7 +253,7 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data ARRAY_SIZE(omap_keyboard_latency), 0); if (IS_ERR(od)) { - WARN(1, "Cant build omap_device for %s:%s.\n", + WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name); return PTR_ERR(od); } @@ -373,7 +373,7 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused) od = omap_device_build(name, spi_num, oh, pdata, sizeof(*pdata), omap_mcspi_latency, ARRAY_SIZE(omap_mcspi_latency), 0); - WARN(IS_ERR(od), "Cant build omap_device for %s:%s\n", + WARN(IS_ERR(od), "Can't build omap_device for %s:%s\n", name, oh->name); kfree(pdata); return 0; @@ -725,7 +725,7 @@ static int __init omap_init_wdt(void) od = omap_device_build(dev_name, id, oh, NULL, 0, omap_wdt_latency, ARRAY_SIZE(omap_wdt_latency), 0); - WARN(IS_ERR(od), "Cant build omap_device for %s:%s.\n", + WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n", dev_name, oh->name); return 0; } diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 34922b2d2e3f..c9ff0e79703d 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -262,7 +262,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0); kfree(p); if (IS_ERR(od)) { - pr_err("%s: Cant build omap_device for %s:%s.\n", + pr_err("%s: Can't build omap_device for %s:%s.\n", __func__, name, oh->name); return PTR_ERR(od); } diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 413de18c1d2b..9529842ae054 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -82,7 +82,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) kfree(pdata); if (IS_ERR(od)) { - WARN(1, "Cant build omap_device for %s:%s.\n", + WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name); return PTR_ERR(od); } diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 137e1a5f3d85..b2f30bed5a20 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -465,7 +465,7 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data, sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false); if (IS_ERR(od)) { - WARN(1, "Cant build omap_device for %s:%s.\n", name, oh->name); + WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name); kfree(mmc_data->slots[0].name); goto done; } diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 565b9064a328..4a6ef6ab8458 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -149,7 +149,7 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) ARRAY_SIZE(omap2_mcbsp_latency), false); kfree(pdata); if (IS_ERR(od)) { - pr_err("%s: Cant build omap_device for %s:%s.\n", __func__, + pr_err("%s: Can't build omap_device for %s:%s.\n", __func__, name, oh->name); return PTR_ERR(od); } diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index bb043cbb3886..a4ab1e364313 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -518,7 +518,7 @@ static int omap_mux_dbg_board_show(struct seq_file *s, void *unused) seq_printf(s, "/* %s */\n", m->muxnames[mode]); /* - * XXX: Might be revisited to support differences accross + * XXX: Might be revisited to support differences across * same OMAP generation. */ seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def); diff --git a/arch/arm/mach-omap2/mux2430.h b/arch/arm/mach-omap2/mux2430.h index adbea0d03e08..9fd93149ebd9 100644 --- a/arch/arm/mach-omap2/mux2430.h +++ b/arch/arm/mach-omap2/mux2430.h @@ -22,7 +22,7 @@ * absolute addresses. The name in the macro is the mode-0 name of * the pin. NOTE: These registers are 8-bits wide. * - * Note that these defines use SDMMC instead of MMC for compability + * Note that these defines use SDMMC instead of MMC for compatibility * with signal names used in 3630. */ #define OMAP2430_CONTROL_PADCONF_GPMC_CLK_OFFSET 0x000 diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index a860fb5024c2..e6e3810db77f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -1559,7 +1559,7 @@ static struct omap_hwmod omap2430_i2c1_hwmod = { * I2CHS IP's do not follow the usual pattern. * prcm_reg_id alone cannot be used to program * the iclk and fclk. Needs to be handled using - * additonal flags when clk handling is moved + * additional flags when clk handling is moved * to hwmod framework. */ .module_offs = CORE_MOD, diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c index e2e605fe9138..05f6abc96b0d 100644 --- a/arch/arm/mach-omap2/omap_phy_internal.c +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -112,12 +112,12 @@ int omap4430_phy_power(struct device *dev, int ID, int on) else /* * Enable VBUS Valid, AValid and IDDIG - * high impedence + * high impedance */ __raw_writel(IDDIG | AVALID | VBUSVALID, ctrl_base + USBOTGHS_CONTROL); } else { - /* Enable session END and IDIG to high impedence. */ + /* Enable session END and IDIG to high impedance. */ __raw_writel(SESSEND | IDDIG, ctrl_base + USBOTGHS_CONTROL); } diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index 0a8e74e3e811..07d6140baa9d 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c @@ -308,7 +308,7 @@ int __init omap3_twl_init(void) * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages, * in those scenarios this bit is to be cleared (enable = false). * - * Returns 0 on sucess, error is returned if I2C read/write fails. + * Returns 0 on success, error is returned if I2C read/write fails. */ int __init omap3_twl_set_sr_bit(bool enable) { diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 49c6513e90d8..9af08473bf10 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -196,7 +196,7 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) /** * pwrdm_init - set up the powerdomain layer * @pwrdm_list: array of struct powerdomain pointers to register - * @custom_funcs: func pointers for arch specfic implementations + * @custom_funcs: func pointers for arch specific implementations * * Loop through the array of powerdomains @pwrdm_list, registering all * that are available on the current CPU. If pwrdm_list is supplied diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 027f40bd235d..d23d979b9c34 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -121,7 +121,7 @@ struct powerdomain { }; /** - * struct pwrdm_ops - Arch specfic function implementations + * struct pwrdm_ops - Arch specific function implementations * @pwrdm_set_next_pwrst: Set the target power state for a pd * @pwrdm_read_next_pwrst: Read the target power state set for a pd * @pwrdm_read_pwrst: Read the current power state of a pd diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c index 9c9c113788b9..469a920a74dc 100644 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c @@ -72,7 +72,7 @@ static struct powerdomain mpu_3xxx_pwrdm = { /* * The USBTLL Save-and-Restore mechanism is broken on - * 3430s upto ES3.0 and 3630ES1.0. Hence this feature + * 3430s up to ES3.0 and 3630ES1.0. Hence this feature * needs to be disabled on these chips. * Refer: 3430 errata ID i459 and 3630 errata ID i579 * diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 8f674c9442bf..13e24f913dd4 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -247,7 +247,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr) * driver register and sr device intializtion API's. Only one call * will ultimately succeed. * - * Currenly this function registers interrrupt handler for a particular SR + * Currently this function registers interrrupt handler for a particular SR * if smartreflex class driver is already registered and has * requested for interrupts and the SR interrupt line in present. */ diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index c6facf7becf8..6fb520999b6e 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -851,7 +851,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm, * @voltdm: pointer to the VDD whose voltage is to be reset. * * This API finds out the correct voltage the voltage domain is supposed - * to be at and resets the voltage to that level. Should be used expecially + * to be at and resets the voltage to that level. Should be used especially * while disabling any voltage compensation modules. */ void omap_voltage_reset(struct voltagedomain *voltdm) @@ -912,7 +912,7 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm, * This API searches only through the non-compensated voltages int the * voltage table. * Returns pointer to the voltage table entry corresponding to volt on - * sucess. Returns -ENODATA if no voltage table exisits for the passed voltage + * success. Returns -ENODATA if no voltage table exisits for the passed voltage * domain or if there is no matching entry. */ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c index 1a5d6a0e2602..5ceafdccc456 100644 --- a/arch/arm/mach-orion5x/addr-map.c +++ b/arch/arm/mach-orion5x/addr-map.c @@ -19,7 +19,7 @@ #include "common.h" /* - * The Orion has fully programable address map. There's a separate address + * The Orion has fully programmable address map. There's a separate address * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB, * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own * address decode windows that allow it to access any of the Orion resources. diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c index 429ecafe9fdd..a5930f83958b 100644 --- a/arch/arm/mach-orion5x/net2big-setup.c +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -190,7 +190,7 @@ err_free_1: * The power front LEDs (blue and red) and SATA red LEDs are controlled via a * single GPIO line and are compatible with the leds-gpio driver. * - * The SATA blue LEDs have some hardware blink capabilities which are detailled + * The SATA blue LEDs have some hardware blink capabilities which are detailed * in the following array: * * SATAx blue LED | SATAx activity | LED state diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index f0f43e13ac87..e6d64494d3de 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -36,7 +36,7 @@ /**************************************************************************** * 8MiB NOR flash. The struct mtd_partition is not in the same order as the - * partitions on the device because we want to keep compatability with + * partitions on the device because we want to keep compatibility with * existing QNAP firmware. * * Layout as used by QNAP: diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c index 92f393f08fa4..9eac8192d923 100644 --- a/arch/arm/mach-orion5x/ts409-setup.c +++ b/arch/arm/mach-orion5x/ts409-setup.c @@ -56,7 +56,7 @@ /**************************************************************************** * 8MiB NOR flash. The struct mtd_partition is not in the same order as the - * partitions on the device because we want to keep compatability with + * partitions on the device because we want to keep compatibility with * existing QNAP firmware. * * Layout as used by QNAP: diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h index e4fb4668c26e..207ecb49a61b 100644 --- a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h @@ -38,7 +38,7 @@ #define PCMD(x) __REG(0x40F50110 + ((x) << 2)) /* - * Slave Power Managment Unit + * Slave Power Management Unit */ #define ASCR __REG(0x40f40000) /* Application Subsystem Power Status/Configuration */ #define ARSR __REG(0x40f40004) /* Application Subsystem Reset Status */ diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h index faa408ab7ad7..0641f31a56b7 100644 --- a/arch/arm/mach-pxa/include/mach/zeus.h +++ b/arch/arm/mach-pxa/include/mach/zeus.h @@ -64,7 +64,7 @@ /* * CPLD registers: - * Only 4 registers, but spreaded over a 32MB address space. + * Only 4 registers, but spread over a 32MB address space. * Be gentle, and remap that over 32kB... */ diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index dd13bb63259b..23925db8ff74 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -458,7 +458,7 @@ static struct platform_device strataflash = { /* * Suspend/Resume bootstrap management * - * MIO A701 reboot sequence is highly ROM dependant. From the one dissassembled, + * MIO A701 reboot sequence is highly ROM dependent. From the one dissassembled, * this sequence is as follows : * - disables interrupts * - initialize SDRAM (self refresh RAM into active RAM) diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index cf68136cc668..b2b2a5bb275e 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -19,7 +19,7 @@ #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ /* We use `virtual` dma channels to hide the fact we have only a limited - * number of DMA channels, and not of all of them (dependant on the device) + * number of DMA channels, and not of all of them (dependent on the device) * can be attached to any DMA source. We therefore let the DMA core handle * the allocation of hardware channels to clients. */ diff --git a/arch/arm/mach-s3c2410/include/mach/regs-mem.h b/arch/arm/mach-s3c2410/include/mach/regs-mem.h index 7f7c52947963..988a6863e54b 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-mem.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-mem.h @@ -101,7 +101,7 @@ #define S3C2410_BANKCON_PMC16 (0x03) /* bank configurations for banks 0..7, note banks - * 6 and 7 have differnt configurations depending on + * 6 and 7 have different configurations depending on * the memory type bits */ #define S3C2410_BANKCON_Tacp2 (0x0 << 2) diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 66f44440d5d3..079dcaa602d3 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -252,7 +252,7 @@ static struct s3c24xx_led_platdata n30_blue_led_pdata = { .def_trigger = "", }; -/* This is the blue LED on the device. Originaly used to indicate GPS activity +/* This is the blue LED on the device. Originally used to indicate GPS activity * by flashing. */ static struct s3c24xx_led_platdata n35_blue_led_pdata = { .name = "blue_led", diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index dfedc9c9e005..dd3120df09fe 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -155,7 +155,7 @@ static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = { * the same timings, however, anything smaller than 1024x768 * will only be displayed in the top left corner of a 1024x768 * XGA output unless you add optional dip switches to the shield. - * Therefore timings for other resolutions have been ommited here. + * Therefore timings for other resolutions have been omitted here. */ [2] = { _LCD_DECLARE( diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c index c35585cf8c4f..b197171e7d03 100644 --- a/arch/arm/mach-s3c64xx/dma.c +++ b/arch/arm/mach-s3c64xx/dma.c @@ -315,7 +315,7 @@ int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op) case S3C2410_DMAOP_FLUSH: return s3c64xx_dma_flush(chan); - /* belive PAUSE/RESUME are no-ops */ + /* believe PAUSE/RESUME are no-ops */ case S3C2410_DMAOP_PAUSE: case S3C2410_DMAOP_RESUME: case S3C2410_DMAOP_STARTED: diff --git a/arch/arm/mach-s5pc100/include/mach/regs-fb.h b/arch/arm/mach-s5pc100/include/mach/regs-fb.h index 4be4cc9abf75..07aa4d6054fe 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-fb.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-fb.h @@ -29,7 +29,7 @@ #define WPALCON_H (0x19c) #define WPALCON_L (0x1a0) -/* Pallete contro for WPAL0 and WPAL1 is the same as in S3C64xx, but +/* Palette control for WPAL0 and WPAL1 is the same as in S3C64xx, but * different for WPAL2-4 */ /* In WPALCON_L (aka WPALCON) */ diff --git a/arch/arm/mach-s5pc100/setup-sdhci.c b/arch/arm/mach-s5pc100/setup-sdhci.c index f16946e456e9..be25879bb2ee 100644 --- a/arch/arm/mach-s5pc100/setup-sdhci.c +++ b/arch/arm/mach-s5pc100/setup-sdhci.c @@ -40,7 +40,7 @@ void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev, { u32 ctrl2, ctrl3; - /* don't need to alter anything acording to card-type */ + /* don't need to alter anything according to card-type */ writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4); diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h index 1f4b595534c2..a5a1e331f8ed 100644 --- a/arch/arm/mach-s5pv210/include/mach/gpio.h +++ b/arch/arm/mach-s5pv210/include/mach/gpio.h @@ -18,7 +18,7 @@ #define gpio_cansleep __gpio_cansleep #define gpio_to_irq __gpio_to_irq -/* Practically, GPIO banks upto MP03 are the configurable gpio banks */ +/* Practically, GPIO banks up to MP03 are the configurable gpio banks */ /* GPIO bank sizes */ #define S5PV210_GPIO_A0_NR (8) diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c index 746777d56df9..3e3ac05bb7b1 100644 --- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c +++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c @@ -32,10 +32,10 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) switch (width) { case 8: - /* GPG1[3:6] special-funtion 3 */ + /* GPG1[3:6] special-function 3 */ s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3)); case 4: - /* GPG0[3:6] special-funtion 2 */ + /* GPG0[3:6] special-function 2 */ s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2)); default: break; diff --git a/arch/arm/mach-s5pv210/setup-sdhci.c b/arch/arm/mach-s5pv210/setup-sdhci.c index c32e202731c1..a83b6c909f6b 100644 --- a/arch/arm/mach-s5pv210/setup-sdhci.c +++ b/arch/arm/mach-s5pv210/setup-sdhci.c @@ -38,7 +38,7 @@ void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev, { u32 ctrl2, ctrl3; - /* don't need to alter anything acording to card-type */ + /* don't need to alter anything according to card-type */ writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4); diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index e697691eed28..41252d22e659 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -50,7 +50,7 @@ led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o # LEDs support obj-$(CONFIG_LEDS) += $(led-y) -# Miscelaneous functions +# Miscellaneous functions obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_SA1100_SSP) += ssp.o diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index 07d4e8ba3719..aaa8acf76b7b 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -68,7 +68,7 @@ * clock change in ROM and jump to that code from the kernel. The main * disadvantage is that the ROM has to be modified, which is not * possible on all SA-1100 platforms. Another disadvantage is that - * jumping to ROM makes clock switching unecessary complicated. + * jumping to ROM makes clock switching unnecessary complicated. * * The idea behind this driver is that the memory configuration can be * changed while running from DRAM (even with interrupts turned on!) diff --git a/arch/arm/mach-sa1100/include/mach/SA-1100.h b/arch/arm/mach-sa1100/include/mach/SA-1100.h index 4f7ea012e1e5..bae8296f5dbf 100644 --- a/arch/arm/mach-sa1100/include/mach/SA-1100.h +++ b/arch/arm/mach-sa1100/include/mach/SA-1100.h @@ -1794,7 +1794,7 @@ (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \ DDAR_Ser4SSPRc + DDAR_DevAdd (__PREG(Ser4SSDR))) -#define DCSR_RUN 0x00000001 /* DMA RUNing */ +#define DCSR_RUN 0x00000001 /* DMA running */ #define DCSR_IE 0x00000002 /* DMA Interrupt Enable */ #define DCSR_ERROR 0x00000004 /* DMA ERROR */ #define DCSR_DONEA 0x00000008 /* DONE DMA transfer buffer A */ diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index 9d490c66891c..f50b00bd18a0 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c @@ -29,7 +29,7 @@ static unsigned long jornada_ssp_flags; /** * jornada_ssp_reverse - reverses input byte * - * we need to reverse all data we recieve from the mcu due to its physical location + * we need to reverse all data we receive from the mcu due to its physical location * returns : 01110111 -> 11101110 */ u8 inline jornada_ssp_reverse(u8 byte) @@ -179,7 +179,7 @@ static int __devinit jornada_ssp_probe(struct platform_device *dev) static int jornada_ssp_remove(struct platform_device *dev) { - /* Note that this doesnt actually remove the driver, since theres nothing to remove + /* Note that this doesn't actually remove the driver, since theres nothing to remove * It just makes sure everything is turned off */ GPSR = GPIO_GPIO25; ssp_exit(); diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c index e945ae28ee77..f4ef5eb317bd 100644 --- a/arch/arm/mach-tegra/dma.c +++ b/arch/arm/mach-tegra/dma.c @@ -223,7 +223,7 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch, * - Change the source selector to invalid to stop the DMA from * FIFO to memory. * - Read the status register to know the number of pending - * bytes to be transfered. + * bytes to be transferred. * - Finally stop or program the DMA to the next buffer in the * list. */ @@ -244,7 +244,7 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch, if (status & STA_BUSY) req->bytes_transferred -= to_transfer; - /* In continous transfer mode, DMA only tracks the count of the + /* In continuous transfer mode, DMA only tracks the count of the * half DMA buffer. So, if the DMA already finished half the DMA * then add the half buffer to the completed count. * diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h index 39011bd9a925..d0132e8031a1 100644 --- a/arch/arm/mach-tegra/include/mach/dma.h +++ b/arch/arm/mach-tegra/include/mach/dma.h @@ -92,11 +92,11 @@ struct tegra_dma_req { /* This is a called from the DMA ISR context when the DMA is still in * progress and is actively filling same buffer. * - * In case of continous mode receive, this threshold is 1/2 the buffer + * In case of continuous mode receive, this threshold is 1/2 the buffer * size. In other cases, this will not even be called as there is no * hardware support for it. * - * In the case of continous mode receive, if there is next req already + * In the case of continuous mode receive, if there is next req already * queued, DMA programs the HW to use that req when this req is * completed. If there is no "next req" queued, then DMA ISR doesn't do * anything before calling this callback. diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index fabcc49abe80..5535dd0a78c9 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c @@ -263,7 +263,7 @@ static void disable_i2s0_vcxo(void) val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO; writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - /* Deactivate VCXO if noone else is using VCXO */ + /* Deactivate VCXO if no one else is using VCXO */ if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO)) val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); @@ -283,7 +283,7 @@ static void disable_i2s1_vcxo(void) val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO; writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); - /* Deactivate VCXO if noone else is using VCXO */ + /* Deactivate VCXO if no one else is using VCXO */ if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO)) val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); @@ -649,7 +649,7 @@ static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate) */ long clk_round_rate(struct clk *clk, unsigned long rate) { - /* TODO: get apropriate switches for EMIFCLK, AHBCLK and MCLK */ + /* TODO: get appropriate switches for EMIFCLK, AHBCLK and MCLK */ /* Else default to fixed value */ if (clk->round_rate) { diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index dc8746d7826e..af913741e6ec 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -52,7 +52,7 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { * on value present in GpioSel1 to GpioSel6 and AlternatFunction * register. This is the array of 7 configuration settings. * One has to compile time decide these settings. Below is the - * explaination of these setting + * explanation of these setting * GpioSel1 = 0x00 => Pins GPIO1 to GPIO8 are not used as GPIO * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO * GpioSel3 = 0x80 => Pin GPIO24 is configured as GPIO diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 0fefb34c11e4..16647b255378 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -58,7 +58,7 @@ #define U8500_GPIO2_BASE (U8500_PER2_BASE + 0xE000) #define U8500_GPIO3_BASE (U8500_PER5_BASE + 0x1E000) -/* per7 base addressess */ +/* per7 base addresses */ #define U8500_CR_BASE_ED (U8500_PER7_BASE_ED + 0x8000) #define U8500_MTU0_BASE_ED (U8500_PER7_BASE_ED + 0xa000) #define U8500_MTU1_BASE_ED (U8500_PER7_BASE_ED + 0xb000) @@ -68,7 +68,7 @@ #define U8500_UART0_BASE (U8500_PER1_BASE + 0x0000) #define U8500_UART1_BASE (U8500_PER1_BASE + 0x1000) -/* per6 base addressess */ +/* per6 base addresses */ #define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000) #define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000) #define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000) @@ -79,11 +79,11 @@ #define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000) #define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000) -/* per5 base addressess */ +/* per5 base addresses */ #define U8500_USBOTG_BASE (U8500_PER5_BASE + 0x00000) #define U8500_CLKRST5_BASE (U8500_PER5_BASE + 0x1f000) -/* per4 base addressess */ +/* per4 base addresses */ #define U8500_BACKUPRAM0_BASE (U8500_PER4_BASE + 0x00000) #define U8500_BACKUPRAM1_BASE (U8500_PER4_BASE + 0x01000) #define U8500_RTT0_BASE (U8500_PER4_BASE + 0x02000) @@ -106,7 +106,7 @@ #define U8500_SDI5_BASE (U8500_PER3_BASE + 0x8000) #define U8500_CLKRST3_BASE (U8500_PER3_BASE + 0xf000) -/* per2 base addressess */ +/* per2 base addresses */ #define U8500_I2C3_BASE (U8500_PER2_BASE + 0x0000) #define U8500_SPI2_BASE (U8500_PER2_BASE + 0x1000) #define U8500_SPI1_BASE (U8500_PER2_BASE + 0x2000) diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index d3644db467b7..f40c69656d8d 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -32,7 +32,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. * * Size Clean (ticks) Dirty (ticks) * 4096 21 20 21 53 55 54 diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 49c2b66cf3dd..a7b276dbda11 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -34,7 +34,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. * * *** This needs benchmarking */ diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 6136e68ce953..dc18d81ef8ce 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -96,7 +96,7 @@ ENDPROC(v7_flush_dcache_all) * Flush the entire cache system. * The data cache flush is now achieved using atomic clean / invalidates * working outwards from L1 cache. This is done using Set/Way based cache - * maintainance instructions. + * maintenance instructions. * The instruction cache can still be invalidated back to the point of * unification in a single instruction. * diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 226e3d8351c2..6c4e7fd6c8af 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -64,7 +64,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. */ #define CACHE_DLIMIT 32768 diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 86d9c2cf0bce..4ce947c19623 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -64,7 +64,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. */ #define CACHE_DLIMIT 32768 diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 83d3dd34f846..c8884c5413a2 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -53,7 +53,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. */ #define CACHE_DLIMIT 32768 diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 686043ee7281..413684660aad 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -53,7 +53,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. */ #define CACHE_DLIMIT 32768 diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index 665266da143c..7a06e5964f59 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -63,7 +63,7 @@ ENTRY(cpu_arm720_proc_fin) /* * Function: arm720_proc_do_idle(void) * Params : r0 = unused - * Purpose : put the processer in proper idle mode + * Purpose : put the processor in proper idle mode */ ENTRY(cpu_arm720_do_idle) mov pc, lr diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 219980ec8b6e..b46eb21f05c7 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -53,7 +53,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. */ #define CACHE_DLIMIT 65536 diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 36154b1e792a..95ba1fc56e4d 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -54,7 +54,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. (I think this should + * cache line maintenance instructions. (I think this should * be 32768). */ #define CACHE_DLIMIT 8192 diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 89c5e0009c4c..541e4774eea1 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -77,7 +77,7 @@ /* * This is the size at which it becomes more efficient to * clean the whole cache, rather than using the individual - * cache line maintainence instructions. + * cache line maintenance instructions. */ #define CACHE_DLIMIT 8192 diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index e32fa499194c..34261f9486b9 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -85,7 +85,7 @@ /* * Sanity check the PTE configuration for the code below - which makes - * certain assumptions about how these bits are layed out. + * certain assumptions about how these bits are laid out. */ #ifdef CONFIG_MMU #if L_PTE_SHARED != PTE_EXT_SHARED diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 832b6bdc192c..bfa0c9f611c5 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -132,7 +132,7 @@ ENTRY(cpu_v6_do_suspend) mrc p15, 0, r6, c3, c0, 0 @ Domain ID mrc p15, 0, r7, c2, c0, 0 @ Translation table base 0 mrc p15, 0, r8, c2, c0, 1 @ Translation table base 1 - mrc p15, 0, r9, c1, c0, 1 @ auxillary control register + mrc p15, 0, r9, c1, c0, 1 @ auxiliary control register mrc p15, 0, r10, c1, c0, 2 @ co-processor access control mrc p15, 0, r11, c1, c0, 0 @ control register stmia r0, {r4 - r11} @@ -151,7 +151,7 @@ ENTRY(cpu_v6_do_resume) mcr p15, 0, r6, c3, c0, 0 @ Domain ID mcr p15, 0, r7, c2, c0, 0 @ Translation table base 0 mcr p15, 0, r8, c2, c0, 1 @ Translation table base 1 - mcr p15, 0, r9, c1, c0, 1 @ auxillary control register + mcr p15, 0, r9, c1, c0, 1 @ auxiliary control register mcr p15, 0, r10, c1, c0, 2 @ co-processor access control mcr p15, 0, ip, c2, c0, 2 @ TTB control register mcr p15, 0, ip, c7, c5, 4 @ ISB diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 262fa88a7439..c35618e42f6f 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -237,7 +237,7 @@ ENTRY(cpu_v7_do_resume) mcr p15, 0, r7, c2, c0, 0 @ TTB 0 mcr p15, 0, r8, c2, c0, 1 @ TTB 1 mcr p15, 0, ip, c2, c0, 2 @ TTB control register - mcr p15, 0, r10, c1, c0, 1 @ Auxillary control register + mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register mcr p15, 0, r11, c1, c0, 2 @ Co-processor access control ldr r4, =PRRR @ PRRR ldr r5, =NMRR @ NMRR diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index ce81481becf1..4268a2bdf145 100644 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -13,7 +13,7 @@ /* * A driver for the Freescale Semiconductor i.MXC CPUfreq module. - * The CPUFREQ driver is for controling CPU frequency. It allows you to change + * The CPUFREQ driver is for controlling CPU frequency. It allows you to change * the CPU clock speed on the fly. */ diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S index bd9bb9799141..2e49e71b1b98 100644 --- a/arch/arm/plat-mxc/include/mach/entry-macro.S +++ b/arch/arm/plat-mxc/include/mach/entry-macro.S @@ -33,9 +33,9 @@ .macro arch_ret_to_user, tmp1, tmp2 .endm - @ this macro checks which interrupt occured + @ this macro checks which interrupt occurred @ and returns its number in irqnr - @ and returns if an interrupt occured in irqstat + @ and returns if an interrupt occurred in irqstat .macro get_irqnr_and_base, irqnr, irqstat, base, tmp #ifndef CONFIG_MXC_TZIC @ Load offset & priority of the highest priority diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h index 04c0d060d814..6bb96ef1600b 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_nand.h +++ b/arch/arm/plat-mxc/include/mach/mxc_nand.h @@ -24,7 +24,7 @@ struct mxc_nand_platform_data { unsigned int width; /* data bus width in bytes */ - unsigned int hw_ecc:1; /* 0 if supress hardware ECC */ + unsigned int hw_ecc:1; /* 0 if suppress hardware ECC */ unsigned int flash_bbt:1; /* set to 1 to use a flash based bbt */ struct mtd_partition *parts; /* partition table */ int nr_parts; /* size of parts */ diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 7d9f815cedec..ea28f98d5d6a 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -280,7 +280,7 @@ EXPORT_SYMBOL(omap_dsp_get_mempool_base); * Claiming GPIOs, and setting their direction and initial values, is the * responsibility of the device drivers. So is responding to probe(). * - * Board-specific knowlege like creating devices or pin setup is to be + * Board-specific knowledge like creating devices or pin setup is to be * kept out of drivers as much as possible. In particular, pin setup * may be handled by the boot loader, and drivers should expect it will * normally have been done by the time they're probed. diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 2ec3b5d9f214..c22217c2ee5f 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1019,7 +1019,7 @@ EXPORT_SYMBOL(omap_set_dma_callback); * If the channel is running the caller must disable interrupts prior calling * this function and process the returned value before re-enabling interrupt to * prevent races with the interrupt handler. Note that in continuous mode there - * is a chance for CSSA_L register overflow inbetween the two reads resulting + * is a chance for CSSA_L register overflow between the two reads resulting * in incorrect return value. */ dma_addr_t omap_get_dma_src_pos(int lch) @@ -1046,7 +1046,7 @@ EXPORT_SYMBOL(omap_get_dma_src_pos); * If the channel is running the caller must disable interrupts prior calling * this function and process the returned value before re-enabling interrupt to * prevent races with the interrupt handler. Note that in continuous mode there - * is a chance for CDSA_L register overflow inbetween the two reads resulting + * is a chance for CDSA_L register overflow between the two reads resulting * in incorrect return value. */ dma_addr_t omap_get_dma_dst_pos(int lch) diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index d6f9fa0f62af..cac2e8ac6968 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -93,7 +93,7 @@ extern void omap_gpio_restore_context(void); /* Wrappers for "new style" GPIO calls, using the new infrastructure * which lets us plug in FPGA, I2C, and other implementations. * * - * The original OMAP-specfic calls should eventually be removed. + * The original OMAP-specific calls should eventually be removed. */ #include diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 12b316165037..1527929b445a 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -90,7 +90,7 @@ enum omap_ecc { /* 1-bit ecc: stored at end of spare area */ OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */ OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ - /* 1-bit ecc: stored at begining of spare area as romcode */ + /* 1-bit ecc: stored at beginning of spare area as romcode */ OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ }; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index d598d9fd65ac..5587acf0eb2c 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -1103,7 +1103,7 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf) /* resend */ return -1; } else { - /* wait for recieve confirmation */ + /* wait for receive confirmation */ int attemps = 0; while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) { if (attemps++ > 1000) { diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h index 75f656471240..89e68e07b0a8 100644 --- a/arch/arm/plat-pxa/include/plat/mfp.h +++ b/arch/arm/plat-pxa/include/plat/mfp.h @@ -434,7 +434,7 @@ typedef unsigned long mfp_cfg_t; * * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which * represents a range of MFP pins from "start" to "end", with the offset - * begining at "offset", to define a single pin, let "end" = -1. + * beginning at "offset", to define a single pin, let "end" = -1. * * use * diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index c2064c308719..0291bd6e236e 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o obj-$(CONFIG_CPU_FREQ_S3C24XX) += cpu-freq.o obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpu-freq-debugfs.o -# Architecture dependant builds +# Architecture dependent builds obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/plat-s3c24xx/cpu-freq.c b/arch/arm/plat-s3c24xx/cpu-freq.c index eea75ff81d15..b3d3d0278997 100644 --- a/arch/arm/plat-s3c24xx/cpu-freq.c +++ b/arch/arm/plat-s3c24xx/cpu-freq.c @@ -455,7 +455,7 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy) /* whilst we will be called later on, we try and re-set the * cpu frequencies as soon as possible so that we do not end - * up resuming devices and then immediatley having to re-set + * up resuming devices and then immediately having to re-set * a number of settings once these devices have restarted. * * as a note, it is expected devices are not used until they diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 6ad274e7593d..27ea852e3370 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -557,7 +557,7 @@ s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) break; case S3C2410_DMALOAD_1LOADED_1RUNNING: - /* I belive in this case we do not have anything to do + /* I believe in this case we do not have anything to do * until the next buffer comes along, and we turn off the * reload */ return; diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c index 46dd078147d8..cd6d67c8382a 100644 --- a/arch/arm/plat-s5p/irq-gpioint.c +++ b/arch/arm/plat-s5p/irq-gpioint.c @@ -208,7 +208,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) } /* - * chained GPIO irq has been sucessfully registered, allocate new gpio + * chained GPIO irq has been successfully registered, allocate new gpio * int group and assign irq nubmers */ diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index 9a82b8874918..983c578b8276 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h @@ -21,7 +21,7 @@ struct clk; * @set_parent: set the clock's parent, see clk_set_parent(). * * Group the common clock implementations together so that we - * don't have to keep setting the same fiels again. We leave + * don't have to keep setting the same fields again. We leave * enable in struct clk. * * Adding an extra layer of indirection into the process should diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index 5603db0b79bc..3ad8386599c3 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h @@ -114,7 +114,7 @@ extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, * of control per GPIO, generally in the form of: * 0000 = Input * 0001 = Output - * others = Special functions (dependant on bank) + * others = Special functions (dependent on bank) * * Note, since the code to deal with the case where there are two control * registers instead of one, we do not have a separate set of functions for diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 5e04fa6eda74..1762dcb4cb9e 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -125,7 +125,7 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, * * These values control the state of the weak pull-{up,down} resistors * available on most pins on the S3C series. Not all chips support both - * up or down settings, and it may be dependant on the chip that is being + * up or down settings, and it may be dependent on the chip that is being * used to whether the particular mode is available. */ #define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00) @@ -138,7 +138,7 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, * @pull: The configuration for the pull resistor. * * This function sets the state of the pull-{up,down} resistor for the - * specified pin. It will return 0 if successfull, or a negative error + * specified pin. It will return 0 if successful, or a negative error * code if the pin cannot support the requested pull setting. * * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP. @@ -202,7 +202,7 @@ extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin); * @drvstr: The new value of the driver strength * * This function sets the driver strength value for the specified pin. - * It will return 0 if successfull, or a negative error code if the pin + * It will return 0 if successful, or a negative error code if the pin * cannot support the requested setting. */ extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index dac35d0a711d..8cad4cf19c3c 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -108,7 +108,7 @@ extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip); * of control per GPIO, generally in the form of: * 0000 = Input * 0001 = Output - * others = Special functions (dependant on bank) + * others = Special functions (dependent on bank) * * Note, since the code to deal with the case where there are two control * registers instead of one, we do not have a separate set of function diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index b0bdf16549d5..058e09654fe8 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h @@ -57,7 +57,7 @@ enum clk_types { * @cfg_gpio: Configure the GPIO for a specific card bit-width * @cfg_card: Configure the interface for a specific card and speed. This * is necessary the controllers and/or GPIO blocks require the - * changing of driver-strength and other controls dependant on + * changing of driver-strength and other controls dependent on * the card and speed of operation. * * Initialisation data specific to either the machine or the platform @@ -108,7 +108,7 @@ extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata; extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata; extern struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata; -/* Helper function availablity */ +/* Helper function availability */ extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w); extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w); diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c index b4ff8d74ac40..f85638c6f5ae 100644 --- a/arch/arm/plat-samsung/s3c-pl330.c +++ b/arch/arm/plat-samsung/s3c-pl330.c @@ -68,7 +68,7 @@ struct s3c_pl330_xfer { * @req: Two requests to communicate with the PL330 engine. * @callback_fn: Callback function to the client. * @rqcfg: Channel configuration for the xfers. - * @xfer_head: Pointer to the xfer to be next excecuted. + * @xfer_head: Pointer to the xfer to be next executed. * @dmac: Pointer to the DMAC that manages this channel, NULL if the * channel is available to be acquired. * @client: Client of this channel. NULL if the diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h index 2ae6606930a6..fcc0d0ad4a1f 100644 --- a/arch/arm/plat-spear/include/plat/clock.h +++ b/arch/arm/plat-spear/include/plat/clock.h @@ -89,7 +89,7 @@ struct rate_config { * @sibling: node for list of clocks having same parents * @private_data: clock specific private data * @node: list to maintain clocks linearly - * @cl: clocklook up assoicated with this clock + * @cl: clocklook up associated with this clock * @dent: object for debugfs */ struct clk { diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index acb83799a215..2641731f24cd 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -59,7 +59,7 @@ config EXACT_HWERR be reported multiple cycles after the error happens. This delay can cause the wrong application, or even the kernel to receive a signal to be killed. If you are getting HW errors in your system, - try turning this on to ensure they are at least comming from the + try turning this on to ensure they are at least coming from the proper thread. On production systems, it is safe (and a small optimization) to say N. diff --git a/arch/blackfin/include/asm/traps.h b/arch/blackfin/include/asm/traps.h index 9fe0da612c09..70c4e511cae6 100644 --- a/arch/blackfin/include/asm/traps.h +++ b/arch/blackfin/include/asm/traps.h @@ -57,7 +57,7 @@ #define HWC_x3(level) \ "External Memory Addressing Error\n" #define EXC_0x04(level) \ - "Unimplmented exception occured\n" \ + "Unimplmented exception occurred\n" \ level " - Maybe you forgot to install a custom exception handler?\n" #define HWC_x12(level) \ "Performance Monitor Overflow\n" diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index b8cfe34989e4..9b80b152435e 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -181,7 +181,7 @@ static int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type) return -ENOSPC; } - /* Becasue hardware data watchpoint impelemented in current + /* Because hardware data watchpoint impelemented in current * Blackfin can not trigger an exception event as the hardware * instrction watchpoint does, we ignaore all data watch point here. * They can be turned on easily after future blackfin design diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 59c1df75e4de..655f25d139a7 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -98,7 +98,7 @@ asmlinkage notrace void trap_c(struct pt_regs *fp) /* send the appropriate signal to the user program */ switch (trapnr) { - /* This table works in conjuction with the one in ./mach-common/entry.S + /* This table works in conjunction with the one in ./mach-common/entry.S * Some exceptions are handled there (in assembly, in exception space) * Some are handled here, (in C, in interrupt space) * Some, like CPLB, are handled in both, where the normal path is diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S index 3edbd8db6598..79caccea85ca 100644 --- a/arch/blackfin/lib/ins.S +++ b/arch/blackfin/lib/ins.S @@ -67,7 +67,7 @@ * - DMA version, which do not suffer from this issue. DMA versions have * different name (prefixed by dma_ ), and are located in * ../kernel/bfin_dma_5xx.c - * Using the dma related functions are recommended for transfering large + * Using the dma related functions are recommended for transferring large * buffers in/out of FIFOs. */ diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S index 80c240acac60..4eca566237a4 100644 --- a/arch/blackfin/lib/memmove.S +++ b/arch/blackfin/lib/memmove.S @@ -60,7 +60,7 @@ ENTRY(_memmove) [P0++] = R1; CC = P2 == 0; /* any remaining bytes? */ - P3 = I0; /* Ammend P3 to updated ptr. */ + P3 = I0; /* Amend P3 to updated ptr. */ IF !CC JUMP .Lbytes; P3 = I1; RTS; diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 2c69785a7bbe..3fa335405b31 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -2530,7 +2530,7 @@ static struct resource bfin_pata_resources[] = { static struct pata_platform_info bfin_pata_platform_data = { .ioport_shift = 0, }; -/* CompactFlash Storage Card Memory Mapped Adressing +/* CompactFlash Storage Card Memory Mapped Addressing * /REG = A11 = 1 */ static struct resource bfin_pata_resources[] = { diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 46ab45704c89..f96933f48a7f 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -268,7 +268,7 @@ ENTRY(_handle_bad_cplb) /* To get here, we just tried and failed to change a CPLB * so, handle things in trap_c (C code), by lowering to * IRQ5, just like we normally do. Since this is not a - * "normal" return path, we have a do alot of stuff to + * "normal" return path, we have a do a lot of stuff to * the stack to get ready so, we can fall through - we * need to make a CPLB exception look like a normal exception */ @@ -817,7 +817,7 @@ _new_old_task: rets = [sp++]; /* - * When we come out of resume, r0 carries "old" task, becuase we are + * When we come out of resume, r0 carries "old" task, because we are * in "new" task. */ rts; diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 581e2b0a71ac..76de5724c1e3 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -174,7 +174,7 @@ ENTRY(__start) sp.l = lo(KERNEL_CLOCK_STACK); sp.h = hi(KERNEL_CLOCK_STACK); call _init_clocks; - sp = usp; /* usp hasnt been touched, so restore from there */ + sp = usp; /* usp hasn't been touched, so restore from there */ #endif /* This section keeps the processor in supervisor mode diff --git a/arch/cris/arch-v10/README.mm b/arch/cris/arch-v10/README.mm index 517d1f027fe8..67731d75cb51 100644 --- a/arch/cris/arch-v10/README.mm +++ b/arch/cris/arch-v10/README.mm @@ -38,7 +38,7 @@ space. We also use it to keep the user-mode virtual mapping in the same map during kernel-mode, so that the kernel easily can access the corresponding user-mode process' data. -As a comparision, the Linux/i386 2.0 puts the kernel and physical RAM at +As a comparison, the Linux/i386 2.0 puts the kernel and physical RAM at address 0, overlapping with the user-mode virtual space, so that descriptor registers are needed for each memory access to specify which MMU space to map through. That changed in 2.2, putting the kernel/physical RAM at diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c index 399dc1ec8e6f..850265373611 100644 --- a/arch/cris/arch-v10/drivers/sync_serial.c +++ b/arch/cris/arch-v10/drivers/sync_serial.c @@ -31,7 +31,7 @@ #include #include -/* The receiver is a bit tricky beacuse of the continuous stream of data.*/ +/* The receiver is a bit tricky because of the continuous stream of data.*/ /* */ /* Three DMA descriptors are linked together. Each DMA descriptor is */ /* responsible for port->bufchunk of a common buffer. */ diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c index 3d751250271b..7b155f8203b8 100644 --- a/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/arch/cris/arch-v32/drivers/axisflashmap.c @@ -215,7 +215,7 @@ static struct mtd_partition main_partition = { }; #endif -/* Auxilliary partition if we find another flash */ +/* Auxiliary partition if we find another flash */ static struct mtd_partition aux_partition = { .name = "aux", .size = 0, diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c index 25d6f2b3a721..f58f2c1c5295 100644 --- a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c +++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c @@ -165,7 +165,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void) /* Enable the following for a flash based bad block table */ /* this->options = NAND_USE_FLASH_BBT; */ - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(crisv32_mtd, 1)) { err = -ENXIO; goto out_mtd; diff --git a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c index c5a0f54763cc..d5b0cc9f976b 100644 --- a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c +++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c @@ -156,7 +156,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void) /* Enable the following for a flash based bad block table */ /* this->options = NAND_USE_FLASH_BBT; */ - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(crisv32_mtd, 1)) { err = -ENXIO; goto out_ior; diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index c8637a9195ea..a6a180bc566f 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c @@ -33,7 +33,7 @@ #include -/* The receiver is a bit tricky beacuse of the continuous stream of data.*/ +/* The receiver is a bit tricky because of the continuous stream of data.*/ /* */ /* Three DMA descriptors are linked together. Each DMA descriptor is */ /* responsible for port->bufchunk of a common buffer. */ diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 0ecb50b8f0d9..3abf12c23e5f 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -182,7 +182,7 @@ _syscall_traced: move.d $r0, [$sp] ;; The registers carrying parameters (R10-R13) are intact. The optional - ;; fifth and sixth parameters is in MOF and SRP respectivly. Put them + ;; fifth and sixth parameters is in MOF and SRP respectively. Put them ;; back on the stack. subq 4, $sp move $srp, [$sp] diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c index 8023176e19b2..68a1a5901ca5 100644 --- a/arch/cris/arch-v32/kernel/irq.c +++ b/arch/cris/arch-v32/kernel/irq.c @@ -374,7 +374,7 @@ crisv32_do_multiple(struct pt_regs* regs) irq_enter(); for (i = 0; i < NBR_REGS; i++) { - /* Get which IRQs that happend. */ + /* Get which IRQs that happened. */ masked[i] = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], r_masked_vect, i); diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c index 6b653323d796..c0343c3ea7f8 100644 --- a/arch/cris/arch-v32/kernel/kgdb.c +++ b/arch/cris/arch-v32/kernel/kgdb.c @@ -925,7 +925,7 @@ stub_is_stopped(int sigval) if (reg.eda >= bp_d_regs[bp * 2] && reg.eda <= bp_d_regs[bp * 2 + 1]) { - /* EDA withing range for this BP; it must be the one + /* EDA within range for this BP; it must be the one we're looking for. */ stopped_data_address = reg.eda; break; diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 562f84718906..0570e8ce603d 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c @@ -149,7 +149,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ /* Set a new TLS ? - * The TLS is in $mof beacuse it is the 5th argument to sys_clone. + * The TLS is in $mof because it is the 5th argument to sys_clone. */ if (p->mm && (clone_flags & CLONE_SETTLS)) { task_thread_info(p)->tls = regs->mof; diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index b3a05ae56214..ce4ab1a5552c 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -610,7 +610,7 @@ ugdb_trap_user(struct thread_info *ti, int sig) user_regs(ti)->spc = 0; } /* FIXME: Filter out false h/w breakpoint hits (i.e. EDA - not withing any configured h/w breakpoint range). Synchronize with + not within any configured h/w breakpoint range). Synchronize with what already exists for kernel debugging. */ if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) { /* Break 8: subtract 2 from ERP unless in a delay slot. */ diff --git a/arch/cris/arch-v32/mach-a3/arbiter.c b/arch/cris/arch-v32/mach-a3/arbiter.c index 8b924db71c9a..15f5c9de2639 100644 --- a/arch/cris/arch-v32/mach-a3/arbiter.c +++ b/arch/cris/arch-v32/mach-a3/arbiter.c @@ -568,7 +568,7 @@ crisv32_foo_arbiter_irq(int irq, void *dev_id) REG_WR(marb_foo_bp, watch->instance, rw_ack, ack); REG_WR(marb_foo, regi_marb_foo, rw_ack_intr, ack_intr); - printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs()); + printk(KERN_DEBUG "IRQ occurred at %X\n", (unsigned)get_irq_regs()); if (watch->cb) watch->cb(); @@ -624,7 +624,7 @@ crisv32_bar_arbiter_irq(int irq, void *dev_id) REG_WR(marb_bar_bp, watch->instance, rw_ack, ack); REG_WR(marb_bar, regi_marb_bar, rw_ack_intr, ack_intr); - printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs()->erp); + printk(KERN_DEBUG "IRQ occurred at %X\n", (unsigned)get_irq_regs()->erp); if (watch->cb) watch->cb(); diff --git a/arch/cris/arch-v32/mach-fs/arbiter.c b/arch/cris/arch-v32/mach-fs/arbiter.c index 82ef293c4c81..3f8ebb5c1477 100644 --- a/arch/cris/arch-v32/mach-fs/arbiter.c +++ b/arch/cris/arch-v32/mach-fs/arbiter.c @@ -395,7 +395,7 @@ static irqreturn_t crisv32_arbiter_irq(int irq, void *dev_id) REG_WR(marb_bp, watch->instance, rw_ack, ack); REG_WR(marb, regi_marb, rw_ack_intr, ack_intr); - printk(KERN_INFO "IRQ occured at %lX\n", get_irq_regs()->erp); + printk(KERN_INFO "IRQ occurred at %lX\n", get_irq_regs()->erp); if (watch->cb) watch->cb(); diff --git a/arch/cris/boot/rescue/head_v10.S b/arch/cris/boot/rescue/head_v10.S index 2fafe247a25b..af55df0994b3 100644 --- a/arch/cris/boot/rescue/head_v10.S +++ b/arch/cris/boot/rescue/head_v10.S @@ -7,7 +7,7 @@ * for each partition that this code should check. * * If any of the checksums fail, we assume the flash is so - * corrupt that we cant use it to boot into the ftp flash + * corrupt that we can't use it to boot into the ftp flash * loader, and instead we initialize the serial port to * receive a flash-loader and new flash image. we dont include * any flash code here, but just accept a certain amount of diff --git a/arch/cris/include/arch-v32/arch/hwregs/Makefile b/arch/cris/include/arch-v32/arch/hwregs/Makefile index f9a05d2aa061..b8b3f8d666e4 100644 --- a/arch/cris/include/arch-v32/arch/hwregs/Makefile +++ b/arch/cris/include/arch-v32/arch/hwregs/Makefile @@ -1,6 +1,6 @@ # Makefile to generate or copy the latest register definitions # and related datastructures and helpermacros. -# The offical place for these files is at: +# The official place for these files is at: RELEASE ?= r1_alfa5 OFFICIAL_INCDIR = /n/asic/projects/guinness/releases/$(RELEASE)/design/top/sw/include/ diff --git a/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile b/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile index a90056a095e3..0747a22e3c07 100644 --- a/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile +++ b/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile @@ -1,7 +1,7 @@ # $Id: Makefile,v 1.3 2004/01/07 20:34:55 johana Exp $ # Makefile to generate or copy the latest register definitions # and related datastructures and helpermacros. -# The offical place for these files is probably at: +# The official place for these files is probably at: RELEASE ?= r1_alfa5 IOPOFFICIAL_INCDIR = /n/asic/projects/guinness/releases/$(RELEASE)/design/top/sw/include/ diff --git a/arch/cris/include/asm/pgtable.h b/arch/cris/include/asm/pgtable.h index 9eaae217b21b..7df430138355 100644 --- a/arch/cris/include/asm/pgtable.h +++ b/arch/cris/include/asm/pgtable.h @@ -97,7 +97,7 @@ extern unsigned long empty_zero_page; #define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) #define pmd_none(x) (!pmd_val(x)) -/* by removing the _PAGE_KERNEL bit from the comparision, the same pmd_bad +/* by removing the _PAGE_KERNEL bit from the comparison, the same pmd_bad * works for both _PAGE_TABLE and _KERNPG_TABLE pmd entries. */ #define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_KERNEL)) != _PAGE_TABLE) diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c index 541efbf09371..8da53f34c7a7 100644 --- a/arch/cris/kernel/traps.c +++ b/arch/cris/kernel/traps.c @@ -183,7 +183,7 @@ __initcall(oops_nmi_register); /* * This gets called from entry.S when the watchdog has bitten. Show something - * similiar to an Oops dump, and if the kernel is configured to be a nice + * similar to an Oops dump, and if the kernel is configured to be a nice * doggy, then halt instead of reboot. */ void diff --git a/arch/frv/include/asm/pci.h b/arch/frv/include/asm/pci.h index 0d5997909850..ef03baf5d89d 100644 --- a/arch/frv/include/asm/pci.h +++ b/arch/frv/include/asm/pci.h @@ -54,7 +54,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, #endif /* - * These are pretty much arbitary with the CoMEM implementation. + * These are pretty much arbitrary with the CoMEM implementation. * We have the whole address space to ourselves. */ #define PCIBIOS_MIN_IO 0x100 diff --git a/arch/frv/include/asm/spr-regs.h b/arch/frv/include/asm/spr-regs.h index 01e6af5e99b8..d3883021f236 100644 --- a/arch/frv/include/asm/spr-regs.h +++ b/arch/frv/include/asm/spr-regs.h @@ -274,7 +274,7 @@ #define MSR0_RD 0xc0000000 /* rounding mode */ #define MSR0_RD_NEAREST 0x00000000 /* - nearest */ #define MSR0_RD_ZERO 0x40000000 /* - zero */ -#define MSR0_RD_POS_INF 0x80000000 /* - postive infinity */ +#define MSR0_RD_POS_INF 0x80000000 /* - positive infinity */ #define MSR0_RD_NEG_INF 0xc0000000 /* - negative infinity */ /* diff --git a/arch/frv/include/asm/virtconvert.h b/arch/frv/include/asm/virtconvert.h index 59788fa2a813..b26d70ab9111 100644 --- a/arch/frv/include/asm/virtconvert.h +++ b/arch/frv/include/asm/virtconvert.h @@ -1,4 +1,4 @@ -/* virtconvert.h: virtual/physical/page address convertion +/* virtconvert.h: virtual/physical/page address conversion * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) diff --git a/arch/frv/kernel/entry-table.S b/arch/frv/kernel/entry-table.S index bf35f33e48c9..06c5ae191e59 100644 --- a/arch/frv/kernel/entry-table.S +++ b/arch/frv/kernel/entry-table.S @@ -86,7 +86,7 @@ __break_usertrap_fixup_table: .globl __break_kerneltrap_fixup_table __break_kerneltrap_fixup_table: - # handler declaration for a sofware or program interrupt + # handler declaration for a software or program interrupt .macro VECTOR_SOFTPROG tbr_tt, vec .section .trap.user .org \tbr_tt @@ -145,7 +145,7 @@ __break_kerneltrap_fixup_table: .long \vec .endm - # handler declaration for an MMU only sofware or program interrupt + # handler declaration for an MMU only software or program interrupt .macro VECTOR_SP_MMU tbr_tt, vec #ifdef CONFIG_MMU VECTOR_SOFTPROG \tbr_tt, \vec diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index c4ea0925cdbd..e5cc56ae6ce3 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -414,11 +414,11 @@ config PERMIT_BSP_REMOVE support. config FORCE_CPEI_RETARGET - bool "Force assumption that CPEI can be re-targetted" + bool "Force assumption that CPEI can be re-targeted" depends on PERMIT_BSP_REMOVE default n ---help--- - Say Y if you need to force the assumption that CPEI can be re-targetted to + Say Y if you need to force the assumption that CPEI can be re-targeted to any cpu in the system. This hint is available via ACPI 3.0 specifications. Tiger4 systems are capable of re-directing CPEI to any CPU other than BSP. This option it useful to enable this feature on older BIOS's as well. diff --git a/arch/ia64/include/asm/pal.h b/arch/ia64/include/asm/pal.h index 6a292505b396..2e69284df8e7 100644 --- a/arch/ia64/include/asm/pal.h +++ b/arch/ia64/include/asm/pal.h @@ -1669,7 +1669,7 @@ typedef union pal_vp_info_u { } pal_vp_info_u_t; /* - * Returns infomation about virtual processor features + * Returns information about virtual processor features */ static inline s64 ia64_pal_vp_info (u64 feature_set, u64 vp_buffer, u64 *vp_info, u64 *vmm_id) diff --git a/arch/ia64/include/asm/perfmon_default_smpl.h b/arch/ia64/include/asm/perfmon_default_smpl.h index 74724b24c2b7..a2d560c67230 100644 --- a/arch/ia64/include/asm/perfmon_default_smpl.h +++ b/arch/ia64/include/asm/perfmon_default_smpl.h @@ -67,8 +67,8 @@ typedef struct { unsigned long ip; /* where did the overflow interrupt happened */ unsigned long tstamp; /* ar.itc when entering perfmon intr. handler */ - unsigned short cpu; /* cpu on which the overflow occured */ - unsigned short set; /* event set active when overflow ocurred */ + unsigned short cpu; /* cpu on which the overflow occurred */ + unsigned short set; /* event set active when overflow occurred */ int tgid; /* thread group id (for NPTL, this is getpid()) */ } pfm_default_smpl_entry_t; diff --git a/arch/ia64/include/asm/sn/bte.h b/arch/ia64/include/asm/sn/bte.h index 96798d2da7c2..cc6c4dbf53af 100644 --- a/arch/ia64/include/asm/sn/bte.h +++ b/arch/ia64/include/asm/sn/bte.h @@ -216,7 +216,7 @@ extern void bte_error_handler(unsigned long); bte_copy(0, dest, len, ((mode) | BTE_ZERO_FILL), notification) /* - * The following is the prefered way of calling bte_unaligned_copy + * The following is the preferred way of calling bte_unaligned_copy * If the copy is fully cache line aligned, then bte_copy is * used instead. Since bte_copy is inlined, this saves a call * stack. NOTE: bte_copy is called synchronously and does block diff --git a/arch/ia64/include/asm/sn/shub_mmr.h b/arch/ia64/include/asm/sn/shub_mmr.h index 7de1d1d4b71a..a84d870f4294 100644 --- a/arch/ia64/include/asm/sn/shub_mmr.h +++ b/arch/ia64/include/asm/sn/shub_mmr.h @@ -459,7 +459,7 @@ /* ==================================================================== */ /* Some MMRs are functionally identical (or close enough) on both SHUB1 */ /* and SHUB2 that it makes sense to define a geberic name for the MMR. */ -/* It is acceptible to use (for example) SH_IPI_INT to reference the */ +/* It is acceptable to use (for example) SH_IPI_INT to reference the */ /* the IPI MMR. The value of SH_IPI_INT is determined at runtime based */ /* on the type of the SHUB. Do not use these #defines in performance */ /* critical code or loops - there is a small performance penalty. */ diff --git a/arch/ia64/include/asm/sn/shubio.h b/arch/ia64/include/asm/sn/shubio.h index 6052422a22b3..ecb8a49476b6 100644 --- a/arch/ia64/include/asm/sn/shubio.h +++ b/arch/ia64/include/asm/sn/shubio.h @@ -1383,7 +1383,7 @@ typedef union ii_ibcr_u { * response is capture in IXSM and IXSS, and IXSS[VALID] is set. The * * errant header is thereby captured, and no further spurious read * * respones are captured until IXSS[VALID] is cleared by setting the * - * appropriate bit in IECLR.Everytime a spurious read response is * + * appropriate bit in IECLR. Every time a spurious read response is * * detected, the SPUR_RD bit of the PRB corresponding to the incoming * * message's SIDN field is set. This always happens, regarless of * * whether a header is captured. The programmer should check * @@ -2738,7 +2738,7 @@ typedef union ii_ippr_u { /************************************************************************ * * * The following defines which were not formed into structures are * - * probably indentical to another register, and the name of the * + * probably identical to another register, and the name of the * * register is provided against each of these registers. This * * information needs to be checked carefully * * * diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c index d52f1f78eff2..1b811c61bdc6 100644 --- a/arch/ia64/kernel/cyclone.c +++ b/arch/ia64/kernel/cyclone.c @@ -31,7 +31,7 @@ static struct clocksource clocksource_cyclone = { .rating = 300, .read = read_cyclone, .mask = (1LL << 40) - 1, - .mult = 0, /*to be caluclated*/ + .mult = 0, /*to be calculated*/ .shift = 16, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; diff --git a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c index 5f637bbfcccd..30c644ea44c9 100644 --- a/arch/ia64/kernel/perfmon_default_smpl.c +++ b/arch/ia64/kernel/perfmon_default_smpl.c @@ -150,7 +150,7 @@ default_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg, struct * current = task running at the time of the overflow. * * per-task mode: - * - this is ususally the task being monitored. + * - this is usually the task being monitored. * Under certain conditions, it might be a different task * * system-wide: diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 44f11ee411c0..14ec641003da 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -703,7 +703,7 @@ int migrate_platform_irqs(unsigned int cpu) data->chip->irq_disable(data); data->chip->irq_set_affinity(data, mask, false); data->chip->irq_enable(data); - printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu); + printk ("Re-targeting CPEI to cpu %d\n", new_cpei_cpu); } } if (!data) { diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 0baa1bbb65fe..0e0e0cc9e392 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -43,7 +43,7 @@ int __ref arch_register_cpu(int num) { #ifdef CONFIG_ACPI /* - * If CPEI can be re-targetted or if this is not + * If CPEI can be re-targeted or if this is not * CPEI target, then it is hotpluggable */ if (can_cpei_retarget() || !is_cpu_cpei_target(num)) diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index bb862fb224f2..b0398740b48d 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c @@ -987,7 +987,7 @@ static void vmm_sanity_check(struct kvm_vcpu *vcpu) static void kvm_do_resume_op(struct kvm_vcpu *vcpu) { - vmm_sanity_check(vcpu); /*Guarantee vcpu runing on healthy vmm!*/ + vmm_sanity_check(vcpu); /*Guarantee vcpu running on healthy vmm!*/ if (test_and_clear_bit(KVM_REQ_RESUME, &vcpu->requests)) { vcpu_do_resume(vcpu); diff --git a/arch/ia64/lib/do_csum.S b/arch/ia64/lib/do_csum.S index 6bec2fc9f5b2..1a431a5cf86f 100644 --- a/arch/ia64/lib/do_csum.S +++ b/arch/ia64/lib/do_csum.S @@ -201,7 +201,7 @@ GLOBAL_ENTRY(do_csum) ;; (p6) adds result1[0]=1,result1[0] (p9) br.cond.sptk .do_csum_exit // if (count == 1) exit - // Fall through to caluculate the checksum, feeding result1[0] as + // Fall through to calculate the checksum, feeding result1[0] as // the initial value in result1[0]. // // Calculate the checksum loading two 8-byte words per loop. diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 7f399f9d99c7..1c50e4cd63ed 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -227,7 +227,7 @@ void sn_set_err_irq_affinity(unsigned int irq) { /* * On systems which support CPU disabling (SHub2), all error interrupts - * are targetted at the boot CPU. + * are targeted at the boot CPU. */ if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) set_irq_affinity_info(irq, cpu_physical_id(0), 0); @@ -435,7 +435,7 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) /* * Bridge types attached to TIO (anything but PIC) do not need this WAR * since they do not target Shub II interrupt registers. If that - * ever changes, this check needs to accomodate. + * ever changes, this check needs to accommodate. */ if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC) return; diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index c659ad5613a0..33def666a664 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -227,7 +227,7 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction) * after doing the read. For PIC this routine then forces a fake interrupt * on another line, which is logically associated with the slot that the PIO * is addressed to. It then spins while watching the memory location that - * the interrupt is targetted to. When the interrupt response arrives, we + * the interrupt is targeted to. When the interrupt response arrives, we * are sure that the DMA has landed in memory and it is safe for the driver * to proceed. For TIOCP use the Device(x) Write Request Buffer Flush * Bridge register since it ensures the data has entered the coherence domain, diff --git a/arch/m32r/include/asm/m32104ut/m32104ut_pld.h b/arch/m32r/include/asm/m32104ut/m32104ut_pld.h index 2dc89d68b6d9..1feae9709f24 100644 --- a/arch/m32r/include/asm/m32104ut/m32104ut_pld.h +++ b/arch/m32r/include/asm/m32104ut/m32104ut_pld.h @@ -4,7 +4,7 @@ /* * include/asm-m32r/m32104ut/m32104ut_pld.h * - * Definitions for Programable Logic Device(PLD) on M32104UT board. + * Definitions for Programmable Logic Device(PLD) on M32104UT board. * Based on m32700ut_pld.h * * Copyright (c) 2002 Takeo Takahashi diff --git a/arch/m32r/include/asm/m32700ut/m32700ut_pld.h b/arch/m32r/include/asm/m32700ut/m32700ut_pld.h index 57623beb44cb..35294670b187 100644 --- a/arch/m32r/include/asm/m32700ut/m32700ut_pld.h +++ b/arch/m32r/include/asm/m32700ut/m32700ut_pld.h @@ -4,7 +4,7 @@ /* * include/asm-m32r/m32700ut/m32700ut_pld.h * - * Definitions for Programable Logic Device(PLD) on M32700UT board. + * Definitions for Programmable Logic Device(PLD) on M32700UT board. * * Copyright (c) 2002 Takeo Takahashi * diff --git a/arch/m32r/include/asm/opsput/opsput_pld.h b/arch/m32r/include/asm/opsput/opsput_pld.h index 3f11ea1aac2d..6901401fe9eb 100644 --- a/arch/m32r/include/asm/opsput/opsput_pld.h +++ b/arch/m32r/include/asm/opsput/opsput_pld.h @@ -4,7 +4,7 @@ /* * include/asm-m32r/opsput/opsput_pld.h * - * Definitions for Programable Logic Device(PLD) on OPSPUT board. + * Definitions for Programmable Logic Device(PLD) on OPSPUT board. * * Copyright (c) 2002 Takeo Takahashi * diff --git a/arch/m32r/include/asm/pgtable-2level.h b/arch/m32r/include/asm/pgtable-2level.h index bca3475f9595..9cdaf7350ef6 100644 --- a/arch/m32r/include/asm/pgtable-2level.h +++ b/arch/m32r/include/asm/pgtable-2level.h @@ -44,7 +44,7 @@ static inline int pgd_present(pgd_t pgd) { return 1; } #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) /* - * (pmds are folded into pgds so this doesnt get actually called, + * (pmds are folded into pgds so this doesn't get actually called, * but the define is needed for a generic inline function.) */ #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c index b8ec002aef8e..2c9aeb453847 100644 --- a/arch/m32r/mm/fault.c +++ b/arch/m32r/mm/fault.c @@ -120,7 +120,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, /* When running in the kernel we expect faults to occur only to * addresses in user space. All other faults represent errors in the - * kernel and should generate an OOPS. Unfortunatly, in the case of an + * kernel and should generate an OOPS. Unfortunately, in the case of an * erroneous fault occurring in a code path which already holds mmap_sem * we will deadlock attempting to validate the fault against the * address space. Luckily the kernel only validly references user @@ -128,7 +128,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, * exceptions table. * * As the vast majority of faults will be valid we will only perform - * the source reference check when there is a possibilty of a deadlock. + * the source reference check when there is a possibility of a deadlock. * Attempt to lock the address space, if we cannot we then validate the * source. If this is invalid we can skip the address space check, * thus avoiding the deadlock. diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 5890897d28bf..b995513d527f 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -130,7 +130,7 @@ KEYBOARD_STATE kb_state; * it's really hard to decide whether they're mouse or keyboard bytes. Since * overruns usually occur when moving the Atari mouse rapidly, they're seen as * mouse bytes here. If this is wrong, only a make code of the keyboard gets - * lost, which isn't too bad. Loosing a break code would be disastrous, + * lost, which isn't too bad. Losing a break code would be disastrous, * because then the keyboard repeat strikes... */ diff --git a/arch/m68k/fpsp040/bindec.S b/arch/m68k/fpsp040/bindec.S index 72f1159cb804..f2e795231046 100644 --- a/arch/m68k/fpsp040/bindec.S +++ b/arch/m68k/fpsp040/bindec.S @@ -609,7 +609,7 @@ do_fint: | A6. This test occurs only on the first pass. If the | result is exactly 10^LEN, decrement ILOG and divide | the mantissa by 10. The calculation of 10^LEN cannot -| be inexact, since all powers of ten upto 10^27 are exact +| be inexact, since all powers of ten up to 10^27 are exact | in extended precision, so the use of a previous power-of-ten | table will introduce no error. | diff --git a/arch/m68k/ifpsp060/src/fpsp.S b/arch/m68k/ifpsp060/src/fpsp.S index 26e85e2b7a5e..78cb60f5bb4d 100644 --- a/arch/m68k/ifpsp060/src/fpsp.S +++ b/arch/m68k/ifpsp060/src/fpsp.S @@ -11813,7 +11813,7 @@ fmul_unfl_ena: bne.b fmul_unfl_ena_sd # no, sgl or dbl # if the rnd mode is anything but RZ, then we have to re-do the above -# multiplication becuase we used RZ for all. +# multiplication because we used RZ for all. fmov.l L_SCR3(%a6),%fpcr # set FPCR fmul_unfl_ena_cont: @@ -18095,7 +18095,7 @@ fscc_mem_op: rts -# addresing mode is post-increment. write the result byte. if the write +# addressing mode is post-increment. write the result byte. if the write # fails then don't update the address register. if write passes then # call inc_areg() to update the address register. fscc_mem_inc: @@ -20876,7 +20876,7 @@ dst_get_dupper: swap %d0 # d0 now in upper word lsl.l &0x4,%d0 # d0 in proper place for dbl prec exp tst.b FTEMP_EX(%a0) # test sign - bpl.b dst_get_dman # if postive, go process mantissa + bpl.b dst_get_dman # if positive, go process mantissa bset &0x1f,%d0 # if negative, set sign dst_get_dman: mov.l FTEMP_HI(%a0),%d1 # get ms mantissa @@ -22943,7 +22943,7 @@ tbl_ovfl_result: # FP_SRC(a6) = packed operand now as a binary FP number # # # # ALGORITHM *********************************************************** # -# Get the correct whihc is the value on the exception stack # +# Get the correct which is the value on the exception stack # # frame w/ maybe a correction factor if the is -(an) or (an)+. # # Then, fetch the operand from memory. If the fetch fails, exit # # through facc_in_x(). # @@ -24096,7 +24096,7 @@ do_fint12: # A6. This test occurs only on the first pass. If the # result is exactly 10^LEN, decrement ILOG and divide # the mantissa by 10. The calculation of 10^LEN cannot -# be inexact, since all powers of ten upto 10^27 are exact +# be inexact, since all powers of ten up to 10^27 are exact # in extended precision, so the use of a previous power-of-ten # table will introduce no error. # diff --git a/arch/m68k/ifpsp060/src/pfpsp.S b/arch/m68k/ifpsp060/src/pfpsp.S index e71ba0ab013c..4aedef973cf6 100644 --- a/arch/m68k/ifpsp060/src/pfpsp.S +++ b/arch/m68k/ifpsp060/src/pfpsp.S @@ -7777,7 +7777,7 @@ dst_get_dupper: swap %d0 # d0 now in upper word lsl.l &0x4,%d0 # d0 in proper place for dbl prec exp tst.b FTEMP_EX(%a0) # test sign - bpl.b dst_get_dman # if postive, go process mantissa + bpl.b dst_get_dman # if positive, go process mantissa bset &0x1f,%d0 # if negative, set sign dst_get_dman: mov.l FTEMP_HI(%a0),%d1 # get ms mantissa @@ -8244,7 +8244,7 @@ fmul_unfl_ena: bne.b fmul_unfl_ena_sd # no, sgl or dbl # if the rnd mode is anything but RZ, then we have to re-do the above -# multiplication becuase we used RZ for all. +# multiplication because we used RZ for all. fmov.l L_SCR3(%a6),%fpcr # set FPCR fmul_unfl_ena_cont: @@ -12903,7 +12903,7 @@ store_fpreg_7: # FP_SRC(a6) = packed operand now as a binary FP number # # # # ALGORITHM *********************************************************** # -# Get the correct whihc is the value on the exception stack # +# Get the correct which is the value on the exception stack # # frame w/ maybe a correction factor if the is -(an) or (an)+. # # Then, fetch the operand from memory. If the fetch fails, exit # # through facc_in_x(). # @@ -14056,7 +14056,7 @@ do_fint12: # A6. This test occurs only on the first pass. If the # result is exactly 10^LEN, decrement ILOG and divide # the mantissa by 10. The calculation of 10^LEN cannot -# be inexact, since all powers of ten upto 10^27 are exact +# be inexact, since all powers of ten up to 10^27 are exact # in extended precision, so the use of a previous power-of-ten # table will introduce no error. # diff --git a/arch/m68k/include/asm/atariints.h b/arch/m68k/include/asm/atariints.h index f597892e43a0..656bbbf5a6ff 100644 --- a/arch/m68k/include/asm/atariints.h +++ b/arch/m68k/include/asm/atariints.h @@ -146,7 +146,7 @@ static inline void clear_mfp_bit( unsigned irq, int type ) /* * {en,dis}able_irq have the usual semantics of temporary blocking the - * interrupt, but not loosing requests that happen between disabling and + * interrupt, but not losing requests that happen between disabling and * enabling. This is done with the MFP mask registers. */ diff --git a/arch/m68k/include/asm/bootstd.h b/arch/m68k/include/asm/bootstd.h index bdc1a4ac4fe9..e518f5a575b7 100644 --- a/arch/m68k/include/asm/bootstd.h +++ b/arch/m68k/include/asm/bootstd.h @@ -31,7 +31,7 @@ #define __BN_flash_write_range 20 /* Calling conventions compatible to (uC)linux/68k - * We use simmilar macros to call into the bootloader as for uClinux + * We use similar macros to call into the bootloader as for uClinux */ #define __bsc_return(type, res) \ diff --git a/arch/m68k/include/asm/commproc.h b/arch/m68k/include/asm/commproc.h index edf5eb6c08d2..a73998528d26 100644 --- a/arch/m68k/include/asm/commproc.h +++ b/arch/m68k/include/asm/commproc.h @@ -88,7 +88,7 @@ typedef struct cpm_buf_desc { /* rx bd status/control bits */ -#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */ +#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */ #define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor in table */ #define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ #define BD_SC_LAST ((ushort)0x0800) /* Last buffer in frame OR control char */ @@ -96,7 +96,7 @@ typedef struct cpm_buf_desc { #define BD_SC_FIRST ((ushort)0x0400) /* 1st buffer in an HDLC frame */ #define BD_SC_ADDR ((ushort)0x0400) /* 1st byte is a multidrop address */ -#define BD_SC_CM ((ushort)0x0200) /* Continous mode */ +#define BD_SC_CM ((ushort)0x0200) /* Continuous mode */ #define BD_SC_ID ((ushort)0x0100) /* Received too many idles */ #define BD_SC_AM ((ushort)0x0080) /* Multidrop address match */ diff --git a/arch/m68k/include/asm/delay_no.h b/arch/m68k/include/asm/delay_no.h index 55cbd6294ab6..c3a0edc90f21 100644 --- a/arch/m68k/include/asm/delay_no.h +++ b/arch/m68k/include/asm/delay_no.h @@ -16,7 +16,7 @@ static inline void __delay(unsigned long loops) * long word alignment which is the faster version. * The 0x4a8e is of course a 'tstl %fp' instruction. This is better * than using a NOP (0x4e71) instruction because it executes in one - * cycle not three and doesn't allow for an arbitary delay waiting + * cycle not three and doesn't allow for an arbitrary delay waiting * for bus cycles to finish. Also fp/a6 isn't likely to cause a * stall waiting for the register to become valid if such is added * to the coldfire at some stage. diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h index c64c7b74cf86..b2046839f4b2 100644 --- a/arch/m68k/include/asm/gpio.h +++ b/arch/m68k/include/asm/gpio.h @@ -31,7 +31,7 @@ * GPIOs in a single control area, others have some GPIOs implemented in * different modules. * - * This implementation attempts accomodate the differences while presenting + * This implementation attempts accommodate the differences while presenting * a generic interface that will optimize to as few instructions as possible. */ #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h index 55d5a4c5fe0b..b6bf2c518bac 100644 --- a/arch/m68k/include/asm/m520xsim.h +++ b/arch/m68k/include/asm/m520xsim.h @@ -157,7 +157,7 @@ #define MCFFEC_SIZE 0x800 /* Register set size */ /* - * Reset Controll Unit. + * Reset Control Unit. */ #define MCF_RCR 0xFC0A0000 #define MCF_RSR 0xFC0A0001 diff --git a/arch/m68k/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h index 8996df62ede4..6235921eca4e 100644 --- a/arch/m68k/include/asm/m523xsim.h +++ b/arch/m68k/include/asm/m523xsim.h @@ -48,7 +48,7 @@ #define MCFSIM_DMR1 (MCF_IPSBAR + 0x54) /* Address mask 1 */ /* - * Reset Controll Unit (relative to IPSBAR). + * Reset Control Unit (relative to IPSBAR). */ #define MCF_RCR 0x110000 #define MCF_RSR 0x110001 diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h index 74855a66c050..758810ef91ec 100644 --- a/arch/m68k/include/asm/m527xsim.h +++ b/arch/m68k/include/asm/m527xsim.h @@ -283,7 +283,7 @@ #endif /* - * Reset Controll Unit (relative to IPSBAR). + * Reset Control Unit (relative to IPSBAR). */ #define MCF_RCR 0x110000 #define MCF_RSR 0x110001 diff --git a/arch/m68k/include/asm/m5307sim.h b/arch/m68k/include/asm/m5307sim.h index 4c94c01f36c4..8f8609fcc9b8 100644 --- a/arch/m68k/include/asm/m5307sim.h +++ b/arch/m68k/include/asm/m5307sim.h @@ -29,7 +29,7 @@ #define MCFSIM_SWSR 0x03 /* SW Watchdog service (r/w) */ #define MCFSIM_PAR 0x04 /* Pin Assignment reg (r/w) */ #define MCFSIM_IRQPAR 0x06 /* Interrupt Assignment reg (r/w) */ -#define MCFSIM_PLLCR 0x08 /* PLL Controll Reg*/ +#define MCFSIM_PLLCR 0x08 /* PLL Control Reg*/ #define MCFSIM_MPARK 0x0C /* BUS Master Control Reg*/ #define MCFSIM_IPR 0x40 /* Interrupt Pend reg (r/w) */ #define MCFSIM_IMR 0x44 /* Interrupt Mask reg (r/w) */ diff --git a/arch/m68k/include/asm/m5407sim.h b/arch/m68k/include/asm/m5407sim.h index 762c58c89050..51e00b00b8a6 100644 --- a/arch/m68k/include/asm/m5407sim.h +++ b/arch/m68k/include/asm/m5407sim.h @@ -29,7 +29,7 @@ #define MCFSIM_SWSR 0x03 /* SW Watchdog service (r/w) */ #define MCFSIM_PAR 0x04 /* Pin Assignment reg (r/w) */ #define MCFSIM_IRQPAR 0x06 /* Interrupt Assignment reg (r/w) */ -#define MCFSIM_PLLCR 0x08 /* PLL Controll Reg*/ +#define MCFSIM_PLLCR 0x08 /* PLL Control Reg*/ #define MCFSIM_MPARK 0x0C /* BUS Master Control Reg*/ #define MCFSIM_IPR 0x40 /* Interrupt Pend reg (r/w) */ #define MCFSIM_IMR 0x44 /* Interrupt Mask reg (r/w) */ diff --git a/arch/m68k/include/asm/m68360_quicc.h b/arch/m68k/include/asm/m68360_quicc.h index 6d40f4d18e10..59414cc108d3 100644 --- a/arch/m68k/include/asm/m68360_quicc.h +++ b/arch/m68k/include/asm/m68360_quicc.h @@ -32,7 +32,7 @@ struct user_data { /* BASE + 0x000: user data memory */ volatile unsigned char udata_bd_ucode[0x400]; /*user data bd's Ucode*/ volatile unsigned char udata_bd[0x200]; /*user data Ucode */ - volatile unsigned char ucode_ext[0x100]; /*Ucode Extention ram */ + volatile unsigned char ucode_ext[0x100]; /*Ucode Extension ram */ volatile unsigned char RESERVED1[0x500]; /* Reserved area */ }; #else diff --git a/arch/m68k/include/asm/mac_oss.h b/arch/m68k/include/asm/mac_oss.h index 7221f7251934..3cf2b6ed685a 100644 --- a/arch/m68k/include/asm/mac_oss.h +++ b/arch/m68k/include/asm/mac_oss.h @@ -61,7 +61,7 @@ /* * OSS Interrupt levels for various sub-systems * - * This mapping is layed out with two things in mind: first, we try to keep + * This mapping is laid out with two things in mind: first, we try to keep * things on their own levels to avoid having to do double-dispatches. Second, * the levels match as closely as possible the alternate IRQ mapping mode (aka * "A/UX mode") available on some VIA machines. diff --git a/arch/m68k/include/asm/mac_via.h b/arch/m68k/include/asm/mac_via.h index 39afb438b656..a59665e1d41b 100644 --- a/arch/m68k/include/asm/mac_via.h +++ b/arch/m68k/include/asm/mac_via.h @@ -204,7 +204,7 @@ #define vT2CL 0x1000 /* [VIA only] Timer two counter low. */ #define vT2CH 0x1200 /* [VIA only] Timer two counter high. */ #define vSR 0x1400 /* [VIA only] Shift register. */ -#define vACR 0x1600 /* [VIA only] Auxilary control register. */ +#define vACR 0x1600 /* [VIA only] Auxiliary control register. */ #define vPCR 0x1800 /* [VIA only] Peripheral control register. */ /* CHRP sez never ever to *write* this. * Mac family says never to *change* this. diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index 50db3591ca15..c2a1c5eac1a6 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h @@ -14,7 +14,7 @@ extern void mac_init_IRQ(void); extern int mac_irq_pending(unsigned int); /* - * Floppy driver magic hook - probably shouldnt be here + * Floppy driver magic hook - probably shouldn't be here */ extern void via1_set_head(int); diff --git a/arch/m68k/include/asm/mcftimer.h b/arch/m68k/include/asm/mcftimer.h index 92b276fe8240..351c27237874 100644 --- a/arch/m68k/include/asm/mcftimer.h +++ b/arch/m68k/include/asm/mcftimer.h @@ -27,7 +27,7 @@ /* * Bit definitions for the Timer Mode Register (TMR). - * Register bit flags are common accross ColdFires. + * Register bit flags are common across ColdFires. */ #define MCFTIMER_TMR_PREMASK 0xff00 /* Prescalar mask */ #define MCFTIMER_TMR_DISCE 0x0000 /* Disable capture */ diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index ef54128baa0b..27622b3273c1 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -134,7 +134,7 @@ * Thanks to a small helping routine enabling the mmu got quite simple * and there is only one way left. mmu_engage makes a complete a new mapping * that only includes the absolute necessary to be able to jump to the final - * postion and to restore the original mapping. + * position and to restore the original mapping. * As this code doesn't need a transparent translation register anymore this * means all registers are free to be used by machines that needs them for * other purposes. @@ -969,7 +969,7 @@ L(mmu_init_amiga): is_not_040_or_060(1f) /* - * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000 + * 040: Map the 16Meg range physical 0x0 up to logical 0x8000.0000 */ mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S /* @@ -982,7 +982,7 @@ L(mmu_init_amiga): 1: /* - * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000 + * 030: Map the 32Meg range physical 0x0 up to logical 0x8000.0000 */ mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030 @@ -1074,7 +1074,7 @@ L(notq40): is_040(1f) /* - * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000 + * 030: Map the 32Meg range physical 0x0 up to logical 0xf000.0000 */ mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030 @@ -1082,7 +1082,7 @@ L(notq40): 1: /* - * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000 + * 040: Map the 16Meg range physical 0x0 up to logical 0xf000.0000 */ mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S @@ -3078,7 +3078,7 @@ func_start serial_putc,%d0/%d1/%a0/%a1 /* * If the loader gave us a board type then we can use that to * select an appropriate output routine; otherwise we just use - * the Bug code. If we haev to use the Bug that means the Bug + * the Bug code. If we have to use the Bug that means the Bug * workspace has to be valid, which means the Bug has to use * the SRAM, which is non-standard. */ diff --git a/arch/m68k/kernel/vmlinux.lds_no.S b/arch/m68k/kernel/vmlinux.lds_no.S index 47e15ebfd893..f4d715cdca0e 100644 --- a/arch/m68k/kernel/vmlinux.lds_no.S +++ b/arch/m68k/kernel/vmlinux.lds_no.S @@ -3,7 +3,7 @@ * * (C) Copyright 2002-2006, Greg Ungerer * - * This linker script is equiped to build either ROM loaded or RAM + * This linker script is equipped to build either ROM loaded or RAM * run kernels. */ diff --git a/arch/m68k/platform/523x/config.c b/arch/m68k/platform/523x/config.c index 418a76feb1e3..71f4436ec809 100644 --- a/arch/m68k/platform/523x/config.c +++ b/arch/m68k/platform/523x/config.c @@ -3,7 +3,7 @@ /* * linux/arch/m68knommu/platform/523x/config.c * - * Sub-architcture dependant initialization code for the Freescale + * Sub-architcture dependent initialization code for the Freescale * 523x CPUs. * * Copyright (C) 1999-2005, Greg Ungerer (gerg@snapgear.com) diff --git a/arch/m68k/platform/5272/intc.c b/arch/m68k/platform/5272/intc.c index 43e6e96f087f..7e715dfe2819 100644 --- a/arch/m68k/platform/5272/intc.c +++ b/arch/m68k/platform/5272/intc.c @@ -33,7 +33,7 @@ * * Note that the external interrupts are edge triggered (unlike the * internal interrupt sources which are level triggered). Which means - * they also need acknowledgeing via acknowledge bits. + * they also need acknowledging via acknowledge bits. */ struct irqmap { unsigned char icr; diff --git a/arch/m68k/platform/527x/config.c b/arch/m68k/platform/527x/config.c index fa359593b613..3ebc769cefda 100644 --- a/arch/m68k/platform/527x/config.c +++ b/arch/m68k/platform/527x/config.c @@ -3,7 +3,7 @@ /* * linux/arch/m68knommu/platform/527x/config.c * - * Sub-architcture dependant initialization code for the Freescale + * Sub-architcture dependent initialization code for the Freescale * 5270/5271 CPUs. * * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com) diff --git a/arch/m68k/platform/528x/config.c b/arch/m68k/platform/528x/config.c index ac39fc661219..7abe77a2f3e3 100644 --- a/arch/m68k/platform/528x/config.c +++ b/arch/m68k/platform/528x/config.c @@ -3,7 +3,7 @@ /* * linux/arch/m68knommu/platform/528x/config.c * - * Sub-architcture dependant initialization code for the Freescale + * Sub-architcture dependent initialization code for the Freescale * 5280, 5281 and 5282 CPUs. * * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) diff --git a/arch/m68k/platform/coldfire/cache.c b/arch/m68k/platform/coldfire/cache.c index 235d3c4f4f0f..71beeaf0c5c4 100644 --- a/arch/m68k/platform/coldfire/cache.c +++ b/arch/m68k/platform/coldfire/cache.c @@ -1,7 +1,7 @@ /***************************************************************************/ /* - * cache.c -- general ColdFire Cache maintainence code + * cache.c -- general ColdFire Cache maintenance code * * Copyright (C) 2010, Greg Ungerer (gerg@snapgear.com) */ diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S index 5837cf080b6d..eab63f09965b 100644 --- a/arch/m68k/platform/coldfire/entry.S +++ b/arch/m68k/platform/coldfire/entry.S @@ -163,7 +163,7 @@ Lsignal_return: /* * This is the generic interrupt handler (for all hardware interrupt - * sources). Calls upto high level code to do all the work. + * sources). Calls up to high level code to do all the work. */ ENTRY(inthandler) SAVE_ALL diff --git a/arch/m68k/platform/coldfire/head.S b/arch/m68k/platform/coldfire/head.S index 129bff4956b5..6ae91a499184 100644 --- a/arch/m68k/platform/coldfire/head.S +++ b/arch/m68k/platform/coldfire/head.S @@ -20,7 +20,7 @@ /* * If we don't have a fixed memory size, then lets build in code - * to auto detect the DRAM size. Obviously this is the prefered + * to auto detect the DRAM size. Obviously this is the preferred * method, and should work for most boards. It won't work for those * that do not have their RAM starting at address 0, and it only * works on SDRAM (not boards fitted with SRAM). diff --git a/arch/m68k/platform/coldfire/intc.c b/arch/m68k/platform/coldfire/intc.c index c28a6ed6cb23..0bbb414856eb 100644 --- a/arch/m68k/platform/coldfire/intc.c +++ b/arch/m68k/platform/coldfire/intc.c @@ -37,7 +37,7 @@ unsigned char mcf_irq2imr[NR_IRQS]; /* * In the early version 2 core ColdFire parts the IMR register was 16 bits * in size. Version 3 (and later version 2) core parts have a 32 bit - * sized IMR register. Provide some size independant methods to access the + * sized IMR register. Provide some size independent methods to access the * IMR register. */ #ifdef MCFSIM_IMR_IS_16BITS diff --git a/arch/m68k/platform/coldfire/sltimers.c b/arch/m68k/platform/coldfire/sltimers.c index 0a1b937c3e18..6a85daf9a7fd 100644 --- a/arch/m68k/platform/coldfire/sltimers.c +++ b/arch/m68k/platform/coldfire/sltimers.c @@ -106,7 +106,7 @@ static cycle_t mcfslt_read_clk(struct clocksource *cs) cycles = mcfslt_cnt; local_irq_restore(flags); - /* substract because slice timers count down */ + /* subtract because slice timers count down */ return cycles - scnt; } diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README index f877b7249790..b26d5f55e91d 100644 --- a/arch/m68k/q40/README +++ b/arch/m68k/q40/README @@ -89,7 +89,7 @@ The main interrupt register IIRQ_REG will indicate whether an IRQ was internal or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs. The Q40 custom chip is programmable to provide 2 periodic timers: - - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!! + - 50 or 200 Hz - level 2, !!THIS CAN'T BE DISABLED!! - 10 or 20 KHz - level 4, used for dma-sound Linux uses the 200 Hz interrupt for timer and beep by default. diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 6f432e6df9af..b23c40eb7a52 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -18,7 +18,7 @@ export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV # rather than bools y/n # Work out HW multipler support. This is tricky. -# 1. Spartan2 has no HW multiplers. +# 1. Spartan2 has no HW multipliers. # 2. MicroBlaze v3.x always uses them, except in Spartan 2 # 3. All other FPGa/CPU ver combos, we can trust the CONFIG_ settings ifeq (,$(findstring spartan2,$(CONFIG_XILINX_MICROBLAZE0_FAMILY))) diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h index eae32220f447..8cdac14b55b0 100644 --- a/arch/microblaze/include/asm/io.h +++ b/arch/microblaze/include/asm/io.h @@ -70,7 +70,7 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) /* * read (readb, readw, readl, readq) and write (writeb, writew, - * writel, writeq) accessors are for PCI and thus littel endian. + * writel, writeq) accessors are for PCI and thus little endian. * Linux 2.4 for Microblaze had this wrong. */ static inline unsigned char readb(const volatile void __iomem *addr) diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h index 10717669e0c2..746df91e5796 100644 --- a/arch/microblaze/include/asm/pci-bridge.h +++ b/arch/microblaze/include/asm/pci-bridge.h @@ -76,7 +76,7 @@ struct pci_controller { * Used for variants of PCI indirect handling and possible quirks: * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1 * EXT_REG - provides access to PCI-e extended registers - * SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS + * SURPRESS_PRIMARY_BUS - we suppress the setting of PCI_PRIMARY_BUS * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS * to determine which bus number to match on when generating type0 * config cycles diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index 2232ff942ba9..ba65cf472544 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -158,7 +158,7 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar, extern void pcibios_setup_bus_devices(struct pci_bus *bus); extern void pcibios_setup_bus_self(struct pci_bus *bus); -/* This part of code was originaly in xilinx-pci.h */ +/* This part of code was originally in xilinx-pci.h */ #ifdef CONFIG_PCI_XILINX extern void __init xilinx_pci_init(void); #else diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index cf0afd90a2c0..4b7d8a3f4aef 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -129,7 +129,7 @@ do { \ * to use for simple wdc or wic. * * start address is cache aligned - * end address is not aligned, if end is aligned then I have to substract + * end address is not aligned, if end is aligned then I have to subtract * cacheline length because I can't flush/invalidate the next cacheline. * If is not, I align it because I will flush/invalidate whole line. */ diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c index cc495d7d99cc..52746e718dfa 100644 --- a/arch/microblaze/lib/memcpy.c +++ b/arch/microblaze/lib/memcpy.c @@ -63,8 +63,8 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) if (likely(c >= 4)) { unsigned value, buf_hold; - /* Align the dstination to a word boundry. */ - /* This is done in an endian independant manner. */ + /* Align the destination to a word boundary. */ + /* This is done in an endian independent manner. */ switch ((unsigned long)dst & 3) { case 1: *dst++ = *src++; @@ -80,7 +80,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) i_dst = (void *)dst; /* Choose a copy scheme based on the source */ - /* alignment relative to dstination. */ + /* alignment relative to destination. */ switch ((unsigned long)src & 3) { case 0x0: /* Both byte offsets are aligned */ i_src = (const void *)src; @@ -173,7 +173,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) } /* Finish off any remaining bytes */ - /* simple fast copy, ... unless a cache boundry is crossed */ + /* simple fast copy, ... unless a cache boundary is crossed */ switch (c) { case 3: *dst++ = *src++; diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c index 810fd68775e3..2146c3752a80 100644 --- a/arch/microblaze/lib/memmove.c +++ b/arch/microblaze/lib/memmove.c @@ -83,8 +83,8 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) if (c >= 4) { unsigned value, buf_hold; - /* Align the destination to a word boundry. */ - /* This is done in an endian independant manner. */ + /* Align the destination to a word boundary. */ + /* This is done in an endian independent manner. */ switch ((unsigned long)dst & 3) { case 3: @@ -193,7 +193,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) dst = (void *)i_dst; } - /* simple fast copy, ... unless a cache boundry is crossed */ + /* simple fast copy, ... unless a cache boundary is crossed */ /* Finish off any remaining bytes */ switch (c) { case 4: diff --git a/arch/microblaze/lib/memset.c b/arch/microblaze/lib/memset.c index 834565d1607e..ddf67939576d 100644 --- a/arch/microblaze/lib/memset.c +++ b/arch/microblaze/lib/memset.c @@ -64,7 +64,7 @@ void *memset(void *v_src, int c, __kernel_size_t n) if (likely(n >= 4)) { /* Align the destination to a word boundary */ - /* This is done in an endian independant manner */ + /* This is done in an endian independent manner */ switch ((unsigned) src & 3) { case 1: *src++ = c; diff --git a/arch/microblaze/pci/indirect_pci.c b/arch/microblaze/pci/indirect_pci.c index 25f18f017f21..4196eb6bd764 100644 --- a/arch/microblaze/pci/indirect_pci.c +++ b/arch/microblaze/pci/indirect_pci.c @@ -108,7 +108,7 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | (devfn << 8) | reg | cfg_type)); - /* surpress setting of PCI_PRIMARY_BUS */ + /* suppress setting of PCI_PRIMARY_BUS */ if (hose->indirect_type & INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) if ((offset == PCI_PRIMARY_BUS) && (bus->number == hose->first_busno)) diff --git a/arch/microblaze/platform/generic/Kconfig.auto b/arch/microblaze/platform/generic/Kconfig.auto index 5d86fc19029d..25a6f019e94d 100644 --- a/arch/microblaze/platform/generic/Kconfig.auto +++ b/arch/microblaze/platform/generic/Kconfig.auto @@ -29,7 +29,7 @@ config KERNEL_BASE_ADDR BASE Address for kernel config XILINX_MICROBLAZE0_FAMILY - string "Targetted FPGA family" + string "Targeted FPGA family" default "virtex5" config XILINX_MICROBLAZE0_USE_MSR_INSTR diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 83aa5fb8e8f1..8e256cc5dcd9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1135,7 +1135,7 @@ config CPU_LOONGSON2E The Loongson 2E processor implements the MIPS III instruction set with many extensions. - It has an internal FPGA northbridge, which is compatiable to + It has an internal FPGA northbridge, which is compatible to bonito64. config CPU_LOONGSON2F diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ac1d5b611a27..53e3514ba10e 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -101,7 +101,7 @@ cflags-y += -ffreestanding # carefully avoid to add it redundantly because gcc 3.3/3.4 complains # when fed the toolchain default! # -# Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of +# Certain gcc versions up to gcc 4.1.1 (probably 4.2-subversion as of # 2006-10-10 don't properly change the predefined symbols if -EB / -EL # are used, so we kludge that here. A bug has been filed at # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413. @@ -314,5 +314,5 @@ define archhelp echo ' vmlinuz.bin - Raw binary zboot image' echo ' vmlinuz.srec - SREC zboot image' echo - echo ' These will be default as apropriate for a configured platform.' + echo ' These will be default as appropriate for a configured platform.' endef diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c index af0fe41055af..f38298a8b98c 100644 --- a/arch/mips/alchemy/common/clocks.c +++ b/arch/mips/alchemy/common/clocks.c @@ -75,7 +75,7 @@ void set_au1x00_uart_baud_base(unsigned long new_baud_base) * counter, if it exists. If we don't have an accurate processor * speed, all of the peripherals that derive their clocks based on * this advertised speed will introduce error and sometimes not work - * properly. This function is futher convoluted to still allow configurations + * properly. This function is further convoluted to still allow configurations * to do that in case they have really, really old silicon with a * write-only PLL register. -- Dan */ diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index 9afc3794ed1b..c8d35684504e 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c @@ -75,7 +75,7 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer) num_cores = cvmx_octeon_num_cores(); - /* Make sure the non existant devices look disabled */ + /* Make sure the non existent devices look disabled */ switch ((chip_id >> 8) & 0xff) { case 6: /* CN50XX */ case 2: /* CN30XX */ diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index cecaf62aef32..cd61d7281d91 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -75,7 +75,7 @@ static int __init octeon_cf_device_init(void) * zero. */ - /* Asume that CS1 immediately follows. */ + /* Assume that CS1 immediately follows. */ mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1)); region_base = mio_boot_reg_cfg.s.base << 16; diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 8b139bf4a1b5..0707fae3f0ee 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -662,7 +662,7 @@ void __init plat_mem_setup(void) * some memory vectors. When SPARSEMEM is in use, it doesn't * verify that the size is big enough for the final * vectors. Making the smallest chuck 4MB seems to be enough - * to consistantly work. + * to consistently work. */ mem_alloc_size = 4 << 20; if (mem_alloc_size > MAX_MEMORY) diff --git a/arch/mips/fw/arc/promlib.c b/arch/mips/fw/arc/promlib.c index c508c00dbb64..b7f9dd3c93c6 100644 --- a/arch/mips/fw/arc/promlib.c +++ b/arch/mips/fw/arc/promlib.c @@ -4,7 +4,7 @@ * for more details. * * Copyright (C) 1996 David S. Miller (dm@sgi.com) - * Compability with board caches, Ulf Carlsson + * Compatibility with board caches, Ulf Carlsson */ #include #include diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h index b9c8203688d5..c0ead6313845 100644 --- a/arch/mips/include/asm/dec/prom.h +++ b/arch/mips/include/asm/dec/prom.h @@ -108,7 +108,7 @@ extern int (*__pmax_close)(int); /* * On MIPS64 we have to call PROM functions via a helper - * dispatcher to accomodate ABI incompatibilities. + * dispatcher to accommodate ABI incompatibilities. */ #define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \ __asm__(#fun " = call_o32") diff --git a/arch/mips/include/asm/floppy.h b/arch/mips/include/asm/floppy.h index 992d232adc83..c5c7c0e6064c 100644 --- a/arch/mips/include/asm/floppy.h +++ b/arch/mips/include/asm/floppy.h @@ -24,7 +24,7 @@ static inline void fd_cacheflush(char * addr, long size) * And on Mips's the CMOS info fails also ... * * FIXME: This information should come from the ARC configuration tree - * or whereever a particular machine has stored this ... + * or wherever a particular machine has stored this ... */ #define FLOPPY0_TYPE fd_drive_type(0) #define FLOPPY1_TYPE fd_drive_type(1) diff --git a/arch/mips/include/asm/hw_irq.h b/arch/mips/include/asm/hw_irq.h index aca05a43a97b..77adda297ad9 100644 --- a/arch/mips/include/asm/hw_irq.h +++ b/arch/mips/include/asm/hw_irq.h @@ -13,7 +13,7 @@ extern atomic_t irq_err_count; /* - * interrupt-retrigger: NOP for now. This may not be apropriate for all + * interrupt-retrigger: NOP for now. This may not be appropriate for all * machines, we'll see ... */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 5b017f23e243..b04e4de5dd2e 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -242,7 +242,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, * This version of ioremap ensures that the memory is marked uncachable * on the CPU as well as honouring existing caching rules from things like * the PCI bus. Note that there are other caches and buffers on many - * busses. In paticular driver authors should read up on PCI writes + * busses. In particular driver authors should read up on PCI writes * * It's useful if some control registers are in such an area and * write combining or read caching is not desirable: diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index 9ef3b0d17896..309cbcd6909c 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -174,7 +174,7 @@ __asm__( "mtc0 \\flags, $2, 1 \n" #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) /* - * Slow, but doesn't suffer from a relativly unlikely race + * Slow, but doesn't suffer from a relatively unlikely race * condition we're having since days 1. */ " beqz \\flags, 1f \n" diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h index 5325084d5c48..32978d32561a 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h @@ -4,7 +4,7 @@ #define TAGVER_LEN 4 /* Length of Tag Version */ #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ #define SIG1_LEN 20 /* Company Signature 1 Length */ -#define SIG2_LEN 14 /* Company Signature 2 Lenght */ +#define SIG2_LEN 14 /* Company Signature 2 Length */ #define BOARDID_LEN 16 /* Length of BoardId */ #define ENDIANFLAG_LEN 2 /* Endian Flag Length */ #define CHIPID_LEN 6 /* Chip Id Length */ diff --git a/arch/mips/include/asm/mach-ip32/mc146818rtc.h b/arch/mips/include/asm/mach-ip32/mc146818rtc.h index c28ba8d84076..6b6bab43d5c1 100644 --- a/arch/mips/include/asm/mach-ip32/mc146818rtc.h +++ b/arch/mips/include/asm/mach-ip32/mc146818rtc.h @@ -26,7 +26,7 @@ static inline void CMOS_WRITE(unsigned char data, unsigned long addr) } /* - * FIXME: Do it right. For now just assume that noone lives in 20th century + * FIXME: Do it right. For now just assume that no one lives in 20th century * and no O2 user in 22th century ;-) */ #define mc146818_decode_year(year) ((year) + 2000) diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h index 021f77ca59ec..2a8e2bb5d539 100644 --- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h +++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h @@ -1,5 +1,5 @@ /* - * The header file of cs5536 sourth bridge. + * The header file of cs5536 south bridge. * * Copyright (C) 2007 Lemote, Inc. * Author : jlliu diff --git a/arch/mips/include/asm/mach-pb1x00/pb1000.h b/arch/mips/include/asm/mach-pb1x00/pb1000.h index 6d1ff9060e44..65059255dc1e 100644 --- a/arch/mips/include/asm/mach-pb1x00/pb1000.h +++ b/arch/mips/include/asm/mach-pb1x00/pb1000.h @@ -1,5 +1,5 @@ /* - * Alchemy Semi Pb1000 Referrence Board + * Alchemy Semi Pb1000 Reference Board * * Copyright 2001, 2008 MontaVista Software Inc. * Author: MontaVista Software, Inc. diff --git a/arch/mips/include/asm/mach-pb1x00/pb1200.h b/arch/mips/include/asm/mach-pb1x00/pb1200.h index 962eb55dc880..fce4332ebb7f 100644 --- a/arch/mips/include/asm/mach-pb1x00/pb1200.h +++ b/arch/mips/include/asm/mach-pb1x00/pb1200.h @@ -1,5 +1,5 @@ /* - * AMD Alchemy Pb1200 Referrence Board + * AMD Alchemy Pb1200 Reference Board * Board Registers defines. * * ######################################################################## diff --git a/arch/mips/include/asm/mach-pb1x00/pb1550.h b/arch/mips/include/asm/mach-pb1x00/pb1550.h index fc4d766641ce..f835c88e9593 100644 --- a/arch/mips/include/asm/mach-pb1x00/pb1550.h +++ b/arch/mips/include/asm/mach-pb1x00/pb1550.h @@ -1,5 +1,5 @@ /* - * AMD Alchemy Semi PB1550 Referrence Board + * AMD Alchemy Semi PB1550 Reference Board * Board Registers defines. * * Copyright 2004 Embedded Edge LLC. diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h index f76029c2406e..a8e72cf12142 100644 --- a/arch/mips/include/asm/mach-powertv/dma-coherence.h +++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h @@ -48,7 +48,7 @@ static inline unsigned long virt_to_phys_from_pte(void *addr) /* check for a valid page */ if (pte_present(pte)) { /* get the physical address the page is - * refering to */ + * referring to */ phys_addr = (unsigned long) page_to_phys(pte_page(pte)); /* add the offset within the page */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 4d9870975382..6a6f8a8f542d 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -922,7 +922,7 @@ do { \ #define write_c0_config7(val) __write_32bit_c0_register($16, 7, val) /* - * The WatchLo register. There may be upto 8 of them. + * The WatchLo register. There may be up to 8 of them. */ #define read_c0_watchlo0() __read_ulong_c0_register($18, 0) #define read_c0_watchlo1() __read_ulong_c0_register($18, 1) @@ -942,7 +942,7 @@ do { \ #define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) /* - * The WatchHi register. There may be upto 8 of them. + * The WatchHi register. There may be up to 8 of them. */ #define read_c0_watchhi0() __read_32bit_c0_register($19, 0) #define read_c0_watchhi1() __read_32bit_c0_register($19, 1) diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index f3c23a43f845..4e4c3a8282d6 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -200,7 +200,7 @@ enum cvmx_chip_types_enum { CVMX_CHIP_TYPE_MAX, }; -/* Compatability alias for NAC38 name change, planned to be removed +/* Compatibility alias for NAC38 name change, planned to be removed * from SDK 1.7 */ #define CVMX_BOARD_TYPE_NAO38 CVMX_BOARD_TYPE_NAC38 diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h index 8e708bdb43f7..877845b84b14 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootmem.h +++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h @@ -67,7 +67,7 @@ struct cvmx_bootmem_block_header { /* * Structure for named memory blocks. Number of descriptors available - * can be changed without affecting compatiblity, but name length + * can be changed without affecting compatibility, but name length * changes require a bump in the bootmem descriptor version Note: This * structure must be naturally 64 bit aligned, as a single memory * image will be used by both 32 and 64 bit programs. diff --git a/arch/mips/include/asm/octeon/cvmx-l2c.h b/arch/mips/include/asm/octeon/cvmx-l2c.h index 0b32c5b118e2..2c8ff9e33ec3 100644 --- a/arch/mips/include/asm/octeon/cvmx-l2c.h +++ b/arch/mips/include/asm/octeon/cvmx-l2c.h @@ -157,7 +157,7 @@ enum cvmx_l2c_tad_event { /** * Configure one of the four L2 Cache performance counters to capture event - * occurences. + * occurrences. * * @counter: The counter to configure. Range 0..3. * @event: The type of L2 Cache event occurrence to count. diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 9d9381e2e3d8..7e1286706d46 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -151,7 +151,7 @@ enum cvmx_mips_space { #endif /** - * Convert a memory pointer (void*) into a hardware compatable + * Convert a memory pointer (void*) into a hardware compatible * memory address (uint64_t). Octeon hardware widgets don't * understand logical addresses. * diff --git a/arch/mips/include/asm/paccess.h b/arch/mips/include/asm/paccess.h index c2394f8b0fe1..9ce5a1e7e14c 100644 --- a/arch/mips/include/asm/paccess.h +++ b/arch/mips/include/asm/paccess.h @@ -7,7 +7,7 @@ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * * Protected memory access. Used for everything that might take revenge - * by sending a DBE error like accessing possibly non-existant memory or + * by sending a DBE error like accessing possibly non-existent memory or * devices. */ #ifndef _ASM_PACCESS_H diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index f1f508e4f971..be44fb0266da 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -262,7 +262,7 @@ typedef volatile struct bridge_s { } bridge_t; /* - * Field formats for Error Command Word and Auxillary Error Command Word + * Field formats for Error Command Word and Auxiliary Error Command Word * of bridge. */ typedef struct bridge_err_cmdword_s { diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h index 60a5a38dd5b2..7d41474e5488 100644 --- a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h @@ -205,7 +205,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr) * custom_read_reg32(address, tmp); <-- Reads the address and put the value * in the 'tmp' variable given * - * From here on out, you are (basicly) atomic, so don't do anything too + * From here on out, you are (basically) atomic, so don't do anything too * fancy! * Also, this code may loop if the end of this block fails to write * everything back safely due do the other CPU, so do NOT do anything diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index ead6928fa6b8..c104f1039a69 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -337,7 +337,7 @@ unsigned long get_wchan(struct task_struct *p); /* * Return_address is a replacement for __builtin_return_address(count) * which on certain architectures cannot reasonably be implemented in GCC - * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386). + * (MIPS, Alpha) or is unusable with -fomit-frame-pointer (i386). * Note that __builtin_return_address(x>=1) is forbidden because GCC * aborts compilation on some CPUs. It's simply not possible to unwind * some CPU's stackframes. diff --git a/arch/mips/include/asm/sgi/ioc.h b/arch/mips/include/asm/sgi/ioc.h index 57a971904cfe..380347b648e2 100644 --- a/arch/mips/include/asm/sgi/ioc.h +++ b/arch/mips/include/asm/sgi/ioc.h @@ -17,7 +17,7 @@ #include /* - * All registers are 8-bit wide alligned on 32-bit boundary. Bad things + * All registers are 8-bit wide aligned on 32-bit boundary. Bad things * happen if you try word access them. You have been warned. */ diff --git a/arch/mips/include/asm/sibyte/sb1250_mac.h b/arch/mips/include/asm/sibyte/sb1250_mac.h index 591b9061fd8e..77f787284235 100644 --- a/arch/mips/include/asm/sibyte/sb1250_mac.h +++ b/arch/mips/include/asm/sibyte/sb1250_mac.h @@ -520,7 +520,7 @@ #define G_MAC_RX_EOP_COUNTER(x) _SB_GETVALUE(x, S_MAC_RX_EOP_COUNTER, M_MAC_RX_EOP_COUNTER) /* - * MAC Recieve Address Filter Exact Match Registers (Table 9-21) + * MAC Receive Address Filter Exact Match Registers (Table 9-21) * Registers: MAC_ADDR0_0 through MAC_ADDR7_0 * Registers: MAC_ADDR0_1 through MAC_ADDR7_1 * Registers: MAC_ADDR0_2 through MAC_ADDR7_2 @@ -538,7 +538,7 @@ /* No bitfields */ /* - * MAC Recieve Address Filter Hash Match Registers (Table 9-22) + * MAC Receive Address Filter Hash Match Registers (Table 9-22) * Registers: MAC_HASH0_0 through MAC_HASH7_0 * Registers: MAC_HASH0_1 through MAC_HASH7_1 * Registers: MAC_HASH0_2 through MAC_HASH7_2 diff --git a/arch/mips/include/asm/siginfo.h b/arch/mips/include/asm/siginfo.h index 1ca64b4d33d9..20ebeb875ee6 100644 --- a/arch/mips/include/asm/siginfo.h +++ b/arch/mips/include/asm/siginfo.h @@ -101,7 +101,7 @@ typedef struct siginfo { /* * si_code values - * Again these have been choosen to be IRIX compatible. + * Again these have been chosen to be IRIX compatible. */ #undef SI_ASYNCIO #undef SI_TIMER diff --git a/arch/mips/include/asm/sn/klconfig.h b/arch/mips/include/asm/sn/klconfig.h index 09e590daca17..fe02900b930d 100644 --- a/arch/mips/include/asm/sn/klconfig.h +++ b/arch/mips/include/asm/sn/klconfig.h @@ -78,7 +78,7 @@ typedef s32 klconf_off_t; */ #define MAX_SLOTS_PER_NODE (1 + 2 + 6 + 2) -/* XXX if each node is guranteed to have some memory */ +/* XXX if each node is guaranteed to have some memory */ #define MAX_PCI_DEVS 8 @@ -539,7 +539,7 @@ typedef struct klinfo_s { /* Generic info */ #define KLSTRUCT_IOC3_TTY 24 /* Early Access IO proms are compatible - only with KLSTRUCT values upto 24. */ + only with KLSTRUCT values up to 24. */ #define KLSTRUCT_FIBERCHANNEL 25 #define KLSTRUCT_MOD_SERIAL_NUM 26 diff --git a/arch/mips/include/asm/sn/sn0/hubio.h b/arch/mips/include/asm/sn/sn0/hubio.h index 31c76c021bb6..46286d8302a7 100644 --- a/arch/mips/include/asm/sn/sn0/hubio.h +++ b/arch/mips/include/asm/sn/sn0/hubio.h @@ -622,7 +622,7 @@ typedef union h1_icrbb_u { */ #define IIO_ICRB_PROC0 0 /* Source of request is Proc 0 */ #define IIO_ICRB_PROC1 1 /* Source of request is Proc 1 */ -#define IIO_ICRB_GB_REQ 2 /* Source is Guranteed BW request */ +#define IIO_ICRB_GB_REQ 2 /* Source is Guaranteed BW request */ #define IIO_ICRB_IO_REQ 3 /* Source is Normal IO request */ /* diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index 58730c5ce4bf..b4ba2449444b 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -346,7 +346,7 @@ * we can't dispatch it directly without trashing * some registers, so we'll try to detect this unlikely * case and program a software interrupt in the VPE, - * as would be done for a cross-VPE IPI. To accomodate + * as would be done for a cross-VPE IPI. To accommodate * the handling of that case, we're doing a DVPE instead * of just a DMT here to protect against other threads. * This is a lot of cruft to cover a tiny window. diff --git a/arch/mips/include/asm/war.h b/arch/mips/include/asm/war.h index 22361d5e3bf0..fa133c1bc1f9 100644 --- a/arch/mips/include/asm/war.h +++ b/arch/mips/include/asm/war.h @@ -227,7 +227,7 @@ #endif /* - * On the R10000 upto version 2.6 (not sure about 2.7) there is a bug that + * On the R10000 up to version 2.6 (not sure about 2.7) there is a bug that * may cause ll / sc and lld / scd sequences to execute non-atomically. */ #ifndef R10000_LLSC_WAR diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index bc18daaa8f84..c3b04be3fb2b 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -65,7 +65,7 @@ static struct nand_ecclayout qi_lb60_ecclayout_1gb = { }; /* Early prototypes of the QI LB60 had only 1GB of NAND. - * In order to support these devices aswell the partition and ecc layout is + * In order to support these devices as well the partition and ecc layout is * initialized depending on the NAND size */ static struct mtd_partition qi_lb60_partitions_1gb[] = { { @@ -439,7 +439,7 @@ static struct platform_device *jz_platform_devices[] __initdata = { static void __init board_gpio_setup(void) { /* We only need to enable/disable pullup here for pins used in generic - * drivers. Everything else is done by the drivers themselfs. */ + * drivers. Everything else is done by the drivers themselves. */ jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N); jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD); } diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index b8bb8ba60869..f305ca14351b 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -73,7 +73,7 @@ static inline void mult_sh_align_mod(long *v1, long *v2, long *w, : "0" (5), "1" (8), "2" (5)); align_mod(align, mod); /* - * The trailing nop is needed to fullfill the two-instruction + * The trailing nop is needed to fulfill the two-instruction * requirement between reading hi/lo and staring a mult/div. * Leaving it out may cause gas insert a nop itself breaking * the desired alignment of the next chunk. diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index d9a7db78ed62..75266ff4cc33 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -721,7 +721,7 @@ static void mipsxx_pmu_start(void) /* * MIPS performance counters can be per-TC. The control registers can - * not be directly accessed accross CPUs. Hence if we want to do global + * not be directly accessed across CPUs. Hence if we want to do global * control, we need cross CPU calls. on_each_cpu() can help us, but we * can not make sure this function is called with interrupts enabled. So * here we pause local counters and then grab a rwlock and leave the diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index ae167df73ddd..d2112d3cf115 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -410,7 +410,7 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, if (!kallsyms_lookup_size_offset(pc, &size, &ofs)) return 0; /* - * Return ra if an exception occured at the first instruction + * Return ra if an exception occurred at the first instruction */ if (unlikely(ofs == 0)) { pc = *ra; diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index c0e81418ba21..1ec56e635d04 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -120,7 +120,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action) local_irq_save(flags); - vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */ + vpflags = dvpe(); /* can't access the other CPU's registers whilst MVPE enabled */ switch (action) { case SMP_CALL_FUNCTION: diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index fb7497405510..1083ad4e1017 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -102,7 +102,7 @@ static __init int cpu_has_mfc0_count_bug(void) case CPU_R4400SC: case CPU_R4400MC: /* - * The published errata for the R4400 upto 3.0 say the CPU + * The published errata for the R4400 up to 3.0 say the CPU * has the mfc0 from count bug. */ if ((current_cpu_data.processor_id & 0xff) <= 0x30) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index ab52b7cf3b6b..dbb6b408f001 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -19,7 +19,7 @@ * VPE support module * * Provides support for loading a MIPS SP program on VPE1. - * The SP enviroment is rather simple, no tlb's. It needs to be relocatable + * The SP environment is rather simple, no tlb's. It needs to be relocatable * (or partially linked). You should initialise your stack in the startup * code. This loader looks for the symbol __start and sets up * execution to resume from there. The MIPS SDE kit contains suitable examples. diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S index c768e3000616..64457162f7e0 100644 --- a/arch/mips/lib/strnlen_user.S +++ b/arch/mips/lib/strnlen_user.S @@ -17,7 +17,7 @@ .previous /* - * Return the size of a string including the ending NUL character upto a + * Return the size of a string including the ending NUL character up to a * maximum of a1 or 0 in case of error. * * Note: for performance reasons we deliberately accept that a user may diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index 1dfbd92ba9d0..daed6834dc15 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -62,7 +62,7 @@ ieee754dp ieee754dp_fsp(ieee754sp x) break; } - /* CANT possibly overflow,underflow, or need rounding + /* CAN'T possibly overflow,underflow, or need rounding */ /* drop the hidden bit */ diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index aa566e785f5a..09175f461920 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -104,7 +104,7 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y) case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): break; } - /* rm = xm * ym, re = xe+ye basicly */ + /* rm = xm * ym, re = xe+ye basically */ assert(xm & DP_HIDDEN_BIT); assert(ym & DP_HIDDEN_BIT); { diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 36d975ae08f8..3c4a8c5ba7f2 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -32,7 +32,7 @@ * not change cp0_epc due to the instruction * * According to the spec: - * 1) it shouldnt be a branch :-) + * 1) it shouldn't be a branch :-) * 2) it can be a COP instruction :-( * 3) if we are tring to run a protected memory space we must take * special care on memory access instructions :-( diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index c06bb4022be5..2722a2570ea4 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -104,7 +104,7 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): break; } - /* rm = xm * ym, re = xe+ye basicly */ + /* rm = xm * ym, re = xe+ye basically */ assert(xm & SP_HIDDEN_BIT); assert(ym & SP_HIDDEN_BIT); diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S index 2d08268bb705..89c412bc4b64 100644 --- a/arch/mips/mm/cex-sb1.S +++ b/arch/mips/mm/cex-sb1.S @@ -79,7 +79,7 @@ LEAF(except_vec2_sb1) recovered_dcache: /* * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA). - * Ought to log the occurence of this recovered dcache error. + * Ought to log the occurrence of this recovered dcache error. */ b recovered mtc0 $0,C0_CERR_D diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 04f9e17db9d0..5ef294fbb6e7 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -352,7 +352,7 @@ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) /* * Write random or indexed TLB entry, and care about the hazards from - * the preceeding mtc0 and for the following eret. + * the preceding mtc0 and for the following eret. */ enum tlb_write_entry { tlb_random, tlb_indexed }; diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c index e67891521ac1..49a38b09a488 100644 --- a/arch/mips/mti-malta/malta-smtc.c +++ b/arch/mips/mti-malta/malta-smtc.c @@ -130,7 +130,7 @@ int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, * cleared in the affinity mask, there will never be any * interrupt forwarding. But as soon as a program or operator * sets affinity for one of the related IRQs, we need to make - * sure that we don't ever try to forward across the VPE boundry, + * sure that we don't ever try to forward across the VPE boundary, * at least not until we engineer a system where the interrupt * _ack() or _end() function can somehow know that it corresponds * to an interrupt taken on another VPE, and perform the appropriate diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 68798f869c0f..8fbfbf2b931c 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -344,7 +344,7 @@ static irqreturn_t bpci_interrupt(int irq, void *dev_id) * PCI_ACCESS_WRITE and PCI_ACCESS_READ. * * bus - pointer to the bus number of the device to - * be targetted for the configuration cycle. + * be targeted for the configuration cycle. * The only element of the pci_bus structure * used is bus->number. This argument determines * if the configuration access will be Type 0 or @@ -354,7 +354,7 @@ static irqreturn_t bpci_interrupt(int irq, void *dev_id) * * devfn - this is an 8-bit field. The lower three bits * specify the function number of the device to - * be targetted for the configuration cycle, with + * be targeted for the configuration cycle, with * all three-bit combinations being legal. The * upper five bits specify the device number, * with legal values being 10 to 31. diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index 6f5e24c6ae67..af8c31996965 100644 --- a/arch/mips/pci/pci-bcm1480.c +++ b/arch/mips/pci/pci-bcm1480.c @@ -210,7 +210,7 @@ static int __init bcm1480_pcibios_init(void) PCIBIOS_MIN_IO = 0x00008000UL; PCIBIOS_MIN_MEM = 0x01000000UL; - /* Set I/O resource limits. - unlimited for now to accomodate HT */ + /* Set I/O resource limits. - unlimited for now to accommodate HT */ ioport_resource.end = 0xffffffffUL; iomem_resource.end = 0xffffffffUL; diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c index 2d74fc9ae3ba..ed1c54284b8f 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c @@ -441,7 +441,7 @@ static void octeon_pci_initialize(void) /* * TDOMC must be set to one in PCI mode. TDOMC should be set to 4 - * in PCI-X mode to allow four oustanding splits. Otherwise, + * in PCI-X mode to allow four outstanding splits. Otherwise, * should not change from its reset value. Don't write PCI_CFG19 * in PCI mode (0x82000001 reset value), write it to 0x82000004 * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero. @@ -515,7 +515,7 @@ static void octeon_pci_initialize(void) #endif /* USE_OCTEON_INTERNAL_ARBITER */ /* - * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE, + * Preferably written to 1 to set MLTD. [RDSATI,TRTAE, * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to * 1..7. */ diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 38bc28005b4a..33bba7bff258 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -125,7 +125,7 @@ void __devinit register_pci_controller(struct pci_controller *hose) hose_tail = &hose->next; /* - * Do not panic here but later - this might hapen before console init. + * Do not panic here but later - this might happen before console init. */ if (!hose->io_map_base) { printk(KERN_WARNING diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c index fb37a10e0309..2413ea67877e 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_setup.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c @@ -239,7 +239,7 @@ void __init prom_init(void) #ifdef CONFIG_PMCTWILED /* * Setup LED states before the subsys_initcall loads other - * dependant drivers/modules. + * dependent drivers/modules. */ pmctwiled_setup(); #endif diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index ce45df17fd09..87167dcc79fa 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c @@ -165,7 +165,7 @@ static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { { .base = PNX833X_I2C0_PORTS_START, .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ - .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */ + .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Preferred HDCP) */ .bus_addr = 0, /* no slave support */ }, { diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig index 5e960ae9735a..bc5e9769bb73 100644 --- a/arch/mips/sgi-ip27/Kconfig +++ b/arch/mips/sgi-ip27/Kconfig @@ -1,7 +1,7 @@ #config SGI_SN0_XXL # bool "IP27 XXL" # depends on SGI_IP27 -# This options adds support for userspace processes upto 16TB size. +# This options adds support for userspace processes up to 16TB size. # Normally the limit is just .5TB. choice diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO index 19f1512c8f2e..160857ff1483 100644 --- a/arch/mips/sgi-ip27/TODO +++ b/arch/mips/sgi-ip27/TODO @@ -13,7 +13,7 @@ being invoked on all nodes in ip27-memory.c. 9. start_thread must turn off UX64 ... and define tlb_refill_debug. 10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable does not agree with pgd_bad/pmd_bad. -11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node. +11. All intrs (ip27_do_irq handlers) are targeted at cpu A on the node. This might need to change later. Only the timer intr is set up to be received on both Cpu A and B. (ip27_do_irq()/bridge_startup()) 13. Cache flushing (specially the SMP version) has to be investigated. diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 51d3a4f2d7e1..923c080f77bd 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -93,7 +93,7 @@ static void __cpuinit per_hub_init(cnodeid_t cnode) /* * Some interrupts are reserved by hardware or by software convention. - * Mark these as reserved right away so they won't be used accidently + * Mark these as reserved right away so they won't be used accidentally * later. */ for (i = 0; i <= BASE_PCI_IRQ; i++) { diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 11488719dd97..0a04603d577c 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -41,7 +41,7 @@ * Linux has a controller-independent x86 interrupt architecture. * every controller has a 'controller-template', that is used * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate + * interrupt source is transparently wired to the appropriate * controller. Thus drivers need not be aware of the * interrupt-controller. * diff --git a/arch/mn10300/include/asm/cpu-regs.h b/arch/mn10300/include/asm/cpu-regs.h index 90ed4a365c97..c54effae2202 100644 --- a/arch/mn10300/include/asm/cpu-regs.h +++ b/arch/mn10300/include/asm/cpu-regs.h @@ -49,7 +49,7 @@ asm(" .am33_2\n"); #define EPSW_IM_6 0x00000600 /* interrupt mode 6 */ #define EPSW_IM_7 0x00000700 /* interrupt mode 7 */ #define EPSW_IE 0x00000800 /* interrupt enable */ -#define EPSW_S 0x00003000 /* software auxilliary bits */ +#define EPSW_S 0x00003000 /* software auxiliary bits */ #define EPSW_T 0x00008000 /* trace enable */ #define EPSW_nSL 0x00010000 /* not supervisor level */ #define EPSW_NMID 0x00020000 /* nonmaskable interrupt disable */ diff --git a/arch/parisc/include/asm/eisa_eeprom.h b/arch/parisc/include/asm/eisa_eeprom.h index 9c9da980402a..8ce8b85ca588 100644 --- a/arch/parisc/include/asm/eisa_eeprom.h +++ b/arch/parisc/include/asm/eisa_eeprom.h @@ -27,7 +27,7 @@ struct eeprom_header u_int8_t ver_maj; u_int8_t ver_min; u_int8_t num_slots; /* number of EISA slots in system */ - u_int16_t csum; /* checksum, I don't know how to calulate this */ + u_int16_t csum; /* checksum, I don't know how to calculate this */ u_int8_t pad[10]; } __attribute__ ((packed)); diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index e5477092a5d4..ead8d2a1034c 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -187,8 +187,8 @@ /* Register definitions for tlb miss handler macros */ - va = r8 /* virtual address for which the trap occured */ - spc = r24 /* space for which the trap occured */ + va = r8 /* virtual address for which the trap occurred */ + spc = r24 /* space for which the trap occurred */ #ifndef CONFIG_64BIT @@ -882,7 +882,7 @@ ENTRY(syscall_exit_rfi) * (we don't store them in the sigcontext), so set them * to "proper" values now (otherwise we'll wind up restoring * whatever was last stored in the task structure, which might - * be inconsistent if an interrupt occured while on the gateway + * be inconsistent if an interrupt occurred while on the gateway * page). Note that we may be "trashing" values the user put in * them, but we don't support the user changing them. */ @@ -1156,11 +1156,11 @@ ENDPROC(intr_save) */ t0 = r1 /* temporary register 0 */ - va = r8 /* virtual address for which the trap occured */ + va = r8 /* virtual address for which the trap occurred */ t1 = r9 /* temporary register 1 */ pte = r16 /* pte/phys page # */ prot = r17 /* prot bits */ - spc = r24 /* space for which the trap occured */ + spc = r24 /* space for which the trap occurred */ ptp = r25 /* page directory/page table pointer */ #ifdef CONFIG_64BIT diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index 4dbdf0ed6fa0..145c5e4caaa0 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -131,7 +131,7 @@ $pgt_fill_loop: ldo THREAD_SZ_ALGN(%r6),%sp #ifdef CONFIG_SMP - /* Set the smp rendevous address into page zero. + /* Set the smp rendezvous address into page zero. ** It would be safer to do this in init_smp_config() but ** it's just way easier to deal with here because ** of 64-bit function ptrs and the address is local to this file. diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index d228d8237879..08324aac3544 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -93,7 +93,7 @@ void __init setup_pdc(void) case 0x6: /* 705, 710 */ case 0x7: /* 715, 725 */ case 0x8: /* 745, 747, 742 */ - case 0xA: /* 712 and similiar */ + case 0xA: /* 712 and similar */ case 0xC: /* 715/64, at least */ pdc_type = PDC_TYPE_SNAKE; diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 609a331878e7..12c1ed33dc18 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -291,7 +291,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc); DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall); - /* FIXME: Should probably be converted aswell for the compat case */ + /* FIXME: Should probably be converted as well for the compat case */ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); } diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 68e75ce838d6..82a52b2fb13f 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -605,7 +605,7 @@ cas_action: copy %r0, %r21 3: - /* Error occured on load or store */ + /* Error occurred on load or store */ /* Free lock */ stw %r20, 0(%sr2,%r20) #if ENABLE_LWS_DEBUG diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 74867dfdabe5..4be85ee10b85 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -34,7 +34,7 @@ /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific * implementation is required on wide palinux. Use ENTRY_COMP where - * the compatability layer has a useful 32-bit implementation. + * the compatibility layer has a useful 32-bit implementation. */ #define ENTRY_SAME(_name_) .dword sys_##_name_ #define ENTRY_DIFF(_name_) .dword sys32_##_name_ diff --git a/arch/parisc/math-emu/dfadd.c b/arch/parisc/math-emu/dfadd.c index e147d7d3b0f4..d37e2d2cb6fe 100644 --- a/arch/parisc/math-emu/dfadd.c +++ b/arch/parisc/math-emu/dfadd.c @@ -303,7 +303,7 @@ dbl_fadd( if(Dbl_iszero_hidden(resultp1)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the result + /* A straight forward algorithm would now shift the result * and extension left until the hidden bit becomes one. Not * all of the extension bits need participate in the shift. * Only the two most significant bits (round and guard) are diff --git a/arch/parisc/math-emu/dfsub.c b/arch/parisc/math-emu/dfsub.c index 87ebc60d465b..2e8b5a79bff7 100644 --- a/arch/parisc/math-emu/dfsub.c +++ b/arch/parisc/math-emu/dfsub.c @@ -306,7 +306,7 @@ dbl_fsub( if(Dbl_iszero_hidden(resultp1)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the result + /* A straight forward algorithm would now shift the result * and extension left until the hidden bit becomes one. Not * all of the extension bits need participate in the shift. * Only the two most significant bits (round and guard) are diff --git a/arch/parisc/math-emu/fmpyfadd.c b/arch/parisc/math-emu/fmpyfadd.c index 5dd7f93a89be..b067c45c872d 100644 --- a/arch/parisc/math-emu/fmpyfadd.c +++ b/arch/parisc/math-emu/fmpyfadd.c @@ -531,7 +531,7 @@ dbl_fmpyfadd( sign_save = Dbl_signextendedsign(resultp1); if (Dbl_iszero_hidden(resultp1)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the + /* A straightforward algorithm would now shift the * result and extension left until the hidden bit * becomes one. Not all of the extension bits need * participate in the shift. Only the two most @@ -1191,7 +1191,7 @@ unsigned int *status; sign_save = Dbl_signextendedsign(resultp1); if (Dbl_iszero_hidden(resultp1)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the + /* A straightforward algorithm would now shift the * result and extension left until the hidden bit * becomes one. Not all of the extension bits need * participate in the shift. Only the two most @@ -1841,7 +1841,7 @@ unsigned int *status; sign_save = Sgl_signextendedsign(resultp1); if (Sgl_iszero_hidden(resultp1)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the + /* A straightforward algorithm would now shift the * result and extension left until the hidden bit * becomes one. Not all of the extension bits need * participate in the shift. Only the two most @@ -2483,7 +2483,7 @@ unsigned int *status; sign_save = Sgl_signextendedsign(resultp1); if (Sgl_iszero_hidden(resultp1)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the + /* A straightforward algorithm would now shift the * result and extension left until the hidden bit * becomes one. Not all of the extension bits need * participate in the shift. Only the two most diff --git a/arch/parisc/math-emu/sfadd.c b/arch/parisc/math-emu/sfadd.c index 008d721b5d22..f802cd6c7869 100644 --- a/arch/parisc/math-emu/sfadd.c +++ b/arch/parisc/math-emu/sfadd.c @@ -298,7 +298,7 @@ sgl_fadd( if(Sgl_iszero_hidden(result)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the result + /* A straightforward algorithm would now shift the result * and extension left until the hidden bit becomes one. Not * all of the extension bits need participate in the shift. * Only the two most significant bits (round and guard) are diff --git a/arch/parisc/math-emu/sfsub.c b/arch/parisc/math-emu/sfsub.c index 24eef61c8e3b..5f90d0f31a52 100644 --- a/arch/parisc/math-emu/sfsub.c +++ b/arch/parisc/math-emu/sfsub.c @@ -301,7 +301,7 @@ sgl_fsub( if(Sgl_iszero_hidden(result)) { /* Handle normalization */ - /* A straight foward algorithm would now shift the result + /* A straightforward algorithm would now shift the result * and extension left until the hidden bit becomes one. Not * all of the extension bits need participate in the shift. * Only the two most significant bits (round and guard) are diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index 2e561876fc89..f18c6d9b9510 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -209,8 +209,8 @@ static __inline__ unsigned long ffz(unsigned long x) return BITS_PER_LONG; /* - * Calculate the bit position of the least signficant '1' bit in x - * (since x has been changed this will actually be the least signficant + * Calculate the bit position of the least significant '1' bit in x + * (since x has been changed this will actually be the least significant * '0' bit in * the original x). Note: (x & -x) gives us a mask that * is the least significant * (RIGHT-most) 1-bit of the value in x. */ diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 2296112e247b..91010e8f8479 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -140,7 +140,7 @@ static inline void __user *arch_compat_alloc_user_space(long len) unsigned long usp = regs->gpr[1]; /* - * We cant access below the stack pointer in the 32bit ABI and + * We can't access below the stack pointer in the 32bit ABI and * can access 288 bytes in the 64bit ABI */ if (!is_32bit_task()) diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index e50323fe941f..4398a6cdcf53 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h @@ -98,7 +98,7 @@ typedef struct cpm_buf_desc { #define BD_SC_INTRPT (0x1000) /* Interrupt on change */ #define BD_SC_LAST (0x0800) /* Last buffer in frame */ #define BD_SC_TC (0x0400) /* Transmit CRC */ -#define BD_SC_CM (0x0200) /* Continous mode */ +#define BD_SC_CM (0x0200) /* Continuous mode */ #define BD_SC_ID (0x0100) /* Rec'd too many idles */ #define BD_SC_P (0x0100) /* xmt preamble */ #define BD_SC_BR (0x0020) /* Break received */ diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index bd07650dca56..8ee4211ca0c6 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h @@ -4,7 +4,7 @@ * * This file contains structures and information for the communication * processor channels. Some CPM control and status is available - * throught the MPC8xx internal memory map. See immap.h for details. + * through the MPC8xx internal memory map. See immap.h for details. * This file only contains what I need for the moment, not the total * CPM capabilities. I (or someone else) will add definitions as they * are needed. -- Dan diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index ec089acfa56b..8edec710cc6d 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -122,7 +122,7 @@ #define H_DABRX_KERNEL (1UL<<(63-62)) #define H_DABRX_USER (1UL<<(63-63)) -/* Each control block has to be on a 4K bondary */ +/* Each control block has to be on a 4K boundary */ #define H_CB_ALIGNMENT 4096 /* pSeries hypervisor opcodes */ diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h index d0e7701fa1f6..be0171afdc0f 100644 --- a/arch/powerpc/include/asm/kprobes.h +++ b/arch/powerpc/include/asm/kprobes.h @@ -50,7 +50,7 @@ typedef unsigned int kprobe_opcode_t; * Handle cases where: * - User passes a <.symbol> or * - User passes a or - * - User passes a non-existant symbol, kallsyms_lookup_name + * - User passes a non-existent symbol, kallsyms_lookup_name * returns 0. Don't deref the NULL pointer in that case */ #define kprobe_lookup_name(name, addr) \ diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h index 26b8c807f8f1..a077adc0b35e 100644 --- a/arch/powerpc/include/asm/lppaca.h +++ b/arch/powerpc/include/asm/lppaca.h @@ -105,7 +105,7 @@ struct lppaca { // processing of external interrupts. Note that PLIC will store the // XIRR directly into the xXirrValue field so that another XIRR will // not be presented until this one clears. The layout of the low - // 4-bytes of this Dword is upto SLIC - PLIC just checks whether the + // 4-bytes of this Dword is up to SLIC - PLIC just checks whether the // entire Dword is zero or not. A non-zero value in the low order // 2-bytes will result in SLIC being granted the highest thread // priority upon return. A 0 will return to SLIC as medium priority. diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index 932f88dcf6fa..812b2cd80aed 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h @@ -169,7 +169,7 @@ do { \ /* * This is the default if a program doesn't have a PT_GNU_STACK * program header entry. The PPC64 ELF ABI has a non executable stack - * stack by default, so in the absense of a PT_GNU_STACK program header + * stack by default, so in the absence of a PT_GNU_STACK program header * we turn execute permission off. */ #define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ diff --git a/arch/powerpc/include/asm/pasemi_dma.h b/arch/powerpc/include/asm/pasemi_dma.h index 19fd7933e2d9..eafa5a5f56de 100644 --- a/arch/powerpc/include/asm/pasemi_dma.h +++ b/arch/powerpc/include/asm/pasemi_dma.h @@ -522,7 +522,7 @@ extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size, extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size, dma_addr_t *handle); -/* Routines to allocate flags (events) for channel syncronization */ +/* Routines to allocate flags (events) for channel synchronization */ extern int pasemi_dma_alloc_flag(void); extern void pasemi_dma_free_flag(int flag); extern void pasemi_dma_set_flag(int flag); diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 5e156e034fe2..b90dbf8e5cd9 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -106,7 +106,7 @@ struct pci_controller { * Used for variants of PCI indirect handling and possible quirks: * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1 * EXT_REG - provides access to PCI-e extended registers - * SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS + * SURPRESS_PRIMARY_BUS - we suppress the setting of PCI_PRIMARY_BUS * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS * to determine which bus number to match on when generating type0 * config cycles diff --git a/arch/powerpc/include/asm/pmac_feature.h b/arch/powerpc/include/asm/pmac_feature.h index 00eedc5a4e61..10902c9375d0 100644 --- a/arch/powerpc/include/asm/pmac_feature.h +++ b/arch/powerpc/include/asm/pmac_feature.h @@ -53,8 +53,8 @@ /* Here is the infamous serie of OHare based machines */ -#define PMAC_TYPE_COMET 0x20 /* Beleived to be PowerBook 2400 */ -#define PMAC_TYPE_HOOPER 0x21 /* Beleived to be PowerBook 3400 */ +#define PMAC_TYPE_COMET 0x20 /* Believed to be PowerBook 2400 */ +#define PMAC_TYPE_HOOPER 0x21 /* Believed to be PowerBook 3400 */ #define PMAC_TYPE_KANGA 0x22 /* PowerBook 3500 (first G3) */ #define PMAC_TYPE_ALCHEMY 0x23 /* Alchemy motherboard base */ #define PMAC_TYPE_GAZELLE 0x24 /* Spartacus, some 5xxx/6xxx */ diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index 76bb195e4f24..811f04ac3660 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h @@ -86,7 +86,7 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); #define PTE_RPN_MASK (~((1UL< #include -/* The physical memory is layed out such that the secondary processor +/* The physical memory is laid out such that the secondary processor * spin code sits at 0x0000...0x00ff. On server, the vectors follow * using the layout described in exceptions-64s.S */ diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 3e02710d9562..5ecf54cfa7d4 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -326,7 +326,7 @@ interrupt_base: NORMAL_EXCEPTION_PROLOG EXC_XFER_EE_LITE(0x0c00, DoSyscall) - /* Auxillary Processor Unavailable Interrupt */ + /* Auxiliary Processor Unavailable Interrupt */ EXCEPTION(0x2900, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE) /* Decrementer Interrupt */ diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S index 2a2f3c3f6d80..97ec8557f974 100644 --- a/arch/powerpc/kernel/l2cr_6xx.S +++ b/arch/powerpc/kernel/l2cr_6xx.S @@ -151,7 +151,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) /**** Might be a good idea to set L2DO here - to prevent instructions from getting into the cache. But since we invalidate the next time we enable the cache it doesn't really matter. - Don't do this unless you accomodate all processor variations. + Don't do this unless you accommodate all processor variations. The bit moved on the 7450..... ****/ diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 16468362ad57..301db65f05a1 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -262,7 +262,7 @@ static void parse_ppp_data(struct seq_file *m) seq_printf(m, "system_active_processors=%d\n", ppp_data.active_system_procs); - /* pool related entries are apropriate for shared configs */ + /* pool related entries are appropriate for shared configs */ if (lppaca_of(0).shared_proc) { unsigned long pool_idle_time, pool_procs; diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index 97e0ae414940..c4063b7f49a0 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c @@ -759,7 +759,7 @@ static int power_pmu_add(struct perf_event *event, int ef_flags) /* * If group events scheduling transaction was started, - * skip the schedulability test here, it will be peformed + * skip the schedulability test here, it will be performed * at commit time(->commit_txn) as a whole */ if (cpuhw->group_flag & PERF_EVENT_TXN) diff --git a/arch/powerpc/kernel/ppc_save_regs.S b/arch/powerpc/kernel/ppc_save_regs.S index e83ba3f078e4..1b1787d52896 100644 --- a/arch/powerpc/kernel/ppc_save_regs.S +++ b/arch/powerpc/kernel/ppc_save_regs.S @@ -15,7 +15,7 @@ /* * Grab the register values as they are now. - * This won't do a particularily good job because we really + * This won't do a particularly good job because we really * want our caller's caller's registers, and our caller has * already executed its prologue. * ToDo: We could reach back into the caller's save area to do diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 05b7139d6a27..e74fa12afc82 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -683,7 +683,7 @@ void __init early_init_devtree(void *params) #endif #ifdef CONFIG_PHYP_DUMP - /* scan tree to see if dump occured during last boot */ + /* scan tree to see if dump occurred during last boot */ of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL); #endif @@ -739,7 +739,7 @@ void __init early_init_devtree(void *params) DBG("Scanning CPUs ...\n"); - /* Retreive CPU related informations from the flat tree + /* Retrieve CPU related informations from the flat tree * (altivec support, boot CPU ID, ...) */ of_scan_flat_dt(early_init_dt_scan_cpus, NULL); diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 895b082f1e48..55613e33e263 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -463,7 +463,7 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset, #ifdef CONFIG_VSX /* * Currently to set and and get all the vsx state, you need to call - * the fp and VMX calls aswell. This only get/sets the lower 32 + * the fp and VMX calls as well. This only get/sets the lower 32 * 128bit VSX registers. */ diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 7980ec0e1e1a..67f6c3b51357 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -465,7 +465,7 @@ static void start_event_scan(void) pr_debug("rtasd: will sleep for %d milliseconds\n", (30000 / rtas_event_scan_rate)); - /* Retreive errors from nvram if any */ + /* Retrieve errors from nvram if any */ retreive_nvram_error_log(); schedule_delayed_work_on(cpumask_first(cpu_online_mask), diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S index b0754e237438..ba4dee3d233f 100644 --- a/arch/powerpc/kernel/swsusp_32.S +++ b/arch/powerpc/kernel/swsusp_32.S @@ -143,7 +143,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) /* Disable MSR:DR to make sure we don't take a TLB or * hash miss during the copy, as our hash table will - * for a while be unuseable. For .text, we assume we are + * for a while be unusable. For .text, we assume we are * covered by a BAT. This works only for non-G5 at this * point. G5 will need a better approach, possibly using * a small temporary hash table filled with large mappings, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index bd74fac169be..5ddb801bc154 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -959,7 +959,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) * ESR_DST (!?) or 0. In the process of chasing this with the * hardware people - not sure if it can happen on any illegal * instruction or only on FP instructions, whether there is a - * pattern to occurences etc. -dgibson 31/Mar/2003 */ + * pattern to occurrences etc. -dgibson 31/Mar/2003 */ switch (do_mathemu(regs)) { case 0: emulate_single_step(regs); diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index b4b167b33643..baa33a7517bc 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -1,5 +1,5 @@ /* - * udbg for NS16550 compatable serial ports + * udbg for NS16550 compatible serial ports * * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp * diff --git a/arch/powerpc/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S index 68d49dd71dcc..cf0c9c9c24f9 100644 --- a/arch/powerpc/kernel/vdso32/sigtramp.S +++ b/arch/powerpc/kernel/vdso32/sigtramp.S @@ -19,7 +19,7 @@ /* The nop here is a hack. The dwarf2 unwind routines subtract 1 from the return address to get an address in the middle of the presumed - call instruction. Since we don't have a call here, we artifically + call instruction. Since we don't have a call here, we artificially extend the range covered by the unwind info by adding a nop before the real start. */ nop diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S index 59eb59bb4082..45ea281e9a21 100644 --- a/arch/powerpc/kernel/vdso64/sigtramp.S +++ b/arch/powerpc/kernel/vdso64/sigtramp.S @@ -20,7 +20,7 @@ /* The nop here is a hack. The dwarf2 unwind routines subtract 1 from the return address to get an address in the middle of the presumed - call instruction. Since we don't have a call here, we artifically + call instruction. Since we don't have a call here, we artificially extend the range covered by the unwind info by padding before the real start. */ nop diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 3079f6b44cf5..5b7dd4ea02b5 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -192,8 +192,8 @@ htab_insert_pte: rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ - mr r4,r29 /* Retreive va */ + ld r6,STK_PARM(r4)(r1) /* Retrieve new pp bits */ + mr r4,r29 /* Retrieve va */ li r7,0 /* !bolted, !secondary */ li r8,MMU_PAGE_4K /* page size */ ld r9,STK_PARM(r9)(r1) /* segment size */ @@ -215,8 +215,8 @@ _GLOBAL(htab_call_hpte_insert1) rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ - mr r4,r29 /* Retreive va */ + ld r6,STK_PARM(r4)(r1) /* Retrieve new pp bits */ + mr r4,r29 /* Retrieve va */ li r7,HPTE_V_SECONDARY /* !bolted, secondary */ li r8,MMU_PAGE_4K /* page size */ ld r9,STK_PARM(r9)(r1) /* segment size */ @@ -495,8 +495,8 @@ htab_special_pfn: rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ - mr r4,r29 /* Retreive va */ + ld r6,STK_PARM(r4)(r1) /* Retrieve new pp bits */ + mr r4,r29 /* Retrieve va */ li r7,0 /* !bolted, !secondary */ li r8,MMU_PAGE_4K /* page size */ ld r9,STK_PARM(r9)(r1) /* segment size */ @@ -522,8 +522,8 @@ _GLOBAL(htab_call_hpte_insert1) rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ - mr r4,r29 /* Retreive va */ + ld r6,STK_PARM(r4)(r1) /* Retrieve new pp bits */ + mr r4,r29 /* Retrieve va */ li r7,HPTE_V_SECONDARY /* !bolted, secondary */ li r8,MMU_PAGE_4K /* page size */ ld r9,STK_PARM(r9)(r1) /* segment size */ @@ -813,8 +813,8 @@ ht64_insert_pte: rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ - mr r4,r29 /* Retreive va */ + ld r6,STK_PARM(r4)(r1) /* Retrieve new pp bits */ + mr r4,r29 /* Retrieve va */ li r7,0 /* !bolted, !secondary */ li r8,MMU_PAGE_64K ld r9,STK_PARM(r9)(r1) /* segment size */ @@ -836,8 +836,8 @@ _GLOBAL(ht64_call_hpte_insert1) rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ - mr r4,r29 /* Retreive va */ + ld r6,STK_PARM(r4)(r1) /* Retrieve new pp bits */ + mr r4,r29 /* Retrieve va */ li r7,HPTE_V_SECONDARY /* !bolted, secondary */ li r8,MMU_PAGE_64K ld r9,STK_PARM(r9)(r1) /* segment size */ diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index a5991facddce..58a022d0f463 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -753,7 +753,7 @@ void __cpuinit early_init_mmu_secondary(void) mtspr(SPRN_SDR1, _SDR1); /* Initialize STAB/SLB. We use a virtual address as it works - * in real mode on pSeries and we want a virutal address on + * in real mode on pSeries and we want a virtual address on * iSeries anyway */ if (cpu_has_feature(CPU_FTR_SLB)) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index a66499650909..57e545b84bf1 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -424,7 +424,7 @@ void clear_user_page(void *page, unsigned long vaddr, struct page *pg) clear_page(page); /* - * We shouldnt have to do this, but some versions of glibc + * We shouldn't have to do this, but some versions of glibc * require it (ld.so assumes zero filled pages are icache clean) * - Anton */ diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 0dc95c0aa3be..5ec1dad2a19d 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -440,11 +440,11 @@ static void read_drconf_cell(struct of_drconf_cell *drmem, const u32 **cellp) } /* - * Retreive and validate the ibm,dynamic-memory property of the device tree. + * Retrieve and validate the ibm,dynamic-memory property of the device tree. * * The layout of the ibm,dynamic-memory property is a number N of memblock * list entries followed by N memblock list entries. Each memblock list entry - * contains information as layed out in the of_drconf_cell struct above. + * contains information as laid out in the of_drconf_cell struct above. */ static int of_get_drconf_memory(struct device_node *memory, const u32 **dm) { @@ -468,7 +468,7 @@ static int of_get_drconf_memory(struct device_node *memory, const u32 **dm) } /* - * Retreive and validate the ibm,lmb-size property for drconf memory + * Retrieve and validate the ibm,lmb-size property for drconf memory * from the device tree. */ static u64 of_get_lmb_size(struct device_node *memory) @@ -490,7 +490,7 @@ struct assoc_arrays { }; /* - * Retreive and validate the list of associativity arrays for drconf + * Retrieve and validate the list of associativity arrays for drconf * memory from the ibm,associativity-lookup-arrays property of the * device tree.. * @@ -604,7 +604,7 @@ static int __cpuinit cpu_numa_callback(struct notifier_block *nfb, * Returns the size the region should have to enforce the memory limit. * This will either be the original value of size, a truncated value, * or zero. If the returned value of size is 0 the region should be - * discarded as it lies wholy above the memory limit. + * discarded as it lies wholly above the memory limit. */ static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size) diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S index 8526bd9d2aa3..33cf704e4e1b 100644 --- a/arch/powerpc/mm/tlb_low_64e.S +++ b/arch/powerpc/mm/tlb_low_64e.S @@ -192,7 +192,7 @@ normal_tlb_miss: or r10,r15,r14 BEGIN_MMU_FTR_SECTION - /* Set the TLB reservation and seach for existing entry. Then load + /* Set the TLB reservation and search for existing entry. Then load * the entry. */ PPC_TLBSRX_DOT(0,r16) @@ -425,7 +425,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_TLBRSRV) virt_page_table_tlb_miss_fault: /* If we fault here, things are a little bit tricky. We need to call - * either data or instruction store fault, and we need to retreive + * either data or instruction store fault, and we need to retrieve * the original fault address and ESR (for data). * * The thing is, we know that in normal circumstances, this is diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index c4d2b7167568..cb515cff745c 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -67,7 +67,7 @@ #define MAX_SPU_COUNT 0xFFFFFF /* maximum 24 bit LFSR value */ -/* Minumum HW interval timer setting to send value to trace buffer is 10 cycle. +/* Minimum HW interval timer setting to send value to trace buffer is 10 cycle. * To configure counter to send value every N cycles set counter to * 2^32 - 1 - N. */ @@ -1470,7 +1470,7 @@ static int cell_global_start(struct op_counter_config *ctr) * trace buffer at the maximum rate possible. The trace buffer is configured * to store the PCs, wrapping when it is full. The performance counter is * initialized to the max hardware count minus the number of events, N, between - * samples. Once the N events have occured, a HW counter overflow occurs + * samples. Once the N events have occurred, a HW counter overflow occurs * causing the generation of a HW counter interrupt which also stops the * writing of the SPU PC values to the trace buffer. Hence the last PC * written to the trace buffer is the SPU PC that we want. Unfortunately, @@ -1656,7 +1656,7 @@ static void cell_handle_interrupt_ppu(struct pt_regs *regs, * The counters were frozen by the interrupt. * Reenable the interrupt and restart the counters. * If there was a race between the interrupt handler and - * the virtual counter routine. The virutal counter + * the virtual counter routine. The virtual counter * routine may have cleared the interrupts. Hence must * use the virt_cntr_inter_mask to re-enable the interrupts. */ diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 80774092db77..8ee51a252cf1 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -207,7 +207,7 @@ static unsigned long get_pc(struct pt_regs *regs) unsigned long mmcra; unsigned long slot; - /* Cant do much about it */ + /* Can't do much about it */ if (!cur_cpu_spec->oprofile_mmcra_sihv) return pc; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c index 6385d883cb8d..9940ce8a2d4e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c @@ -57,7 +57,7 @@ struct mpc52xx_lpbfifo { static struct mpc52xx_lpbfifo lpbfifo; /** - * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transfered + * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transferred */ static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) { @@ -179,7 +179,7 @@ static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) * * On transmit, the dma completion irq triggers before the fifo completion * triggers. Handle the dma completion here instead of the LPB FIFO Bestcomm - * task completion irq becuase everyting is not really done until the LPB FIFO + * task completion irq because everything is not really done until the LPB FIFO * completion irq triggers. * * In other words: @@ -195,7 +195,7 @@ static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) * Exit conditions: * 1) Transfer aborted * 2) FIFO complete without DMA; more data to do - * 3) FIFO complete without DMA; all data transfered + * 3) FIFO complete without DMA; all data transferred * 4) FIFO complete using DMA * * Condition 1 can occur regardless of whether or not DMA is used. diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 3ddea96273ca..1dd15400f6f0 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -512,7 +512,7 @@ void __init mpc52xx_init_irq(void) /** * mpc52xx_get_irq - Get pending interrupt number hook function * - * Called by the interupt handler to determine what IRQ handler needs to be + * Called by the interrupt handler to determine what IRQ handler needs to be * executed. * * Status of pending interrupts is determined by reading the encoded status diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c index 3b894f585280..147069938cfe 100644 --- a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c +++ b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c @@ -90,7 +90,7 @@ int spu_alloc_lscsa(struct spu_state *csa) */ for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) { /* XXX This is likely to fail, we should use a special pool - * similiar to what hugetlbfs does. + * similar to what hugetlbfs does. */ csa->lscsa_pages[i] = alloc_pages(GFP_KERNEL, SPU_64K_PAGE_ORDER); diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 0b0466284932..65203857b0ce 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -846,7 +846,7 @@ static struct spu_context *grab_runnable_context(int prio, int node) struct list_head *rq = &spu_prio->runq[best]; list_for_each_entry(ctx, rq, rq) { - /* XXX(hch): check for affinity here aswell */ + /* XXX(hch): check for affinity here as well */ if (__node_allowed(ctx, node)) { __spu_del_from_rq(ctx); goto found; diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c index 21a9c952d88b..72c905f1ee7a 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_restore.c +++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c @@ -284,7 +284,7 @@ static inline void restore_complete(void) exit_instrs[3] = BR_INSTR; break; default: - /* SPU_Status[R]=1. No additonal instructions. */ + /* SPU_Status[R]=1. No additional instructions. */ break; } spu_sync(); diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index b5e026bdca21..62dabe3c2bfa 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -51,7 +51,7 @@ static int mf_initialized; /* - * This is the structure layout for the Machine Facilites LPAR event + * This is the structure layout for the Machine Facilities LPAR event * flows. */ struct vsp_cmd_data { diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index b5f05d943a90..2376069cdc14 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -396,7 +396,7 @@ static void vio_handleEvent(struct HvLpEvent *event) viopathStatus[remoteLp].mTargetInst)) { printk(VIOPATH_KERN_WARN "message from invalid partition. " - "int msg rcvd, source inst (%d) doesnt match (%d)\n", + "int msg rcvd, source inst (%d) doesn't match (%d)\n", viopathStatus[remoteLp].mTargetInst, event->xSourceInstanceId); return; @@ -407,7 +407,7 @@ static void vio_handleEvent(struct HvLpEvent *event) viopathStatus[remoteLp].mSourceInst)) { printk(VIOPATH_KERN_WARN "message from invalid partition. " - "int msg rcvd, target inst (%d) doesnt match (%d)\n", + "int msg rcvd, target inst (%d) doesn't match (%d)\n", viopathStatus[remoteLp].mSourceInst, event->xTargetInstanceId); return; @@ -418,7 +418,7 @@ static void vio_handleEvent(struct HvLpEvent *event) viopathStatus[remoteLp].mSourceInst) { printk(VIOPATH_KERN_WARN "message from invalid partition. " - "ack msg rcvd, source inst (%d) doesnt match (%d)\n", + "ack msg rcvd, source inst (%d) doesn't match (%d)\n", viopathStatus[remoteLp].mSourceInst, event->xSourceInstanceId); return; @@ -428,7 +428,7 @@ static void vio_handleEvent(struct HvLpEvent *event) viopathStatus[remoteLp].mTargetInst) { printk(VIOPATH_KERN_WARN "message from invalid partition. " - "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n", + "viopath: ack msg rcvd, target inst (%d) doesn't match (%d)\n", viopathStatus[remoteLp].mTargetInst, event->xTargetInstanceId); return; diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c index 09695ae50f91..321a9b3a2d00 100644 --- a/arch/powerpc/platforms/pasemi/dma_lib.c +++ b/arch/powerpc/platforms/pasemi/dma_lib.c @@ -379,9 +379,9 @@ void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size, } EXPORT_SYMBOL(pasemi_dma_free_buf); -/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization +/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel synchronization * - * Allocates a flag for use with channel syncronization (event descriptors). + * Allocates a flag for use with channel synchronization (event descriptors). * Returns allocated flag (0-63), < 0 on error. */ int pasemi_dma_alloc_flag(void) diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 50f169392551..ea47df66fee5 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile @@ -11,7 +11,7 @@ obj-y += pic.o setup.o time.o feature.o pci.o \ obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o -# CONFIG_NVRAM is an arch. independant tristate symbol, for pmac32 we really +# CONFIG_NVRAM is an arch. independent tristate symbol, for pmac32 we really # need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really # CONFIG_NVRAM=y obj-$(CONFIG_NVRAM:m=y) += nvram.o diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 480567e5fa9a..e9c8a607268e 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -904,7 +904,7 @@ static void __init smu_i2c_probe(void) printk(KERN_INFO "SMU i2c %s\n", controller->full_name); /* Look for childs, note that they might not be of the right - * type as older device trees mix i2c busses and other thigns + * type as older device trees mix i2c busses and other things * at the same level */ for (busnode = NULL; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index ab6898942700..f33e08d573ce 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -299,7 +299,7 @@ static void __init setup_chaos(struct pci_controller *hose, * This function deals with some "special cases" devices. * * 0 -> No special case - * 1 -> Skip the device but act as if the access was successfull + * 1 -> Skip the device but act as if the access was successful * (return 0xff's on reads, eventually, cache config space * accesses in a later version) * -1 -> Hide the device (unsuccessful access) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index b74a9230edc9..57ceb92b2288 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -74,7 +74,7 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa) return NULL; /* The configure connector reported name does not contain a - * preceeding '/', so we allocate a buffer large enough to + * preceding '/', so we allocate a buffer large enough to * prepend this to the full_name. */ name = (char *)ccwa + ccwa->name_offset; diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 3cc4d102b1f1..89649173d3a3 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -65,7 +65,7 @@ * with EEH. * * Ideally, a PCI device driver, when suspecting that an isolation - * event has occured (e.g. by reading 0xff's), will then ask EEH + * event has occurred (e.g. by reading 0xff's), will then ask EEH * whether this is the case, and then take appropriate steps to * reset the PCI slot, the PCI device, and then resume operations. * However, until that day, the checking is done here, with the diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index fd50ccd4bac1..ef8c45489e20 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -216,7 +216,7 @@ static void pseries_cpu_die(unsigned int cpu) cpu, pcpu, cpu_status); } - /* Isolation and deallocation are definatly done by + /* Isolation and deallocation are definitely done by * drslot_chrp_cpu. If they were not they would be * done here. Change isolate state to Isolate and * change allocation-state to Unusable. diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 154c464cdca5..6d5412a18b26 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -272,7 +272,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) return tce_ret; } -/* this is compatable with cells for the device tree property */ +/* this is compatible with cells for the device tree property */ struct dynamic_dma_window_prop { __be32 liobn; /* tce table number */ __be64 dma_base; /* address hi,lo */ @@ -976,7 +976,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); /* dev setup for LPAR is a little tricky, since the device tree might - * contain the dma-window properties per-device and not neccesarily + * contain the dma-window properties per-device and not necessarily * for the bus. So we need to search upwards in the tree until we * either hit a dma-window property, OR find a parent with a table * already allocated. @@ -1033,7 +1033,7 @@ static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask) /* * the device tree might contain the dma-window properties - * per-device and not neccesarily for the bus. So we need to + * per-device and not necessarily for the bus. So we need to * search upwards in the tree until we either hit a dma-window * property, OR find a parent with a table already allocated. */ diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index ec8fe22047b7..d6901334d66e 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -897,7 +897,7 @@ void xics_migrate_irqs_away(void) int status; unsigned long flags; - /* We cant set affinity on ISA interrupts */ + /* We can't set affinity on ISA interrupts */ if (virq < NUM_ISA_INTERRUPTS) continue; if (irq_map[virq].host != xics_host) diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index 27402c7d309d..1636dd896707 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -95,7 +95,7 @@ axon_ram_irq_handler(int irq, void *dev) BUG_ON(!bank); - dev_err(&device->dev, "Correctable memory error occured\n"); + dev_err(&device->dev, "Correctable memory error occurred\n"); bank->ecc_counter++; return IRQ_HANDLED; } diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h index 23a95f80dfdb..a0e2e6b19b57 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.h +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h @@ -20,7 +20,7 @@ * struct bcom_bd - Structure describing a generic BestComm buffer descriptor * @status: The current status of this buffer. Exact meaning depends on the * task type - * @data: An array of u32 extra data. Size of array is task dependant. + * @data: An array of u32 extra data. Size of array is task dependent. * * Note: Don't dereference a bcom_bd pointer as an array. The size of the * bcom_bd is variable. Use bcom_get_bd() instead. diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h index eb0d1c883c31..3b52f3ffbdf8 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h +++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h @@ -97,7 +97,7 @@ struct bcom_task_header { u8 reserved[8]; }; -/* Descriptors stucture & co */ +/* Descriptors structure & co */ #define BCOM_DESC_NOP 0x000001f8 #define BCOM_LCD_MASK 0x80000000 #define BCOM_DRD_EXTENDED 0x40000000 diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 8b5aba263323..e0bc944eb23f 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -223,7 +223,7 @@ void __init cpm_reset(void) /* Set SDMA Bus Request priority 5. * On 860T, this also enables FEC priority 6. I am not sure - * this is what we realy want for some applications, but the + * this is what we really want for some applications, but the * manual recommends it. * Bit 25, FAM can also be set to use FEC aggressive mode (860T). */ diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index 7ed809676642..82fdad885d20 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c @@ -117,7 +117,7 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) | (devfn << 8) | reg | cfg_type)); - /* surpress setting of PCI_PRIMARY_BUS */ + /* suppress setting of PCI_PRIMARY_BUS */ if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) if ((offset == PCI_PRIMARY_BUS) && (bus->number == hose->first_busno)) diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h index 56d9e5deccbf..c39a134e8684 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.h +++ b/arch/powerpc/sysdev/ppc4xx_pci.h @@ -324,7 +324,7 @@ #define PESDR0_460EX_IHS2 0x036D /* - * 460SX addtional DCRs + * 460SX additional DCRs */ #define PESDRn_460SX_RCEI 0x02 diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index 5c5ba10384c2..d9db13810d15 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -9,7 +9,7 @@ * * Atomic operations that C can't guarantee us. * Useful for resource counting etc. - * s390 uses 'Compare And Swap' for atomicity in SMP enviroment. + * s390 uses 'Compare And Swap' for atomicity in SMP environment. * */ diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index e34347d567a6..fc50a3342da3 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -183,7 +183,7 @@ struct esw3 { * The irb that is handed to the device driver when an interrupt occurs. For * solicited interrupts, the common I/O layer already performs checks whether * a field is valid; a field not being valid is always passed as %0. - * If a unit check occured, @ecw may contain sense data; this is retrieved + * If a unit check occurred, @ecw may contain sense data; this is retrieved * by the common I/O layer itself if the device doesn't support concurrent * sense (so that the device driver never needs to perform basic sene itself). * For unsolicited interrupts, the irb is passed as-is (expect for sense data, diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S index 5e73dee63baa..9eabbc90795d 100644 --- a/arch/s390/kernel/reipl64.S +++ b/arch/s390/kernel/reipl64.S @@ -78,7 +78,7 @@ do_reipl_asm: basr %r13,0 * in the ESA psw. * Bit 31 of the addresses has to be 0 for the * 31bit lpswe instruction a fact they appear to have - * ommited from the pop. + * omitted from the pop. */ .Lnewpsw: .quad 0x0000000080000000 .quad .Lpg1 diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index ed183c2c6168..f5434d1ecb31 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -708,7 +708,7 @@ static void __init setup_hwcaps(void) * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information * as stored by stfl, bits 32-xxx contain additional facilities. * How many facility words are stored depends on the number of - * doublewords passed to the instruction. The additional facilites + * doublewords passed to the instruction. The additional facilities * are: * Bit 42: decimal floating point facility is installed * Bit 44: perform floating point operation facility is installed diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 9e7b039458da..87be655557aa 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -724,7 +724,7 @@ static void clock_sync_cpu(struct clock_sync_data *sync) } /* - * Sync the TOD clock using the port refered to by aibp. This port + * Sync the TOD clock using the port referred to by aibp. This port * has to be enabled and the other port has to be disabled. The * last eacr update has to be more than 1.6 seconds in the past. */ @@ -1012,7 +1012,7 @@ static void etr_work_fn(struct work_struct *work) eacr = etr_handle_update(&aib, eacr); /* - * Select ports to enable. The prefered synchronization mode is PPS. + * Select ports to enable. The preferred synchronization mode is PPS. * If a port can be enabled depends on a number of things: * 1) The port needs to be online and uptodate. A port is not * disabled just because it is not uptodate, but it is only @@ -1091,7 +1091,7 @@ static void etr_work_fn(struct work_struct *work) /* * Update eacr and try to synchronize the clock. If the update * of eacr caused a stepping port switch (or if we have to - * assume that a stepping port switch has occured) or the + * assume that a stepping port switch has occurred) or the * clock syncing failed, reset the sync check control bit * and set up a timer to try again after 0.5 seconds */ diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 1ccdf4d8aa85..5e8ead4b4aba 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -44,7 +44,7 @@ static inline void set_vtimer(__u64 expires) __u64 timer; asm volatile (" STPT %0\n" /* Store current cpu timer value */ - " SPT %1" /* Set new value immediatly afterwards */ + " SPT %1" /* Set new value immediately afterwards */ : "=m" (timer) : "m" (expires) ); S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; S390_lowcore.last_update_timer = expires; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index bade533ba288..30ca85cce314 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -721,7 +721,7 @@ static int __init kvm_s390_init(void) /* * guests can ask for up to 255+1 double words, we need a full page - * to hold the maximum amount of facilites. On the other hand, we + * to hold the maximum amount of facilities. On the other hand, we * only set facilities that are known to work in KVM. */ facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 9194a4b52b22..73c47bd95db3 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -311,7 +311,7 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) /* * a lot of B2 instructions are priviledged. We first check for - * the priviledges ones, that we can handle in the kernel. If the + * the privileged ones, that we can handle in the kernel. If the * kernel can handle this instruction, we check for the problem * state bit and (a) handle the instruction or (b) send a code 2 * program check. diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 2c57806c0858..9217e332b118 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -392,7 +392,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code, { int fault; - /* Protection exception is supressing, decrement psw address. */ + /* Protection exception is suppressing, decrement psw address. */ regs->psw.addr -= (pgm_int_code >> 16); /* * Check for low-address protection. This needs to be treated diff --git a/arch/score/Makefile b/arch/score/Makefile index d77dc639d8e3..974aefe86123 100644 --- a/arch/score/Makefile +++ b/arch/score/Makefile @@ -40,5 +40,5 @@ archclean: define archhelp echo ' vmlinux.bin - Raw binary boot image' echo - echo ' These will be default as apropriate for a configured platform.' + echo ' These will be default as appropriate for a configured platform.' endef diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 12fec72fec5f..1553d56cf4e0 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -82,7 +82,7 @@ config SH_NO_BSS_INIT help If running in painfully slow environments, such as an RTL simulation or from remote memory via SHdebug, where the memory - can already be gauranteed to ber zeroed on boot, say Y. + can already be guaranteed to ber zeroed on boot, say Y. For all other cases, say N. If this option seems perplexing, or you aren't sure, say N. diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c index 78cf2ab89d7a..f63d323f411f 100644 --- a/arch/sh/boards/mach-dreamcast/irq.c +++ b/arch/sh/boards/mach-dreamcast/irq.c @@ -51,7 +51,7 @@ */ #define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32) -/* Return the hardware event's bit positon within the EMR/ESR */ +/* Return the hardware event's bit position within the EMR/ESR */ #define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31) /* diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index fd4ff25f23b2..30ae2e4283f0 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -936,7 +936,7 @@ static void __init sh_eth_init(struct sh_eth_plat_data *pd) return; } - /* read MAC address frome EEPROM */ + /* read MAC address from EEPROM */ for (i = 0; i < sizeof(pd->mac_addr); i++) { pd->mac_addr[i] = mac_read(a, 0x10 + i); msleep(10); diff --git a/arch/sh/drivers/pci/pci-sh7751.h b/arch/sh/drivers/pci/pci-sh7751.h index 4983a4d20355..5ede38c330d3 100644 --- a/arch/sh/drivers/pci/pci-sh7751.h +++ b/arch/sh/drivers/pci/pci-sh7751.h @@ -61,7 +61,7 @@ #define SH7751_PCICONF3_BIST7 0x80000000 /* Bist Supported */ #define SH7751_PCICONF3_BIST6 0x40000000 /* Bist Executing */ #define SH7751_PCICONF3_BIST3_0 0x0F000000 /* Bist Passed */ - #define SH7751_PCICONF3_HD7 0x00800000 /* Single Funtion device */ + #define SH7751_PCICONF3_HD7 0x00800000 /* Single Function device */ #define SH7751_PCICONF3_HD6_0 0x007F0000 /* Configuration Layout */ #define SH7751_PCICONF3_LAT 0x0000FF00 /* Latency Timer */ #define SH7751_PCICONF3_CLS 0x000000FF /* Cache Line Size */ diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index a09c77dd09db..194231cb5a70 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -84,7 +84,7 @@ int __devinit register_pci_controller(struct pci_channel *hose) hose_tail = &hose->next; /* - * Do not panic here but later - this might hapen before console init. + * Do not panic here but later - this might happen before console init. */ if (!hose->io_map_base) { printk(KERN_WARNING diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index c4e0b3d472b9..822d6084195b 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -186,7 +186,7 @@ typedef struct page *pgtable_t; /* * While BYTES_PER_WORD == 4 on the current sh64 ABI, GCC will still * happily generate {ld/st}.q pairs, requiring us to have 8-byte - * alignment to avoid traps. The kmalloc alignment is gauranteed by + * alignment to avoid traps. The kmalloc alignment is guaranteed by * virtue of L1_CACHE_BYTES, requiring this to only be special cased * for slab caches. */ diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index b799fe71114c..0bce3d81569e 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h @@ -167,7 +167,7 @@ static inline unsigned long copy_ptea_attributes(unsigned long x) #endif /* - * Mask of bits that are to be preserved accross pgprot changes. + * Mask of bits that are to be preserved across pgprot changes. */ #define _PAGE_CHG_MASK \ (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | \ diff --git a/arch/sh/include/asm/unaligned-sh4a.h b/arch/sh/include/asm/unaligned-sh4a.h index c48a9c3420da..95adc500cabc 100644 --- a/arch/sh/include/asm/unaligned-sh4a.h +++ b/arch/sh/include/asm/unaligned-sh4a.h @@ -9,7 +9,7 @@ * struct. * * The same note as with the movli.l/movco.l pair applies here, as long - * as the load is gauranteed to be inlined, nothing else will hook in to + * as the load is guaranteed to be inlined, nothing else will hook in to * r0 and we get the return value for free. * * NOTE: Due to the fact we require r0 encoding, care should be taken to diff --git a/arch/sh/include/mach-common/mach/highlander.h b/arch/sh/include/mach-common/mach/highlander.h index 5d9d4d5154be..6ce944e33e59 100644 --- a/arch/sh/include/mach-common/mach/highlander.h +++ b/arch/sh/include/mach-common/mach/highlander.h @@ -24,7 +24,7 @@ #define PA_OBLED (PA_BCR+0x001c) /* On Board LED control */ #define PA_OBSW (PA_BCR+0x001e) /* On Board Switch control */ #define PA_AUDIOSEL (PA_BCR+0x0020) /* Sound Interface Select control */ -#define PA_EXTPLR (PA_BCR+0x001e) /* Extention Pin Polarity control */ +#define PA_EXTPLR (PA_BCR+0x001e) /* Extension Pin Polarity control */ #define PA_TPCTL (PA_BCR+0x0100) /* Touch Panel Access control */ #define PA_TPDCKCTL (PA_BCR+0x0102) /* Touch Panel Access data control */ #define PA_TPCTLCLR (PA_BCR+0x0104) /* Touch Panel Access control */ @@ -89,7 +89,7 @@ #define PA_OBLED (PA_BCR+0x0018) /* On Board LED control */ #define PA_OBSW (PA_BCR+0x001a) /* On Board Switch control */ #define PA_AUDIOSEL (PA_BCR+0x001c) /* Sound Interface Select control */ -#define PA_EXTPLR (PA_BCR+0x001e) /* Extention Pin Polarity control */ +#define PA_EXTPLR (PA_BCR+0x001e) /* Extension Pin Polarity control */ #define PA_TPCTL (PA_BCR+0x0100) /* Touch Panel Access control */ #define PA_TPDCKCTL (PA_BCR+0x0102) /* Touch Panel Access data control */ #define PA_TPCTLCLR (PA_BCR+0x0104) /* Touch Panel Access control */ diff --git a/arch/sh/include/mach-common/mach/r2d.h b/arch/sh/include/mach-common/mach/r2d.h index 0a800157b826..e04f75eaa153 100644 --- a/arch/sh/include/mach-common/mach/r2d.h +++ b/arch/sh/include/mach-common/mach/r2d.h @@ -18,18 +18,18 @@ #define PA_DISPCTL 0xa4000008 /* Display Timing control */ #define PA_SDMPOW 0xa400000a /* SD Power control */ #define PA_RTCCE 0xa400000c /* RTC(9701) Enable control */ -#define PA_PCICD 0xa400000e /* PCI Extention detect control */ +#define PA_PCICD 0xa400000e /* PCI Extension detect control */ #define PA_VOYAGERRTS 0xa4000020 /* VOYAGER Reset control */ #define PA_R2D1_AXRST 0xa4000022 /* AX_LAN Reset control */ #define PA_R2D1_CFRST 0xa4000024 /* CF Reset control */ #define PA_R2D1_ADMRTS 0xa4000026 /* SD Reset control */ -#define PA_R2D1_EXTRST 0xa4000028 /* Extention Reset control */ +#define PA_R2D1_EXTRST 0xa4000028 /* Extension Reset control */ #define PA_R2D1_CFCDINTCLR 0xa400002a /* CF Insert Interrupt clear */ #define PA_R2DPLUS_CFRST 0xa4000022 /* CF Reset control */ #define PA_R2DPLUS_ADMRTS 0xa4000024 /* SD Reset control */ -#define PA_R2DPLUS_EXTRST 0xa4000026 /* Extention Reset control */ +#define PA_R2DPLUS_EXTRST 0xa4000026 /* Extension Reset control */ #define PA_R2DPLUS_CFCDINTCLR 0xa4000028 /* CF Insert Interrupt clear */ #define PA_R2DPLUS_KEYCTLCLR 0xa400002a /* Key Interrupt clear */ diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index dd0e0f211359..8f63a264a842 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c @@ -67,7 +67,7 @@ int __init __deprecated cpg_clk_init(void) } /* - * Placeholder for compatability, until the lazy CPUs do this + * Placeholder for compatibility, until the lazy CPUs do this * on their own. */ int __init __weak arch_clk_init(void) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 1656b8c91faf..beba32beb6d9 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -648,7 +648,7 @@ static void __init sh7786_usb_setup(void) * The following settings are necessary * for using the USB modules. * - * see "USB Inital Settings" for detail + * see "USB Initial Settings" for detail */ __raw_writel(USBINITVAL1, USBINITREG1); __raw_writel(USBINITVAL2, USBINITREG2); diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 64ea0b165399..91971103b62b 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -183,7 +183,7 @@ asmlinkage void do_softirq(void) ); /* - * Shouldnt happen, we returned above if in_interrupt(): + * Shouldn't happen, we returned above if in_interrupt(): */ WARN_ON_ONCE(softirq_count()); } diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 4f267160c515..58bff45d1156 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -150,7 +150,7 @@ void __init check_for_initrd(void) } /* - * If we got this far inspite of the boot loader's best efforts + * If we got this far in spite of the boot loader's best efforts * to the contrary, assume we actually have a valid initrd and * fix up the root dev. */ diff --git a/arch/sh/lib64/copy_user_memcpy.S b/arch/sh/lib64/copy_user_memcpy.S index 2a62816d2ddd..49aeabeba2c2 100644 --- a/arch/sh/lib64/copy_user_memcpy.S +++ b/arch/sh/lib64/copy_user_memcpy.S @@ -27,7 +27,7 @@ ! 2.: When there are two or three bytes in the last word of an 11-or-more ! bytes memory chunk to b copied, the rest of the word can be read ! without side effects. -! This could be easily changed by increasing the minumum size of +! This could be easily changed by increasing the minimum size of ! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, ! however, this would cost a few extra cyles on average. ! For SHmedia, the assumption is that any quadword can be read in its diff --git a/arch/sh/lib64/memcpy.S b/arch/sh/lib64/memcpy.S index dd300c372ce1..5d682e0ee24f 100644 --- a/arch/sh/lib64/memcpy.S +++ b/arch/sh/lib64/memcpy.S @@ -29,7 +29,7 @@ ! 2.: When there are two or three bytes in the last word of an 11-or-more ! bytes memory chunk to b copied, the rest of the word can be read ! without side effects. -! This could be easily changed by increasing the minumum size of +! This could be easily changed by increasing the minimum size of ! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, ! however, this would cost a few extra cyles on average. ! For SHmedia, the assumption is that any quadword can be read in its diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h index bafe5a631b6d..75686409be24 100644 --- a/arch/sparc/include/asm/hypervisor.h +++ b/arch/sparc/include/asm/hypervisor.h @@ -654,7 +654,7 @@ extern unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions, * ARG3: mmu context * ARG4: flags (HV_MMU_{IMMU,DMMU}) * RET0: status - * ERRORS: EINVAL Invalid virutal address, context, or + * ERRORS: EINVAL Invalid virtual address, context, or * flags value * ENOTSUPPORTED ARG0 or ARG1 is non-zero * @@ -721,7 +721,7 @@ extern void sun4v_mmu_demap_all(void); * ARG2: TTE * ARG3: flags (HV_MMU_{IMMU,DMMU}) * RET0: status - * ERRORS: EINVAL Invalid virutal address or flags value + * ERRORS: EINVAL Invalid virtual address or flags value * EBADPGSZ Invalid page size value * ENORADDR Invalid real address in TTE * ETOOMANY Too many mappings (max of 8 reached) @@ -800,7 +800,7 @@ extern unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr, * ARG1: reserved, must be zero * ARG2: flags (HV_MMU_{IMMU,DMMU}) * RET0: status - * ERRORS: EINVAL Invalid virutal address or flags value + * ERRORS: EINVAL Invalid virtual address or flags value * ENOMAP Specified mapping was not found * * Demaps any permanent page mapping (established via @@ -1205,7 +1205,7 @@ struct hv_trap_trace_control { * structure contents. Attempts to do so will result in undefined * behavior for the guest. * - * Each trap trace buffer entry is layed out as follows: + * Each trap trace buffer entry is laid out as follows: */ #ifndef __ASSEMBLY__ struct hv_trap_trace_entry { @@ -1300,7 +1300,7 @@ struct hv_trap_trace_entry { * state in RET1. Future systems may define various flags for the * enable argument (ARG0), for the moment a guest should pass * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all - * tracing - which will ensure future compatability. + * tracing - which will ensure future compatibility. */ #define HV_FAST_TTRACE_ENABLE 0x92 @@ -1880,7 +1880,7 @@ extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle, * pci_device, at pci_config_offset from the beginning of the device's * configuration space. If there was no error, RET1 is set to zero and * RET2 is set to the data read. Insignificant bits in RET2 are not - * guarenteed to have any specific value and therefore must be ignored. + * guaranteed to have any specific value and therefore must be ignored. * * The data returned in RET2 is size based byte swapped. * @@ -1941,9 +1941,9 @@ extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle, * and return the actual data read in RET2. The data returned is size based * byte swapped. * - * Non-significant bits in RET2 are not guarenteed to have any specific value + * Non-significant bits in RET2 are not guaranteed to have any specific value * and therefore must be ignored. If RET1 is returned as non-zero, the data - * value is not guarenteed to have any specific value and should be ignored. + * value is not guaranteed to have any specific value and should be ignored. * * The caller must have permission to read from the given devhandle, real * address, which must be an IO address. The argument real address must be a @@ -2456,9 +2456,9 @@ extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle, * * As receive queue configuration causes a reset of the queue's head and * tail pointers there is no way for a gues to determine how many entries - * have been received between a preceeding ldc_get_rx_state() API call + * have been received between a preceding ldc_get_rx_state() API call * and the completion of the configuration operation. It should be noted - * that datagram delivery is not guarenteed via domain channels anyway, + * that datagram delivery is not guaranteed via domain channels anyway, * and therefore any higher protocol should be resilient to datagram * loss if necessary. However, to overcome this specific race potential * it is recommended, for example, that a higher level protocol be employed diff --git a/arch/sparc/include/asm/ns87303.h b/arch/sparc/include/asm/ns87303.h index 686defe6aaa0..af755483e17d 100644 --- a/arch/sparc/include/asm/ns87303.h +++ b/arch/sparc/include/asm/ns87303.h @@ -37,7 +37,7 @@ /* Power and Test Register (PTR) bits */ #define PTR_LPTB_IRQ7 0x08 #define PTR_LEVEL_IRQ 0x80 /* When not ECP/EPP: Use level IRQ */ -#define PTR_LPT_REG_DIR 0x80 /* When ECP/EPP: LPT CTR controlls direction */ +#define PTR_LPT_REG_DIR 0x80 /* When ECP/EPP: LPT CTR controls direction */ /* of the parallel port */ /* Function Control Register (FCR) bits */ diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h index 843e4faf6a50..288d7beba051 100644 --- a/arch/sparc/include/asm/pcr.h +++ b/arch/sparc/include/asm/pcr.h @@ -31,7 +31,7 @@ extern unsigned int picl_shift; /* In order to commonize as much of the implementation as * possible, we use PICH as our counter. Mostly this is - * to accomodate Niagara-1 which can only count insn cycles + * to accommodate Niagara-1 which can only count insn cycles * in PICH. */ static inline u64 picl_value(unsigned int nmi_hz) diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h index 30b0b797dc0c..c7ad3fe2b252 100644 --- a/arch/sparc/include/asm/ptrace.h +++ b/arch/sparc/include/asm/ptrace.h @@ -33,7 +33,7 @@ struct pt_regs { * things like "in a system call" etc. for an arbitray * process. * - * The PT_REGS_MAGIC is choosen such that it can be + * The PT_REGS_MAGIC is chosen such that it can be * loaded completely using just a sethi instruction. */ unsigned int magic; diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 1504df8ddf70..8e607b3b0ed9 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -801,7 +801,7 @@ vac_linesize_patch_32: subcc %l7, 32, %l7 .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on /* - * Ugly, but we cant use hardware flushing on the sun4 and we'd require + * Ugly, but we can't use hardware flushing on the sun4 and we'd require * two instructions (Anton) */ vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 @@ -851,7 +851,7 @@ sun4c_fault: sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4 /* If the kernel references a bum kernel pointer, or a pte which - * points to a non existant page in ram, we will run this code + * points to a non existent page in ram, we will run this code * _forever_ and lock up the machine!!!!! So we must check for * this condition, the AC_SYNC_ERR bits are what we must examine. * Also a parity error would make this happen as well. So we just diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index f8f21050448b..aa594c792d19 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -85,7 +85,7 @@ sparc_ramdisk_image64: sparc64_boot: mov %o4, %l7 - /* We need to remap the kernel. Use position independant + /* We need to remap the kernel. Use position independent * code to remap us to KERNBASE. * * SILO can invoke us with 32-bit address masking enabled, diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index 5fe3d65581f7..35f141a9f506 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c @@ -15,7 +15,7 @@ EXPORT_SYMBOL(init_task); /* .text section in head.S is aligned at 8k boundary and this gets linked * right after that so that the init_thread_union is aligned properly as well. - * If this is not aligned on a 8k boundry, then you should change code + * If this is not aligned on a 8k boundary, then you should change code * in etrap.S which assumes it. */ union thread_union init_thread_union __init_task_data = diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 63cd4e5d47c2..5c149689bb20 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -459,7 +459,7 @@ apply_interrupt_map(struct device_node *dp, struct device_node *pp, * * Handle this by deciding that, if we didn't get a * match in the parent's 'interrupt-map', and the - * parent is an IRQ translater, then use the parent as + * parent is an IRQ translator, then use the parent as * our IRQ controller. */ if (pp->irq_trans) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 760578687e7c..ee8426ede7c7 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1027,7 +1027,7 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags) /* * If group events scheduling transaction was started, - * skip the schedulability test here, it will be peformed + * skip the schedulability test here, it will be performed * at commit time(->commit_txn) as a whole */ if (cpuc->group_flag & PERF_EVENT_TXN) diff --git a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile index b9085ecbb27b..825dbee94d84 100644 --- a/arch/sparc/math-emu/Makefile +++ b/arch/sparc/math-emu/Makefile @@ -2,7 +2,7 @@ # Makefile for the FPU instruction emulation. # -# supress all warnings - as math.c produces a lot! +# suppress all warnings - as math.c produces a lot! ccflags-y := -w obj-y := math_$(BITS).o diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 6e2cdd5ae96b..e32b0c23c4c8 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -51,7 +51,7 @@ config GENERIC_TIME config GENERIC_CLOCKEVENTS def_bool y -# FIXME: tilegx can implement a more efficent rwsem. +# FIXME: tilegx can implement a more efficient rwsem. config RWSEM_GENERIC_SPINLOCK def_bool y diff --git a/arch/tile/include/hv/drv_xgbe_intf.h b/arch/tile/include/hv/drv_xgbe_intf.h index 146e47d5334b..f13188ac281a 100644 --- a/arch/tile/include/hv/drv_xgbe_intf.h +++ b/arch/tile/include/hv/drv_xgbe_intf.h @@ -319,7 +319,7 @@ typedef union * is an error code, or zero if no error. The val0 member is the * updated value of seqno; it has been incremented by 1 for each * packet sent. That increment may be less than nentries if an - * error occured, or if some of the entries in the vector contain + * error occurred, or if some of the entries in the vector contain * handles equal to NETIO_PKT_HANDLE_NONE. The val1 member is the * updated value of nentries; it has been decremented by 1 for each * vector entry processed. Again, that decrement may be less than diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h index 1b8bf03d62a0..ee41bca4c8c4 100644 --- a/arch/tile/include/hv/hypervisor.h +++ b/arch/tile/include/hv/hypervisor.h @@ -1340,7 +1340,7 @@ typedef struct * this operation. If any permanent delivery errors were encountered, * the routine returns HV_ERECIP. In the event of permanent delivery * errors, it may be the case that delivery was not attempted to all - * recipients; if any messages were succesfully delivered, however, + * recipients; if any messages were successfully delivered, however, * recipients' state values will be updated appropriately. * * It is explicitly legal to specify a recipient structure whose state @@ -1359,7 +1359,7 @@ typedef struct * never call hv_receive_message, or could register a different state * buffer, losing the message. * - * Specifiying the same recipient more than once in the recipient list + * Specifying the same recipient more than once in the recipient list * is an error, which will not result in an error return but which may * or may not result in more than one message being delivered to the * recipient tile. diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index a1ee25be9ad9..ea38f0c9ec7c 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -36,7 +36,7 @@ * Initialization flow and process * ------------------------------- * - * This files containes the routines to search for PCI buses, + * This files contains the routines to search for PCI buses, * enumerate the buses, and configure any attached devices. * * There are two entry points here: @@ -519,7 +519,7 @@ static int __devinit tile_cfg_read(struct pci_bus *bus, /* - * See tile_cfg_read() for relevent comments. + * See tile_cfg_read() for relevant comments. * Note that "val" is the value to write, not a pointer to that value. */ static int __devinit tile_cfg_write(struct pci_bus *bus, diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index 758f597f488c..51f8663bf074 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -290,7 +290,7 @@ static int handle_page_fault(struct pt_regs *regs, /* * Early on, we need to check for migrating PTE entries; * see homecache.c. If we find a migrating PTE, we wait until - * the backing page claims to be done migrating, then we procede. + * the backing page claims to be done migrating, then we proceed. * For kernel PTEs, we rewrite the PTE and return and retry. * Otherwise, we treat the fault like a normal "no PTE" fault, * rather than trying to patch up the existing PTE. diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c index 201a582c4137..42cfcba4e1ef 100644 --- a/arch/tile/mm/hugetlbpage.c +++ b/arch/tile/mm/hugetlbpage.c @@ -219,7 +219,7 @@ try_again: if (mm->free_area_cache < len) goto fail; - /* either no address requested or cant fit in requested address hole */ + /* either no address requested or can't fit in requested address hole */ addr = (mm->free_area_cache - len) & huge_page_mask(h); do { /* diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net index 9e9a4aaa703d..3160b1a5adb7 100644 --- a/arch/um/Kconfig.net +++ b/arch/um/Kconfig.net @@ -186,7 +186,7 @@ config UML_NET_SLIRP other transports, SLiRP works without the need of root level privleges, setuid binaries, or SLIP devices on the host. This also means not every type of connection is possible, but most - situations can be accomodated with carefully crafted slirp + situations can be accommodated with carefully crafted slirp commands that can be passed along as part of the network device's setup string. The effect of this transport on the UML is similar that of a host behind a firewall that masquerades all network diff --git a/arch/unicore32/include/mach/regs-umal.h b/arch/unicore32/include/mach/regs-umal.h index 885bb62fee71..aa22df74e11d 100644 --- a/arch/unicore32/include/mach/regs-umal.h +++ b/arch/unicore32/include/mach/regs-umal.h @@ -52,7 +52,7 @@ */ #define UMAL_MIISTATUS (PKUNITY_UMAL_BASE + 0x0030) /* - * MII Managment Indicator UMAL_MIIIDCT + * MII Management Indicator UMAL_MIIIDCT */ #define UMAL_MIIIDCT (PKUNITY_UMAL_BASE + 0x0034) /* @@ -91,7 +91,7 @@ #define UMAL_FIFORAM6 (PKUNITY_UMAL_BASE + 0x0078) #define UMAL_FIFORAM7 (PKUNITY_UMAL_BASE + 0x007c) -/* MAHBE MODUEL OF UMAL */ +/* MAHBE MODULE OF UMAL */ /* UMAL's MAHBE module interfaces to the host system through 32-bit AHB Master * and Slave ports.Registers within the M-AHBE provide Control and Status * information concerning these transfers. diff --git a/arch/unicore32/kernel/head.S b/arch/unicore32/kernel/head.S index 92255f3ab6a7..8caf322e110d 100644 --- a/arch/unicore32/kernel/head.S +++ b/arch/unicore32/kernel/head.S @@ -164,7 +164,7 @@ ENTRY(stext) ENDPROC(stext) /* - * Enable the MMU. This completely changes the stucture of the visible + * Enable the MMU. This completely changes the structure of the visible * memory space. You will not be able to trace execution through this. * * r0 = cp#0 control register diff --git a/arch/xtensa/include/asm/dma.h b/arch/xtensa/include/asm/dma.h index 137ca3945b07..bb099a373b5a 100644 --- a/arch/xtensa/include/asm/dma.h +++ b/arch/xtensa/include/asm/dma.h @@ -37,7 +37,7 @@ * the size of the statically mapped kernel segment * (XCHAL_KSEG_{CACHED,BYPASS}_SIZE), ie. 128 MB. * - * NOTE: When the entire KSEG area is DMA capable, we substract + * NOTE: When the entire KSEG area is DMA capable, we subtract * one from the max address so that the virt_to_phys() macro * works correctly on the address (otherwise the address * enters another area, and virt_to_phys() may not return diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 5fd01f6aaf37..6223f3346b5c 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1026,7 +1026,7 @@ ENTRY(fast_syscall_unrecoverable) * TRY adds an entry to the __ex_table fixup table for the immediately * following instruction. * - * CATCH catches any exception that occurred at one of the preceeding TRY + * CATCH catches any exception that occurred at one of the preceding TRY * statements and continues from there * * Usage TRY l32i a0, a1, 0 diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 2bef5705ce24..f0605ab2a761 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -868,7 +868,7 @@ static void blkio_update_policy_rule(struct blkio_policy_node *oldpn, } /* - * Some rules/values in blkg have changed. Propogate those to respective + * Some rules/values in blkg have changed. Propagate those to respective * policies. */ static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg, @@ -903,7 +903,7 @@ static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg, } /* - * A policy node rule has been updated. Propogate this update to all the + * A policy node rule has been updated. Propagate this update to all the * block groups which might be affected by this update. */ static void blkio_update_policy_node_blkg(struct blkio_cgroup *blkcg, diff --git a/block/blk-core.c b/block/blk-core.c index e0a062363937..071ae6d2768b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1184,7 +1184,7 @@ static bool bio_attempt_front_merge(struct request_queue *q, /* * Attempts to merge with the plugged list in the current process. Returns - * true if merge was succesful, otherwise false. + * true if merge was successful, otherwise false. */ static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q, struct bio *bio) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 5352bdafbcf0..c8b16c88b315 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -916,7 +916,7 @@ static void throtl_update_blkio_group_common(struct throtl_data *td, /* * For all update functions, key should be a valid pointer because these * update functions are called under blkcg_lock, that means, blkg is - * valid and in turn key is valid. queue exit path can not race becuase + * valid and in turn key is valid. queue exit path can not race because * of blkcg_lock * * Can not take queue lock in update functions as queue lock under blkcg_lock diff --git a/block/blk.h b/block/blk.h index c8db371a921d..61263463e38e 100644 --- a/block/blk.h +++ b/block/blk.h @@ -32,7 +32,7 @@ enum rq_atomic_flags { /* * EH timer and IO completion will both attempt to 'grab' the request, make - * sure that only one of them suceeds + * sure that only one of them succeeds */ static inline int blk_mark_rq_complete(struct request *rq) { diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 7785169f3c8f..3be881ec95ad 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -888,7 +888,7 @@ cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg) /* * Currently put the group at the end. Later implement something * so that groups get lesser vtime based on their weights, so that - * if group does not loose all if it was not continously backlogged. + * if group does not loose all if it was not continuously backlogged. */ n = rb_last(&st->rb); if (n) { diff --git a/block/genhd.c b/block/genhd.c index c91a2dac6b6b..b364bd038a18 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -739,7 +739,7 @@ void __init printk_all_partitions(void) /* * Don't show empty devices or things that have been - * surpressed + * suppressed */ if (get_capacity(disk) == 0 || (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index 2bc332142849..ffa0245e2abc 100644 --- a/crypto/ansi_cprng.c +++ b/crypto/ansi_cprng.c @@ -83,7 +83,7 @@ static void xor_vectors(unsigned char *in1, unsigned char *in2, } /* * Returns DEFAULT_BLK_SZ bytes of random data per call - * returns 0 if generation succeded, <0 if something went wrong + * returns 0 if generation succeeded, <0 if something went wrong */ static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test) { diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c index 079ae8ca590b..bc28337fded2 100644 --- a/crypto/async_tx/async_xor.c +++ b/crypto/async_tx/async_xor.c @@ -94,7 +94,7 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list, if (unlikely(!tx)) async_tx_quiesce(&submit->depend_tx); - /* spin wait for the preceeding transactions to complete */ + /* spin wait for the preceding transactions to complete */ while (unlikely(!tx)) { dma_async_issue_pending(chan); tx = dma->device_prep_dma_xor(chan, dma_dest, diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c index a90d260528d4..df35e4ccd07e 100644 --- a/crypto/gf128mul.c +++ b/crypto/gf128mul.c @@ -89,7 +89,7 @@ } /* Given the value i in 0..255 as the byte overflow when a field element - in GHASH is multipled by x^8, this function will return the values that + in GHASH is multiplied by x^8, this function will return the values that are generated in the lo 16-bit word of the field value by applying the modular polynomial. The values lo_byte and hi_byte are returned via the macro xp_fun(lo_byte, hi_byte) so that the values can be assembled into diff --git a/crypto/vmac.c b/crypto/vmac.c index 0999274a27ac..f35ff8a3926e 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c @@ -95,7 +95,7 @@ const u64 mpoly = UINT64_C(0x1fffffff1fffffff); /* Poly key mask */ /* * For highest performance the L1 NH and L2 polynomial hashes should be - * carefully implemented to take advantage of one's target architechture. + * carefully implemented to take advantage of one's target architecture. * Here these two hash functions are defined multiple time; once for * 64-bit architectures, once for 32-bit SSE2 architectures, and once * for the rest (32-bit) architectures. diff --git a/crypto/xts.c b/crypto/xts.c index 555ecaab1e54..851705446c82 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -45,7 +45,7 @@ static int setkey(struct crypto_tfm *parent, const u8 *key, return -EINVAL; } - /* we need two cipher instances: one to compute the inital 'tweak' + /* we need two cipher instances: one to compute the initial 'tweak' * by encrypting the IV (usually the 'plain' iv) and the other * one to encrypt and decrypt the data */ diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index d1d484d4a06a..f703b2881153 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -241,7 +241,7 @@ static inline int ghes_severity(int severity) case CPER_SEV_FATAL: return GHES_SEV_PANIC; default: - /* Unkown, go panic */ + /* Unknown, go panic */ return GHES_SEV_PANIC; } } diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index fa84e9744330..ad3501739563 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -1164,7 +1164,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, */ if (!match_pr->flags.throttling) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Throttling Controll is unsupported " + "Throttling Control is unsupported " "on CPU %d\n", i)); continue; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 31e9e10f657e..ec574fc8fbc6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1354,7 +1354,7 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, status = acpi_video_bus_get_one_device(dev, video); if (ACPI_FAILURE(status)) { printk(KERN_WARNING PREFIX - "Cant attach device\n"); + "Can't attach device\n"); continue; } } @@ -1373,7 +1373,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) acpi_video_device_notify); if (ACPI_FAILURE(status)) { printk(KERN_WARNING PREFIX - "Cant remove video notify handler\n"); + "Can't remove video notify handler\n"); } if (device->backlight) { backlight_device_unregister(device->backlight); diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 6d2bb2524b6e..821040503154 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -760,7 +760,7 @@ int amba_request_regions(struct amba_device *dev, const char *name) } /** - * amba_release_regions - release mem regions assoicated with device + * amba_release_regions - release mem regions associated with device * @dev: amba_device structure for device * * Release regions claimed by a successful call to amba_request_regions. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e62f693be8ea..39d829cd82dd 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -926,7 +926,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) /* * Acer eMachines G725 has the same problem. BIOS * V1.03 is known to be broken. V3.04 is known to - * work. Inbetween, there are V1.06, V2.06 and V3.03 + * work. Between, there are V1.06, V2.06 and V3.03 * that we don't have much idea about. For now, * blacklist anything older than V3.04. * diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index ccaf08122058..39865009c251 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -225,7 +225,7 @@ enum { /* em_ctl bits */ EM_CTL_RST = (1 << 9), /* Reset */ EM_CTL_TM = (1 << 8), /* Transmit Message */ - EM_CTL_MR = (1 << 0), /* Message Recieved */ + EM_CTL_MR = (1 << 0), /* Message Received */ EM_CTL_ALHD = (1 << 26), /* Activity LED */ EM_CTL_XMT = (1 << 25), /* Transmit Only */ EM_CTL_SMB = (1 << 24), /* Single Message Buffer */ @@ -281,7 +281,7 @@ struct ahci_port_priv { }; struct ahci_host_priv { - void __iomem * mmio; /* bus-independant mem map */ + void __iomem * mmio; /* bus-independent mem map */ unsigned int flags; /* AHCI_HFLAG_* */ u32 cap; /* cap to use */ u32 cap2; /* cap2 to use */ diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index cdec4ab3b159..0bc3fd6c3fdb 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -38,16 +38,16 @@ * Hardware documentation available at http://developer.intel.com/ * * Documentation - * Publically available from Intel web site. Errata documentation - * is also publically available. As an aide to anyone hacking on this + * Publicly available from Intel web site. Errata documentation + * is also publicly available. As an aide to anyone hacking on this * driver the list of errata that are relevant is below, going back to * PIIX4. Older device documentation is now a bit tricky to find. * * The chipsets all follow very much the same design. The original Triton - * series chipsets do _not_ support independant device timings, but this + * series chipsets do _not_ support independent device timings, but this * is fixed in Triton II. With the odd mobile exception the chips then * change little except in gaining more modes until SATA arrives. This - * driver supports only the chips with independant timing (that is those + * driver supports only the chips with independent timing (that is those * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix * for the early chip drivers. * @@ -122,7 +122,7 @@ enum { P2 = 2, /* port 2 */ P3 = 3, /* port 3 */ IDE = -1, /* IDE */ - NA = -2, /* not avaliable */ + NA = -2, /* not available */ RV = -3, /* reserved */ PIIX_AHCI_DEVICE = 6, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b91e19cab102..423c0a6952b2 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5340,7 +5340,7 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) * * Resume @host. Actual operation is performed by EH. This * function requests EH to perform PM operations and returns. - * Note that all resume operations are performed parallely. + * Note that all resume operations are performed parallelly. * * LOCKING: * Kernel thread context (may sleep). diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index df3f3140c9c7..88cd22fa65cd 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -771,7 +771,7 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) /* process port suspend request */ ata_eh_handle_port_suspend(ap); - /* Exception might have happend after ->error_handler + /* Exception might have happened after ->error_handler * recovered the port but before this point. Repeat * EH in such case. */ @@ -1742,7 +1742,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) * * Analyze taskfile of @qc and further determine cause of * failure. This function also requests ATAPI sense data if - * avaliable. + * available. * * LOCKING: * Kernel thread context (may sleep). @@ -1893,7 +1893,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) * occurred during last 5 mins, NCQ_OFF. * * 3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors - * ocurred during last 5 mins, FALLBACK_TO_PIO + * occurred during last 5 mins, FALLBACK_TO_PIO * * 4. If more than 3 TOUT_HSM or UNK_DEV errors occurred * during last 10 mins, NCQ_OFF. @@ -2577,7 +2577,7 @@ int ata_eh_reset(struct ata_link *link, int classify, if (link->flags & ATA_LFLAG_NO_SRST) softreset = NULL; - /* make sure each reset attemp is at least COOL_DOWN apart */ + /* make sure each reset attempt is at least COOL_DOWN apart */ if (ehc->i.flags & ATA_EHI_DID_RESET) { now = jiffies; WARN_ON(time_after(ehc->last_reset, now)); @@ -2736,7 +2736,7 @@ int ata_eh_reset(struct ata_link *link, int classify, if (!reset) { ata_link_printk(link, KERN_ERR, "follow-up softreset required " - "but no softreset avaliable\n"); + "but no softreset available\n"); failed_link = link; rc = -EINVAL; goto fail; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a83419991357..e2f57e9e12f0 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -999,7 +999,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) * @qc: Command that we are erroring out * * Generate sense block for a failed ATA command @qc. Descriptor - * format is used to accomodate LBA48 block address. + * format is used to accommodate LBA48 block address. * * LOCKING: * None. diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index cf7acbc0cfcb..f8380ce0f4d1 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2839,7 +2839,7 @@ unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) bmdma_stopped = true; if (unlikely(host_stat & ATA_DMA_ERR)) { - /* error when transfering data to/from memory */ + /* error when transferring data to/from memory */ qc->err_mask |= AC_ERR_HOST_BUS; ap->hsm_task_state = HSM_ST_ERR; } @@ -3032,7 +3032,7 @@ void ata_bmdma_start(struct ata_queued_cmd *qc) * Or maybe I'm just being paranoid. * * FIXME: The posting of this write means I/O starts are - * unneccessarily delayed for MMIO + * unnecessarily delayed for MMIO */ } EXPORT_SYMBOL_GPL(ata_bmdma_start); diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 620a07cabe31..b0975a5ad8c4 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -11,7 +11,7 @@ * Power management on ports * * - * Documentation publically available. + * Documentation publicly available. */ #include diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 65cee74605b4..719bb73a73e0 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -385,7 +385,7 @@ static inline int wait4buf(struct arasan_cf_dev *acdev) return -ETIMEDOUT; } - /* Check if PIO Error interrupt has occured */ + /* Check if PIO Error interrupt has occurred */ if (acdev->dma_status & ATA_DMA_ERR) return -EAGAIN; @@ -450,7 +450,7 @@ static int sg_xfer(struct arasan_cf_dev *acdev, struct scatterlist *sg) /* * For each sg: * MAX_XFER_COUNT data will be transferred before we get transfer - * complete interrupt. Inbetween after FIFO_SIZE data + * complete interrupt. Between after FIFO_SIZE data * buffer available interrupt will be generated. At this time we will * fill FIFO again: max FIFO_SIZE data. */ @@ -463,7 +463,7 @@ static int sg_xfer(struct arasan_cf_dev *acdev, struct scatterlist *sg) acdev->vbase + XFER_CTR); spin_unlock_irqrestore(&acdev->host->lock, flags); - /* continue dma xfers untill current sg is completed */ + /* continue dma xfers until current sg is completed */ while (xfer_cnt) { /* wait for read to complete */ if (!write) { @@ -563,7 +563,7 @@ static void data_xfer(struct work_struct *work) chan_request_fail: spin_lock_irqsave(&acdev->host->lock, flags); - /* error when transfering data to/from memory */ + /* error when transferring data to/from memory */ qc->err_mask |= AC_ERR_HOST_BUS; qc->ap->hsm_task_state = HSM_ST_ERR; diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index e0b58b8dfe6f..ea64967000ff 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1342,7 +1342,7 @@ static unsigned int bfin_ata_host_intr(struct ata_port *ap, ap->ops->bmdma_stop(qc); if (unlikely(host_stat & ATA_DMA_ERR)) { - /* error when transfering data to/from memory */ + /* error when transferring data to/from memory */ qc->err_mask |= AC_ERR_HOST_BUS; ap->hsm_task_state = HSM_ST_ERR; } diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 030952f1f97c..e3254fcff0f1 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -29,7 +29,7 @@ * General Public License for more details. * * Documentation: - * Not publically available. + * Not publicly available. */ #include #include diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index b21f0021f54a..d8d9c5807740 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -15,7 +15,7 @@ * with PCI IDE and also that we do not disable the device when our driver is * unloaded (as it has many other functions). * - * The driver conciously keeps this logic internally to avoid pushing quirky + * The driver consciously keeps this logic internally to avoid pushing quirky * PATA history into the clean libata layer. * * Thinkpad specific note: If you boot an MPIIX using a thinkpad with a PCMCIA diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 4a454a88aa9d..4d04471794b6 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -112,7 +112,7 @@ static int rz1000_reinit_one(struct pci_dev *pdev) if (rc) return rc; - /* If this fails on resume (which is a "cant happen" case), we + /* If this fails on resume (which is a "can't happen" case), we must stop as any progress risks data loss */ if (rz1000_fifo_disable(pdev)) panic("rz1000 fifo"); diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 00eefbd84b33..118787caa93f 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -11,7 +11,7 @@ * * May be copied or modified under the terms of the GNU General Public License * - * Documentation publically available. + * Documentation publicly available. * * If you have strange problems with nVidia chipset systems please * see the SI support documentation and update your system BIOS @@ -43,7 +43,7 @@ * * Turn a config register offset into the right address in either * PCI space or MMIO space to access the control register in question - * Thankfully this is a configuration operation so isnt performance + * Thankfully this is a configuration operation so isn't performance * criticial. */ diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index c04abc393fc5..be08ff92db17 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -331,7 +331,7 @@ static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev) if (adev->dma_mode < XFER_UDMA_0) { /* bits 3-0 hold recovery timing bits 8-10 active timing and - the higher bits are dependant on the device */ + the higher bits are dependent on the device */ timing &= ~0x870F; timing |= mwdma_bits[speed]; } else { @@ -371,7 +371,7 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev) if (adev->dma_mode < XFER_UDMA_0) { /* bits 3-0 hold recovery timing bits 8-10 active timing and - the higher bits are dependant on the device, bit 15 udma */ + the higher bits are dependent on the device, bit 15 udma */ timing &= ~0x870F; timing |= mwdma_bits[speed]; } else { diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index 0d1f89e571dd..03b6d69d6197 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -30,7 +30,7 @@ * Loosely based on the piix & svwks drivers. * * Documentation: - * Not publically available. + * Not publicly available. */ #include diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 0f91e583892e..35a71d875d0e 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -42,7 +42,7 @@ enum { /* * SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and - * chained indirect PRDEs upto a max count of 63. + * chained indirect PRDEs up to a max count of 63. * We are allocating an array of 63 PRDEs contiguously, but PRDE#15 will * be setup as an indirect descriptor, pointing to it's next * (contiguous) PRDE. Though chained indirect PRDE arrays are @@ -907,7 +907,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class, ata_msleep(ap, 1); /* - * SATA device enters reset state after receving a Control register + * SATA device enters reset state after receiving a Control register * FIS with SRST bit asserted and it awaits another H2D Control reg. * FIS with SRST bit cleared, then the device does internal diags & * initialization, followed by indicating it's initialization status diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index cd40651e9b72..b52c0519ad0b 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1352,7 +1352,7 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val) /* * Workaround for 88SX60x1 FEr SATA#26: * - * COMRESETs have to take care not to accidently + * COMRESETs have to take care not to accidentally * put the drive to sleep when writing SCR_CONTROL. * Setting bits 12..15 prevents this problem. * @@ -2044,7 +2044,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) cw = &pp->crqb[in_index].ata_cmd[0]; - /* Sadly, the CRQB cannot accomodate all registers--there are + /* Sadly, the CRQB cannot accommodate all registers--there are * only 11 bytes...so we must pick and choose required * registers based on the command. So, we drop feature and * hob_feature for [RW] DMA commands, but they are needed for diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 42344e3c686d..f173ef3bfc10 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -2121,7 +2121,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap) host_stat = ap->ops->bmdma_status(ap); if (unlikely(host_stat & ATA_DMA_ERR)) { - /* error when transfering data to/from memory */ + /* error when transferring data to/from memory */ ata_ehi_clear_desc(ehi); ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); ehi->err_mask |= AC_ERR_HOST_BUS; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 21242c5709a0..54434db15b12 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -582,7 +582,7 @@ static void svia_configure(struct pci_dev *pdev, int board_id) * When host issues HOLD, device may send up to 20DW of data * before acknowledging it with HOLDA and the host should be * able to buffer them in FIFO. Unfortunately, some WD drives - * send upto 40DW before acknowledging HOLD and, in the + * send up to 40DW before acknowledging HOLD and, in the * default configuration, this ends up overflowing vt6421's * FIFO, making the controller abort the transaction with * R_ERR. diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 9f47e8625266..a5fcb1eb862f 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -497,7 +497,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { // VC layer stats atomic_inc(&atm_vcc->stats->rx); __net_timestamp(skb); - // end of our responsability + // end of our responsibility atm_vcc->push (atm_vcc, skb); return; diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 049650d42c88..ef7a658312a6 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -1782,7 +1782,7 @@ static int __devinit fs_init (struct fs_dev *dev) write_fs (dev, RAS0, RAS0_DCD_XHLT | (((1 << FS155_VPI_BITS) - 1) * RAS0_VPSEL) | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL)); - /* We can chose the split arbitarily. We might be able to + /* We can chose the split arbitrarily. We might be able to support more. Whatever. This should do for now. */ dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS; dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS; diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index 7f97c09aaea5..ba34a02b717d 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -263,7 +263,7 @@ typedef enum opcode { } opcode_t; -/* virtual path / virtual channel identifers */ +/* virtual path / virtual channel identifiers */ typedef struct vpvc { BITFIELD3( @@ -926,7 +926,7 @@ typedef struct fore200e_vcc { #define PCA200E_PCI_LATENCY 0x40 /* maximum slave latenty */ #define PCA200E_PCI_MASTER_CTRL 0x41 /* master control */ -#define PCA200E_PCI_THRESHOLD 0x42 /* burst / continous req threshold */ +#define PCA200E_PCI_THRESHOLD 0x42 /* burst / continuous req threshold */ /* PBI master control register */ diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 24761e1d6642..d58e3fcb9db3 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -169,13 +169,13 @@ static inline void __init show_version (void) { Real Time (cdv and max CDT given) CBR(pcr) pcr bandwidth always available - rtVBR(pcr,scr,mbs) scr bandwidth always available, upto pcr at mbs too + rtVBR(pcr,scr,mbs) scr bandwidth always available, up to pcr at mbs too Non Real Time - nrtVBR(pcr,scr,mbs) scr bandwidth always available, upto pcr at mbs too + nrtVBR(pcr,scr,mbs) scr bandwidth always available, up to pcr at mbs too UBR() - ABR(mcr,pcr) mcr bandwidth always available, upto pcr (depending) too + ABR(mcr,pcr) mcr bandwidth always available, up to pcr (depending) too mbs is max burst size (bucket) pcr and scr have associated cdvt values @@ -944,7 +944,7 @@ static void hrz_close_rx (hrz_dev * dev, u16 vc) { // to be fixed soon, so do not define TAILRECUSRIONWORKS unless you // are sure it does as you may otherwise overflow the kernel stack. -// giving this fn a return value would help GCC, alledgedly +// giving this fn a return value would help GCC, allegedly static void rx_schedule (hrz_dev * dev, int irq) { unsigned int rx_bytes; @@ -1036,7 +1036,7 @@ static void rx_schedule (hrz_dev * dev, int irq) { // VC layer stats atomic_inc(&vcc->stats->rx); __net_timestamp(skb); - // end of our responsability + // end of our responsibility vcc->push (vcc, skb); } } diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index bfb7feee0400..048f99fe6f83 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3495,7 +3495,7 @@ init_card(struct atm_dev *dev) return -1; } if (dev->phy->ioctl == NULL) { - printk("%s: LT had no IOCTL funtion defined.\n", card->name); + printk("%s: LT had no IOCTL function defined.\n", card->name); deinit_card(card); return -1; } diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h index f53a43ae2bbe..3a82cc23a053 100644 --- a/drivers/atm/idt77252.h +++ b/drivers/atm/idt77252.h @@ -766,7 +766,7 @@ struct idt77252_dev #define SAR_RCTE_BUFFSTAT_MASK 0x00003000 /* buffer status */ #define SAR_RCTE_EFCI 0x00000800 /* EFCI Congestion flag */ #define SAR_RCTE_CLP 0x00000400 /* Cell Loss Priority flag */ -#define SAR_RCTE_CRC 0x00000200 /* Recieved CRC Error */ +#define SAR_RCTE_CRC 0x00000200 /* Received CRC Error */ #define SAR_RCTE_CELLCNT_MASK 0x000001FF /* cell Count */ #define SAR_RCTE_AAL0 0x00000000 /* AAL types for ALL field */ diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index d80d51b62a1a..1c674a91f146 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -1025,7 +1025,7 @@ static void desc_dbg(IADEV *iadev) { } -/*----------------------------- Recieving side stuff --------------------------*/ +/*----------------------------- Receiving side stuff --------------------------*/ static void rx_excp_rcvd(struct atm_dev *dev) { @@ -1195,7 +1195,7 @@ static void rx_intr(struct atm_dev *dev) if (status & RX_PKT_RCVD) { /* do something */ - /* Basically recvd an interrupt for receving a packet. + /* Basically recvd an interrupt for receiving a packet. A descriptor would have been written to the packet complete queue. Get all the descriptors and set up dma to move the packets till the packet complete queue is empty.. @@ -1855,7 +1855,7 @@ static int open_tx(struct atm_vcc *vcc) return -EINVAL; } if (vcc->qos.txtp.max_pcr > iadev->LineRate) { - IF_CBR(printk("PCR is not availble\n");) + IF_CBR(printk("PCR is not available\n");) return -1; } vc->type = CBR; diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 52880c8387d8..4e8ba56f75d3 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -1255,7 +1255,7 @@ static inline void lanai_endtx(struct lanai_dev *lanai, /* * Since the "butt register" is a shared resounce on the card we * serialize all accesses to it through this spinlock. This is - * mostly just paranoia sicne the register is rarely "busy" anyway + * mostly just paranoia since the register is rarely "busy" anyway * but is needed for correctness. */ spin_lock(&lanai->endtxlock); @@ -1990,7 +1990,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) /* * We _can_ use VCI==0 for normal traffic, but only for UBR (or we'll - * get a CBRZERO interrupt), and we can use it only if noone is receiving + * get a CBRZERO interrupt), and we can use it only if no one is receiving * AAL0 traffic (since they will use the same queue) - according to the * docs we shouldn't even use it for AAL0 traffic */ diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c index 49758593a5ba..41ce4bd96813 100644 --- a/drivers/auxdisplay/cfag12864b.c +++ b/drivers/auxdisplay/cfag12864b.c @@ -49,7 +49,7 @@ static unsigned int cfag12864b_rate = CONFIG_CFAG12864B_RATE; module_param(cfag12864b_rate, uint, S_IRUGO); MODULE_PARM_DESC(cfag12864b_rate, - "Refresh rate (hertzs)"); + "Refresh rate (hertz)"); unsigned int cfag12864b_getrate(void) { @@ -60,7 +60,7 @@ unsigned int cfag12864b_getrate(void) * cfag12864b Commands * * E = Enable signal - * Everytime E switch from low to high, + * Every time E switch from low to high, * cfag12864b/ks0108 reads the command/data. * * CS1 = First ks0108controller. diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 54597c859ecb..3172c60d23a9 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -443,7 +443,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) * * Check if the device's run-time PM status allows it to be resumed. Cancel * any scheduled or pending requests. If another resume has been started - * earlier, either return imediately or wait for it to finish, depending on the + * earlier, either return immediately or wait for it to finish, depending on the * RPM_NOWAIT and RPM_ASYNC flags. Similarly, if there's a suspend running in * parallel with this function, either tell the other process to resume after * suspending (deferred_resume) or wait for it to finish. If the RPM_ASYNC diff --git a/drivers/base/sys.c b/drivers/base/sys.c index fbe72da6c414..acde9b5ee131 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -197,7 +197,7 @@ kset_put: } /** - * sysdev_driver_register - Register auxillary driver + * sysdev_driver_register - Register auxiliary driver * @cls: Device class driver belongs to. * @drv: Driver. * @@ -250,7 +250,7 @@ unlock: } /** - * sysdev_driver_unregister - Remove an auxillary driver. + * sysdev_driver_unregister - Remove an auxiliary driver. * @cls: Class driver belongs to. * @drv: Driver. */ @@ -302,7 +302,7 @@ int sysdev_register(struct sys_device *sysdev) * code that should have called us. */ - /* Notify class auxillary drivers */ + /* Notify class auxiliary drivers */ list_for_each_entry(drv, &cls->drivers, entry) { if (drv->add) drv->add(sysdev); @@ -335,7 +335,7 @@ void sysdev_unregister(struct sys_device *sysdev) * * Loop over each class of system devices, and the devices in each * of those classes. For each device, we call the shutdown method for - * each driver registered for the device - the auxillaries, + * each driver registered for the device - the auxiliaries, * and the class driver. * * Note: The list is iterated in reverse order, so that we shut down @@ -360,7 +360,7 @@ void sysdev_shutdown(void) struct sysdev_driver *drv; pr_debug(" %s\n", kobject_name(&sysdev->kobj)); - /* Call auxillary drivers first */ + /* Call auxiliary drivers first */ list_for_each_entry(drv, &cls->drivers, entry) { if (drv->shutdown) drv->shutdown(sysdev); @@ -385,7 +385,7 @@ static void __sysdev_resume(struct sys_device *dev) WARN_ONCE(!irqs_disabled(), "Interrupts enabled after %pF\n", cls->resume); - /* Call auxillary drivers next. */ + /* Call auxiliary drivers next. */ list_for_each_entry(drv, &cls->drivers, entry) { if (drv->resume) drv->resume(dev); @@ -432,7 +432,7 @@ int sysdev_suspend(pm_message_t state) list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { pr_debug(" %s\n", kobject_name(&sysdev->kobj)); - /* Call auxillary drivers first */ + /* Call auxiliary drivers first */ list_for_each_entry(drv, &cls->drivers, entry) { if (drv->suspend) { ret = drv->suspend(sysdev, state); diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 79882104e431..8066d086578a 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1790,7 +1790,7 @@ static bool DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T unsigned short LogicalDeviceNumber = 0; int ModelNameLength; - /* Get data into dma-able area, then copy into permanant location */ + /* Get data into dma-able area, then copy into permanent location */ if (!DAC960_V2_NewControllerInfo(Controller)) return DAC960_Failure(Controller, "GET CONTROLLER INFO"); memcpy(ControllerInfo, Controller->V2.NewControllerInformation, diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 2a1642bc451d..c6828b68d77b 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -30,7 +30,7 @@ /* We maintain a trivial check sum in our on disk activity log. * With that we can ensure correct operation even when the storage - * device might do a partial (last) sector write while loosing power. + * device might do a partial (last) sector write while losing power. */ struct __packed al_transaction { u32 magic; diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 81030d8d654b..b2699bb2e530 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -622,7 +622,7 @@ DCBP_set_pad_bits(struct p_compressed_bm *p, int n) /* one bitmap packet, including the p_header, * should fit within one _architecture independend_ page. * so we need to use the fixed size 4KiB page size - * most architechtures have used for a long time. + * most architectures have used for a long time. */ #define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header80)) #define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long)) @@ -810,7 +810,7 @@ enum { /* global flag bits */ enum { - CREATE_BARRIER, /* next P_DATA is preceeded by a P_BARRIER */ + CREATE_BARRIER, /* next P_DATA is preceded by a P_BARRIER */ SIGNAL_ASENDER, /* whether asender wants to be interrupted */ SEND_PING, /* whether asender should send a ping asap */ @@ -1126,7 +1126,7 @@ struct drbd_conf { int c_sync_rate; /* current resync rate after syncer throttle magic */ struct fifo_buffer rs_plan_s; /* correction values of resync planer */ int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */ - int rs_planed; /* resync sectors already planed */ + int rs_planed; /* resync sectors already planned */ atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */ }; @@ -1144,7 +1144,7 @@ static inline unsigned int mdev_to_minor(struct drbd_conf *mdev) return mdev->minor; } -/* returns 1 if it was successfull, +/* returns 1 if it was successful, * returns 0 if there was no data socket. * so wherever you are going to use the data.socket, e.g. do * if (!drbd_get_data_sock(mdev)) @@ -2079,7 +2079,7 @@ static inline void inc_ap_pending(struct drbd_conf *mdev) /* counts how many resync-related answers we still expect from the peer * increase decrease * C_SYNC_TARGET sends P_RS_DATA_REQUEST (and expects P_RS_DATA_REPLY) - * C_SYNC_SOURCE sends P_RS_DATA_REPLY (and expects P_WRITE_ACK whith ID_SYNCER) + * C_SYNC_SOURCE sends P_RS_DATA_REPLY (and expects P_WRITE_ACK with ID_SYNCER) * (or P_NEG_ACK with ID_SYNCER) */ static inline void inc_rs_pending(struct drbd_conf *mdev) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index dfc85f32d317..5b525c179f39 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1561,7 +1561,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (drbd_send_state(mdev)) dev_warn(DEV, "Notified peer that I'm now diskless.\n"); /* corresponding get_ldev in __drbd_set_state - * this may finaly trigger drbd_ldev_destroy. */ + * this may finally trigger drbd_ldev_destroy. */ put_ldev(mdev); } @@ -3706,7 +3706,7 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); if (!drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) { - /* NOTE: cant do normal error processing here as this is + /* NOTE: can't do normal error processing here as this is called BEFORE disk is attached */ dev_err(DEV, "Error while reading metadata.\n"); rv = ERR_IO_MD_DISK; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index fe1564c7d8b6..fd26666c0b08 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -862,7 +862,7 @@ retry: msock->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ; /* we don't want delays. - * we use TCP_CORK where apropriate, though */ + * we use TCP_CORK where appropriate, though */ drbd_tcp_nodelay(sock); drbd_tcp_nodelay(msock); diff --git a/drivers/block/drbd/drbd_vli.h b/drivers/block/drbd/drbd_vli.h index fc824006e721..8cb1532a3816 100644 --- a/drivers/block/drbd/drbd_vli.h +++ b/drivers/block/drbd/drbd_vli.h @@ -32,7 +32,7 @@ * the bitmap transfer time can take much too long, * if transmitted in plain text. * - * We try to reduce the transfered bitmap information + * We try to reduce the transferred bitmap information * by encoding runlengths of bit polarity. * * We never actually need to encode a "zero" (runlengths are positive). diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 30ec6b37424e..007c630904c1 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -733,7 +733,7 @@ static int __init hd_init(void) * the BIOS or CMOS. This doesn't work all that well, * since this assumes that this is a primary or secondary * drive, and if we're using this legacy driver, it's - * probably an auxilliary controller added to recover + * probably an auxiliary controller added to recover * legacy data off an ST-506 drive. Either way, it's * definitely safest to have the user explicitly specify * the information. diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index e2ff697697c2..9a5b2a2d616d 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -94,7 +94,7 @@ static const struct vio_error_entry viodasd_err_table[] = { { 0x0204, EIO, "Use Error" }, { 0x0205, EIO, "Release Error" }, { 0x0206, EINVAL, "Invalid Disk" }, - { 0x0207, EBUSY, "Cant Lock" }, + { 0x0207, EBUSY, "Can't Lock" }, { 0x0208, EIO, "Already Locked" }, { 0x0209, EIO, "Already Unlocked" }, { 0x020A, EIO, "Invalid Arg" }, diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 73354b081ed3..645ff765cd12 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -621,7 +621,7 @@ static void ace_fsm_dostate(struct ace_device *ace) ace_dump_mem(ace->cf_id, 512); /* Debug: Dump out disk ID */ if (ace->data_result) { - /* Error occured, disable the disk */ + /* Error occurred, disable the disk */ ace->media_change = 1; set_capacity(ace->gd, 0); dev_err(ace->dev, "error fetching CF id (%i)\n", @@ -801,7 +801,7 @@ static int ace_interrupt_checkstate(struct ace_device *ace) u32 sreg = ace_in32(ace, ACE_STATUS); u16 creg = ace_in(ace, ACE_CTRL); - /* Check for error occurance */ + /* Check for error occurrence */ if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) && (creg & ACE_CTRL_ERRORIRQ)) { dev_err(ace->dev, "transfer failure\n"); @@ -1169,7 +1169,7 @@ static int __devinit ace_probe(struct platform_device *dev) irq = dev->resource[i].start; } - /* Call the bus-independant setup code */ + /* Call the bus-independent setup code */ return ace_alloc(&dev->dev, id, physaddr, irq, bus_width); } @@ -1222,7 +1222,7 @@ static int __devinit ace_of_probe(struct platform_device *op) if (of_find_property(op->dev.of_node, "8-bit", NULL)) bus_width = ACE_BUS_WIDTH_8; - /* Call the bus-independant setup code */ + /* Call the bus-independent setup code */ return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0, physaddr, irq, bus_width); } diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 38595e782d02..7e4b435f79f0 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -207,7 +207,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu) /* * This state means that both the host and the BRF chip * have simultaneously sent a wake-up-indication packet. - * Traditionaly, in this case, receiving a wake-up-indication + * Traditionally, in this case, receiving a wake-up-indication * was enough and an additional wake-up-ack wasn't needed. * This has changed with the BRF6350, which does require an * explicit wake-up-ack. Other BRF versions, which do not diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index e2c48a7eccff..514dd8efaf73 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -30,7 +30,7 @@ changelog for the 1.x series, David? 2.00 Dec 2, 1997 -- Erik Andersen - -- New maintainer! As David A. van Leeuwen has been too busy to activly + -- New maintainer! As David A. van Leeuwen has been too busy to actively maintain and improve this driver, I am now carrying on the torch. If you have a problem with this driver, please feel free to contact me. @@ -2520,7 +2520,7 @@ static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, /* * Ok, this is where problems start. The current interface for the * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that - * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, while this + * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunately, while this * is often the case, it is also very common for CDs to have some tracks * with data, and some tracks with audio. Just because I feel like it, * I declare the following to be the best way to cope. If the CD has ANY diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 3e67ddde9e16..923f99df4f1c 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -237,7 +237,7 @@ extern int agp_try_unsupported_boot; long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -/* Chipset independant registers (from AGP Spec) */ +/* Chipset independent registers (from AGP Spec) */ #define AGP_APBASE 0x10 #define AGPSTAT 0x4 diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 45681c0ff3b6..f7e88787af97 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -272,7 +272,7 @@ static void amd_irongate_cleanup(void) * This routine could be implemented by taking the addresses * written to the GATT, and flushing them individually. However * currently it just flushes the whole table. Which is probably - * more efficent, since agp_memory blocks can be a large number of + * more efficient, since agp_memory blocks can be a large number of * entries. */ diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 13acaaf64edb..f02f9b07fd4c 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -229,7 +229,7 @@ static int serverworks_fetch_size(void) * This routine could be implemented by taking the addresses * written to the GATT, and flushing them individually. However * currently it just flushes the whole table. Which is probably - * more efficent, since agp_memory blocks can be a large number of + * more efficient, since agp_memory blocks can be a large number of * entries. */ static void serverworks_tlbflush(struct agp_memory *temp) diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index df67e80019d2..8bc384937401 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -400,7 +400,7 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata = * the traditional AGP which resides only in chipset. AGP is used * by 3D driver which wasn't available for the VT3336 and VT3364 * generation until now. Unfortunately, by testing, VT3364 works - * but VT3336 doesn't. - explaination from via, just leave this as + * but VT3336 doesn't. - explanation from via, just leave this as * as a placeholder to avoid future patches adding it back in. */ #if 0 diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 0dec5da000ef..2efa176beab0 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -122,7 +122,7 @@ static struct ipmi_recv_msg halt_recv_msg = { /* - * Code to send a message and wait for the reponse. + * Code to send a message and wait for the response. */ static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index d28b484aee45..cc6c9b2546a3 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -339,7 +339,7 @@ static void return_hosed_msg(struct smi_info *smi_info, int cCode) cCode = IPMI_ERR_UNSPECIFIED; /* else use it as is */ - /* Make it a reponse */ + /* Make it a response */ msg->rsp[0] = msg->data[0] | 4; msg->rsp[1] = msg->data[1]; msg->rsp[2] = cCode; @@ -2927,7 +2927,7 @@ static void return_hosed_msg_badsize(struct smi_info *smi_info) { struct ipmi_smi_msg *msg = smi_info->curr_msg; - /* Make it a reponse */ + /* Make it a response */ msg->rsp[0] = msg->data[0] | 4; msg->rsp[1] = msg->data[1]; msg->rsp[2] = CANNOT_RETURN_REQUESTED_LENGTH; diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h index ba671589f4cb..1a36884c48b5 100644 --- a/drivers/char/mbcs.h +++ b/drivers/char/mbcs.h @@ -36,13 +36,13 @@ #define MBCS_RD_DMA_CTRL 0x0110 /* Read DMA Control */ #define MBCS_RD_DMA_AMO_DEST 0x0118 /* Read DMA AMO Destination */ #define MBCS_RD_DMA_INT_DEST 0x0120 /* Read DMA Interrupt Destination */ -#define MBCS_RD_DMA_AUX_STAT 0x0130 /* Read DMA Auxillary Status */ +#define MBCS_RD_DMA_AUX_STAT 0x0130 /* Read DMA Auxiliary Status */ #define MBCS_WR_DMA_SYS_ADDR 0x0200 /* Write DMA System Address */ #define MBCS_WR_DMA_LOC_ADDR 0x0208 /* Write DMA Local Address */ #define MBCS_WR_DMA_CTRL 0x0210 /* Write DMA Control */ #define MBCS_WR_DMA_AMO_DEST 0x0218 /* Write DMA AMO Destination */ #define MBCS_WR_DMA_INT_DEST 0x0220 /* Write DMA Interrupt Destination */ -#define MBCS_WR_DMA_AUX_STAT 0x0230 /* Write DMA Auxillary Status */ +#define MBCS_WR_DMA_AUX_STAT 0x0230 /* Write DMA Auxiliary Status */ #define MBCS_ALG_AMO_DEST 0x0300 /* Algorithm AMO Destination */ #define MBCS_ALG_INT_DEST 0x0308 /* Algorithm Interrupt Destination */ #define MBCS_ALG_OFFSETS 0x0310 diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h index 270431ca7dae..fba6ab1160ce 100644 --- a/drivers/char/mwave/3780i.h +++ b/drivers/char/mwave/3780i.h @@ -122,7 +122,7 @@ typedef struct { typedef struct { unsigned char Dma:3; /* RW: DMA channel selection */ unsigned char NumTransfers:2; /* RW: Maximum # of transfers once being granted the ISA bus */ - unsigned char ReRequest:2; /* RW: Minumum delay between releasing the ISA bus and requesting it again */ + unsigned char ReRequest:2; /* RW: Minimum delay between releasing the ISA bus and requesting it again */ unsigned char MEMCS16:1; /* RW: ISA signal MEMCS16: 0=disabled, 1=enabled */ } DSP_BUSMASTER_CFG_1; diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 8994ce32e6c7..04a480f86c6c 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -75,7 +75,7 @@ int button_add_callback (void (*callback) (void), int count) * with -EINVAL. If there is more than one entry with the same address, * because it searches the list from end to beginning, it will unregister the * last one to be registered first (FILO- First In Last Out). - * Note that this is not neccessarily true if the entries are not submitted + * Note that this is not necessarily true if the entries are not submitted * at the same time, because another driver could have unregistered a callback * between the submissions creating a gap earlier in the list, which would * be filled first at submission time. diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index bcbbc71febb7..90bd01671c70 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -806,7 +806,7 @@ static void monitor_card(unsigned long p) dev->flags1 = 0x01; xoutb(dev->flags1, REG_FLAGS1(iobase)); - /* atr is present (which doesnt mean it's valid) */ + /* atr is present (which doesn't mean it's valid) */ set_bit(IS_ATR_PRESENT, &dev->flags); if (dev->atr[0] == 0x03) str_invert_revert(dev->atr, dev->atr_len); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index beca80bb9bdb..b575411c69b2 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1290,7 +1290,7 @@ static int startup(MGSLPC_INFO * info, struct tty_struct *tty) /* Allocate and claim adapter resources */ retval = claim_resources(info); - /* perform existance check and diagnostics */ + /* perform existence check and diagnostics */ if ( !retval ) retval = adapter_test(info); @@ -2680,7 +2680,7 @@ static void rx_free_buffers(MGSLPC_INFO *info) static int claim_resources(MGSLPC_INFO *info) { if (rx_alloc_buffers(info) < 0 ) { - printk( "Cant allocate rx buffer %s\n", info->device_name); + printk( "Can't allocate rx buffer %s\n", info->device_name); release_resources(info); return -ENODEV; } diff --git a/drivers/char/random.c b/drivers/char/random.c index 5e29e8031bbc..d4ddeba56682 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -732,7 +732,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, size_t nbytes, int min, int rsvd); /* - * This utility inline function is responsible for transfering entropy + * This utility inline function is responsible for transferring entropy * from the primary pool to the secondary extraction pool. We make * sure we pull enough for a 'catastrophic reseed'. */ diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 79e36c878a4c..1ee8ce7d2762 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1241,7 +1241,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, while (check_ioport && check->port1) { if (!request_region(check->port1, sonypi_device.region_size, - "Sony Programable I/O Device Check")) { + "Sony Programmable I/O Device Check")) { printk(KERN_ERR "sonypi: ioport 0x%.4x busy, using sony-laptop? " "if not use check_ioport=0\n", check->port1); @@ -1255,7 +1255,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, if (request_region(ioport_list->port1, sonypi_device.region_size, - "Sony Programable I/O Device")) { + "Sony Programmable I/O Device")) { dev->ioport1 = ioport_list->port1; dev->ioport2 = ioport_list->port2; return 0; diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index d3c9d755ed98..d6412c16385f 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -67,7 +67,7 @@ * cp foo.bit /dev/icap0 * * Note that unless foo.bit is an appropriately constructed partial - * bitstream, this has a high likelyhood of overwriting the design + * bitstream, this has a high likelihood of overwriting the design * currently programmed in the FPGA. */ diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b03771d4787c..2dafc5c38ae7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1782,7 +1782,7 @@ error_out: * cpufreq_update_policy - re-evaluate an existing cpufreq policy * @cpu: CPU which shall be re-evaluated * - * Usefull for policy notifiers which have different necessities + * Useful for policy notifiers which have different necessities * at different times. */ int cpufreq_update_policy(unsigned int cpu) diff --git a/drivers/crypto/amcc/crypto4xx_sa.c b/drivers/crypto/amcc/crypto4xx_sa.c index 466fd94cd4a3..de8a7a48775a 100644 --- a/drivers/crypto/amcc/crypto4xx_sa.c +++ b/drivers/crypto/amcc/crypto4xx_sa.c @@ -17,7 +17,7 @@ * @file crypto4xx_sa.c * * This file implements the security context - * assoicate format. + * associate format. */ #include #include diff --git a/drivers/crypto/amcc/crypto4xx_sa.h b/drivers/crypto/amcc/crypto4xx_sa.h index 4b83ed7e5570..1352d58d4e34 100644 --- a/drivers/crypto/amcc/crypto4xx_sa.h +++ b/drivers/crypto/amcc/crypto4xx_sa.h @@ -15,7 +15,7 @@ * GNU General Public License for more details. * * This file defines the security context - * assoicate format. + * associate format. */ #ifndef __CRYPTO4XX_SA_H__ diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 0d662213c066..4c20c5bf6058 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -1044,7 +1044,7 @@ static int aead_perform(struct aead_request *req, int encrypt, memcpy(crypt->iv, req->iv, ivsize); if (req->src != req->dst) { - BUG(); /* -ENOTSUP because of my lazyness */ + BUG(); /* -ENOTSUP because of my laziness */ } /* ASSOC data */ diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3d7d705f026f..235f53bf494e 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -167,7 +167,7 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc) /** * atc_assign_cookie - compute and assign new cookie * @atchan: channel we work on - * @desc: descriptor to asign cookie for + * @desc: descriptor to assign cookie for * * Called with atchan->lock held and bh disabled */ diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 00deabd9a04b..f48e54006518 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -529,7 +529,7 @@ static void coh901318_pause(struct dma_chan *chan) val = readl(virtbase + COH901318_CX_CFG + COH901318_CX_CFG_SPACING * channel); - /* Stopping infinit transfer */ + /* Stopping infinite transfer */ if ((val & COH901318_CX_CTRL_TC_ENABLE) == 0 && (val & COH901318_CX_CFG_CH_ENABLE)) cohc->stopped = 1; diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 798f46a4590d..3d4ec38b9b62 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -911,8 +911,8 @@ static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan) /** * midc_handle_error - Handle DMA txn error - * @mid: controller where error occured - * @midc: chan where error occured + * @mid: controller where error occurred + * @midc: chan where error occurred * * Scan the descriptor for error */ @@ -1099,7 +1099,7 @@ static int mid_setup_dma(struct pci_dev *pdev) dma->mask_reg = ioremap(LNW_PERIPHRAL_MASK_BASE, LNW_PERIPHRAL_MASK_SIZE); if (dma->mask_reg == NULL) { - pr_err("ERR_MDMA:Cant map periphral intr space !!\n"); + pr_err("ERR_MDMA:Can't map periphral intr space !!\n"); return -ENOMEM; } } else @@ -1373,7 +1373,7 @@ int dma_resume(struct pci_dev *pci) pci_restore_state(pci); ret = pci_enable_device(pci); if (ret) { - pr_err("MDMA: device cant be enabled for %x\n", pci->device); + pr_err("MDMA: device can't be enabled for %x\n", pci->device); return ret; } device->state = RUNNING; diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h index 709fecbdde79..aea5ee88ce03 100644 --- a/drivers/dma/intel_mid_dma_regs.h +++ b/drivers/dma/intel_mid_dma_regs.h @@ -174,8 +174,8 @@ union intel_mid_dma_cfg_hi { * @dma: dma device struture pointer * @busy: bool representing if ch is busy (active txn) or not * @in_use: bool representing if ch is in use or not - * @raw_tfr: raw trf interrupt recieved - * @raw_block: raw block interrupt recieved + * @raw_tfr: raw trf interrupt received + * @raw_block: raw block interrupt received */ struct intel_mid_dma_chan { struct dma_chan chan; diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 4f95d31f5a20..b9bae94f2015 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -328,7 +328,7 @@ static irqreturn_t mpc_dma_irq(int irq, void *data) return IRQ_HANDLED; } -/* proccess completed descriptors */ +/* process completed descriptors */ static void mpc_dma_process_completed(struct mpc_dma *mdma) { dma_cookie_t last_cookie = 0; diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index af955de035f4..94ee15dd3aed 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -90,7 +90,7 @@ struct d40_lli_pool { * @lli_log: Same as above but for logical channels. * @lli_pool: The pool with two entries pre-allocated. * @lli_len: Number of llis of current descriptor. - * @lli_current: Number of transfered llis. + * @lli_current: Number of transferred llis. * @lcla_alloc: Number of LCLA entries allocated. * @txd: DMA engine struct. Used for among other things for communication * during a transfer. @@ -1214,7 +1214,7 @@ static void dma_tasklet(unsigned long data) return; err: - /* Rescue manouver if receiving double interrupts */ + /* Rescue manoeuvre if receiving double interrupts */ if (d40c->pending_tx > 0) d40c->pending_tx--; spin_unlock_irqrestore(&d40c->lock, flags); diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index fac1a2002e67..af1a17d42bd7 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -45,7 +45,7 @@ config EDAC_DECODE_MCE default y ---help--- Enable this option if you want to decode Machine Check Exceptions - occuring on your machine in human-readable form. + occurring on your machine in human-readable form. You should definitely say Y here in case you want to decode MCEs which occur really early upon boot, before the module infrastructure diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index b9a781c47e3c..837ad8f85b48 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -817,7 +817,7 @@ static void cpc925_del_edac_devices(void) } } -/* Convert current back-ground scrub rate into byte/sec bandwith */ +/* Convert current back-ground scrub rate into byte/sec bandwidth */ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci) { struct cpc925_mc_pdata *pdata = mci->pvt_info; diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 3d965347a673..eefa3501916b 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -164,7 +164,7 @@ enum mem_type { /* chipset Error Detection and Correction capabilities and mode */ enum edac_type { EDAC_UNKNOWN = 0, /* Unknown if ECC is available */ - EDAC_NONE, /* Doesnt support ECC */ + EDAC_NONE, /* Doesn't support ECC */ EDAC_RESERVED, /* Reserved ECC type */ EDAC_PARITY, /* Detects parity errors */ EDAC_EC, /* Error Checking - no correction */ @@ -233,7 +233,7 @@ enum scrub_type { * of these in parallel provides 64 bits which is common * for a memory stick. * - * Memory Stick: A printed circuit board that agregates multiple + * Memory Stick: A printed circuit board that aggregates multiple * memory devices in parallel. This is the atomic * memory component that is purchaseable by Joe consumer * and loaded into a memory socket. @@ -385,7 +385,7 @@ struct mem_ctl_info { /* Get the current sdram memory scrub rate from the internal representation and converts it to the closest matching - bandwith in bytes/sec. + bandwidth in bytes/sec. */ int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci); @@ -823,7 +823,7 @@ extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, * There are a limited number of error logging registers that can * be exausted. When all registers are exhausted and an additional * error occurs then an error overflow register records that an - * error occured and the type of error, but doesn't have any + * error occurred and the type of error, but doesn't have any * further information. The ce/ue versions make for cleaner * reporting logic and function interface - reduces conditional * statement clutter and extra function arguments. diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index d5e13c94714f..a7408cf86f37 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -672,7 +672,7 @@ void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev, block->counters.ce_count++; } - /* Propogate the count up the 'totals' tree */ + /* Propagate the count up the 'totals' tree */ instance->counters.ce_count++; edac_dev->counters.ce_count++; @@ -718,7 +718,7 @@ void edac_device_handle_ue(struct edac_device_ctl_info *edac_dev, block->counters.ue_count++; } - /* Propogate the count up the 'totals' tree */ + /* Propagate the count up the 'totals' tree */ instance->counters.ue_count++; edac_dev->counters.ue_count++; diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index 400de071cabc..86649df00285 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c @@ -533,7 +533,7 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, memset(&block->kobj, 0, sizeof(struct kobject)); /* bump the main kobject's reference count for this controller - * and this instance is dependant on the main + * and this instance is dependent on the main */ main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { @@ -635,7 +635,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, instance->ctl = edac_dev; /* bump the main kobject's reference count for this controller - * and this instance is dependant on the main + * and this instance is dependent on the main */ main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index a4e9db2d6524..1d8056049072 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -724,7 +724,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, * Some MC's can remap memory so that it is still available * at a different address when PCI devices map into memory. * MC's that can't do this lose the memory where PCI devices - * are mapped. This mapping is MC dependant and so we call + * are mapped. This mapping is MC dependent and so we call * back into the MC driver for it to map the MC page to * a physical (CPU) page which can then be mapped to a virtual * page - which can then be scrubbed. diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 73196f7b7229..26343fd46596 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -850,7 +850,7 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, /* * loop if there are attributes and until we hit a NULL entry - * Remove first all the atributes + * Remove first all the attributes */ while (sysfs_attrib) { debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib); diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 023b01cb5175..495198ad059c 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -352,7 +352,7 @@ static int edac_pci_main_kobj_setup(void) return 0; /* First time, so create the main kobject and its - * controls and atributes + * controls and attributes */ edac_class = edac_get_sysfs_class(); if (edac_class == NULL) { @@ -551,7 +551,7 @@ static void edac_pci_dev_parity_clear(struct pci_dev *dev) /* * PCI Parity polling * - * Fucntion to retrieve the current parity status + * Function to retrieve the current parity status * and decode it * */ diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index a5cefab8d65d..87f427c2ce5c 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1372,7 +1372,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) * actual number of slots/dimms per channel, we thus utilize the * resource as specified by the chipset. Thus, we might have * have more DIMMs per channel than actually on the mobo, but this - * allows the driver to support upto the chipset max, without + * allows the driver to support up to the chipset max, without * some fancy mobo determination. */ i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel, diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 0448da0af75d..bcbdeeca48b8 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -11,7 +11,7 @@ * * The intel 5100 has two independent channels. EDAC core currently * can not reflect this configuration so instead the chip-select - * rows for each respective channel are layed out one after another, + * rows for each respective channel are laid out one after another, * the first half belonging to channel 0, the second half belonging * to channel 1. */ diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 38a9be9e1c7c..80a465efbae8 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -648,7 +648,7 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, return; } - /* Miscelaneous errors */ + /* Miscellaneous errors */ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); branch = extract_fbdchan_indx(info->ferr_nf_fbd); @@ -1240,7 +1240,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) * actual number of slots/dimms per channel, we thus utilize the * resource as specified by the chipset. Thus, we might have * have more DIMMs per channel than actually on the mobo, but this - * allows the driver to support upto the chipset max, without + * allows the driver to support up to the chipset max, without * some fancy mobo determination. */ num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 76d1f576cdc8..363cc1602944 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -1065,7 +1065,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, * actual number of slots/dimms per channel, we thus utilize the * resource as specified by the chipset. Thus, we might have * have more DIMMs per channel than actually on the mobo, but this - * allows the driver to support upto the chipset max, without + * allows the driver to support up to the chipset max, without * some fancy mobo determination. */ num_dimms_per_channel = MAX_SLOTS; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 81154ab296b6..465cbc25149f 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1772,7 +1772,7 @@ static void i7core_check_error(struct mem_ctl_info *mci) /* * MCE first step: Copy all mce errors into a temporary buffer * We use a double buffering here, to reduce the risk of - * loosing an error. + * losing an error. */ smp_rmb(); count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in) diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 678405ab04e4..4329d39f902c 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -203,7 +203,7 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, row_high_limit = ((u32) drbar << 23); /* find the DRAM Chip Select Base address and mask */ debugf1("MC%d: %s: %s() Row=%d, " - "Boundry Address=%#0x, Last = %#0x\n", + "Boundary Address=%#0x, Last = %#0x\n", mci->mc_idx, __FILE__, __func__, index, row_high_limit, row_high_limit_last); @@ -305,7 +305,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) i82443bxgx_init_csrows(mci, pdev, edac_mode, mtype); /* Many BIOSes don't clear error flags on boot, so do this - * here, or we get "phantom" errors occuring at module-load + * here, or we get "phantom" errors occurring at module-load * time. */ pci_write_bits32(pdev, I82443BXGX_EAP, (I82443BXGX_EAP_OFFSET_SBE | diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c index 733a7e7a8d6f..a4987e03f59e 100644 --- a/drivers/edac/mce_amd_inj.c +++ b/drivers/edac/mce_amd_inj.c @@ -90,7 +90,7 @@ static ssize_t edac_inject_bank_store(struct kobject *kobj, if (value > 5) if (boot_cpu_data.x86 != 0x15 || value > 6) { - printk(KERN_ERR "Non-existant MCE bank: %lu\n", value); + printk(KERN_ERR "Non-existent MCE bank: %lu\n", value); return -EINVAL; } diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 6a822c631ef5..678513738c33 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -120,7 +120,7 @@ * write 0=NOP */ -#define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundry Address +#define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundary Address * Registers * * 7:0 Address lines 30:24 - upper limit of @@ -217,7 +217,7 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, { struct csrow_info *csrow; int index; - u8 drbar; /* SDRAM Row Boundry Address Register */ + u8 drbar; /* SDRAM Row Boundary Address Register */ u32 row_high_limit, row_high_limit_last; u32 reg_sdram, ecc_on, row_base; @@ -236,7 +236,7 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, row_high_limit = ((u32) drbar << 24); /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ - debugf1("%s() Row=%d, Boundry Address=%#0x, Last = %#0x\n", + debugf1("%s() Row=%d, Boundary Address=%#0x, Last = %#0x\n", __func__, index, row_high_limit, row_high_limit_last); /* Empty row [p.57] */ diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 7ed08fd1214e..3f04dd3681cf 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -453,7 +453,7 @@ static bool fwnet_pd_update(struct fwnet_peer *peer, memcpy(pd->pbuf + frag_off, frag_buf, frag_len); /* - * Move list entry to beginnig of list so that oldest partial + * Move list entry to beginning of list so that oldest partial * datagrams percolate to the end of the list */ list_move_tail(&pd->pd_link, &peer->pd_list); diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/mc33880.c index 00f6d24c669d..4ec797593bdb 100644 --- a/drivers/gpio/mc33880.c +++ b/drivers/gpio/mc33880.c @@ -45,7 +45,7 @@ * To save time we cache them here in memory */ struct mc33880 { - struct mutex lock; /* protect from simultanous accesses */ + struct mutex lock; /* protect from simultaneous accesses */ u8 port_config; struct gpio_chip chip; struct spi_device *spi; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 799e1490cf24..872747c5a544 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1699,7 +1699,7 @@ int drm_mode_addfb(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); - /* TODO check buffer is sufficently large */ + /* TODO check buffer is sufficiently large */ /* TODO setup destructor callback */ fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); @@ -1750,7 +1750,7 @@ int drm_mode_rmfb(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); - /* TODO check that we realy get a framebuffer back. */ + /* TODO check that we really get a framebuffer back. */ if (!obj) { DRM_ERROR("mode invalid framebuffer id\n"); ret = -EINVAL; diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index add1737dae0d..5d00b0fc0d91 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -551,7 +551,7 @@ EXPORT_SYMBOL(drm_mm_scan_add_block); * corrupted. * * When the scan list is empty, the selected memory nodes can be freed. An - * immediatly following drm_mm_search_free with best_match = 0 will then return + * immediately following drm_mm_search_free with best_match = 0 will then return * the just freed block (because its at the top of the free_stack list). * * Returns one if this block should be evicted, zero otherwise. Will always diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5004724ea57e..1c1b27c97e5c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -630,7 +630,7 @@ typedef struct drm_i915_private { * Flag if the hardware appears to be wedged. * * This is set when attempts to idle the device timeout. - * It prevents command submission from occuring and makes + * It prevents command submission from occurring and makes * every pending request fail */ atomic_t wedged; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0daefca5cbb8..cb8578b7e443 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -213,7 +213,7 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_PANEL; } - /* only refuse the mode on non eDP since we have seen some wierd eDP panels + /* only refuse the mode on non eDP since we have seen some weird eDP panels which are outside spec tolerances but somehow work by magic */ if (!is_edp(intel_dp) && (intel_dp_link_required(connector->dev, intel_dp, mode->clock) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index a386b022e538..4f4e23bc2d16 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -230,7 +230,7 @@ struct intel_sdvo_set_target_input_args { } __attribute__((packed)); /** - * Takes a struct intel_sdvo_output_flags of which outputs are targetted by + * Takes a struct intel_sdvo_output_flags of which outputs are targeted by * future output commands. * * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 1e1eb1d7e971..5ccb65deb83c 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -426,7 +426,7 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags) * Bootstrap the driver for AGP DMA. * * \todo - * Investigate whether there is any benifit to storing the WARP microcode in + * Investigate whether there is any benefit to storing the WARP microcode in * AGP memory. If not, the microcode may as well always be put in PCI * memory. * diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 3837090d66af..4cea35c57d15 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -200,7 +200,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, /* disable the fifo caches */ pfifo->reassign(dev, false); - /* Construct inital RAMFC for new channel */ + /* Construct initial RAMFC for new channel */ ret = pfifo->create_context(chan); if (ret) { nouveau_channel_put(&chan); @@ -278,7 +278,7 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan) return; } - /* noone wants the channel anymore */ + /* no one wants the channel anymore */ NV_DEBUG(dev, "freeing channel %d\n", chan->id); nouveau_debugfs_channel_fini(chan); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index fff180a99867..57e5302503db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -216,7 +216,7 @@ struct nouveau_channel { /* mapping of the fifo itself */ struct drm_local_map *map; - /* mapping of the regs controling the fifo */ + /* mapping of the regs controlling the fifo */ void __iomem *user; uint32_t user_get; uint32_t user_put; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 4fcbd091a117..5bb2859001e2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -963,7 +963,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) if (ret) goto err_mmio; - /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ + /* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */ if (dev_priv->card_type >= NV_40) { int ramin_bar = 2; if (pci_resource_len(dev->pdev, ramin_bar) == 0) diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index a260fbbe3d9b..748b9d9c2949 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -164,7 +164,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode, nv_crtc->index); - if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */ + if (nv_crtc->last_dpms == mode) /* Don't do unnecessary mode changes. */ return; nv_crtc->last_dpms = mode; @@ -677,7 +677,7 @@ static void nv_crtc_prepare(struct drm_crtc *crtc) NVBlankScreen(dev, nv_crtc->index, true); - /* Some more preperation. */ + /* Some more preparation. */ NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA); if (dev_priv->card_type == NV_40) { uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900); diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 18d30c2c1aa6..fceb44c0ec74 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -181,7 +181,7 @@ nv40_graph_load_context(struct nouveau_channel *chan) NV40_PGRAPH_CTXCTL_CUR_LOADED); /* 0x32E0 records the instance address of the active FIFO's PGRAPH * context. If at any time this doesn't match 0x40032C, you will - * recieve PGRAPH_INTR_CONTEXT_SWITCH + * receive PGRAPH_INTR_CONTEXT_SWITCH */ nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst); return 0; diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 04b269d14a59..7fd88497b930 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -738,13 +738,13 @@ typedef struct _ATOM_DIG_ENCODER_CONFIG_V3 { #if ATOM_BIG_ENDIAN UCHAR ucReserved1:1; - UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) UCHAR ucReserved:3; UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz #else UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz UCHAR ucReserved:3; - UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) UCHAR ucReserved1:1; #endif }ATOM_DIG_ENCODER_CONFIG_V3; @@ -785,13 +785,13 @@ typedef struct _ATOM_DIG_ENCODER_CONFIG_V4 { #if ATOM_BIG_ENDIAN UCHAR ucReserved1:1; - UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) UCHAR ucReserved:2; UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version #else UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version UCHAR ucReserved:2; - UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F) UCHAR ucReserved1:1; #endif }ATOM_DIG_ENCODER_CONFIG_V4; @@ -2126,7 +2126,7 @@ typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO // Structures used in FirmwareInfoTable /****************************************************************************/ -// usBIOSCapability Defintion: +// usBIOSCapability Definition: // Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; // Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; // Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; @@ -3341,7 +3341,7 @@ typedef struct _ATOM_SPREAD_SPECTRUM_INFO /****************************************************************************/ // Structure used in AnalogTV_InfoTable (Top level) /****************************************************************************/ -//ucTVBootUpDefaultStd definiton: +//ucTVBootUpDefaultStd definition: //ATOM_TV_NTSC 1 //ATOM_TV_NTSCJ 2 @@ -3816,7 +3816,7 @@ typedef struct _ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO UCHAR Reserved [6]; // for potential expansion }ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO; -//Related definitions, all records are differnt but they have a commond header +//Related definitions, all records are different but they have a commond header typedef struct _ATOM_COMMON_RECORD_HEADER { UCHAR ucRecordType; //An emun to indicate the record type @@ -4365,14 +4365,14 @@ ucUMAChannelNumber: System memory channel numbers. ulCSR_M3_ARB_CNTL_DEFAULT[10]: Arrays with values for CSR M3 arbiter for default ulCSR_M3_ARB_CNTL_UVD[10]: Arrays with values for CSR M3 arbiter for UVD playback. ulCSR_M3_ARB_CNTL_FS3D[10]: Arrays with values for CSR M3 arbiter for Full Screen 3D applications. -sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high +sAvail_SCLK[5]: Arrays to provide available list of SLCK and corresponding voltage, order from low to high ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. ulMinimumNClk: Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. ulIdleNClk: NCLK speed while memory runs in self-refresh state. Unit in 10kHz. ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns. ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns. -usPCIEClkSSPercentage: PCIE Clock Spred Spectrum Percentage in unit 0.01%; 100 mean 1%. -usPCIEClkSSType: PCIE Clock Spred Spectrum Type. 0 for Down spread(default); 1 for Center spread. +usPCIEClkSSPercentage: PCIE Clock Spread Spectrum Percentage in unit 0.01%; 100 mean 1%. +usPCIEClkSSType: PCIE Clock Spread Spectrum Type. 0 for Down spread(default); 1 for Center spread. usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. @@ -4555,7 +4555,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LIT2AC 4 -//Byte aligned defintion for BIOS usage +//Byte aligned definition for BIOS usage #define ATOM_S0_CRT1_MONOb0 0x01 #define ATOM_S0_CRT1_COLORb0 0x02 #define ATOM_S0_CRT1_MASKb0 (ATOM_S0_CRT1_MONOb0+ATOM_S0_CRT1_COLORb0) @@ -4621,7 +4621,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 #define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK 0xC0000000L -//Byte aligned defintion for BIOS usage +//Byte aligned definition for BIOS usage #define ATOM_S2_TV1_STANDARD_MASKb0 0x0F #define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF #define ATOM_S2_DEVICE_DPMS_STATEb2 0x01 @@ -4671,7 +4671,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 #define ATOM_S3_ALLOW_FAST_PWR_SWITCH 0x40000000L #define ATOM_S3_RQST_GPU_USE_MIN_PWR 0x80000000L -//Byte aligned defintion for BIOS usage +//Byte aligned definition for BIOS usage #define ATOM_S3_CRT1_ACTIVEb0 0x01 #define ATOM_S3_LCD1_ACTIVEb0 0x02 #define ATOM_S3_TV1_ACTIVEb0 0x04 @@ -4707,7 +4707,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 #define ATOM_S4_LCD1_REFRESH_MASK 0x0000FF00L #define ATOM_S4_LCD1_REFRESH_SHIFT 8 -//Byte aligned defintion for BIOS usage +//Byte aligned definition for BIOS usage #define ATOM_S4_LCD1_PANEL_ID_MASKb0 0x0FF #define ATOM_S4_LCD1_REFRESH_MASKb1 ATOM_S4_LCD1_PANEL_ID_MASKb0 #define ATOM_S4_VRAM_INFO_MASKb2 ATOM_S4_LCD1_PANEL_ID_MASKb0 @@ -4786,7 +4786,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 #define ATOM_S6_VRI_BRIGHTNESS_CHANGE 0x40000000L #define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK 0x80000000L -//Byte aligned defintion for BIOS usage +//Byte aligned definition for BIOS usage #define ATOM_S6_DEVICE_CHANGEb0 0x01 #define ATOM_S6_SCALER_CHANGEb0 0x02 #define ATOM_S6_LID_CHANGEb0 0x04 @@ -5027,7 +5027,7 @@ typedef struct _ENABLE_GRAPH_SURFACE_PS_ALLOCATION typedef struct _MEMORY_CLEAN_UP_PARAMETERS { - USHORT usMemoryStart; //in 8Kb boundry, offset from memory base address + USHORT usMemoryStart; //in 8Kb boundary, offset from memory base address USHORT usMemorySize; //8Kb blocks aligned }MEMORY_CLEAN_UP_PARAMETERS; #define MEMORY_CLEAN_UP_PS_ALLOCATION MEMORY_CLEAN_UP_PARAMETERS @@ -6855,7 +6855,7 @@ typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table /**************************************************************************/ -// Following definitions are for compatiblity issue in different SW components. +// Following definitions are for compatibility issue in different SW components. #define ATOM_MASTER_DATA_TABLE_REVISION 0x01 #define Object_Info Object_Header #define AdjustARB_SEQ MC_InitParameter diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index edde90b37554..23d36417158d 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -442,7 +442,7 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 } ib = p->ib->ptr; switch (reg) { - /* force following reg to 0 in an attemp to disable out buffer + /* force following reg to 0 in an attempt to disable out buffer * which will need us to better understand how it works to perform * security check on it (Jerome) */ diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 8713731fa014..55a7f190027e 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -437,7 +437,7 @@ int r300_asic_reset(struct radeon_device *rdev) status = RREG32(R_000E40_RBBM_STATUS); dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); /* resetting the CP seems to be problematic sometimes it end up - * hard locking the computer, but it's necessary for successfull + * hard locking the computer, but it's necessary for successful * reset more test & playing is needed on R3XX/R4XX to find a * reliable (if any solution) */ diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index f0bce399c9f3..00c0d2ba22d3 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h @@ -608,7 +608,7 @@ * My guess is that there are two bits for each zbias primitive * (FILL, LINE, POINT). * One to enable depth test and one for depth write. - * Yet this doesnt explain why depth writes work ... + * Yet this doesn't explain why depth writes work ... */ #define R300_RE_OCCLUSION_CNTL 0x42B4 # define R300_OCCLUSION_ON (1<<1) @@ -817,7 +817,7 @@ # define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11) # define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11) -/* NOTE: NEAREST doesnt seem to exist. +/* NOTE: NEAREST doesn't seem to exist. * Im not seting MAG_FILTER_MASK and (3 << 11) on for all * anisotropy modes because that would void selected mag filter */ diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 3324620b2db6..fd18be9871ab 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -921,7 +921,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx return 0; ib = p->ib->ptr; switch (reg) { - /* force following reg to 0 in an attemp to disable out buffer + /* force following reg to 0 in an attempt to disable out buffer * which will need us to better understand how it works to perform * security check on it (Jerome) */ diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 50db6d62eec2..f5ac7e788d81 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -334,7 +334,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - /* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */ + /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF); WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF); WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index cfe3af1a7935..93f536594c73 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -679,11 +679,11 @@ struct radeon_wb { * @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP) * @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP) * @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP) - * @sclk: GPU clock Mhz (core bandwith depends of this clock) + * @sclk: GPU clock Mhz (core bandwidth depends of this clock) * @needed_bandwidth: current bandwidth needs * * It keeps track of various data needed to take powermanagement decision. - * Bandwith need is used to determine minimun clock of the GPU and memory. + * Bandwidth need is used to determine minimun clock of the GPU and memory. * Equation between gpu/memory clock and available bandwidth is hw dependent * (type of memory, bus size, efficiency, ...) */ diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 3d599e33b9cc..75867792a4e2 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -244,7 +244,7 @@ void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) u32 agp_base_lo = agp_base & 0xffffffff; u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff; - /* R6xx/R7xx must be aligned to a 4MB boundry */ + /* R6xx/R7xx must be aligned to a 4MB boundary */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base); else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 017ac54920fb..bdf2fa1189ae 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -226,7 +226,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, y += crtc->y; DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); - /* avivo cursor image can't end on 128 pixel boundry or + /* avivo cursor image can't end on 128 pixel boundary or * go past the end of the frame if both crtcs are enabled */ list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f0209be7a34b..890217e678d3 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -262,7 +262,7 @@ int radeon_wb_init(struct radeon_device *rdev) * Note: GTT start, end, size should be initialized before calling this * function on AGP platform. * - * Note: We don't explictly enforce VRAM start to be aligned on VRAM size, + * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size, * this shouldn't be a problem as we are using the PCI aperture as a reference. * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but * not IGP. diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 4be58793dc17..bdbab5c43bdc 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1492,7 +1492,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * * \return Flags, or'ed together as follows: * - * DRM_SCANOUTPOS_VALID = Query successfull. + * DRM_SCANOUTPOS_VALID = Query successful. * DRM_SCANOUTPOS_INVBL = Inside vblank. * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of * this flag means that returned position may be offset by a constant but diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 5cba46b9779a..a1b59ca96d01 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -271,7 +271,7 @@ typedef struct drm_radeon_private { int have_z_offset; - /* starting from here on, data is preserved accross an open */ + /* starting from here on, data is preserved across an open */ uint32_t flags; /* see radeon_chip_flags */ resource_size_t fb_aper_offset; diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 7f8e778dba46..ede6c13628f2 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -87,7 +87,7 @@ static inline void radeon_bo_unreserve(struct radeon_bo *bo) * Returns current GPU offset of the object. * * Note: object should either be pinned or reserved when calling this - * function, it might be usefull to add check for this for debugging. + * function, it might be useful to add check for this for debugging. */ static inline u64 radeon_bo_gpu_offset(struct radeon_bo *bo) { diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 4ae5a3d1074e..92e7ea73b7c5 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -980,7 +980,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, } /* hyper z clear */ - /* no docs available, based on reverse engeneering by Stephane Marchesin */ + /* no docs available, based on reverse engineering by Stephane Marchesin */ if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) && (flags & RADEON_CLEAR_FASTZ)) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index cceeb42789b6..dfe32e62bd90 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -245,7 +245,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, /* TODO handle none page aligned offsets */ /* TODO handle partial uploads and pitch != 256 */ /* TODO handle more then one copy (size != 64) */ - DRM_ERROR("lazy programer, cant handle wierd stuff\n"); + DRM_ERROR("lazy programmer, can't handle weird stuff\n"); return; } diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index ace2b1623b21..be8d4cb5861c 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -151,7 +151,7 @@ static inline void vga_irq_set_state(struct vga_device *vgadev, bool state) static void vga_check_first_use(void) { /* we should inform all GPUs in the system that - * VGA arb has occured and to try and disable resources + * VGA arb has occurred and to try and disable resources * if they can */ if (!vga_arbiter_used) { vga_arbiter_used = true; @@ -774,7 +774,7 @@ static ssize_t vga_arb_read(struct file *file, char __user * buf, */ spin_lock_irqsave(&vga_lock, flags); - /* If we are targetting the default, use it */ + /* If we are targeting the default, use it */ pdev = priv->target; if (pdev == NULL || pdev == PCI_INVALID_CARD) { spin_unlock_irqrestore(&vga_lock, flags); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e9687768a335..453e7e6da0c2 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -306,7 +306,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_PUSH: if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { - dbg_hid("global enviroment stack overflow\n"); + dbg_hid("global environment stack overflow\n"); return -1; } @@ -317,7 +317,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_POP: if (!parser->global_stack_ptr) { - dbg_hid("global enviroment stack underflow\n"); + dbg_hid("global environment stack underflow\n"); return -1; } diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 555382fc7417..bae48745bb42 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -341,7 +341,7 @@ static const struct hid_usage_entry hid_usage_table[] = { { 0x85, 0x83, "DesignCapacity" }, { 0x85, 0x85, "ManufacturerDate" }, { 0x85, 0x89, "iDeviceChemistry" }, - { 0x85, 0x8b, "Rechargable" }, + { 0x85, 0x8b, "Rechargeable" }, { 0x85, 0x8f, "iOEMInformation" }, { 0x85, 0x8d, "CapacityGranularity1" }, { 0x85, 0xd0, "ACPresent" }, diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 318cc40df92d..7a6137346097 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -76,7 +76,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches * are down and the touch providing for single touch emulation is lifted, * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is - * occuring, single_touch_id corresponds with the tracking id of the touch used. + * occurring, single_touch_id corresponds with the tracking id of the touch used. */ #define NO_TOUCHES -1 #define SINGLE_TOUCH_UP -2 diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 657da5a3d5c6..b2f56a13bcf5 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c @@ -1806,13 +1806,13 @@ static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, /* * Notes: * - concurrent writing is prevented by mutex and all writes must be - * n*64 bytes and 64-byte aligned, each write being preceeded by an + * n*64 bytes and 64-byte aligned, each write being preceded by an * ERASE which erases a 64byte block. * If less than requested was written or an error is returned for an * otherwise correct write request the next 64-byte block which should * have been written is in undefined state (mostly: original, erased, * (half-)written with write error) - * - reading can happend without special restriction + * - reading can happen without special restriction */ static const struct file_operations picolcd_debug_flash_fops = { .owner = THIS_MODULE, diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 64abb5b8a59a..4109a028e138 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h @@ -166,7 +166,7 @@ enum kone_mouse_events { /* osd events are thought to be display on screen */ kone_mouse_event_osd_dpi = 0xa0, kone_mouse_event_osd_profile = 0xb0, - /* TODO clarify meaning and occurence of kone_mouse_event_calibration */ + /* TODO clarify meaning and occurrence of kone_mouse_event_calibration */ kone_mouse_event_calibration = 0xc0, kone_mouse_event_call_overlong_macro = 0xe0, /* switch events notify if user changed values with mousebutton click */ diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index 0e05aa179eaa..e7d4c4687f02 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -1422,7 +1422,7 @@ static int __init abituguru_detect(void) at DATA and 0xAC, when this driver has already been loaded once DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either scenario but some will hold 0x00. - Some uGuru's initally hold 0x09 at DATA and will only hold 0x08 + Some uGuru's initially hold 0x09 at DATA and will only hold 0x08 after reading CMD first, so CMD must be read first! */ u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD); u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA); diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 034cebfcd273..e89d572e3320 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -151,7 +151,7 @@ struct abituguru3_data { /* Pointer to the sensors info for the detected motherboard */ const struct abituguru3_sensor_info *sensors; - /* The abituguru3 supports upto 48 sensors, and thus has registers + /* The abituguru3 supports up to 48 sensors, and thus has registers sets for 48 sensors, for convienence reasons / simplicity of the code we always read and store all registers for all 48 sensors */ diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index be0fdd58aa29..0531867484f4 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -175,7 +175,7 @@ static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; * these macros are called: arguments may be evaluated more than once. */ -/* IN are scaled acording to built-in resistors. These are the +/* IN are scaled according to built-in resistors. These are the * voltages corresponding to 3/4 of full scale (192 or 0xc0) * NOTE: The -12V input needs an additional factor to account * for the Vref pullup resistor. diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index cf47e6e476ed..250d099ca398 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -130,7 +130,7 @@ enum chips { these macros are called: arguments may be evaluated more than once. */ -/* IN are scaled acording to built-in resistors */ +/* IN are scaled according to built-in resistors */ static const int lm85_scaling[] = { /* .001 Volts */ 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 /*EMC6D100*/ diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 812781c655a7..c43b4e9f96a9 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -356,7 +356,7 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) /* * There is a trick here. We have to read two registers to have the * sensor temperature, but we have to beware a conversion could occur - * inbetween the readings. The datasheet says we should either use + * between the readings. The datasheet says we should either use * the one-shot conversion register, which we don't want to do * (disables hardware monitoring) or monitor the busy bit, which is * impossible (we can't read the values and monitor that bit at the diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 1a9c32d6893a..f4e617adb220 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -52,7 +52,7 @@ #define SHT15_TSU 150 /* data setup time */ /** - * struct sht15_temppair - elements of voltage dependant temp calc + * struct sht15_temppair - elements of voltage dependent temp calc * @vdd: supply voltage in microvolts * @d1: see data sheet */ @@ -251,7 +251,7 @@ static inline int sht15_update_single_val(struct sht15_data *data, enable_irq(gpio_to_irq(data->pdata->gpio_data)); if (gpio_get_value(data->pdata->gpio_data) == 0) { disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); - /* Only relevant if the interrupt hasn't occured. */ + /* Only relevant if the interrupt hasn't occurred. */ if (!atomic_read(&data->interrupt_handled)) schedule_work(&data->read_work); } @@ -452,7 +452,7 @@ static void sht15_bh_read_data(struct work_struct *work_s) */ atomic_set(&data->interrupt_handled, 0); enable_irq(gpio_to_irq(data->pdata->gpio_data)); - /* If still not occured or another handler has been scheduled */ + /* If still not occurred or another handler has been scheduled */ if (gpio_get_value(data->pdata->gpio_data) || atomic_read(&data->interrupt_handled)) return; diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 93187c3cb5e7..5bd194968801 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -166,7 +166,7 @@ static int __devinit tmp102_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { - dev_err(&client->dev, "adapter doesnt support SMBus word " + dev_err(&client->dev, "adapter doesn't support SMBus word " "transactions\n"); return -ENODEV; } diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 400a88bde278..17cf1ab95521 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -556,7 +556,7 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 63841f8cec07..f3e7130c4cda 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -244,7 +244,7 @@ FAN_TO_REG(long rpm, int div) #define TEMP1_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ : (val)) / 1000, 0, 0xff)) #define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) -/* for temp2 and temp3, because they need addtional resolution */ +/* for temp2 and temp3, because they need additional resolution */ #define TEMP_ADD_FROM_REG(val1, val2) \ ((((val1) & 0x80 ? (val1)-0x100 \ : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0)) diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index e3bdedfb5347..854f9117f1aa 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -1921,7 +1921,7 @@ static void w83793_update_nonvolatile(struct device *dev) struct w83793_data *data = i2c_get_clientdata(client); int i, j; /* - They are somewhat "stable" registers, and to update them everytime + They are somewhat "stable" registers, and to update them every time takes so much time, it's just not worthy. Update them in a long interval to avoid exception. */ diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 2b9a8f54bb2c..4ca9cf9cde73 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -343,7 +343,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, ret = curmsg; out: - DEB1("}}} transfered %d/%d messages. " + DEB1("}}} transferred %d/%d messages. " "status is %#04x. control is %#04x\n", curmsg, num, pca_status(adap), pca_get_con(adap)); diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 906a3ca50db6..dd364171f9c5 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -295,7 +295,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) } /* Unfortunately the ALI SMB controller maps "no response" and "bus - * collision" into a single bit. No reponse is the usual case so don't + * collision" into a single bit. No response is the usual case so don't * do a printk. This means that bus collisions go unreported. */ if (temp & ALI1535_STS_BUSERR) { diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index b14f6d68221d..83e8a60cdc86 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -318,7 +318,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) /* Unfortunately the ALI SMB controller maps "no response" and "bus - collision" into a single bit. No reponse is the usual case so don't + collision" into a single bit. No response is the usual case so don't do a printk. This means that bus collisions go unreported. */ diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 5795c8398c7c..a76d85fa3ad7 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -355,7 +355,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) /* * Write mode register first as needed for correct behaviour * on OMAP-L138, but don't set STT yet to avoid a race with XRDY - * occuring before we have loaded DXR + * occurring before we have loaded DXR */ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index b664ed8bbdb3..b7a51c43b185 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c @@ -178,7 +178,7 @@ static char *abort_sources[] = { * @lock: protect this struct and IO registers * @clk: input reference clock * @cmd_err: run time hadware error code - * @msgs: points to an array of messages currently being transfered + * @msgs: points to an array of messages currently being transferred * @msgs_num: the number of elements in msgs * @msg_write_idx: the element index of the current tx message in the msgs * array diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index e5b1a3bf5b80..37e2e82a9c88 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -22,7 +22,7 @@ /* With some changes from Kyösti Mälkki and even Frodo Looijaard */ -/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of +/* Partially rewriten by Oleg I. Vdovikin for mmapped support of for Alpha Processor Inc. UP-2000(+) boards */ #include diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ed2e0c5ea37c..72c0415f6f94 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -96,7 +96,7 @@ #define SMBHSTCFG_SMB_SMI_EN 2 #define SMBHSTCFG_I2C_EN 4 -/* Auxillary control register bits, ICH4+ only */ +/* Auxiliary control register bits, ICH4+ only */ #define SMBAUXCTL_CRC 1 #define SMBAUXCTL_E32B 2 diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index e4f88dca99b5..3c110fbc409b 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -494,7 +494,7 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, if (unlikely(ret < 0)) break; else if (unlikely(ret != count)){ - DBG("%d: xfer_bytes, requested %d, transfered %d\n", + DBG("%d: xfer_bytes, requested %d, transferred %d\n", dev->idx, count, ret); /* If it's not a last part of xfer, abort it */ @@ -593,7 +593,7 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){ DBG("%d: iic_xfer, bus is not free\n", dev->idx); - /* Usually it means something serious has happend. + /* Usually it means something serious has happened. * We *cannot* have unfinished previous transfer * so it doesn't make any sense to try to stop it. * Probably we were not able to recover from the diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c index c71492782bbd..e828ac85cfa7 100644 --- a/drivers/i2c/busses/i2c-intel-mid.c +++ b/drivers/i2c/busses/i2c-intel-mid.c @@ -170,8 +170,8 @@ struct intel_mid_i2c_private { /* Raw Interrupt Status Register */ #define IC_RAW_INTR_STAT 0x34 /* Read Only */ #define GEN_CALL (1 << 11) /* General call */ -#define START_DET (1 << 10) /* (RE)START occured */ -#define STOP_DET (1 << 9) /* STOP occured */ +#define START_DET (1 << 10) /* (RE)START occurred */ +#define STOP_DET (1 << 9) /* STOP occurred */ #define ACTIVITY (1 << 8) /* Bus busy */ #define RX_DONE (1 << 7) /* Not used in Master mode */ #define TX_ABRT (1 << 6) /* Transmit Abort */ @@ -375,7 +375,7 @@ static int intel_mid_i2c_disable(struct i2c_adapter *adap) * I2C should be disabled prior to other register operation. If failed, an * errno is returned. Mask and Clear all interrpts, this should be done at * first. Set common registers which will not be modified during normal - * transfers, including: controll register, FIFO threshold and clock freq. + * transfers, including: control register, FIFO threshold and clock freq. * Check APB data width at last. */ static int intel_mid_i2c_hwinit(struct intel_mid_i2c_private *i2c) @@ -455,7 +455,7 @@ static inline bool intel_mid_i2c_address_neq(const struct i2c_msg *p1, * * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be * distingushed. At present, no circumstances have been found out that - * multiple errors would be occured simutaneously, so we simply use the + * multiple errors would be occurred simutaneously, so we simply use the * register value directly. * * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need @@ -469,7 +469,7 @@ static void intel_mid_i2c_abort(struct intel_mid_i2c_private *i2c) /* Single transfer error check: * According to databook, TX/RX FIFOs would be flushed when - * the abort interrupt occured. + * the abort interrupt occurred. */ if (abort & ABRT_MASTER_DIS) dev_err(&adap->dev, @@ -569,7 +569,7 @@ static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) * Return Values: * 0 if the read transfer succeeds * -ETIMEDOUT if we cannot read the "raw" interrupt register - * -EINVAL if a transfer abort occured + * -EINVAL if a transfer abort occurred * * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to * data transfer. The actual "write" operation will be performed when the @@ -697,7 +697,7 @@ static int intel_mid_i2c_setup(struct i2c_adapter *adap, struct i2c_msg *pmsg) * @num: number of i2c_msg * * Return Values: - * + number of messages transfered + * + number of messages transferred * -ETIMEDOUT If cannot disable I2C controller or read IC_STATUS * -EINVAL If the address in i2c_msg is invalid * diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index ddc258edb34f..0682f8f277b0 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -141,7 +141,7 @@ static int sch_transaction(void) * This is the main access entry for i2c-sch access * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write * (0 for read and 1 for write), size is i2c transaction type and data is the - * union of transaction for data to be transfered or data read from bus. + * union of transaction for data to be transferred or data read from bus. * return 0 for success and others for failure. */ static s32 sch_access(struct i2c_adapter *adap, u16 addr, diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index caf96dc8ca1b..7e78f7c87857 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -149,7 +149,7 @@ static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, * We have to copy the slave address (u8) and buffer (arbitrary number * of u8) into the data register (u32). To achieve that, the u8 are put * into the MSBs of 'data' which is then shifted for the next u8. When - * apropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 + * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 * looks like this: * * 3 2 1 0 diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 594ed5059c4a..e10e5cf3751a 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -126,9 +126,9 @@ enum i2c_operation { /** * struct i2c_nmk_client - client specific data * @slave_adr: 7-bit slave address - * @count: no. bytes to be transfered + * @count: no. bytes to be transferred * @buffer: client data buffer - * @xfer_bytes: bytes transfered till now + * @xfer_bytes: bytes transferred till now * @operation: current I2C operation */ struct i2c_nmk_client { @@ -330,7 +330,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) * slsu defines the data setup time after SCL clock * stretching in terms of i2c clk cycles. The * needed setup time for the three modes are 250ns, - * 100ns, 10ns repectively thus leading to the values + * 100ns, 10ns respectively thus leading to the values * of 14, 6, 2 for a 48 MHz i2c clk. */ writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR); @@ -364,7 +364,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) /* * set the speed mode. Currently we support * only standard and fast mode of operation - * TODO - support for fast mode plus (upto 1Mb/s) + * TODO - support for fast mode plus (up to 1Mb/s) * and high speed (up to 3.4 Mb/s) */ if (dev->cfg.sm > I2C_FREQ_MODE_FAST) { diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c index cadc0216e02f..cb5d01e279c6 100644 --- a/drivers/i2c/busses/i2c-s6000.c +++ b/drivers/i2c/busses/i2c-s6000.c @@ -318,7 +318,7 @@ static int __devinit s6i2c_probe(struct platform_device *dev) rc = request_irq(iface->irq, s6i2c_interrupt_entry, IRQF_SHARED, dev->name, iface); if (rc) { - dev_err(&p_adap->dev, "s6i2c: cant get IRQ %d\n", iface->irq); + dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq); goto err_clk_dis; } diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 266135ddf7fa..99879617e686 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -497,7 +497,7 @@ static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) u32 val; int i = 0; - /* Locate the apropriate clock setting */ + /* Locate the appropriate clock setting */ while (i < ARRAY_SIZE(stu300_clktable) - 1 && stu300_clktable[i].rate < clkrate) i++; @@ -644,7 +644,7 @@ static int stu300_send_address(struct stu300_dev *dev, ret = stu300_await_event(dev, STU300_EVENT_6); /* - * Clear any pending EVENT 6 no matter what happend during + * Clear any pending EVENT 6 no matter what happened during * await_event. */ val = stu300_r8(dev->virtbase + I2C_CR); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 3921f664c9c3..b4ab39b741eb 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -386,7 +386,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); return IRQ_HANDLED; err: - /* An error occured, mask all interrupts */ + /* An error occurred, mask all interrupts */ tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST | I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ | I2C_INT_RX_FIFO_DATA_REQ); diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 9fbd7e6fe32e..e9d5ff4d1496 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -21,7 +21,7 @@ * to the automotive development board Russellville. The copyright holder * as seen in the header is Intel corporation. * Mocean Laboratories forked off the GNU/Linux platform work into a - * separate company called Pelagicore AB, which commited the code to the + * separate company called Pelagicore AB, which committed the code to the * kernel. */ diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e5f76a0372fd..70c30e6bce0b 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -348,7 +348,7 @@ EXPORT_SYMBOL(i2c_verify_client); /* This is a permissive address validity check, I2C address map constraints - * are purposedly not enforced, except for the general call address. */ + * are purposely not enforced, except for the general call address. */ static int i2c_check_client_addr_validity(const struct i2c_client *client) { if (client->flags & I2C_CLIENT_TEN) { diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 9383f67deae1..3be60da52123 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -67,7 +67,7 @@ static void cy82c693_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) /* * note: below we set the value for Bus Master IDE TimeOut Register - * I'm not absolutly sure what this does, but it solved my problem + * I'm not absolutely sure what this does, but it solved my problem * with IDE DMA and sound, so I now can play sound and work with * my IDE driver at the same time :-) * diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 5406b6ea3ad1..5a702d02c848 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -107,7 +107,7 @@ static int ide_floppy_callback(ide_drive_t *drive, int dsc) static void ide_floppy_report_error(struct ide_disk_obj *floppy, struct ide_atapi_pc *pc) { - /* supress error messages resulting from Medium not present */ + /* suppress error messages resulting from Medium not present */ if (floppy->sense_key == 0x02 && floppy->asc == 0x3a && floppy->ascq == 0x00) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 34b9872f35d1..600c89a3d137 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -201,7 +201,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) u8 stat; /* - * Last sector was transfered, wait until device is ready. This can + * Last sector was transferred, wait until device is ready. This can * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms. */ for (retries = 0; retries < 1000; retries++) { diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 1bdca49e5a03..b59d04c72051 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -8,8 +8,8 @@ * * Documentation: * - * Publically available from Intel web site. Errata documentation - * is also publically available. As an aide to anyone hacking on this + * Publicly available from Intel web site. Errata documentation + * is also publicly available. As an aide to anyone hacking on this * driver the list of errata that are relevant is below.going back to * PIIX4. Older device documentation is now a bit tricky to find. * diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index db7f4e761dbc..4a0022567758 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -53,7 +53,7 @@ #define DRV_NAME "sis5513" -/* registers layout and init values are chipset family dependant */ +/* registers layout and init values are chipset family dependent */ #define ATA_16 0x01 #define ATA_33 0x02 @@ -406,7 +406,7 @@ static int __devinit sis_find_family(struct pci_dev *dev) pci_name(dev)); chipset_family = ATA_133; - /* Check for 5513 compability mapping + /* Check for 5513 compatibility mapping * We must use this, else the port enabled code will fail, * as it expects the enablebits at 0x4a. */ diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c index 7953447eae0f..e53a1b78378b 100644 --- a/drivers/ide/triflex.c +++ b/drivers/ide/triflex.c @@ -22,7 +22,7 @@ * Loosely based on the piix & svwks drivers. * * Documentation: - * Not publically available. + * Not publicly available. */ #include diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index d2a0997b78f8..f46f49cfcc28 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -14,7 +14,7 @@ * Andre Hedrick * * Documentation: - * Obsolete device documentation publically available from via.com.tw + * Obsolete device documentation publicly available from via.com.tw * Current device documentation available under NDA only */ diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c index 62af74295dbe..24f9e3a90e8e 100644 --- a/drivers/infiniband/hw/amso1100/c2_ae.c +++ b/drivers/infiniband/hw/amso1100/c2_ae.c @@ -157,7 +157,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index) int status; /* - * retreive the message + * retrieve the message */ wr = c2_mq_consume(mq); if (!wr) diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c index d8f4bb8bf42e..0d7b6f23caff 100644 --- a/drivers/infiniband/hw/amso1100/c2_qp.c +++ b/drivers/infiniband/hw/amso1100/c2_qp.c @@ -612,7 +612,7 @@ void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp) c2_unlock_cqs(send_cq, recv_cq); /* - * Destory qp in the rnic... + * Destroy qp in the rnic... */ destroy_qp(c2dev, qp); diff --git a/drivers/infiniband/hw/amso1100/c2_wr.h b/drivers/infiniband/hw/amso1100/c2_wr.h index c65fbdd6e469..8d4b4ca463ca 100644 --- a/drivers/infiniband/hw/amso1100/c2_wr.h +++ b/drivers/infiniband/hw/amso1100/c2_wr.h @@ -131,7 +131,7 @@ enum c2wr_ids { * All the preceding IDs are fixed, and must not change. * You can add new IDs, but must not remove or reorder * any IDs. If you do, YOU will ruin any hope of - * compatability between versions. + * compatibility between versions. */ CCWR_LAST, @@ -242,7 +242,7 @@ enum c2_acf { /* * to fix bug 1815 we define the max size allowable of the * terminate message (per the IETF spec).Refer to the IETF - * protocal specification, section 12.1.6, page 64) + * protocol specification, section 12.1.6, page 64) * The message is prefixed by 20 types of DDP info. * * Then the message has 6 bytes for the terminate control diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 47db4bf34628..58c0e417bc30 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -2392,7 +2392,7 @@ void ipath_shutdown_device(struct ipath_devdata *dd) /* * clear SerdesEnable and turn the leds off; do this here because * we are unloading, so don't count on interrupts to move along - * Turn the LEDs off explictly for the same reason. + * Turn the LEDs off explicitly for the same reason. */ dd->ipath_f_quiet_serdes(dd); diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 6d4b29c4cd89..ee79a2d97b14 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -1972,7 +1972,7 @@ static int ipath_do_user_init(struct file *fp, * 0 to 1. So for those chips, we turn it off and then back on. * This will (very briefly) affect any other open ports, but the * duration is very short, and therefore isn't an issue. We - * explictly set the in-memory tail copy to 0 beforehand, so we + * explicitly set the in-memory tail copy to 0 beforehand, so we * don't have to wait to be sure the DMA update has happened * (chip resets head/tail to 0 on transition to enable). */ diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index fef0f4201257..7c1eebe8c7c9 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c @@ -335,7 +335,7 @@ done: * @dd: the infinipath device * * sanity check at least some of the values after reset, and - * ensure no receive or transmit (explictly, in case reset + * ensure no receive or transmit (explicitly, in case reset * failed */ static int init_chip_reset(struct ipath_devdata *dd) diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 7420715256a9..e8a2a915251e 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c @@ -86,7 +86,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) } /* - * A GRH is expected to preceed the data even if not + * A GRH is expected to precede the data even if not * present on the wire. */ length = swqe->length; @@ -515,7 +515,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, } /* - * A GRH is expected to preceed the data even if not + * A GRH is expected to precede the data even if not * present on the wire. */ wc.byte_len = tlen + sizeof(struct ib_grh); diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c index be78f6643c06..f5cb13b21445 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c @@ -236,7 +236,7 @@ static int ipath_user_sdma_num_pages(const struct iovec *iov) return 1 + ((epage - spage) >> PAGE_SHIFT); } -/* truncate length to page boundry */ +/* truncate length to page boundary */ static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len) { const unsigned long offset = addr & ~PAGE_MASK; diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index cfa3a2b22232..33c7eedaba6c 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1397,7 +1397,7 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node) cleanup_retrans_entry(cm_node); cm_node->state = NES_CM_STATE_CLOSING; send_ack(cm_node, NULL); - /* Wait for ACK as this is simultanous close.. + /* Wait for ACK as this is simultaneous close.. * After we receive ACK, do not send anything.. * Just rm the node.. Done.. */ break; diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 08c194861af5..10d0a5ec9add 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -80,7 +80,7 @@ static void nes_terminate_start_timer(struct nes_qp *nesqp); #ifdef CONFIG_INFINIBAND_NES_DEBUG static unsigned char *nes_iwarp_state_str[] = { - "Non-Existant", + "Non-Existent", "Idle", "RTS", "Closing", @@ -91,7 +91,7 @@ static unsigned char *nes_iwarp_state_str[] = { }; static unsigned char *nes_tcp_state_str[] = { - "Non-Existant", + "Non-Existent", "Closed", "Listen", "SYN Sent", diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 2c9c1933bbe3..e96b8fb5d44c 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -902,7 +902,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); } - nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n", + nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscuous = %d, All Multicast = %d.\n", mc_count, !!(netdev->flags & IFF_PROMISC), !!(netdev->flags & IFF_ALLMULTI)); if (!mc_all_on) { diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 73225eee3cc6..769a1d9da4b7 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -653,7 +653,7 @@ struct diag_observer_list_elt; /* device data struct now contains only "general per-device" info. * fields related to a physical IB port are in a qib_pportdata struct, - * described above) while fields only used by a particualr chip-type are in + * described above) while fields only used by a particular chip-type are in * a qib_chipdata struct, whose contents are opaque to this file. */ struct qib_devdata { diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 75bfad16c114..406fca50d036 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1539,7 +1539,7 @@ done_chk_sdma: /* * If process has NOT already set it's affinity, select and - * reserve a processor for it, as a rendevous for all + * reserve a processor for it, as a rendezvous for all * users of the driver. If they don't actually later * set affinity to this cpu, or set it to some other cpu, * it just means that sooner or later we don't recommend @@ -1657,7 +1657,7 @@ static int qib_do_user_init(struct file *fp, * 0 to 1. So for those chips, we turn it off and then back on. * This will (very briefly) affect any other open ctxts, but the * duration is very short, and therefore isn't an issue. We - * explictly set the in-memory tail copy to 0 beforehand, so we + * explicitly set the in-memory tail copy to 0 beforehand, so we * don't have to wait to be sure the DMA update has happened * (chip resets head/tail to 0 on transition to enable). */ diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 774dea897e9c..7de4b7ebffc5 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -1799,7 +1799,7 @@ static int qib_6120_setup_reset(struct qib_devdata *dd) /* * Keep chip from being accessed until we are ready. Use * writeq() directly, to allow the write even though QIB_PRESENT - * isnt' set. + * isn't' set. */ dd->flags &= ~(QIB_INITTED | QIB_PRESENT); dd->int_counter = 0; /* so we check interrupts work again */ @@ -2171,7 +2171,7 @@ static void rcvctrl_6120_mod(struct qib_pportdata *ppd, unsigned int op, * Init the context registers also; if we were * disabled, tail and head should both be zero * already from the enable, but since we don't - * know, we have to do it explictly. + * know, we have to do it explicitly. */ val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt); qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt); diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index de799f17cb9e..74fe0360bec7 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -2111,7 +2111,7 @@ static int qib_setup_7220_reset(struct qib_devdata *dd) /* * Keep chip from being accessed until we are ready. Use * writeq() directly, to allow the write even though QIB_PRESENT - * isnt' set. + * isn't' set. */ dd->flags &= ~(QIB_INITTED | QIB_PRESENT); dd->int_counter = 0; /* so we check interrupts work again */ @@ -2479,7 +2479,7 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val) * we command the link down. As with width, only write the * actual register if the link is currently down, otherwise * takes effect on next link change. Since setting is being - * explictly requested (via MAD or sysfs), clear autoneg + * explicitly requested (via MAD or sysfs), clear autoneg * failure status if speed autoneg is enabled. */ ppd->link_speed_enabled = val; @@ -2778,7 +2778,7 @@ static void rcvctrl_7220_mod(struct qib_pportdata *ppd, unsigned int op, * Init the context registers also; if we were * disabled, tail and head should both be zero * already from the enable, but since we don't - * know, we have to do it explictly. + * know, we have to do it explicitly. */ val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt); qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt); diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 4a2d21e15a70..55de3cf3441c 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -3299,7 +3299,7 @@ static int qib_do_7322_reset(struct qib_devdata *dd) /* * Keep chip from being accessed until we are ready. Use * writeq() directly, to allow the write even though QIB_PRESENT - * isnt' set. + * isn't' set. */ dd->flags &= ~(QIB_INITTED | QIB_PRESENT | QIB_BADINTR); dd->flags |= QIB_DOING_RESET; @@ -3727,7 +3727,7 @@ static int qib_7322_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val) /* * As with width, only write the actual register if the * link is currently down, otherwise takes effect on next - * link change. Since setting is being explictly requested + * link change. Since setting is being explicitly requested * (via MAD or sysfs), clear autoneg failure status if speed * autoneg is enabled. */ @@ -4163,7 +4163,7 @@ static void rcvctrl_7322_mod(struct qib_pportdata *ppd, unsigned int op, * Init the context registers also; if we were * disabled, tail and head should both be zero * already from the enable, but since we don't - * know, we have to do it explictly. + * know, we have to do it explicitly. */ val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt); qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt); @@ -7483,7 +7483,7 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd) /* Baseline Wander Correction Gain [13:4-0] (leave as default) */ /* Baseline Wander Correction Gain [3:7-5] (leave as default) */ /* Data Rate Select [5:7-6] (leave as default) */ - /* RX Parralel Word Width [3:10-8] (leave as default) */ + /* RX Parallel Word Width [3:10-8] (leave as default) */ /* RX REST */ /* Single- or Multi-channel reset */ diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index ffefb78b8949..a01f3fce8eb3 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -346,7 +346,7 @@ done: * @dd: the qlogic_ib device * * sanity check at least some of the values after reset, and - * ensure no receive or transmit (explictly, in case reset + * ensure no receive or transmit (explicitly, in case reset * failed */ static int init_after_reset(struct qib_devdata *dd) diff --git a/drivers/infiniband/hw/qib/qib_mad.h b/drivers/infiniband/hw/qib/qib_mad.h index 147aff9117d7..7840ab593bcf 100644 --- a/drivers/infiniband/hw/qib/qib_mad.h +++ b/drivers/infiniband/hw/qib/qib_mad.h @@ -73,7 +73,7 @@ struct ib_mad_notice_attr { struct { __be16 reserved; - __be16 lid; /* LID where change occured */ + __be16 lid; /* LID where change occurred */ u8 reserved2; u8 local_changes; /* low bit - local changes */ __be32 new_cap_mask; /* new capability mask */ diff --git a/drivers/infiniband/hw/qib/qib_twsi.c b/drivers/infiniband/hw/qib/qib_twsi.c index 6f31ca5039db..ddde72e11edb 100644 --- a/drivers/infiniband/hw/qib/qib_twsi.c +++ b/drivers/infiniband/hw/qib/qib_twsi.c @@ -41,7 +41,7 @@ * QLogic_IB "Two Wire Serial Interface" driver. * Originally written for a not-quite-i2c serial eeprom, which is * still used on some supported boards. Later boards have added a - * variety of other uses, most board-specific, so teh bit-boffing + * variety of other uses, most board-specific, so the bit-boffing * part has been split off to this file, while the other parts * have been moved to chip-specific files. * diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c index 4a51fd1e9cb7..828609fa4d28 100644 --- a/drivers/infiniband/hw/qib/qib_ud.c +++ b/drivers/infiniband/hw/qib/qib_ud.c @@ -116,7 +116,7 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe) } /* - * A GRH is expected to preceed the data even if not + * A GRH is expected to precede the data even if not * present on the wire. */ length = swqe->length; @@ -520,7 +520,7 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, goto drop; /* - * A GRH is expected to preceed the data even if not + * A GRH is expected to precede the data even if not * present on the wire. */ wc.byte_len = tlen + sizeof(struct ib_grh); diff --git a/drivers/infiniband/hw/qib/qib_user_sdma.c b/drivers/infiniband/hw/qib/qib_user_sdma.c index 66208bcd7c13..82442085cbe6 100644 --- a/drivers/infiniband/hw/qib/qib_user_sdma.c +++ b/drivers/infiniband/hw/qib/qib_user_sdma.c @@ -239,7 +239,7 @@ static int qib_user_sdma_num_pages(const struct iovec *iov) } /* - * Truncate length to page boundry. + * Truncate length to page boundary. */ static int qib_user_sdma_page_length(unsigned long addr, unsigned long len) { diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index f1df01567bb6..2f02ab0ccc1e 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -91,7 +91,7 @@ #define SIZE_4K (1UL << SHIFT_4K) #define MASK_4K (~(SIZE_4K-1)) - /* support upto 512KB in one RDMA */ + /* support up to 512KB in one RDMA */ #define ISCSI_ISER_SG_TABLESIZE (0x80000 >> SHIFT_4K) #define ISER_DEF_CMD_PER_LUN 128 diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 3182c9cd1b0e..5688b5c88f24 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -758,7 +758,7 @@ static void joydev_remove_chrdev(struct joydev *joydev) } /* - * Mark device non-existant. This disables writes, ioctls and + * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted * blocking reads will stay, however new ones will fail. */ @@ -777,7 +777,7 @@ static void joydev_cleanup(struct joydev *joydev) joydev_hangup(joydev); joydev_remove_chrdev(joydev); - /* joydev is marked dead so noone else accesses joydev->open */ + /* joydev is marked dead so no one else accesses joydev->open */ if (joydev->open) input_close_device(handle); } diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index d259b41354b8..1639ab2b94b7 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -3,7 +3,7 @@ */ /* - * FP-Gaming Assasin 3D joystick driver for Linux + * FP-Gaming Assassin 3D joystick driver for Linux */ /* @@ -34,7 +34,7 @@ #include #include -#define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver" +#define DRIVER_DESC "FP-Gaming Assassin 3D joystick driver" MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index a91ee941b5c1..cd89d17162a3 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -5,7 +5,7 @@ * * Author: Miguel Aguilar * - * Intial Code: Sandeep Paulraj + * Initial Code: Sandeep Paulraj * * 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 diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index de5900d50788..144ddbdeb9b3 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -716,7 +716,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, pdata = dev->platform_data; if (!pdata) { dev_dbg(dev, - "No platfrom data: Using default initialization\n"); + "No platform data: Using default initialization\n"); pdata = &adxl34x_default_init; } diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index a93c525475c6..fc62256c963f 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -312,7 +312,7 @@ static void keyspan_check_data(struct usb_keyspan *remote) remote->data.tester = remote->data.tester >> 5; remote->data.bits_left -= 5; } else { - err("Bad message recieved, no stop bit found.\n"); + err("Bad message received, no stop bit found.\n"); } dev_dbg(&remote->udev->dev, diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 12501de0c5cd..52b419348983 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -274,7 +274,7 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ - { KE_WIFI, 0x78 }, /* satelite dish button */ + { KE_WIFI, 0x78 }, /* satellite dish button */ { KE_END, 0 } }; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 3aead91bacc8..3126983c004a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -639,7 +639,7 @@ exit: * device, resulting in trackpad malfunction under certain * circumstances. To get around this problem, there is at least one * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to - * recieve a reset_resume request rather than the normal resume. + * receive a reset_resume request rather than the normal resume. * Since the implementation of reset_resume is equal to mode switch * plus start_traffic, it seems easier to always do the switch when * starting traffic on the device. diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index f6aa26d305ed..cba3c84d2f21 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -462,7 +462,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work) * While interrupt driven, there is no real need to poll the device. * But touchpads are very sensitive, so there could be errors * related to physical environment and the attention line isn't - * neccesarily asserted. In such case we can lose the touchpad. + * necessarily asserted. In such case we can lose the touchpad. * We poll the device once in THREAD_IRQ_SLEEP_SECS and * if error is detected, we try to reset and reconfigure the touchpad. */ diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index bf2c0c80d6cc..eb9a3cfbeefa 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -334,7 +334,7 @@ static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse) * M: manufacturer location code * R: revision code * E: Error code. If it's in the range of 0x00..0x1f, only some - * minor problem occured. Errors >= 0x20 are considered bad + * minor problem occurred. Errors >= 0x20 are considered bad * and the device may not work properly... * D: <0010> == mouse, <0100> == tablet */ diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 8c0b51c31424..42206205e4f5 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -955,7 +955,7 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); ret = hp_sdc_init(); - /* after successfull initialization give SDC some time to settle + /* after successful initialization give SDC some time to settle * and then load the hp_sdc_mlc upper layer driver */ if (!ret) schedule_delayed_work(&moduleloader_work, diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 7540bafc95cf..80baa53da5b1 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -225,7 +225,7 @@ static void sxps2_close(struct serio *pserio) /** * xps2_of_probe - probe method for the PS/2 device. * @of_dev: pointer to OF device structure - * @match: pointer to the stucture used for matching a device + * @match: pointer to the structure used for matching a device * * This function probes the PS/2 device in the device tree. * It initializes the driver data structure and the hardware. diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index c0307b22d86f..66c96bfc5522 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c @@ -542,7 +542,7 @@ static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev) * ADC power on, start, enable PENDET and set loop delay * ADC loop delay is set to 4.5 ms approximately * Loop delay more than this results in jitter in adc readings - * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET + * Setting loop delay to 0 (continuous loop) in MAXIM stops PENDET * interrupt generation sometimes. */ diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 028a5363eea1..3b5b5df04dd6 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -6,7 +6,7 @@ * Copyright: MontaVista Software, Inc. * * Spliting done by: Marek Vasut - * If something doesnt work and it worked before spliting, e-mail me, + * If something doesn't work and it worked before spliting, e-mail me, * dont bother Nicolas please ;-) * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 6b5be742c27d..98e61175d3f5 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c @@ -306,7 +306,7 @@ static int wm9705_acc_enable(struct wm97xx *wm, int enable) dig2 = wm->dig[2]; if (enable) { - /* continous mode */ + /* continuous mode */ if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0) return ret; diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 7490b05c3566..2bc2fb801009 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -419,7 +419,7 @@ static int wm9712_acc_enable(struct wm97xx *wm, int enable) dig2 = wm->dig[2]; if (enable) { - /* continous mode */ + /* continuous mode */ if (wm->mach_ops->acc_startup) { ret = wm->mach_ops->acc_startup(wm); if (ret < 0) diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 238b5132712e..73ec99568f12 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -431,7 +431,7 @@ static int wm9713_acc_enable(struct wm97xx *wm, int enable) dig3 = wm->dig[2]; if (enable) { - /* continous mode */ + /* continuous mode */ if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0) return ret; diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 6b75c9f660ae..5dbe73af2f8f 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -335,7 +335,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) */ if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) { if (wm->pen_is_down && !pen_was_down) { - /* Data is not availiable immediately on pen down */ + /* Data is not available immediately on pen down */ queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1); } @@ -354,7 +354,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) * Codec PENDOWN irq handler * * We have to disable the codec interrupt in the handler because it - * can take upto 1ms to clear the interrupt source. We schedule a task + * can take up to 1ms to clear the interrupt source. We schedule a task * in a work queue to do the actual interaction with the chip. The * interrupt is then enabled again in the slow handler when the source * has been cleared. diff --git a/drivers/isdn/hardware/eicon/divacapi.h b/drivers/isdn/hardware/eicon/divacapi.h index 9f5b68037a26..e330da0c5fc0 100644 --- a/drivers/isdn/hardware/eicon/divacapi.h +++ b/drivers/isdn/hardware/eicon/divacapi.h @@ -673,7 +673,7 @@ struct async_s { /*------------------------------------------------------------------*/ -/* auxilliary states for supplementary services */ +/* auxiliary states for supplementary services */ /*------------------------------------------------------------------*/ #define IDLE 0 diff --git a/drivers/isdn/hardware/eicon/io.h b/drivers/isdn/hardware/eicon/io.h index 0c6c650d76bb..a6f175596364 100644 --- a/drivers/isdn/hardware/eicon/io.h +++ b/drivers/isdn/hardware/eicon/io.h @@ -60,7 +60,7 @@ typedef struct _diva_xdi_capi_cfg { -------------------------------------------------------------------------- */ struct _ISDN_ADAPTER { void (* DIRequest)(PISDN_ADAPTER, ENTITY *) ; - int State ; /* from NT4 1.srv, a good idea, but a poor achievment */ + int State ; /* from NT4 1.srv, a good idea, but a poor achievement */ int Initialized ; int RegisteredWithDidd ; int Unavailable ; /* callback function possible? */ diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index 341ef17c22ac..8c5c563c4f12 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c @@ -2639,7 +2639,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, } else { - /* local reply if assign unsuccessfull + /* local reply if assign unsuccessful or B3 protocol allows only one layer 3 connection and already connected or B2 protocol not any LAPD @@ -8189,7 +8189,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) dlc[ 0] = 15; if(b2_config->length >= 8) { /* PIAFS control abilities */ dlc[ 7] = 10; - dlc[16] = 2; /* Length of PIAFS extention */ + dlc[16] = 2; /* Length of PIAFS extension */ dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */ dlc[18] = b2_config_parms[4].info[0]; /* value */ dlc[ 0] = 18; diff --git a/drivers/isdn/hardware/eicon/pc.h b/drivers/isdn/hardware/eicon/pc.h index 1c6945768a35..bf6b01812400 100644 --- a/drivers/isdn/hardware/eicon/pc.h +++ b/drivers/isdn/hardware/eicon/pc.h @@ -701,7 +701,7 @@ Byte | 8 7 6 5 4 3 2 1 #define PROTCAP_FREE12 0x1000 /* not used */ #define PROTCAP_FREE13 0x2000 /* not used */ #define PROTCAP_FREE14 0x4000 /* not used */ -#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */ +#define PROTCAP_EXTENSION 0x8000 /* used for future extensions */ /* -----------------------------------------------------------* */ /* Onhook data transmission ETS30065901 */ /* Message Type */ diff --git a/drivers/isdn/hardware/eicon/um_idi.c b/drivers/isdn/hardware/eicon/um_idi.c index 6563db998d06..ac0bdd1f23fa 100644 --- a/drivers/isdn/hardware/eicon/um_idi.c +++ b/drivers/isdn/hardware/eicon/um_idi.c @@ -363,7 +363,7 @@ int diva_um_idi_read(void *entity, if ((ret = (*cp_fn) (os_handle, dst, data, length)) >= 0) { /* - Acknowledge only if read was successfull + Acknowledge only if read was successful */ diva_data_q_ack_segment4read(q); } diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 4e3780d78ac7..f6f3c87cc7c2 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -118,7 +118,7 @@ * -> See hfc_multi.h for HFC_IO_MODE_* values * By default, the IO mode is pci memory IO (MEMIO). * Some cards require specific IO mode, so it cannot be changed. - * It may be usefull to set IO mode to register io (REGIO) to solve + * It may be useful to set IO mode to register io (REGIO) to solve * PCI bridge problems. * If unsure, don't give this parameter. * @@ -903,7 +903,7 @@ vpm_echocan_off(struct hfc_multi *hc, int ch) /* * Speech Design resync feature * NOTE: This is called sometimes outside interrupt handler. - * We must lock irqsave, so no other interrupt (other card) will occurr! + * We must lock irqsave, so no other interrupt (other card) will occur! * Also multiple interrupts may nest, so must lock each access (lists, card)! */ static inline void diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 15d323b8be60..4343abac0b13 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -272,7 +272,7 @@ reset_hfcpci(struct hfc_pci *hc) * D- and monitor/CI channel are not enabled * STIO1 is used as output for data, B1+B2 from ST->IOM+HFC * STIO2 is used as data input, B1+B2 from IOM->ST - * ST B-channel send disabled -> continous 1s + * ST B-channel send disabled -> continuous 1s * The IOM slots are always enabled */ if (test_bit(HFC_CFG_PCM, &hc->cfg)) { diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 3147020d188b..0cb0546ead88 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -146,7 +146,7 @@ reset_hfcpci(struct IsdnCardState *cs) /* D- and monitor/CI channel are not enabled */ /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */ /* STIO2 is used as data input, B1+B2 from IOM->ST */ - /* ST B-channel send disabled -> continous 1s */ + /* ST B-channel send disabled -> continuous 1s */ /* The IOM slots are always enabled */ cs->hw.hfcpci.conn = 0x36; /* set data flow directions */ Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 1235b7131ae1..156d7c63d944 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -399,7 +399,7 @@ reset_hfcsx(struct IsdnCardState *cs) /* D- and monitor/CI channel are not enabled */ /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */ /* STIO2 is used as data input, B1+B2 from IOM->ST */ - /* ST B-channel send disabled -> continous 1s */ + /* ST B-channel send disabled -> continuous 1s */ /* The IOM slots are always enabled */ cs->hw.hfcsx.conn = 0x36; /* set data flow directions */ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h index e79f56568d30..2f581c0b4693 100644 --- a/drivers/isdn/hisax/hfc_usb.h +++ b/drivers/isdn/hisax/hfc_usb.h @@ -126,7 +126,7 @@ static struct hfcusb_symbolic_list urb_errlist[] = { /* - * device dependant information to support different + * device dependent information to support different * ISDN Ta's using the HFC-S USB chip */ diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index cc6ee2d39880..8e2fd02ecce0 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -1595,7 +1595,7 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) * Bearer Capabilities */ p = skb->data; - /* only the first occurence 'll be detected ! */ + /* only the first occurrence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; @@ -2161,7 +2161,7 @@ static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) /***********************************************/ /* handle special commands for this protocol. */ -/* Examples are call independant services like */ +/* Examples are call independent services like */ /* remote operations with dummy callref. */ /***********************************************/ static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic) diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c index f9584491fe8e..7b229c0ce115 100644 --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c @@ -1449,7 +1449,7 @@ l3ni1_setup(struct l3_process *pc, u_char pr, void *arg) * Bearer Capabilities */ p = skb->data; - /* only the first occurence 'll be detected ! */ + /* only the first occurrence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; @@ -2017,7 +2017,7 @@ static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) /***********************************************/ /* handle special commands for this protocol. */ -/* Examples are call independant services like */ +/* Examples are call independent services like */ /* remote operations with dummy callref. */ /***********************************************/ static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic) diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index 2344e7b33448..a1b89524b505 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c @@ -167,7 +167,7 @@ static int __devinit njs_pci_probe(struct pci_dev *dev_netjet, return(0); } /* the TJ300 and TJ320 must be detected, the IRQ handling is different - * unfortunatly the chips use the same device ID, but the TJ320 has + * unfortunately the chips use the same device ID, but the TJ320 has * the bit20 in status PCI cfg register set */ pci_read_config_dword(dev_netjet, 0x04, &cfg); diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index e56e5af889b6..ed4bc564dc63 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -124,7 +124,7 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr) } /* - * Start transfering (flags or data) on the B channel, since + * Start transferring (flags or data) on the B channel, since * FIFO counters has been set to a non-zero value. */ static void st5481B_start_xfer(void *context) diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index 10d41c5d73ed..159e8fa00fd6 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -470,7 +470,7 @@ void st5481_release_isocpipes(struct urb* urb[2]) /* * Decode frames received on the B/D channel. - * Note that this function will be called continously + * Note that this function will be called continuously * with 64Kbit/s / 16Kbit/s of data and hence it will be * called 50 times per second with 20 ISOC descriptors. * Called at interrupt. diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 282a4467ef19..aa25e183bf79 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -9,7 +9,7 @@ Also inspired by ELSA PCMCIA driver by Klaus Lichtenwalder - Extentions to new hisax_pcmcia by Karsten Keil + Extensions to new hisax_pcmcia by Karsten Keil minor changes to be compatible with kernel 2.4.x by Jan.Schubert@GMX.li diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c index 81db4a190d41..3674d30d6a03 100644 --- a/drivers/isdn/hysdn/hysdn_sched.c +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -143,7 +143,7 @@ hysdn_sched_tx(hysdn_card *card, unsigned char *buf, /* send one config line to the card and return 0 if successful, otherwise a */ /* negative error code. */ /* The function works with timeouts perhaps not giving the greatest speed */ -/* sending the line, but this should be meaningless beacuse only some lines */ +/* sending the line, but this should be meaningless because only some lines */ /* are to be sent and this happens very seldom. */ /*****************************************************************************/ int diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index afeede7ee295..2a7d17c19489 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1530,7 +1530,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) printk (KERN_WARNING "UPDOWN: Line protocol on Interface %s," " changed state to down\n", lp->netdev->dev->name); - /* should stop routing higher-level data accross */ + /* should stop routing higher-level data across */ } else if ((!lp->cisco_line_state) && (myseq_diff >= 0) && (myseq_diff <= 2)) { /* line down -> up */ @@ -1538,7 +1538,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) printk (KERN_WARNING "UPDOWN: Line protocol on Interface %s," " changed state to up\n", lp->netdev->dev->name); - /* restart routing higher-level data accross */ + /* restart routing higher-level data across */ } if (lp->cisco_debserint) diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 9e8162c80bb0..1b002b0002a4 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -1514,7 +1514,7 @@ int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp) #define MP_LONGSEQ_MAXBIT ((MP_LONGSEQ_MASK+1)>>1) #define MP_SHORTSEQ_MAXBIT ((MP_SHORTSEQ_MASK+1)>>1) -/* sequence-wrap safe comparisions (for long sequence)*/ +/* sequence-wrap safe comparisons (for long sequence)*/ #define MP_LT(a,b) ((a-b)&MP_LONGSEQ_MAXBIT) #define MP_LE(a,b) !((b-a)&MP_LONGSEQ_MAXBIT) #define MP_GT(a,b) ((b-a)&MP_LONGSEQ_MAXBIT) @@ -1746,7 +1746,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, * then next fragment should be the start of new reassembly * if sequence is contiguous, but we haven't reassembled yet, * keep going. - * if sequence is not contiguous, either clear everyting + * if sequence is not contiguous, either clear everything * below low watermark and set start to the next frag or * clear start ptr. */ diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 3d88f15aa218..607d846ae063 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -792,7 +792,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m) } /* isdn_tty_resume() tries to resume a suspended call - * setup of the lower levels before that. unfortunatly here is no + * setup of the lower levels before that. unfortunately here is no * checking for compatibility of used protocols implemented by Q931 * It does the same things like isdn_tty_dial, the last command * is different, may be we can merge it. diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index b8a1098b66ed..d497db0a26d0 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -954,7 +954,7 @@ isdnloop_parse_cmd(isdnloop_card * card) /* * Put command-strings into the of the 'card'. In reality, execute them * right in place by calling isdnloop_parse_cmd(). Also copy every - * command to the read message ringbuffer, preceeding it with a '>'. + * command to the read message ringbuffer, preceding it with a '>'. * These mesagges can be read at /dev/isdnctrl. * * Parameter: diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h index 18af86879c05..8549431430f0 100644 --- a/drivers/isdn/mISDN/dsp.h +++ b/drivers/isdn/mISDN/dsp.h @@ -21,7 +21,7 @@ /* options may be: * * bit 0 = use ulaw instead of alaw - * bit 1 = enable hfc hardware accelleration for all channels + * bit 1 = enable hfc hardware acceleration for all channels * */ #define DSP_OPT_ULAW (1<<0) diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 309bacf1fadc..4d395dea32f3 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c @@ -1513,7 +1513,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) /* -> if echo is NOT enabled */ if (!dsp->echo.software) { /* - * -> substract rx-data from conf-data, + * -> subtract rx-data from conf-data, * if tx-data is available, mix */ while (r != rr && t != tt) { @@ -1572,7 +1572,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) send_packet: /* * send tx-data if enabled - don't filter, - * becuase we want what we send, not what we filtered + * because we want what we send, not what we filtered */ if (dsp->tx_data) { if (tx_data_only) { diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 6f5b54864283..2877291a9ed8 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -115,7 +115,7 @@ * * The CMX has special functions for conferences with one, two and more * members. It will allow different types of data flow. Receive and transmit - * data to/form upper layer may be swithed on/off individually without loosing + * data to/form upper layer may be swithed on/off individually without losing * features of CMX, Tones and DTMF. * * Echo Cancellation: Sometimes we like to cancel echo from the interface. @@ -127,9 +127,9 @@ * * If all used features can be realized in hardware, and if transmit and/or * receive data ist disabled, the card may not send/receive any data at all. - * Not receiving is usefull if only announcements are played. Not sending is - * usefull if an answering machine records audio. Not sending and receiving is - * usefull during most states of the call. If supported by hardware, tones + * Not receiving is useful if only announcements are played. Not sending is + * useful if an answering machine records audio. Not sending and receiving is + * useful during most states of the call. If supported by hardware, tones * will be played without cpu load. Small PBXs and NT-Mode applications will * not need expensive hardware when processing calls. * diff --git a/drivers/isdn/mISDN/dsp_dtmf.c b/drivers/isdn/mISDN/dsp_dtmf.c index 9ae2d33b06f7..5b484c3f4af6 100644 --- a/drivers/isdn/mISDN/dsp_dtmf.c +++ b/drivers/isdn/mISDN/dsp_dtmf.c @@ -106,7 +106,7 @@ void dsp_dtmf_hardware(struct dsp *dsp) * tested it allot. it even works with very short tones (40ms). the only * disadvantage is, that it doesn't work good with different volumes of both * tones. this will happen, if accoustically coupled dialers are used. - * it sometimes detects tones during speach, which is normal for decoders. + * it sometimes detects tones during speech, which is normal for decoders. * use sequences to given commands during calls. * * dtmf - points to a structure of the current dtmf state @@ -244,7 +244,7 @@ coefficients: if (result[i] < tresh) { lowgroup = -1; highgroup = -1; - break; /* noise inbetween */ + break; /* noise in between */ } /* good level found. This is allowed only one time per group */ if (i < NCOEFF/2) { diff --git a/drivers/isdn/mISDN/dsp_tones.c b/drivers/isdn/mISDN/dsp_tones.c index 7dbe54ed1deb..4e4440e8bae5 100644 --- a/drivers/isdn/mISDN/dsp_tones.c +++ b/drivers/isdn/mISDN/dsp_tones.c @@ -394,7 +394,7 @@ void dsp_tone_copy(struct dsp *dsp, u8 *data, int len) while (len) { /* find sample to start with */ while (42) { - /* warp arround */ + /* wrap around */ if (!pat->seq[index]) { count = 0; index = 0; diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index bd526f664a39..22f8ec8b9247 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -179,7 +179,7 @@ NOTE: A value of 0 equals 256 bytes of data. - Time Base = Timestamp of first sample in frame The "Time Base" is used to rearange packets and to detect packet loss. The 16 bits are sent in network order (MSB first) and count 1/8000 th of a -second. This causes a wrap arround each 8,192 seconds. There is no requirement +second. This causes a wrap around each 8,192 seconds. There is no requirement for the initial "Time Base", but 0 should be used for the first packet. In case of HDLC data, this timestamp counts the packet or byte number. @@ -205,7 +205,7 @@ On Demand: If the ondemand parameter is given, the remote IP is set to 0 on timeout. This will stop keepalive traffic to remote. If the remote is online again, -traffic will continue to the remote address. This is usefull for road warriors. +traffic will continue to the remote address. This is useful for road warriors. This feature only works with ID set, otherwhise it is highly unsecure. @@ -590,7 +590,7 @@ multiframe: return; } } else - mlen = len-2; /* single frame, substract timebase */ + mlen = len-2; /* single frame, subtract timebase */ if (len < 2) { printk(KERN_WARNING "%s: packet error - packet too short, time " diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 4ae75053c9d2..d0aeb44ee7c0 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -1864,7 +1864,7 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) psapi >>= 2; ptei >>= 1; if (psapi != l2->sapi) { - /* not our bussiness */ + /* not our business */ if (*debug & DEBUG_L2) printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n", __func__, psapi, l2->sapi); @@ -1872,7 +1872,7 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) return 0; } if ((ptei != l2->tei) && (ptei != GROUP_TEI)) { - /* not our bussiness */ + /* not our business */ if (*debug & DEBUG_L2) printk(KERN_DEBUG "%s: tei %d/%d mismatch\n", __func__, ptei, l2->tei); diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index afac338d5025..5bf63af09ddf 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -58,7 +58,7 @@ static struct i2c_driver pca9532_driver = { .id_table = pca9532_id, }; -/* We have two pwm/blinkers, but 16 possible leds to drive. Additionaly, +/* We have two pwm/blinkers, but 16 possible leds to drive. Additionally, * the clever Thecus people are using one pwm to drive the beeper. So, * as a compromise we average one pwm to the values requested by all * leds that are not ON/OFF. diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index a04523273282..f14edd82cb00 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c @@ -215,13 +215,13 @@ static int wm8350_led_probe(struct platform_device *pdev) isink = regulator_get(&pdev->dev, "led_isink"); if (IS_ERR(isink)) { - printk(KERN_ERR "%s: cant get ISINK\n", __func__); + printk(KERN_ERR "%s: can't get ISINK\n", __func__); return PTR_ERR(isink); } dcdc = regulator_get(&pdev->dev, "led_vcc"); if (IS_ERR(dcdc)) { - printk(KERN_ERR "%s: cant get DCDC\n", __func__); + printk(KERN_ERR "%s: can't get DCDC\n", __func__); ret = PTR_ERR(dcdc); goto err_isink; } diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 3c781cdddda9..948c547b8e9e 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -130,7 +130,7 @@ static int add_eventfd(struct lguest *lg, unsigned long addr, int fd) rcu_assign_pointer(lg->eventfds, new); /* - * We're not in a big hurry. Wait until noone's looking at old + * We're not in a big hurry. Wait until no one's looking at old * version, then free it. */ synchronize_rcu(); diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 5396c67ba0a4..09d72bb00d12 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -328,7 +328,7 @@ adbhid_input_keycode(int id, int scancode, int repeat) switch (keycode) { case ADB_KEY_CAPSLOCK: if (!restore_capslock_events) { - /* Generate down/up events for CapsLock everytime. */ + /* Generate down/up events for CapsLock every time. */ input_report_key(ahid->input, KEY_CAPSLOCK, 1); input_sync(ahid->input); input_report_key(ahid->input, KEY_CAPSLOCK, 0); diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index bd6da7a9c55b..b6ef8f590764 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -147,7 +147,7 @@ static int macio_adb_reset_bus(void) /* Hrm... we may want to not lock interrupts for so * long ... oh well, who uses that chip anyway ? :) - * That function will be seldomly used during boot + * That function will be seldom used during boot * on rare machines, so... */ spin_lock_irqsave(&macio_lock, flags); diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 9e3e2c566598..02367308ff2e 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -662,7 +662,7 @@ static void thermostat_create_files(void) err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); if (err) printk(KERN_WARNING - "Failed to create tempertaure attribute file(s).\n"); + "Failed to create temperature attribute file(s).\n"); } static void thermostat_remove_files(void) diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index bca2af2e3760..d25df48b437b 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -91,7 +91,7 @@ * * Mar. 10, 2005 : 1.2 * - Add basic support for Xserve G5 - * - Retreive pumps min/max from EEPROM image in device-tree (broken) + * - Retrieve pumps min/max from EEPROM image in device-tree (broken) * - Use min/max macros here or there * - Latest darwin updated U3H min fan speed to 20% PWM * @@ -375,7 +375,7 @@ static int read_smon_adc(struct cpu_pid_state *state, int chan) rc = i2c_master_send(state->monitor, buf, 2); if (rc <= 0) goto error; - /* Wait for convertion */ + /* Wait for conversion */ msleep(1); /* Switch to data register */ buf[0] = 4; @@ -1192,7 +1192,7 @@ static int init_cpu_state(struct cpu_pid_state *state, int index) err |= device_create_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm); } if (err) - printk(KERN_WARNING "Failed to create some of the atribute" + printk(KERN_WARNING "Failed to create some of the attribute" "files for CPU %d\n", index); return 0; diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index d37819fd5ad3..46c4e95f10d6 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -45,7 +45,7 @@ #include #include -#define LOG_TEMP 0 /* continously log temperature */ +#define LOG_TEMP 0 /* continuously log temperature */ static struct { volatile int running; diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index 931a7a7c3796..d0aeaf46d932 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -45,7 +45,7 @@ * * The counter counts pending write requests, plus the on-disk bit. * When the counter is '1' and the resync bits are clear, the on-disk - * bit can be cleared aswell, thus setting the counter to 0. + * bit can be cleared as well, thus setting the counter to 0. * When we set a bit, or in the counter (to start a write), if the fields is * 0, we first set the disk bit and set the counter to 1. * diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index dad011aed0c9..7771ed212182 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -419,7 +419,7 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio) /* * Possible cases: * 1) DM_RH_DIRTY - * 2) DM_RH_NOSYNC: was dirty, other preceeding writes failed + * 2) DM_RH_NOSYNC: was dirty, other preceding writes failed * 3) DM_RH_RECOVERING: flushing pending writes * Either case, the region should have not been connected to list. */ diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 339fdc670751..23078dabb6df 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -30,7 +30,7 @@ * * Different modes can be active at a time, but only * one can be set at array creation. Others can be added later. - * A mode can be one-shot or recurrent with the recurrance being + * A mode can be one-shot or recurrent with the recurrence being * once in every N requests. * The bottom 5 bits of the "layout" indicate the mode. The * remainder indicate a period, or 0 for one-shot. diff --git a/drivers/md/md.c b/drivers/md/md.c index 8b66e04c2ea6..b12b3776c0c0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6266,7 +6266,7 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) * rt is a sector_t, so could be 32bit or 64bit. * So we divide before multiply in case it is 32bit and close * to the limit. - * We scale the divisor (db) by 32 to avoid loosing precision + * We scale the divisor (db) by 32 to avoid losing precision * near the end of resync when the number of remaining sectors * is close to 'db'. * We then divide rt by 32 after multiplying by db to compensate. diff --git a/drivers/md/md.h b/drivers/md/md.h index 12215d437fcc..52b407369e13 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -94,7 +94,7 @@ struct mdk_rdev_s #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ #define AutoDetected 7 /* added by auto-detect */ -#define Blocked 8 /* An error occured on an externally +#define Blocked 8 /* An error occurred on an externally * managed array, don't allow writes * until it is cleared */ wait_queue_head_t blocked_wait; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f7b62370b374..2da83d566592 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -5,7 +5,7 @@ * * RAID-10 support for md. * - * Base on code in raid1.c. See raid1.c for futher copyright information. + * Base on code in raid1.c. See raid1.c for further copyright information. * * * This program is free software; you can redistribute it and/or modify @@ -340,14 +340,14 @@ static void raid10_end_write_request(struct bio *bio, int error) /* * RAID10 layout manager - * Aswell as the chunksize and raid_disks count, there are two + * As well as the chunksize and raid_disks count, there are two * parameters: near_copies and far_copies. * near_copies * far_copies must be <= raid_disks. * Normally one of these will be 1. * If both are 1, we get raid0. * If near_copies == raid_disks, we get raid1. * - * Chunks are layed out in raid0 style with near_copies copies of the + * Chunks are laid out in raid0 style with near_copies copies of the * first chunk, followed by near_copies copies of the next chunk and * so on. * If far_copies > 1, then after 1/far_copies of the array has been assigned diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 2316ac2e8e21..944b1104d3b4 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -17,8 +17,8 @@ struct r10_private_data_s { spinlock_t device_lock; /* geometry */ - int near_copies; /* number of copies layed out raid0 style */ - int far_copies; /* number of copies layed out + int near_copies; /* number of copies laid out raid0 style */ + int far_copies; /* number of copies laid out * at large strides across drives */ int far_offset; /* far_copies are offset by 1 stripe diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 74ee172b5bc9..b2ba9dc0dd6d 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -161,7 +161,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev) msleep(SAA7146_I2C_DELAY); } - /* if any error is still present, a fatal error has occured ... */ + /* if any error is still present, a fatal error has occurred ... */ status = saa7146_i2c_status(dev); if ( dev->i2c_bitrate != status ) { DEB_I2C(("fatal error. status:0x%08x\n",status)); @@ -326,9 +326,9 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m if ( 0 != err) { /* this one is unsatisfying: some i2c slaves on some dvb cards don't acknowledge correctly, so the saa7146 - thinks that an address error occured. in that case, the + thinks that an address error occurred. in that case, the transaction should be retrying, even if an address error - occured. analog saa7146 based cards extensively rely on + occurred. analog saa7146 based cards extensively rely on i2c address probing, however, and address errors indicate that a device is really *not* there. retrying in that case increases the time the device needs to probe greatly, so @@ -365,7 +365,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m DEB_I2C(("transmission successful. (msg:%d).\n",err)); out: /* another bug in revision 0: the i2c-registers get uploaded randomly by other - uploads, so we better clear them out before continueing */ + uploads, so we better clear them out before continuing */ if( 0 == dev->revision ) { __le32 zero = 0; saa7146_i2c_reset(dev); diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 605e28b73263..0d6e09419044 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -106,7 +106,7 @@ enum { /* MXL5005 Tuner Register Struct */ struct TunerReg { u16 Reg_Num; /* Tuner Register Address */ - u16 Reg_Val; /* Current sw programmed value waiting to be writen */ + u16 Reg_Val; /* Current sw programmed value waiting to be written */ }; enum { diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h index 3abb221f3d07..50cfa8cebb93 100644 --- a/drivers/media/common/tuners/tda18271.h +++ b/drivers/media/common/tuners/tda18271.h @@ -98,7 +98,7 @@ struct tda18271_config { /* output options that can be disabled */ enum tda18271_output_options output_opt; - /* some i2c providers cant write all 39 registers at once */ + /* some i2c providers can't write all 39 registers at once */ enum tda18271_small_i2c small_i2c; /* force rf tracking filter calibration on startup */ diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 227c0200b70a..955254090a0e 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -58,7 +58,7 @@ struct flexcop_pci { int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ u32 last_dma1_cur_pos; - /* position of the pointer last time the timer/packet irq occured */ + /* position of the pointer last time the timer/packet irq occurred */ int count; int count_prev; int stream_problem; diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 78fc469f0f69..1e1106dcd063 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -427,10 +427,10 @@ static void or51211_reset(struct dvb_frontend * fe) struct dvb_bt8xx_card *bt = fe->dvb->priv; /* RESET DEVICE - * reset is controled by GPIO-0 + * reset is controlled by GPIO-0 * when set to 0 causes reset and when to 1 for normal op * must remain reset for 128 clock cycles on a 50Mhz clock - * also PRM1 PRM2 & PRM4 are controled by GPIO-1,GPIO-2 & GPIO-4 + * also PRM1 PRM2 & PRM4 are controlled by GPIO-1,GPIO-2 & GPIO-4 * We assume that the reset has be held low long enough or we * have been reset by a power on. When the driver is unloaded * reset set to 0 so if reloaded we have been reset. diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index cad6634610ea..31e2c0d45db3 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1638,7 +1638,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, case FE_READ_STATUS: { fe_status_t* status = parg; - /* if retune was requested but hasn't occured yet, prevent + /* if retune was requested but hasn't occurred yet, prevent * that user get signal state from previous tuning */ if (fepriv->state == FESTATE_RETUNE || fepriv->state == FESTATE_ERROR) { @@ -1729,7 +1729,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, * Dish network legacy switches (as used by Dish500) * are controlled by sending 9-bit command words * spaced 8msec apart. - * the actual command word is switch/port dependant + * the actual command word is switch/port dependent * so it is up to the userspace application to send * the right command. * The command must always start with a '0' after diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c index 199ece0d4883..6ad94745bbdd 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c @@ -580,7 +580,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw) NS_coeff2_8k = 0x724925; break; default: - err("Invalid bandwith %d.", bw); + err("Invalid bandwidth %d.", bw); return -EINVAL; } @@ -789,7 +789,7 @@ static int af9005_fe_select_bw(struct dvb_usb_device *d, fe_bandwidth_t bw) temp = 2; break; default: - err("Invalid bandwith %d.", bw); + err("Invalid bandwidth %d.", bw); return -EINVAL; } return af9005_write_register_bits(d, xd_g_reg_bw, reg_bw_pos, @@ -930,7 +930,7 @@ static int af9005_fe_init(struct dvb_frontend *fe) if (ret) return ret; - /* init other parameters: program cfoe and select bandwith */ + /* init other parameters: program cfoe and select bandwidth */ deb_info("program cfoe\n"); if ((ret = af9005_fe_program_cfoe(state->d, BANDWIDTH_6_MHZ))) return ret; @@ -1167,7 +1167,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe, if (ret) return ret; - /* select bandwith */ + /* select bandwidth */ deb_info("select bandwidth"); ret = af9005_fe_select_bw(state->d, fep->u.ofdm.bandwidth); if (ret) diff --git a/drivers/media/dvb/dvb-usb/friio.h b/drivers/media/dvb/dvb-usb/friio.h index af8d55e390fb..0f461ca10cb9 100644 --- a/drivers/media/dvb/dvb-usb/friio.h +++ b/drivers/media/dvb/dvb-usb/friio.h @@ -20,7 +20,7 @@ * Frontend: comtech JDVBT-90502 * (tuner PLL: tua6034, I2C addr:(0xC0 >> 1)) * (OFDM demodulator: TC90502, I2C addr:(0x30 >> 1)) - * LED x3 (+LNB) controll: PIC 16F676 + * LED x3 (+LNB) control: PIC 16F676 * EEPROM: 24C08 * * (USB smart card reader: AU9522) diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index cd26e7c1536a..f2db01212ca1 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -321,7 +321,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); - info("INT Interupt Service Started"); + info("INT Interrupt Service Started"); return 0; } @@ -482,7 +482,7 @@ static int lme2510_msg(struct dvb_usb_device *d, break; } - deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)", + deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)", wbuf[3], rbuf[1]); } @@ -632,11 +632,11 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap) } d->rc_dev = rc; - /* Start the Interupt */ + /* Start the Interrupt */ ret = lme2510_int_read(adap); if (ret < 0) { rc_unregister_device(rc); - info("INT Unable to start Interupt Service"); + info("INT Unable to start Interrupt Service"); return -ENODEV; } @@ -1003,7 +1003,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) return -ENODEV; } - /* Start the Interupt & Remote*/ + /* Start the Interrupt & Remote*/ ret = lme2510_int_service(adap); return ret; @@ -1171,7 +1171,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d) usb_kill_urb(st->lme_urb); usb_free_coherent(d->udev, 5000, st->buffer, st->lme_urb->transfer_dma); - info("Interupt Service Stopped"); + info("Interrupt Service Stopped"); rc_unregister_device(d->rc_dev); info("Remote Stopped"); } diff --git a/drivers/media/dvb/frontends/atbm8830.h b/drivers/media/dvb/frontends/atbm8830.h index e8149f393300..024273374bd8 100644 --- a/drivers/media/dvb/frontends/atbm8830.h +++ b/drivers/media/dvb/frontends/atbm8830.h @@ -39,7 +39,7 @@ struct atbm8830_config { /* parallel or serial transport stream */ u8 serial_ts; - /* transport stream clock output only when receving valid stream */ + /* transport stream clock output only when receiving valid stream */ u8 ts_clk_gated; /* Decoder sample TS data at rising edge of clock */ diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index 65f6a36dfb21..1d572940e243 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c @@ -635,7 +635,7 @@ static int au8522_led_gpio_enable(struct au8522_state *state, int onoff) struct au8522_led_config *led_config = state->config->led_cfg; u8 val; - /* bail out if we cant control an LED */ + /* bail out if we can't control an LED */ if (!led_config || !led_config->gpio_output || !led_config->gpio_output_enable || !led_config->gpio_output_disable) return 0; @@ -665,7 +665,7 @@ static int au8522_led_ctrl(struct au8522_state *state, int led) struct au8522_led_config *led_config = state->config->led_cfg; int i, ret = 0; - /* bail out if we cant control an LED */ + /* bail out if we can't control an LED */ if (!led_config || !led_config->gpio_leds || !led_config->num_led_states || !led_config->led_states) return 0; @@ -803,7 +803,7 @@ static int au8522_led_status(struct au8522_state *state, const u16 *snr) int led; u16 strong; - /* bail out if we cant control an LED */ + /* bail out if we can't control an LED */ if (!led_config) return 0; diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index cf5e576dfdcf..8aff5868a5e1 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -155,7 +155,7 @@ static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len) unsigned long t; /* Check if any previous HAB request still needs to be serviced by the - * Aquisition Processor before sending new request */ + * Acquisition Processor before sending new request */ if ((ret = bcm3510_readB(st,0xa8,&v)) < 0) return ret; if (v.HABSTAT_a8.HABR) { @@ -361,7 +361,7 @@ static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a) /* Set duration of the initial state of TUNCTL = 3.34 micro Sec */ c.TUNCTL_state = 0x40; -/* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */ +/* PRESCALER DIVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */ c.ctl_dat[0].ctrl.size = BITS_8; c.ctl_dat[0].data = 0x80 | bc; @@ -397,7 +397,7 @@ static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a) c.ctl_dat[7].ctrl.cs0 = 1; c.ctl_dat[7].data = 0x40; -/* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */ +/* PRESCALER DIVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */ c.ctl_dat[8].ctrl.size = BITS_8; c.ctl_dat[8].data = 0x80; diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c index 5fbc0fc37ecd..0142214b0133 100644 --- a/drivers/media/dvb/frontends/cx22700.c +++ b/drivers/media/dvb/frontends/cx22700.c @@ -179,7 +179,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet cx22700_writereg (state, 0x06, val); cx22700_writereg (state, 0x08, 0x04 | 0x02); /* use user tps parameters */ - cx22700_writereg (state, 0x08, 0x04); /* restart aquisition */ + cx22700_writereg (state, 0x08, 0x04); /* restart acquisition */ return 0; } diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index ff6c4983051c..3139558148ba 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -55,7 +55,7 @@ MODULE_PARM_DESC(debug, "Enable verbose debug messages"); /* Register values to initialise the demod */ static const u8 init_tab[] = { - 0x00, 0x00, /* Stop aquisition */ + 0x00, 0x00, /* Stop acquisition */ 0x0B, 0x06, 0x09, 0x01, 0x0D, 0x41, @@ -310,7 +310,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe, & 0xfc); cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40); - cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */ + cx22702_writereg(state, 0x00, 0x01); /* Begin acquisition */ dprintk("%s: Autodetecting\n", __func__); return 0; } @@ -424,7 +424,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe, cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40); - /* Begin channel aquisition */ + /* Begin channel acquisition */ cx22702_writereg(state, 0x00, 0x01); return 0; diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index 7a1a5bc337d8..bf9c999aa470 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -544,7 +544,7 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par cx24110_set_inversion (state, p->inversion); cx24110_set_fec (state, p->u.qpsk.fec_inner); cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate); - cx24110_writereg(state,0x04,0x05); /* start aquisition */ + cx24110_writereg(state,0x04,0x05); /* start acquisition */ return 0; } diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h index 5de0f7ffd8d2..01eb7b9c28f4 100644 --- a/drivers/media/dvb/frontends/cx24113.h +++ b/drivers/media/dvb/frontends/cx24113.h @@ -1,5 +1,5 @@ /* - * Driver for Conexant CX24113/CX24128 Tuner (Satelite) + * Driver for Conexant CX24113/CX24128 Tuner (Satellite) * * Copyright (C) 2007-8 Patrick Boettcher * diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index fad6a990a39b..b1dd8acc607a 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -949,7 +949,7 @@ static int cx24123_set_frontend(struct dvb_frontend *fe, else err("it seems I don't have a tuner..."); - /* Enable automatic aquisition and reset cycle */ + /* Enable automatic acquisition and reset cycle */ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07)); cx24123_writereg(state, 0x00, 0x10); cx24123_writereg(state, 0x00, 0); diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index a05007c80985..536f02b17338 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c @@ -1097,7 +1097,7 @@ static int drx397x_init(struct dvb_frontend *fe) s->config.ifagc.w0A = 0x3ff; s->config.ifagc.w0C = 0x388; - /* for signal strenght calculations */ + /* for signal strength calculations */ s->config.ss76 = 820; s->config.ss78 = 2200; s->config.ss7A = 150; diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 33b63235b86e..c283112051b1 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1630,7 +1630,7 @@ static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe, state->srate = p->u.qpsk.symbol_rate / 1000; if (!mb86a16_set_fe(state)) { - dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK"); + dprintk(verbose, MB86A16_ERROR, 1, "Successfully acquired LOCK"); return DVBFE_ALGO_SEARCH_SUCCESS; } diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c index cc4acd2f920d..0f867a5055fb 100644 --- a/drivers/media/dvb/frontends/mb86a20s.c +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -406,7 +406,7 @@ err: printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n"); } else { state->need_init = false; - dprintk("Initialization succeded.\n"); + dprintk("Initialization succeeded.\n"); } return rc; } diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 472907d43460..83e6f1a1b700 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -670,7 +670,7 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) if (ret < 0) goto error; - /* preserve this bit to not accidently shutdown ADC */ + /* preserve this bit to not accidentally shutdown ADC */ val &= 0x80; break; } diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index e87b747ea99c..17f8cdf8afef 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -225,7 +225,7 @@ static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, unsigned long timeout; int result = 0; - /* setup for DISEQC recieve */ + /* setup for DISEQC receive */ val = s5h1420_readreg(state, 0x3b); s5h1420_writereg(state, 0x3b, 0x82); /* FIXME: guess - do we need to set DIS_RDY(0x08) in receive mode? */ msleep(15); diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index 64673b8b64a2..bc1a8af4f6e1 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -360,7 +360,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) else odiv = 0; - /* VCO enabled, seach clock off as per LL3.7, 3.4.1 */ + /* VCO enabled, search clock off as per LL3.7, 3.4.1 */ regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT); /* OSM */ diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 4fd7479bb62b..84d88f33275e 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -435,7 +435,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par return -EINVAL; } - // determine inversion dependant parameters + // determine inversion dependent parameters inversion = p->inversion; if (state->config->invert) inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON; diff --git a/drivers/media/dvb/frontends/stv0367.c b/drivers/media/dvb/frontends/stv0367.c index 4e0e6a873b8c..e57ab53e2e27 100644 --- a/drivers/media/dvb/frontends/stv0367.c +++ b/drivers/media/dvb/frontends/stv0367.c @@ -1328,7 +1328,7 @@ stv0367_ter_signal_type stv0367ter_lock_algo(struct stv0367_state *state) /*guard=stv0367_readbits(state,F367TER_SYR_GUARD); */ - /*supress EPQ auto for SYR_GARD 1/16 or 1/32 + /*suppress EPQ auto for SYR_GARD 1/16 or 1/32 and set channel predictor in automatic */ #if 0 switch (guard) { diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h index b62b0f0a4fef..e0ea74c8e093 100644 --- a/drivers/media/dvb/frontends/stv0900_priv.h +++ b/drivers/media/dvb/frontends/stv0900_priv.h @@ -238,7 +238,7 @@ enum fe_stv0900_demod_mode { }; struct stv0900_init_params{ - u32 dmd_ref_clk;/* Refrence,Input clock for the demod in Hz */ + u32 dmd_ref_clk;/* Reference,Input clock for the demod in Hz */ /* Demodulator Type (single demod or dual demod) */ enum fe_stv0900_demod_mode demod_mode; diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 41d0f0a6655d..52d8712411e5 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1424,7 +1424,7 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0) goto err; - /*enlarge the timing bandwith for Low SR*/ + /*enlarge the timing bandwidth for Low SR*/ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) goto err; } else { @@ -1432,17 +1432,17 @@ static int stv090x_start_search(struct stv090x_state *state) Set The carrier search up and low to auto mode */ if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) goto err; - /*reduce the timing bandwith for high SR*/ + /*reduce the timing bandwidth for high SR*/ if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) goto err; } } else { /* >= Cut 3 */ if (state->srate <= 5000000) { - /* enlarge the timing bandwith for Low SR */ + /* enlarge the timing bandwidth for Low SR */ STV090x_WRITE_DEMOD(state, RTCS2, 0x68); } else { - /* reduce timing bandwith for high SR */ + /* reduce timing bandwidth for high SR */ STV090x_WRITE_DEMOD(state, RTCS2, 0x44); } @@ -2482,7 +2482,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); } if (dvbs2_fly_wheel < 0xd) { - /*FALSE lock, The demod is loosing lock */ + /*FALSE lock, The demod is losing lock */ lock = 0; if (trials < 2) { if (state->internal->dev_ver >= 0x20) { @@ -3202,7 +3202,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) goto err; - if (stv090x_set_srate(state, 1000000) < 0) /* inital srate = 1Msps */ + if (stv090x_set_srate(state, 1000000) < 0) /* initial srate = 1Msps */ goto err; } else { /* known srate */ diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index 97b889e8a341..f807c8ba26e4 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -172,7 +172,7 @@ int mantis_uart_init(struct mantis_pci *mantis) mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); schedule_work(&mantis->uart_work); - dprintk(MANTIS_DEBUG, 1, "UART succesfully initialized"); + dprintk(MANTIS_DEBUG, 1, "UART successfully initialized"); return 0; } diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 175a0f6c2a4c..ccc2d1af49d4 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -122,7 +122,7 @@ static void demux_tasklet(unsigned long data) Cur->ngeneBuffer.SR.Flags &= ~0x40; break; - /* Stop proccessing stream */ + /* Stop processing stream */ } } else { /* We got a valid buffer, @@ -133,7 +133,7 @@ static void demux_tasklet(unsigned long data) printk(KERN_ERR DEVICE_NAME ": OOPS\n"); if (chan->HWState == HWSTATE_RUN) { Cur->ngeneBuffer.SR.Flags &= ~0x40; - break; /* Stop proccessing stream */ + break; /* Stop processing stream */ } } if (chan->AudioDTOUpdated) { diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 6ca6713d527a..7cb79ec685f0 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -294,13 +294,13 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets) /* Workaround for broken hardware: * [1] On startup NBPACKETS seems to contain an uninitialized value, - * but no packets have been transfered. + * but no packets have been transferred. * [2] Sometimes (actually very often) NBPACKETS stays at zero - * although one packet has been transfered. + * although one packet has been transferred. * [3] Sometimes (actually rarely), the card gets into an erroneous * mode where it continuously generates interrupts, claiming it - * has recieved nbpackets>TS_DMA_PACKETS packets, but no packet - * has been transfered. Only a reset seems to solve this + * has received nbpackets>TS_DMA_PACKETS packets, but no packet + * has been transferred. Only a reset seems to solve this */ if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) { unsigned int i = 0; @@ -332,7 +332,7 @@ static irqreturn_t pluto_irq(int irq, void *dev_id) struct pluto *pluto = dev_id; u32 tscr; - /* check whether an interrupt occured on this device */ + /* check whether an interrupt occurred on this device */ tscr = pluto_readreg(pluto, REG_TSCR); if (!(tscr & (TSCR_DE | TSCR_OVR))) return IRQ_NONE; diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index b80d09b035a1..37c594f82782 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -650,7 +650,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, if (status & FE_HAS_LOCK) return ret; - /* previous tune didnt lock - enable LNA and tune again */ + /* previous tune didn't lock - enable LNA and tune again */ sms_board_lna_control(client->coredev, 1); } diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index fc0a60f8a1e1..3d20719fce1a 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2332,7 +2332,7 @@ static int frontend_init(struct av7110 *av7110) * increment. That's how the 7146 is programmed to do event * counting in this budget-patch.c * I *think* HPS setting has something to do with the phase - * of HS but I cant be 100% sure in that. + * of HS but I can't be 100% sure in that. * * hardware debug note: a working budget card (including budget patch) * with vpeirq() interrupt setup in mode "0x90" (every 64K) will diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index 579835590690..3395d1a90516 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -539,7 +539,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ** increment. That's how the 7146 is programmed to do event ** counting in this budget-patch.c ** I *think* HPS setting has something to do with the phase -** of HS but I cant be 100% sure in that. +** of HS but I can't be 100% sure in that. ** hardware debug note: a working budget card (including budget patch) ** with vpeirq() interrupt setup in mode "0x90" (every 64K) will diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index fe1b8037b247..f893bffa08a3 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -234,7 +234,7 @@ static void ttusb_dec_handle_irq( struct urb *urb) * (with buffer[3] == 0x40) in an intervall of ~100ms. * But to handle this correctly we had to imlemenent some * kind of timer which signals a 'key up' event if no - * keyrepeat signal is recieved for lets say 200ms. + * keyrepeat signal is received for lets say 200ms. * this should/could be added later ... * for now lets report each signal as a key down and up*/ dprintk("%s:rc signal:%d\n", __func__, buffer[4]); diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index e6b2d085a449..b3a635b95820 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -99,7 +99,7 @@ devices, that would be 76 and 91. */ /* * Commands that device should understand - * List isnt full and will be updated with implementation of new functions + * List isn't full and will be updated with implementation of new functions */ #define AMRADIO_SET_FREQ 0xa4 #define AMRADIO_SET_MUTE 0xab diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index 0fab6f8f7e24..deca2e06ff22 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c @@ -481,7 +481,7 @@ unlock: } /* - * si4713_wait_stc - Waits STC interrupt and clears status bits. Usefull + * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS * @sdev: si4713_device structure for the device we are communicating * @usecs: timeout to wait for STC interrupt signal diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 64454d39c0ca..26fb9cbd7530 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -352,7 +352,7 @@ static void send_tasklet(unsigned long arg) if (!atomic_read(&fmdev->tx_cnt)) return; - /* Check, is there any timeout happenned to last transmitted packet */ + /* Check, is there any timeout happened to last transmitted packet */ if ((jiffies - fmdev->last_tx_jiffies) > FM_DRV_TX_TIMEOUT) { fmerr("TX timeout occurred\n"); atomic_set(&fmdev->tx_cnt, 1); @@ -478,7 +478,7 @@ u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, return -ETIMEDOUT; } if (!fmdev->resp_skb) { - fmerr("Reponse SKB is missing\n"); + fmerr("Response SKB is missing\n"); return -EFAULT; } spin_lock_irqsave(&fmdev->resp_skb_lock, flags); @@ -1592,7 +1592,7 @@ u32 fmc_release(struct fmdev *fmdev) fmdbg("FM Core is already down\n"); return 0; } - /* Sevice pending read */ + /* Service pending read */ wake_up_interruptible(&fmdev->rx.rds.read_queue); tasklet_kill(&fmdev->tx_task); diff --git a/drivers/media/radio/wl128x/fmdrv_common.h b/drivers/media/radio/wl128x/fmdrv_common.h index 427c4164cece..aee243bb6630 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.h +++ b/drivers/media/radio/wl128x/fmdrv_common.h @@ -362,7 +362,7 @@ struct fm_event_msg_hdr { #define FM_TX_PREEMPH_50US 0 #define FM_TX_PREEMPH_75US 2 -/* FM TX antenna impedence values */ +/* FM TX antenna impedance values */ #define FM_TX_ANT_IMP_50 0 #define FM_TX_ANT_IMP_200 1 #define FM_TX_ANT_IMP_500 2 diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 1ac49139158d..a43ed6c41bfc 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -520,7 +520,7 @@ static void ene_rx_disable(struct ene_device *dev) dev->rx_enabled = false; } -/* This resets the receiver. Usefull to stop stream of spaces at end of +/* This resets the receiver. Useful to stop stream of spaces at end of * transmission */ static void ene_rx_reset(struct ene_device *dev) @@ -1089,7 +1089,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) if (error < 0) goto error; - ene_notice("driver has been succesfully loaded"); + ene_notice("driver has been successfully loaded"); return 0; error: if (dev && dev->irq >= 0) diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index f714e1a22c92..ebd68edf5b24 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1293,7 +1293,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) * contain a position coordinate (x,y), with each component ranging * from -14 to 14. We want to down-sample this to only 4 discrete values * for up/down/left/right arrow keys. Also, when you get too close to - * diagonals, it has a tendancy to jump back and forth, so lets try to + * diagonals, it has a tendency to jump back and forth, so lets try to * ignore when they get too close. */ if (ictx->product != 0xffdc) { diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 01f258a2a57a..11c19d8d0ee0 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -153,7 +153,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) works - * in similiar manner to ir_raw_event_store_edge. + * in similar manner to ir_raw_event_store_edge. * This routine is intended for devices with limited internal buffer * It automerges samples of same type, and handles timeouts */ diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c index 3c1913926c1a..afae14fd152e 100644 --- a/drivers/media/rc/keymaps/rc-lme2510.c +++ b/drivers/media/rc/keymaps/rc-lme2510.c @@ -55,7 +55,7 @@ static struct rc_map_table lme2510_rc[] = { { 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */ { 0xff40e51a, KEY_PAUSE }, /* Timeshift */ { 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ - { 0xff40f906, KEY_VOLUMEDOWN }, /* Volumne defined as right hand*/ + { 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ { 0xff40fe01, KEY_CHANNELUP }, { 0xff40fa05, KEY_CHANNELDOWN }, { 0xff40eb14, KEY_ZOOM }, @@ -76,7 +76,7 @@ static struct rc_map_table lme2510_rc[] = { { 0xff00bb44, KEY_MEDIA_REPEAT}, /* Recall */ { 0xff00b54a, KEY_PAUSE }, /* Timeshift */ { 0xff00b847, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ - { 0xff00bc43, KEY_VOLUMEDOWN }, /* Volumne defined as right hand*/ + { 0xff00bc43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ { 0xff00b946, KEY_CHANNELUP }, { 0xff00bf40, KEY_CHANNELDOWN }, { 0xff00f708, KEY_ZOOM }, diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c index 18b37facb0dd..fdd213ff1adf 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c @@ -29,7 +29,7 @@ static struct rc_map_table msi_tvanywhere[] = { { 0x0c, KEY_MUTE }, { 0x0f, KEY_SCREEN }, /* Full Screen */ - { 0x10, KEY_FN }, /* Funtion */ + { 0x10, KEY_FN }, /* Function */ { 0x11, KEY_TIME }, /* Time shift */ { 0x12, KEY_POWER }, { 0x13, KEY_MEDIA }, /* MTS */ diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c index f1c1281fbc17..f9f2fa2819b8 100644 --- a/drivers/media/rc/keymaps/rc-norwood.c +++ b/drivers/media/rc/keymaps/rc-norwood.c @@ -49,7 +49,7 @@ static struct rc_map_table norwood[] = { { 0x37, KEY_PLAY }, /* Play */ { 0x36, KEY_PAUSE }, /* Pause */ { 0x2b, KEY_STOP }, /* Stop */ - { 0x67, KEY_FASTFORWARD }, /* Foward */ + { 0x67, KEY_FASTFORWARD }, /* Forward */ { 0x66, KEY_REWIND }, /* Rewind */ { 0x3e, KEY_SEARCH }, /* Auto Scan */ { 0x2e, KEY_CAMERA }, /* Capture Video */ diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 5ac1baf45c8e..f53f9c68d38d 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -255,7 +255,7 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, * @rc_map: scancode table to be searched * @scancode: the desired scancode * @resize: controls whether we allowed to resize the table to - * accomodate not yet present scancodes + * accommodate not yet present scancodes * @return: index of the mapping containing scancode in question * or -1U in case of failure. * @@ -1037,7 +1037,7 @@ int rc_register_device(struct rc_dev *dev) goto out_table; /* - * Default delay of 250ms is too short for some protocols, expecially + * Default delay of 250ms is too short for some protocols, especially * since the timeout is currently set to 250ms. Increase it to 500ms, * to avoid wrong repetition of the keycodes. Note that this must be * set after the call to input_register_device(). diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 6ad83a15d073..c03eb29a9ee6 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -502,7 +502,7 @@ static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, /* Get the next buffer */ *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); - /* Cleans up buffer - Usefull for testing for frame/URB loss */ + /* Cleans up buffer - Useful for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); memset(outp, 0x00, (*buf)->vb.size); diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 242f0d512238..3c9e6c7e7b52 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2244,8 +2244,8 @@ struct tvcard bttv_tvcards[] = { }, [BTTV_BOARD_PICOLO_TETRA_CHIP] = { /*Eric DEBIEF */ - /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ - /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/ + /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controlled*/ + /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the following declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/ /*0x79 in bttv.h*/ .name = "Euresys Picolo Tetra", .video_inputs = 4, @@ -4567,7 +4567,7 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) * at one input while the monitor is looking at another. * * Since I've couldn't be bothered figuring out how to add an - * independant muxsel for the monitor bus, I've just set it to + * independent muxsel for the monitor bus, I've just set it to * whatever the card is looking at. * * OUT0 of the TDA8540's is connected to MUX0 (0x03) diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c index fd604d32bbb9..13ce72c04b33 100644 --- a/drivers/media/video/bt8xx/bttv-gpio.c +++ b/drivers/media/video/bt8xx/bttv-gpio.c @@ -3,7 +3,7 @@ bttv-gpio.c -- gpio sub drivers sysfs-based sub driver interface for bttv - mainly intented for gpio access + mainly intended for gpio access Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 55ffd60ffa7f..664703398493 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -383,7 +383,7 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, * causes the device to die. * Use a busy-wait because we often send a large quantity of small * commands at-once; using msleep() would cause a lot of context - * switches which take longer than 2ms, resulting in a noticable + * switches which take longer than 2ms, resulting in a noticeable * boot-time and capture-start delays. */ mdelay(2); diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 188c9c3d2db1..e9c69d9c9e4a 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -109,7 +109,7 @@ struct cx18_av_state { int is_initialized; /* - * The VBI slicer starts operating and counting lines, begining at + * The VBI slicer starts operating and counting lines, beginning at * slicer line count of 1, at D lines after the deassertion of VRESET. * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525 * line systems respectively. Sliced ancillary data captured on VBI diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 86c30b9963e5..4f041c033c54 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -312,7 +312,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, /* * Set the digitizer registers for raw active VBI. - * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid + * Note cx18_av_vbi_wipes out a lot of the passed in fmt under valid * calling conditions */ ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi); diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 582227522cf0..6d3121ff45a2 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -29,7 +29,7 @@ /* * Raster Reference/Protection (RP) bytes, used in Start/End Active * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start - * of VBI sample or VBI ancilliary data regions in the digitial ratser line. + * of VBI sample or VBI ancillary data regions in the digitial ratser line. * * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0 */ diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index 62843d39817c..280df43ca446 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -2577,7 +2577,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) break; case 6: /* ts1 parallel mode */ - cx231xx_info("%s: set ts1 parrallel mode registers\n", + cx231xx_info("%s: set ts1 parallel mode registers\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 1d914488dbb3..1c7a4daafecf 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -631,7 +631,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, /* Get the next buffer */ *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); - /* Cleans up buffer - Usefull for testing for frame/URB loss */ + /* Cleans up buffer - Useful for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); memset(outp, 0, (*buf)->vb.size); diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index ffd5af914c44..a69c24d8db06 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -309,7 +309,7 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, /* Get the next buffer */ *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); - /* Cleans up buffer - Usefull for testing for frame/URB loss */ + /* Cleans up buffer - Useful for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); memset(outp, 0, (*buf)->vb.size); diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index 209b971bd267..c9f15d6dec40 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c @@ -449,7 +449,7 @@ int netup_ci_init(struct cx23885_tsport *port) 0x04, /* ack active low */ 0x00, /* LOCK = 0 */ 0x33, /* serial mode, rising in, rising out, MSB first*/ - 0x31, /* syncronization */ + 0x31, /* synchronization */ }; int ret; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 8db2797bc7c3..c186473fc570 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -214,7 +214,7 @@ struct cx23885_board { /* Vendors can and do run the PCIe bridge at different * clock rates, driven physically by crystals on the PCBs. - * The core has to accomodate this. This allows the user + * The core has to accommodate this. This allows the user * to add new boards with new frequencys. The value is * expressed in Hz. * diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 35796e035247..b7ee2ae70583 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -2,7 +2,7 @@ * * Copyright (C) 2004 Ulf Eklund * - * Based on the saa7115 driver and on the first verison of Chris Kennedy's + * Based on the saa7115 driver and on the first version of Chris Kennedy's * cx25840 driver. * * Changes by Tyler Trafford @@ -445,7 +445,7 @@ static void cx25840_initialize(struct i2c_client *client) cx25840_write(client, 0x918, 0xa0); cx25840_write(client, 0x919, 0x01); - /* stereo prefered */ + /* stereo preferred */ cx25840_write(client, 0x809, 0x04); /* AC97 shift */ cx25840_write(client, 0x8cf, 0x0f); @@ -546,7 +546,7 @@ static void cx23885_initialize(struct i2c_client *client) * Aux PLL * Initial setup for audio sample clock: * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz - * Intial I2S output/master clock(?): + * Initial I2S output/master clock(?): * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz */ switch (state->id) { @@ -903,7 +903,7 @@ static void input_change(struct i2c_client *client) } else if (std & V4L2_STD_PAL) { /* Autodetect audio standard and audio system */ cx25840_write(client, 0x808, 0xff); - /* Since system PAL-L is pretty much non-existant and + /* Since system PAL-L is pretty much non-existent and not used by any public broadcast network, force 6.5 MHz carrier to be interpreted as System DK, this avoids DK audio detection instability */ @@ -1851,7 +1851,7 @@ static u32 get_cx2388x_ident(struct i2c_client *client) ret = V4L2_IDENT_CX23885_AV; } else { /* CX23887 has a broken DIF, but the registers - * appear valid (but unsed), good enough to detect. */ + * appear valid (but unused), good enough to detect. */ ret = V4L2_IDENT_CX23887_AV; } } else if (cx25840_read4(client, 0x300) & 0x0fffffff) { diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index 490aafb34e2f..c8b32c1c7386 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c @@ -258,7 +258,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) /* * Allocate memory for FPC table if current * FPC table buffer is not big enough to - * accomodate FPC Number requested + * accommodate FPC Number requested */ if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { if (fpc_physaddr != NULL) { @@ -436,7 +436,7 @@ void ccdc_config_ycbcr(void) /* * configure the horizontal line offset. This should be a - * on 32 byte bondary. So clear LSB 5 bits + * on 32 byte boundary. So clear LSB 5 bits */ regw(((params->win.width * 2 + 31) & ~0x1f), CCDC_HSIZE_OFF); diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 71e961e53a56..5b38fc93ff28 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1691,7 +1691,7 @@ static int vpfe_s_crop(struct file *file, void *priv, goto unlock_out; } - /* adjust the width to 16 pixel boundry */ + /* adjust the width to 16 pixel boundary */ crop->c.width = ((crop->c.width + 15) & ~0xf); /* make sure parameters are valid */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a83131bd00b2..7b6461d2d1ff 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -377,7 +377,7 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, /* Get the next buffer */ *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - /* Cleans up buffer - Usefull for testing for frame/URB loss */ + /* Cleans up buffer - Useful for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); memset(outp, 0, (*buf)->vb.size); @@ -404,7 +404,7 @@ static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q, /* Get the next buffer */ *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - /* Cleans up buffer - Usefull for testing for frame/URB loss */ + /* Cleans up buffer - Useful for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); memset(outp, 0x00, (*buf)->vb.size); diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c index c276a7debdec..b57160e04866 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ b/drivers/media/video/gspca/gl860/gl860-mi1320.c @@ -201,7 +201,7 @@ void mi1320_init_settings(struct gspca_dev *gspca_dev) sd->vmax.backlight = 2; sd->vmax.brightness = 8; sd->vmax.sharpness = 7; - sd->vmax.contrast = 0; /* 10 but not working with tihs driver */ + sd->vmax.contrast = 0; /* 10 but not working with this driver */ sd->vmax.gamma = 40; sd->vmax.hue = 5 + 1; sd->vmax.saturation = 8; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 9c6a643caf01..e526aa3dedaf 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -857,7 +857,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) } /* the bandwidth is not wide enough - * negociate or try a lower alternate setting */ + * negotiate or try a lower alternate setting */ PDEBUG(D_ERR|D_STREAM, "bandwidth not wide enough - trying again"); msleep(20); /* wait for kill complete */ @@ -2346,7 +2346,7 @@ void gspca_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); /* release the device */ - /* (this will call gspca_release() immediatly or on last close) */ + /* (this will call gspca_release() immediately or on last close) */ video_unregister_device(&gspca_dev->vdev); /* PDEBUG(D_PROBE, "disconnect complete"); */ diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index cb4d0bf0d784..0196209a948a 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -361,7 +361,7 @@ static int sd_start(struct gspca_dev *gspca_dev) mi_w(gspca_dev, i + 1, mi_data[i]); data[0] = 0x00; - data[1] = 0x4d; /* ISOC transfering enable... */ + data[1] = 0x4d; /* ISOC transferring enable... */ reg_w(gspca_dev, 2); gspca_dev->ctrl_inac = 0; /* activate the illuminator controls */ diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 3884c9d300c5..97e507967434 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -469,7 +469,7 @@ static void lcd_stop(struct gspca_dev *gspca_dev) static int isoc_enable(struct gspca_dev *gspca_dev) { gspca_dev->usb_buf[0] = 0x00; - gspca_dev->usb_buf[1] = 0x4d; /* ISOC transfering enable... */ + gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */ return mr_write(gspca_dev, 2); } diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index fd1b6082c96d..36a46fc78734 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -381,7 +381,7 @@ static const struct v4l2_pix_format ov519_sif_mode[] = { larger then necessary, however they need to be this big as the ov511 / ov518 always fills the entire isoc frame, using 0 padding bytes when it doesn't have any data. So with low framerates the amount of data - transfered can become quite large (libv4l will remove all the 0 padding + transferred can become quite large (libv4l will remove all the 0 padding in userspace). */ static const struct v4l2_pix_format ov518_vga_mode[] = { {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, @@ -4368,7 +4368,7 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, gspca_dev->last_packet_type = DISCARD_PACKET; return; } - /* Add 11 byte footer to frame, might be usefull */ + /* Add 11 byte footer to frame, might be useful */ gspca_frame_add(gspca_dev, LAST_PACKET, in, 11); return; } else { diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5a08738fba30..146b459b08d5 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -827,7 +827,7 @@ static void setexposure(struct gspca_dev *gspca_dev) possible to use less exposure then what the fps maximum allows by setting register 10. register 10 configures the actual exposure as quotient of the full exposure, with 0 - being no exposure at all (not very usefull) and reg10_max + being no exposure at all (not very useful) and reg10_max being max exposure possible at that framerate. The code maps our 0 - 510 ms exposure ctrl to these 2 diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 45552c3ff8d9..3e76951e3c19 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -607,7 +607,7 @@ static void spca500_reinit(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x00, 0x8880, 2); /* family cam Quicksmart stuff */ reg_w(gspca_dev, 0x00, 0x800a, 0x00); - /* Set agc transfer: synced inbetween frames */ + /* Set agc transfer: synced between frames */ reg_w(gspca_dev, 0x00, 0x820f, 0x01); /* Init SDRAM - needed for SDRAM access */ reg_w(gspca_dev, 0x00, 0x870a, 0x04); @@ -831,7 +831,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* familycam Quicksmart pocketDV stuff */ reg_w(gspca_dev, 0x00, 0x800a, 0x00); - /* Set agc transfer: synced inbetween frames */ + /* Set agc transfer: synced between frames */ reg_w(gspca_dev, 0x00, 0x820f, 0x01); /* Init SDRAM - needed for SDRAM access */ reg_w(gspca_dev, 0x00, 0x870a, 0x04); diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 348319371523..41dce49fb43d 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -592,7 +592,7 @@ static const u16 spca508_sightcam_init_data[][2] = { /* This line seems to setup the frame/canvas */ {0x000f, 0x8402}, -/* Theese 6 lines are needed to startup the webcam */ +/* These 6 lines are needed to startup the webcam */ {0x0090, 0x8110}, {0x0001, 0x8114}, {0x0001, 0x8114}, diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index 2e9c06175192..5ba96aff2252 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -22,7 +22,7 @@ * History and Acknowledgments * * The original Linux driver for SQ905 based cameras was written by - * Marcell Lengyel and furter developed by many other contributers + * Marcell Lengyel and furter developed by many other contributors * and is available from http://sourceforge.net/projects/sqcam/ * * This driver takes advantage of the reverse engineering work done for diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index 17531b41a073..b8156855f2b7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -569,7 +569,7 @@ static int hdcs_init(struct sd *sd) if (err < 0) return err; - /* Enable continous frame capture, bit 2: stop when frame complete */ + /* Enable continuous frame capture, bit 2: stop when frame complete */ err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3)); if (err < 0) return err; diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index cdf8b191f710..cbc505a2fc29 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -261,7 +261,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) /* the saa7146 provides some controls (brightness, contrast, saturation) which gets registered *after* this function. because of this we have - to return with a value != 0 even if the function succeded.. */ + to return with a value != 0 even if the function succeeded.. */ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index 4df01947a7df..14a1cea1d70d 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -179,7 +179,7 @@ static volatile struct ivtv_mailbox __iomem *ivtv_search_mailbox(const volatile { int i; - /* mailbox is preceeded by a 16 byte 'magic cookie' starting at a 256-byte + /* mailbox is preceded by a 16 byte 'magic cookie' starting at a 256-byte address boundary */ for (i = 0; i < size; i += 0x100) { if (readl(mem + i) == 0x12345678 && @@ -377,7 +377,7 @@ int ivtv_firmware_check(struct ivtv *itv, char *where) "Reloading\n", where); res = ivtv_firmware_restart(itv); /* - * Even if restarted ok, still signal a problem had occured. + * Even if restarted ok, still signal a problem had occurred. * The caller can come through this function again to check * if things are really ok after the restart. */ diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index f0316d02f09f..17247451c693 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -1080,7 +1080,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN); if (!oi->ivtvfb_info.pseudo_palette) { - IVTVFB_ERR("abort, unable to alloc pseudo pallete\n"); + IVTVFB_ERR("abort, unable to alloc pseudo palette\n"); return -ENOMEM; } diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index b1763ac93ab3..8126622fb4f5 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -69,7 +69,7 @@ MODULE_LICENSE("GPL"); /* module parameters */ static int opmode = OPMODE_AUTO; int msp_debug; /* msp_debug output */ -int msp_once; /* no continous stereo monitoring */ +int msp_once; /* no continuous stereo monitoring */ int msp_amsound; /* hard-wire AM sound at 6.5 Hz (france), the autoscan seems work well only with FM... */ int msp_standard = 1; /* Override auto detect of audio msp_standard, @@ -551,7 +551,7 @@ static int msp_log_status(struct v4l2_subdev *sd) switch (state->mode) { case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; case MSP_MODE_FM_RADIO: p = "FM Radio"; break; - case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono/stereo"; break; + case MSP_MODE_FM_TERRA: p = "Terrestrial FM-mono/stereo"; break; case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break; case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break; case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break; diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index b376fcdee652..80387e2c3eca 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -87,7 +87,7 @@ static struct msp3400c_init_data_dem { {-8, -8, 4, 6, 78, 107}, MSP_CARRIER(10.7), MSP_CARRIER(10.7), 0x00d0, 0x0480, 0x0020, 0x3000 - }, { /* Terrestial FM-mono + FM-stereo */ + }, { /* Terrestrial FM-mono + FM-stereo */ {3, 18, 27, 48, 66, 72}, {3, 18, 27, 48, 66, 72}, MSP_CARRIER(5.5), MSP_CARRIER(5.5), diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 029a4babfd61..d4fe7bc92a1d 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -473,7 +473,7 @@ static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, /* * Convert V4L2 rotation to DSS rotation * V4L2 understand 0, 90, 180, 270. - * Convert to 0, 1, 2 and 3 repsectively for DSS + * Convert to 0, 1, 2 and 3 respectively for DSS */ static int v4l2_rot_to_dss_rot(int v4l2_rotation, enum dss_rotation *rotation, bool mirror) @@ -1142,7 +1142,7 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q, } /* - * Buffer queue funtion will be called from the videobuf layer when _QBUF + * Buffer queue function will be called from the videobuf layer when _QBUF * ioctl is called. It is used to enqueue buffer, which is ready to be * displayed. */ diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c index b941c761eef9..2aa6a76c5e59 100644 --- a/drivers/media/video/omap/omap_voutlib.c +++ b/drivers/media/video/omap/omap_voutlib.c @@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(omap_vout_default_crop); /* Given a new render window in new_win, adjust the window to the * nearest supported configuration. The adjusted window parameters are * returned in new_win. - * Returns zero if succesful, or -EINVAL if the requested window is + * Returns zero if successful, or -EINVAL if the requested window is * impossible and cannot reasonably be adjusted. */ int omap_vout_try_window(struct v4l2_framebuffer *fbuf, @@ -101,7 +101,7 @@ EXPORT_SYMBOL_GPL(omap_vout_try_window); * will also be adjusted if necessary. Preference is given to keeping the * the window as close to the requested configuration as possible. If * successful, new_win, vout->win, and crop are updated. - * Returns zero if succesful, or -EINVAL if the requested preview window is + * Returns zero if successful, or -EINVAL if the requested preview window is * impossible and cannot reasonably be adjusted. */ int omap_vout_new_window(struct v4l2_rect *crop, @@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(omap_vout_new_window); * window would fall outside the display boundaries, the cropping rectangle * will also be adjusted to maintain the rescaling ratios. If successful, crop * and win are updated. - * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is + * Returns zero if successful, or -EINVAL if the requested cropping rectangle is * impossible and cannot reasonably be adjusted. */ int omap_vout_new_crop(struct v4l2_pix_format *pix, diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index eab31cbd68eb..5954b9306630 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c @@ -687,7 +687,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev, * In CONTIG mode, the current buffer parameters had already * been entered into the DMA programming register set while the * buffer was fetched with prepare_next_vb(), they may have also - * been transfered into the runtime set and already active if + * been transferred into the runtime set and already active if * the DMA still running. */ } else { @@ -835,7 +835,7 @@ static irqreturn_t cam_isr(int irq, void *data) /* * If exactly 2 sgbufs from the next sglist have * been programmed into the DMA engine (the - * frist one already transfered into the DMA + * first one already transferred into the DMA * runtime register set, the second one still * in the programming set), then we are in sync. */ diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c index 1a9963bd6d40..503bd7922bd6 100644 --- a/drivers/media/video/omap3isp/isp.c +++ b/drivers/media/video/omap3isp/isp.c @@ -715,7 +715,7 @@ static int isp_pipeline_link_notify(struct media_pad *source, * Walk the entities chain starting at the pipeline output video node and start * all modules in the chain in the given mode. * - * Return 0 if successfull, or the return value of the failed video::s_stream + * Return 0 if successful, or the return value of the failed video::s_stream * operation otherwise. */ static int isp_pipeline_enable(struct isp_pipeline *pipe, @@ -883,7 +883,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe) * Set the pipeline to the given stream state. Pipelines can be started in * single-shot or continuous mode. * - * Return 0 if successfull, or the return value of the failed video::s_stream + * Return 0 if successful, or the return value of the failed video::s_stream * operation otherwise. */ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe, @@ -1283,7 +1283,7 @@ static void __isp_subclk_update(struct isp_device *isp) clk |= ISPCTRL_RSZ_CLK_EN; /* NOTE: For CCDC & Preview submodules, we need to affect internal - * RAM aswell. + * RAM as well. */ if (isp->subclk_resources & OMAP3_ISP_SUBCLK_CCDC) clk |= ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN; @@ -1431,7 +1431,7 @@ static int isp_get_clocks(struct isp_device *isp) * Increment the reference count on the ISP. If the first reference is taken, * enable clocks and power-up all submodules. * - * Return a pointer to the ISP device structure, or NULL if an error occured. + * Return a pointer to the ISP device structure, or NULL if an error occurred. */ struct isp_device *omap3isp_get(struct isp_device *isp) { diff --git a/drivers/media/video/omap3isp/ispccdc.h b/drivers/media/video/omap3isp/ispccdc.h index d403af5d31d2..483a19cac1ad 100644 --- a/drivers/media/video/omap3isp/ispccdc.h +++ b/drivers/media/video/omap3isp/ispccdc.h @@ -150,7 +150,7 @@ struct ispccdc_lsc { * @input: Active input * @output: Active outputs * @video_out: Output video node - * @error: A hardware error occured during capture + * @error: A hardware error occurred during capture * @alaw: A-law compression enabled (1) or disabled (0) * @lpf: Low pass filter enabled (1) or disabled (0) * @obclamp: Optical-black clamp enabled (1) or disabled (0) @@ -163,7 +163,7 @@ struct ispccdc_lsc { * @shadow_update: Controls update in progress by userspace * @syncif: Interface synchronization configuration * @vpcfg: Video port configuration - * @underrun: A buffer underrun occured and a new buffer has been queued + * @underrun: A buffer underrun occurred and a new buffer has been queued * @state: Streaming state * @lock: Serializes shadow_update with interrupt handler * @wait: Wait queue used to stop the module diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c index 0efef2e78d93..0e16cab8e089 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/video/omap3isp/ispccp2.c @@ -772,7 +772,7 @@ static int ccp2_enum_frame_size(struct v4l2_subdev *sd, * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @fmt : pointer to v4l2 subdev format structure - * return -EINVAL or zero on sucess + * return -EINVAL or zero on success */ static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c index fb503f3db3be..69161a682b3d 100644 --- a/drivers/media/video/omap3isp/ispcsi2.c +++ b/drivers/media/video/omap3isp/ispcsi2.c @@ -969,7 +969,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd, * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on sucess + * return -EINVAL or zero on success */ static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index baf9374201dc..2b16988a501d 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c @@ -34,7 +34,7 @@ #include "ispreg.h" #include "isppreview.h" -/* Default values in Office Flourescent Light for RGBtoRGB Blending */ +/* Default values in Office Fluorescent Light for RGBtoRGB Blending */ static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = { { /* RGB-RGB Matrix */ {0x01E2, 0x0F30, 0x0FEE}, @@ -44,7 +44,7 @@ static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = { {0x0000, 0x0000, 0x0000} }; -/* Default values in Office Flourescent Light for RGB to YUV Conversion*/ +/* Default values in Office Fluorescent Light for RGB to YUV Conversion*/ static struct omap3isp_prev_csc flr_prev_csc = { { /* CSC Coef Matrix */ {66, 129, 25}, @@ -54,22 +54,22 @@ static struct omap3isp_prev_csc flr_prev_csc = { {0x0, 0x0, 0x0} }; -/* Default values in Office Flourescent Light for CFA Gradient*/ +/* Default values in Office Fluorescent Light for CFA Gradient*/ #define FLR_CFA_GRADTHRS_HORZ 0x28 #define FLR_CFA_GRADTHRS_VERT 0x28 -/* Default values in Office Flourescent Light for Chroma Suppression*/ +/* Default values in Office Fluorescent Light for Chroma Suppression*/ #define FLR_CSUP_GAIN 0x0D #define FLR_CSUP_THRES 0xEB -/* Default values in Office Flourescent Light for Noise Filter*/ +/* Default values in Office Fluorescent Light for Noise Filter*/ #define FLR_NF_STRGTH 0x03 /* Default values for White Balance */ #define FLR_WBAL_DGAIN 0x100 #define FLR_WBAL_COEF 0x20 -/* Default values in Office Flourescent Light for Black Adjustment*/ +/* Default values in Office Fluorescent Light for Black Adjustment*/ #define FLR_BLKADJ_BLUE 0x0 #define FLR_BLKADJ_GREEN 0x0 #define FLR_BLKADJ_RED 0x0 @@ -137,7 +137,7 @@ preview_enable_invalaw(struct isp_prev_device *prev, u8 enable) * @enable: 1 - Enable, 0 - Disable * * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also - * The proccess is applied for each captured frame. + * The process is applied for each captured frame. */ static void preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable) @@ -157,7 +157,7 @@ preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable) * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is * subtracted with the pixels in the current frame. * - * The proccess is applied for each captured frame. + * The process is applied for each captured frame. */ static void preview_enable_drkframe(struct isp_prev_device *prev, u8 enable) @@ -1528,7 +1528,7 @@ static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) * preview_set_stream - Enable/Disable streaming on preview subdev * @sd : pointer to v4l2 subdev structure * @enable: 1 == Enable, 0 == Disable - * return -EINVAL or zero on sucess + * return -EINVAL or zero on success */ static int preview_set_stream(struct v4l2_subdev *sd, int enable) { @@ -1780,7 +1780,7 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd, * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on sucess + * return -EINVAL or zero on success */ static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h index f2d63ca4bd6f..fa943bd05c7f 100644 --- a/drivers/media/video/omap3isp/isppreview.h +++ b/drivers/media/video/omap3isp/isppreview.h @@ -163,7 +163,7 @@ struct isptables_update { * @output: Bitmask of the active output * @video_in: Input video entity * @video_out: Output video entity - * @error: A hardware error occured during capture + * @error: A hardware error occurred during capture * @params: Module configuration data * @shadow_update: If set, update the hardware configured in the next interrupt * @underrun: Whether the preview entity has queued buffers on the output diff --git a/drivers/media/video/omap3isp/ispqueue.h b/drivers/media/video/omap3isp/ispqueue.h index 251de3e1679d..92c5a12157d5 100644 --- a/drivers/media/video/omap3isp/ispqueue.h +++ b/drivers/media/video/omap3isp/ispqueue.h @@ -46,9 +46,9 @@ struct scatterlist; * device yet. * @ISP_BUF_STATE_ACTIVE: The buffer is in use for an active video transfer. * @ISP_BUF_STATE_ERROR: The device is done with the buffer and an error - * occured. For capture device the buffer likely contains corrupted data or + * occurred. For capture device the buffer likely contains corrupted data or * no data at all. - * @ISP_BUF_STATE_DONE: The device is done with the buffer and no error occured. + * @ISP_BUF_STATE_DONE: The device is done with the buffer and no error occurred. * For capture devices the buffer contains valid data. */ enum isp_video_buffer_state { diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c index 75d39b115d42..653f88ba56db 100644 --- a/drivers/media/video/omap3isp/ispresizer.c +++ b/drivers/media/video/omap3isp/ispresizer.c @@ -751,7 +751,7 @@ static void resizer_print_status(struct isp_res_device *res) * ratio will thus result in a resizing factor slightly larger than the * requested value. * - * To accomodate that, and make sure the TRM equations are satisfied exactly, we + * To accommodate that, and make sure the TRM equations are satisfied exactly, we * compute the input crop rectangle as the last step. * * As if the situation wasn't complex enough, the maximum output width depends @@ -1386,7 +1386,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd, * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @fmt : pointer to v4l2 subdev format structure - * return -EINVAL or zero on sucess + * return -EINVAL or zero on success */ static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c index a0bb5db9cb8a..208a7ec739d7 100644 --- a/drivers/media/video/omap3isp/ispvideo.c +++ b/drivers/media/video/omap3isp/ispvideo.c @@ -494,12 +494,12 @@ static const struct isp_video_queue_operations isp_video_queue_ops = { /* * omap3isp_video_buffer_next - Complete the current buffer and return the next * @video: ISP video object - * @error: Whether an error occured during capture + * @error: Whether an error occurred during capture * * Remove the current video buffer from the DMA queue and fill its timestamp, * field count and state fields before waking up its completion handler. * - * The buffer state is set to VIDEOBUF_DONE if no error occured (@error is 0) + * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0) * or VIDEOBUF_ERROR otherwise (@error is non-zero). * * The DMA queue is expected to contain at least one buffer. @@ -578,7 +578,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video, /* * omap3isp_video_resume - Perform resume operation on the buffers * @video: ISP video object - * @continuous: Pipeline is in single shot mode if 0 or continous mode otherwise + * @continuous: Pipeline is in single shot mode if 0 or continuous mode otherwise * * This function is intended to be used on suspend/resume scenario. It * requests video queue layer to discard buffers marked as DONE if it's in diff --git a/drivers/media/video/ov6650.c b/drivers/media/video/ov6650.c index fe8e3ebd9ce4..456d9ad9ae5a 100644 --- a/drivers/media/video/ov6650.c +++ b/drivers/media/video/ov6650.c @@ -1038,7 +1038,7 @@ static int ov6650_reset(struct i2c_client *client) ret = ov6650_reg_rmw(client, REG_COMA, COMA_RESET, 0); if (ret) dev_err(&client->dev, - "An error occured while entering soft reset!\n"); + "An error occurred while entering soft reset!\n"); return ret; } diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 53d88a2ab920..5173ac449dd8 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -273,7 +273,7 @@ static int ov9640_reset(struct i2c_client *client) ret = ov9640_reg_write(client, OV9640_COM7, OV9640_COM7_SCCB_RESET); if (ret) dev_err(&client->dev, - "An error occured while entering soft reset!\n"); + "An error occurred while entering soft reset!\n"); return ret; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c index aeed1c2945fb..9515f3a68f8f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c @@ -32,7 +32,7 @@ Read and analyze data in the eeprom. Use tveeprom to figure out the packet structure, since this is another Hauppauge device and - internally it has a family resemblence to ivtv-type devices + internally it has a family resemblance to ivtv-type devices */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 51d3009ab57f..d7753ae9ff46 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -75,7 +75,7 @@ enum pvr2_v4l_type { * (but it might still on the bus). In this state there's nothing we can * do; it must be replugged in order to recover. * - * COLD - Device is in an unusuable state, needs microcontroller firmware. + * COLD - Device is in an unusable state, needs microcontroller firmware. * * WARM - We can communicate with the device and the proper * microcontroller firmware is running, but other device initialization is diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 02686771740d..c1ee09a043ba 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -714,7 +714,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, * * The DMA chaining is done with DMA running. This means a tiny temporal window * remains, where a buffer is queued on the chain, while the chain is already - * stopped. This means the tailed buffer would never be transfered by DMA. + * stopped. This means the tailed buffer would never be transferred by DMA. * This function restarts the capture for this corner case, where : * - DADR() == DADDR_STOP * - a videobuffer is queued on the pcdev->capture list diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index 4d929a394521..4893b2d91d84 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c @@ -356,7 +356,7 @@ void fimc_hw_en_capture(struct fimc_ctx *ctx) /* one shot mode */ cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN; } else { - /* Continous frame capture mode (freerun). */ + /* Continuous frame capture mode (freerun). */ cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_CPT_FRMOD_CNT); cfg |= S5P_CIIMGCPT_IMGCPTEN; diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 61c6007c8ea6..50f1be05ebd3 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -7460,7 +7460,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3; break; default: - printk(KERN_ERR "%s Cant determine tuner type %x from EEPROM\n", dev->name, tuner_t); + printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t); } } else if ((data[1] != 0) && (data[1] != 0xff)) { /* new config structure */ @@ -7480,7 +7480,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) printk(KERN_INFO "%s Board has DVB-T\n", dev->name); break; default: - printk(KERN_ERR "%s Cant determine tuner type %x from EEPROM\n", dev->name, tuner_t); + printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t); } } else { printk(KERN_ERR "%s unexpected config structure\n", dev->name); diff --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/video/saa7164/saa7164-cmd.c index 6a4c217ed3a7..62fac7f9d04e 100644 --- a/drivers/media/video/saa7164/saa7164-cmd.c +++ b/drivers/media/video/saa7164/saa7164-cmd.c @@ -257,7 +257,7 @@ out: } /* Wait for a signal event, without holding a mutex. Either return TIMEOUT if - * the event never occured, or SAA_OK if it was signaled during the wait. + * the event never occurred, or SAA_OK if it was signaled during the wait. */ int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno) { diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c index b369300cce06..a266bf0169e6 100644 --- a/drivers/media/video/saa7164/saa7164-fw.c +++ b/drivers/media/video/saa7164/saa7164-fw.c @@ -444,7 +444,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) printk(KERN_INFO " .Reserved = 0x%x\n", hdr->reserved); printk(KERN_INFO " .Version = 0x%x\n", hdr->version); - /* Retreive bootloader if reqd */ + /* Retrieve bootloader if reqd */ if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) /* Second bootloader in the firmware file */ filesize = hdr->reserved * 16; diff --git a/drivers/media/video/saa7164/saa7164-types.h b/drivers/media/video/saa7164/saa7164-types.h index df1d2997fa6c..1d2140a3eb38 100644 --- a/drivers/media/video/saa7164/saa7164-types.h +++ b/drivers/media/video/saa7164/saa7164-types.h @@ -412,7 +412,7 @@ struct tmComResVBIFormatDescrHeader { u8 StartLine; /* NTSC Start = 10 */ u8 EndLine; /* NTSC = 21 */ u8 FieldRate; /* 60 for NTSC */ - u8 bNumLines; /* Unsed - scheduled for removal */ + u8 bNumLines; /* Unused - scheduled for removal */ } __attribute__((packed)); struct tmComResProbeCommit { diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index ce56a1cdbf0a..0e07c493e6f0 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1810,7 +1810,7 @@ static int sn9c102_open(struct file *filp) /* We will not release the "open_mutex" lock, so that only one process can be in the wait queue below. This way the process - will be sleeping while holding the lock, without loosing its + will be sleeping while holding the lock, without losing its priority after any wake_up(). */ err = wait_event_interruptible_exclusive(cam->wait_open, diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 7f38549715b6..3679970dba2c 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -180,7 +180,7 @@ struct sn9c102_sensor { It should be used to initialize the sensor only, but may also configure part of the SN9C1XX chip if necessary. You don't need to setup picture settings like brightness, contrast, etc.. here, if - the corrisponding controls are implemented (see below), since + the corresponding controls are implemented (see below), since they are adjusted in the core driver by calling the set_ctrl() method after init(), where the arguments are the default values specified in the v4l2_queryctrl list of supported controls; diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index 54681a535822..b6ee1bd342dc 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c @@ -493,7 +493,7 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s, int val, r; struct vcontrol *lvc; - /* exposure time is special, spread accross 2 registers */ + /* exposure time is special, spread across 2 registers */ if (vc->id == V4L2_CID_EXPOSURE) { int val_lower, val_upper; @@ -538,7 +538,7 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s, struct vcontrol *lvc; int val = vc->value; - /* exposure time is special, spread accross 2 registers */ + /* exposure time is special, spread across 2 registers */ if (vc->id == V4L2_CID_EXPOSURE) { int val_lower, val_upper; val_lower = val & TCM825X_MASK(TCM825X_ESRSPD_L); diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index a25e2b5e1944..c46a3bb95852 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1058,11 +1058,11 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TDA9875_MVR 0x1b /* Main volume droite */ #define TDA9875_MBA 0x1d /* Main Basse */ #define TDA9875_MTR 0x1e /* Main treble */ -#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ -#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ -#define TDA9875_AVR 0x21 /* Auxilary volume droite */ -#define TDA9875_ABA 0x22 /* Auxilary Basse */ -#define TDA9875_ATR 0x23 /* Auxilary treble */ +#define TDA9875_ACS 0x1f /* Auxiliary channel select (FM) 0b0000000*/ +#define TDA9875_AVL 0x20 /* Auxiliary volume gauche */ +#define TDA9875_AVR 0x21 /* Auxiliary volume droite */ +#define TDA9875_ABA 0x22 /* Auxiliary Basse */ +#define TDA9875_ATR 0x23 /* Auxiliary treble */ #define TDA9875_MSR 0x02 /* Monitor select register */ #define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 545c0294813d..fc766b9f24c5 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -394,11 +394,11 @@ int uvc_commit_video(struct uvc_streaming *stream, * * uvc_video_decode_end is called with header data at the end of a bulk or * isochronous payload. It performs any additional header data processing and - * returns 0 or a negative error code if an error occured. As header data have + * returns 0 or a negative error code if an error occurred. As header data have * already been processed by uvc_video_decode_start, this functions isn't * required to perform sanity checks a second time. * - * For isochronous transfers where a payload is always transfered in a single + * For isochronous transfers where a payload is always transferred in a single * URB, the three functions will be called in a row. * * To let the decoder process header data and update its internal state even @@ -658,7 +658,7 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, buf); } while (ret == -EAGAIN); - /* If an error occured skip the rest of the payload. */ + /* If an error occurred skip the rest of the payload. */ if (ret < 0 || buf == NULL) { stream->bulk.skip_payload = 1; } else { @@ -821,7 +821,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, return stream->urb_size / psize; /* Compute the number of packets. Bulk endpoints might transfer UVC - * payloads accross multiple URBs. + * payloads across multiple URBs. */ npackets = DIV_ROUND_UP(size, psize); if (npackets > UVC_MAX_PACKETS) diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index a01ed39e6c16..506edcc2ddeb 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -48,7 +48,7 @@ printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\ } while (0) -/* Zero out the end of the struct pointed to by p. Everthing after, but +/* Zero out the end of the struct pointed to by p. Everything after, but * not including, the specified field is cleared. */ #define CLEAR_AFTER_FIELD(p, field) \ memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \ diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 75301d10a838..ca372eb911d0 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -354,7 +354,7 @@ static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* Here we back up the input selection because it gets overwritten when we fill the registers with the - choosen video norm */ + chosen video norm */ temp_input = vpx3220_fp_read(sd, 0xf2); v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std); diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/video/zoran/videocodec.h index b654bfff8740..def55585ad23 100644 --- a/drivers/media/video/zoran/videocodec.h +++ b/drivers/media/video/zoran/videocodec.h @@ -57,7 +57,7 @@ therfor they may not be initialized. The other functions are just for convenience, as they are for sure used by - most/all of the codecs. The last ones may be ommited, too. + most/all of the codecs. The last ones may be omitted, too. See the structure declaration below for more information and which data has to be set up for the master and the slave. diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 4bb368e6fd47..f3f640014928 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -259,7 +259,7 @@ struct card_info { struct vfe_polarity vfe_pol; u8 gpio_pol[ZR_GPIO_MAX]; - /* is the /GWS line conected? */ + /* is the /GWS line connected? */ u8 gws_not_connected; /* avs6eyes mux setting */ diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 7c3921de9589..2771d818406e 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1254,7 +1254,7 @@ static int setup_overlay(struct zoran_fh *fh, int on) { struct zoran *zr = fh->zr; - /* If there is nothing to do, return immediatly */ + /* If there is nothing to do, return immediately */ if ((on && fh->overlay_active != ZORAN_FREE) || (!on && fh->overlay_active == ZORAN_FREE)) return 0; diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 57b42bfc7d23..4a1909a32b60 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -973,7 +973,7 @@ try_again: } /* Memory allocated for attributes by this function should be freed by - * mspro_block_data_clear, no matter if the initialization process succeded + * mspro_block_data_clear, no matter if the initialization process succeeded * or failed. */ static int mspro_block_read_attributes(struct memstick_dev *card) diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 700d420a59ac..668f5c6a0399 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -796,7 +796,7 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (memstick_add_host(host)) goto error7; - message("driver succesfully loaded"); + message("driver successfully loaded"); return 0; error7: free_irq(dev->irq, dev); diff --git a/drivers/memstick/host/r592.h b/drivers/memstick/host/r592.h index eee264e6028f..c5726c1e8832 100644 --- a/drivers/memstick/host/r592.h +++ b/drivers/memstick/host/r592.h @@ -43,12 +43,12 @@ /* Error detection via CRC */ #define R592_STATUS_SEND_ERR (1 << 24) /* Send failed */ -#define R592_STATUS_RECV_ERR (1 << 25) /* Recieve failed */ +#define R592_STATUS_RECV_ERR (1 << 25) /* Receive failed */ /* Card state */ -#define R592_STATUS_RDY (1 << 28) /* RDY signal recieved */ +#define R592_STATUS_RDY (1 << 28) /* RDY signal received */ #define R592_STATUS_CED (1 << 29) /* INT: Command done (serial mode)*/ -#define R592_STATUS_SFIFO_INPUT (1 << 30) /* Small fifo recieved data*/ +#define R592_STATUS_SFIFO_INPUT (1 << 30) /* Small fifo received data*/ #define R592_SFIFO_SIZE 32 /* total size of small fifo is 32 bytes */ #define R592_SFIFO_PACKET 8 /* packet size of small fifo */ diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h index face6e7acc72..03be8b217709 100644 --- a/drivers/message/fusion/lsi/mpi_log_fc.h +++ b/drivers/message/fusion/lsi/mpi_log_fc.h @@ -38,8 +38,8 @@ typedef enum _MpiIocLogInfoFc { MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000, MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */ - MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */ - MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */ + MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primitive */ + MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primitive */ MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */ MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */ diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 8b04810df469..f62960b5d527 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -56,9 +56,9 @@ #define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE (0x0003E000) /* Tried to upload from flash, but there is none */ #define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE (0x0003E001) /* ImageType field contents were invalid */ #define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */ -#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */ -#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED (0x0003E004) /* Error occured while attempting to upload single flash region */ -#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE (0x0003E005) /* Problem occured while DMAing FW to host memory */ +#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occurred while attempting to upload the entire flash */ +#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED (0x0003E004) /* Error occurred while attempting to upload single flash region */ +#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE (0x0003E005) /* Problem occurred while DMAing FW to host memory */ #define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */ @@ -187,8 +187,8 @@ #define PL_LOGINFO_SUB_CODE_BREAK_ON_INCOMPLETE_BREAK_RCVD (0x00005000) #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occurred on SMP Read */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occurred on SMP Write */ #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ @@ -207,8 +207,8 @@ #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ #define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ -#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ -#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transferring data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transferring sense data */ #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index ec8080c98081..fa15e853d4e8 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -3435,7 +3435,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) * If memory has already been allocated, the same (cached) value * is returned. * - * Return 0 if successfull, or non-zero for failure + * Return 0 if successful, or non-zero for failure **/ int mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) @@ -6932,7 +6932,7 @@ EXPORT_SYMBOL(mpt_halt_firmware); * Message Unit Reset - instructs the IOC to reset the Reply Post and * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded. * All posted buffers are freed, and event notification is turned off. - * IOC doesnt reply to any outstanding request. This will transfer IOC + * IOC doesn't reply to any outstanding request. This will transfer IOC * to READY state. **/ int @@ -7905,7 +7905,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) "Owner", /* 15h */ "Open Transmit DMA Abort", /* 16h */ "IO Device Missing Delay Retry", /* 17h */ - "IO Cancelled Due to Recieve Error", /* 18h */ + "IO Cancelled Due to Receive Error", /* 18h */ NULL, /* 19h */ NULL, /* 1Ah */ NULL, /* 1Bh */ diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 878bda0cce70..6e6e16aab9da 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -985,7 +985,7 @@ retry_wait: ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply; iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; if (iocstat == MPI_IOCSTATUS_SUCCESS) { - printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); + printk(MYIOC_s_INFO_FMT "F/W update successful!\n", iocp->name); return 0; } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) { printk(MYIOC_s_WARN_FMT "Hmmm... F/W download not supported!?!\n", @@ -2407,7 +2407,7 @@ done_free_mem: } /* mf is null if command issued successfully - * otherwise, failure occured after mf acquired. + * otherwise, failure occurred after mf acquired. */ if (mf) mpt_free_msg_frame(ioc, mf); diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index f5a14afad2cd..66f94125de4e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -307,7 +307,7 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } -/* free memory assoicated to a sas firmware event */ +/* free memory associated to a sas firmware event */ static void mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event) { @@ -1094,7 +1094,7 @@ mptsas_block_io_starget(struct scsi_target *starget) /** * mptsas_target_reset_queue * - * Receive request for TARGET_RESET after recieving an firmware + * Receive request for TARGET_RESET after receiving an firmware * event NOT_RESPONDING_EVENT, then put command in link list * and queue if task_queue already in use. * @@ -1403,7 +1403,7 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, /** * mptsas_add_end_device - report a new end device to sas transport layer * @ioc: Pointer to MPT_ADAPTER structure - * @phy_info: decribes attached device + * @phy_info: describes attached device * * return (0) success (1) failure * @@ -1481,7 +1481,7 @@ mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info) /** * mptsas_del_end_device - report a deleted end device to sas transport layer * @ioc: Pointer to MPT_ADAPTER structure - * @phy_info: decribes attached device + * @phy_info: describes attached device * **/ static void diff --git a/drivers/message/i2o/README b/drivers/message/i2o/README index 911fc3021e3b..f072a8eb3041 100644 --- a/drivers/message/i2o/README +++ b/drivers/message/i2o/README @@ -53,7 +53,7 @@ Symbios Logic (Now LSI) BoxHill Corporation Loan of initial FibreChannel disk array used for development work. -European Comission +European Commission Funding the work done by the University of Helsinki SysKonnect diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 0ee4264f5db7..4547db99f7da 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -65,7 +65,7 @@ int i2o_device_claim(struct i2o_device *dev) rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); if (!rc) - pr_debug("i2o: claim of device %d succeded\n", + pr_debug("i2o: claim of device %d succeeded\n", dev->lct_data.tid); else pr_debug("i2o: claim of device %d failed %d\n", @@ -110,7 +110,7 @@ int i2o_device_claim_release(struct i2o_device *dev) } if (!rc) - pr_debug("i2o: claim release of device %d succeded\n", + pr_debug("i2o: claim release of device %d succeeded\n", dev->lct_data.tid); else pr_debug("i2o: claim release of device %d failed %d\n", @@ -248,7 +248,7 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) goto unreg_dev; } - /* create user entries refering to this device */ + /* create user entries referring to this device */ list_for_each_entry(tmp, &c->devices, list) if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) && (tmp != i2o_dev)) { @@ -267,7 +267,7 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) goto rmlink1; } - /* create parent entries refering to this device */ + /* create parent entries referring to this device */ list_for_each_entry(tmp, &c->devices, list) if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) && (tmp != i2o_dev)) { diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 47ec5bc0ed21..643ad52e3ca2 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -610,7 +610,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) /* * This is to deail with the case of an application - * opening a device and then the device dissapears while + * opening a device and then the device disappears while * it's in use, and then the application tries to release * it. ex: Unmounting a deleted RAID volume at reboot. * If we send messages, it will just cause FAILs since @@ -717,7 +717,7 @@ static unsigned int i2o_block_check_events(struct gendisk *disk, /** * i2o_block_transfer - Transfer a request to/from the I2O controller - * @req: the request which should be transfered + * @req: the request which should be transferred * * This function converts the request into a I2O message. The necessary * DMA buffers are allocated and after everything is setup post the message diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index 67f921b4419b..cf8873cbca3f 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -73,7 +73,7 @@ struct i2o_block_device { struct i2o_device *i2o_dev; /* pointer to I2O device */ struct gendisk *gd; spinlock_t lock; /* queue lock */ - struct list_head open_queue; /* list of transfered, but unfinished + struct list_head open_queue; /* list of transferred, but unfinished requests */ unsigned int open_queue_depth; /* number of requests in the queue */ diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 97bdf82ec905..f003957e8e1c 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -204,7 +204,7 @@ static int i2o_scsi_remove(struct device *dev) * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it * @dev: device to verify if it is a I2O SCSI device * - * Retrieve channel, id and lun for I2O device. If everthing goes well + * Retrieve channel, id and lun for I2O device. If everything goes well * register the I2O device as SCSI device on the I2O SCSI controller. * * Returns 0 on success or negative error code on failure. diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index e2fea580585a..3ed3ff06be5d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -201,7 +201,7 @@ config TWL4030_POWER as clock request handshaking. This driver uses board-specific data to initialize the resources - and load scripts controling which resources are switched off/on + and load scripts controlling which resources are switched off/on or reset when a sleep, wakeup or warm reset event occurs. config TWL4030_CODEC diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index bc93b2e8230c..6421ad1160de 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -314,7 +314,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) /* wait for completion of conversion */ if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, 2*HZ)) { dev_err(gpadc->dev, - "timeout: didnt recieve GPADC conversion interrupt\n"); + "timeout: didn't receive GPADC conversion interrupt\n"); ret = -EINVAL; goto out; } diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index f2f4029e21a0..43a76c41cfcc 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -185,7 +185,7 @@ static void pcap_isr_work(struct work_struct *work) ezx_pcap_read(pcap, PCAP_REG_MSR, &msr); ezx_pcap_read(pcap, PCAP_REG_ISR, &isr); - /* We cant service/ack irqs that are assigned to port 2 */ + /* We can't service/ack irqs that are assigned to port 2 */ if (!(pdata->config & PCAP_SECOND_PORT)) { ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel); isr &= ~int_sel; @@ -457,7 +457,7 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi) pcap->workqueue = create_singlethread_workqueue("pcapd"); if (!pcap->workqueue) { ret = -ENOMEM; - dev_err(&spi->dev, "cant create pcap thread\n"); + dev_err(&spi->dev, "can't create pcap thread\n"); goto free_pcap; } diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index cb01209754e0..53450f433f10 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -332,7 +332,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) int i; if (!pdata) { - dev_err(dev, "Missing platfrom data\n"); + dev_err(dev, "Missing platform data\n"); ret = -ENOMEM; goto end_probe; } diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index c7687f6a78a0..57868416c760 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -51,7 +51,7 @@ static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data) } -/* Read a block of upto 32 regs */ +/* Read a block of up to 32 regs */ int pcf50633_read_block(struct pcf50633 *pcf, u8 reg, int nr_regs, u8 *data) { @@ -65,7 +65,7 @@ int pcf50633_read_block(struct pcf50633 *pcf, u8 reg, } EXPORT_SYMBOL_GPL(pcf50633_read_block); -/* Write a block of upto 32 regs */ +/* Write a block of up to 32 regs */ int pcf50633_write_block(struct pcf50633 *pcf , u8 reg, int nr_regs, u8 *data) { diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index fa937052fbab..dfbae34e1804 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c @@ -229,7 +229,7 @@ int twl6030_mmc_card_detect_config(void) twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK, REG_INT_MSK_STS_B); /* - * Intially Configuring MMC_CTRL for receving interrupts & + * Initially Configuring MMC_CTRL for receiving interrupts & * Card status on TWL6030 for MMC1 */ ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val, TWL6030_MMCCTRL); @@ -275,7 +275,7 @@ int twl6030_mmc_card_detect(struct device *dev, int slot) /* TWL6030 provide's Card detect support for * only MMC1 controller. */ - pr_err("Unkown MMC controller %d in %s\n", pdev->id, __func__); + pr_err("Unknown MMC controller %d in %s\n", pdev->id, __func__); return ret; } /* diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c index d73f84ba0f08..daf69527ed83 100644 --- a/drivers/mfd/ucb1400_core.c +++ b/drivers/mfd/ucb1400_core.c @@ -8,7 +8,7 @@ * Copyright: MontaVista Software, Inc. * * Spliting done by: Marek Vasut - * If something doesnt work and it worked before spliting, e-mail me, + * If something doesn't work and it worked before spliting, e-mail me, * dont bother Nicolas please ;-) * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c index ecd276ad6b19..5f898cb706a6 100644 --- a/drivers/misc/bmp085.c +++ b/drivers/misc/bmp085.c @@ -2,7 +2,7 @@ This driver supports the bmp085 digital barometric pressure and temperature sensor from Bosch Sensortec. The datasheet - is avaliable from their website: + is available from their website: http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf A pressure measurement is issued by reading from pressure0_input. @@ -429,7 +429,7 @@ static int __devinit bmp085_probe(struct i2c_client *client, if (err) goto exit_free; - dev_info(&data->client->dev, "Succesfully initialized bmp085!\n"); + dev_info(&data->client->dev, "Successfully initialized bmp085!\n"); goto exit; exit_free: diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c index 338dcc121507..778fc3fdfb9b 100644 --- a/drivers/misc/c2port/c2port-duramar2150.c +++ b/drivers/misc/c2port/c2port-duramar2150.c @@ -41,7 +41,7 @@ static void duramar2150_c2port_access(struct c2port_device *dev, int status) outb(v | (C2D | C2CK), DIR_PORT); else /* When access is "off" is important that both lines are set - * as inputs or hi-impedence */ + * as inputs or hi-impedance */ outb(v & ~(C2D | C2CK), DIR_PORT); mutex_unlock(&update_lock); diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h index 72acf5af7a2a..00dbf1d4373a 100644 --- a/drivers/misc/ibmasm/remote.h +++ b/drivers/misc/ibmasm/remote.h @@ -20,7 +20,7 @@ * * Author: Max Asböck * - * Orignally written by Pete Reynolds + * Originally written by Pete Reynolds */ #ifndef _IBMASM_REMOTE_H_ diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c index 727af07f1fbd..b1f4563be9ae 100644 --- a/drivers/misc/iwmc3200top/main.c +++ b/drivers/misc/iwmc3200top/main.c @@ -268,7 +268,7 @@ static void iwmct_irq_read_worker(struct work_struct *ws) LOG_INFO(priv, IRQ, "ACK barker arrived " "- starting FW download\n"); } else { /* REBOOT barker */ - LOG_INFO(priv, IRQ, "Recieved reboot barker: %x\n", barker); + LOG_INFO(priv, IRQ, "Received reboot barker: %x\n", barker); priv->barker = barker; if (barker & BARKER_DNLOAD_SYNC_MSK) { diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 27dc463097f3..74f16f167b8e 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -645,7 +645,7 @@ static int validate_simple_test(char *put_str) while (*chk_str != '\0' && *put_str != '\0') { /* If someone does a * to match the rest of the string, allow - * it, or stop if the recieved string is complete. + * it, or stop if the received string is complete. */ if (*put_str == '#' || *chk_str == '*') return 0; diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index 34749ee88dfa..9e9bddaa95ae 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c @@ -229,7 +229,7 @@ again: bid = blade_id < 0 ? uv_numa_blade_id() : blade_id; bs = gru_base[bid]; - /* Handle the case where migration occured while waiting for the sema */ + /* Handle the case where migration occurred while waiting for the sema */ down_read(&bs->bs_kgts_sema); if (blade_id < 0 && bid != uv_numa_blade_id()) { up_read(&bs->bs_kgts_sema); diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index 7a8b9068ea03..5c3ce2459675 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h @@ -379,7 +379,7 @@ struct gru_thread_state { required for contest */ char ts_cch_req_slice;/* CCH packet slice */ char ts_blade; /* If >= 0, migrate context if - ref from diferent blade */ + ref from different blade */ char ts_force_cch_reload; char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each allocated CB */ diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 9ee4c788aa69..b4488c8f6b23 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -649,7 +649,7 @@ static int kim_probe(struct platform_device *pdev) /* multiple devices could exist */ st_kim_devices[pdev->id] = pdev; } else { - /* platform's sure about existance of 1 device */ + /* platform's sure about existence of 1 device */ st_kim_devices[0] = pdev; } diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index f5cedeccad42..abc1a63bcc5e 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -292,7 +292,7 @@ static void mmc_test_free_mem(struct mmc_test_mem *mem) } /* - * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case + * Allocate a lot of memory, preferably max_sz but at least min_sz. In case * there isn't much memory do not exceed 1/16th total lowmem pages. Also do * not exceed a maximum number of segments and try not to make segments much * bigger than maximum segment size. diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 14e95f39a7bf..772d0d0a541b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -538,7 +538,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, /* * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF - * bit. This bit will be lost everytime after a reset or power off. + * bit. This bit will be lost every time after a reset or power off. */ if (card->ext_csd.enhanced_area_en) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 60842f878ded..f3b22bf89cc9 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -105,7 +105,7 @@ int mmc_go_idle(struct mmc_host *host) * that in case of hardware that won't pull up DAT3/nCS otherwise. * * SPI hosts ignore ios.chip_select; it's managed according to - * rules that must accomodate non-MMC slaves which this layer + * rules that must accommodate non-MMC slaves which this layer * won't even know about. */ if (!mmc_host_is_spi(host)) { diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index bb192f90e8e9..b3001617e67d 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -45,7 +45,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card) struct sdio_func *func = card->sdio_func[i - 1]; if (!func) { printk(KERN_WARNING "%s: pending IRQ for " - "non-existant function\n", + "non-existent function\n", mmc_card_id(card)); ret = -EINVAL; } else if (func->irq_handler) { diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 80bc9a5c25cc..ea3888b65d5d 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -127,7 +127,7 @@ struct atmel_mci_dma { * EVENT_DATA_COMPLETE is set in @pending_events, all data-related * interrupts must be disabled and @data_status updated with a * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the - * CMDRDY interupt must be disabled and @cmd_status updated with a + * CMDRDY interrupt must be disabled and @cmd_status updated with a * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the * bytes_xfered field of @data must be written. This is ensured by * using barriers. @@ -1082,7 +1082,7 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) /* * Update the MMC clock rate if necessary. This may be * necessary if set_ios() is called when a different slot is - * busy transfering data. + * busy transferring data. */ if (host->need_clock_update) { mci_writel(host, MR, host->mode_reg); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 2f7fc0c5146f..7c1e16aaf17f 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -99,7 +99,7 @@ #define r1b_timeout (HZ * 3) /* One of the critical speed parameters is the amount of data which may - * be transfered in one command. If this value is too low, the SD card + * be transferred in one command. If this value is too low, the SD card * controller has to do multiple partial block writes (argggh!). With * today (2008) SD cards there is little speed gain if we transfer more * than 64 KBytes at a time. So use this value until there is any indication diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 1ccd4b256cee..a04f87d7ee3d 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -874,7 +874,7 @@ static void finalize_request(struct s3cmci_host *host) if (!mrq->data) goto request_done; - /* Calulate the amout of bytes transfer if there was no error */ + /* Calculate the amout of bytes transfer if there was no error */ if (mrq->data->error == 0) { mrq->data->bytes_xfered = (mrq->data->blocks * mrq->data->blksz); @@ -882,7 +882,7 @@ static void finalize_request(struct s3cmci_host *host) mrq->data->bytes_xfered = 0; } - /* If we had an error while transfering data we flush the + /* If we had an error while transferring data we flush the * DMA channel and the fifo to clear out any garbage. */ if (mrq->data->error != 0) { if (s3cmci_host_usedma(host)) @@ -980,7 +980,7 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data) if ((data->blksz & 3) != 0) { /* We cannot deal with unaligned blocks with more than - * one block being transfered. */ + * one block being transferred. */ if (data->blocks > 1) { pr_warning("%s: can't do non-word sized block transfers (blksz %d)\n", __func__, data->blksz); diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 6ae8d2f00ec7..62d37de6de76 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -355,7 +355,7 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command /* * This chip always returns (at least?) as much data as you ask for. * I'm unsure what happens if you ask for less than a block. This should be - * looked into to ensure that a funny length read doesnt hose the controller. + * looked into to ensure that a funny length read doesn't hose the controller. */ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) { diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 7fca0a386ba0..62e5a4d171e1 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -484,7 +484,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host) /* * Check that we aren't being called after the - * entire buffer has been transfered. + * entire buffer has been transferred. */ if (host->num_sg == 0) return; @@ -828,7 +828,7 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq) /* * If this is a data transfer the request * will be finished after the data has - * transfered. + * transferred. */ if (cmd->data && !cmd->error) { /* @@ -904,7 +904,7 @@ static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) setup &= ~WBSD_DAT3_H; /* - * We cannot resume card detection immediatly + * We cannot resume card detection immediately * because of capacitance and delays in the chip. */ mod_timer(&host->ignore_timer, jiffies + HZ / 100); diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 35c6a23b183b..b1e3c26edd6d 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -19,7 +19,7 @@ config MTD_JEDECPROBE help This option enables JEDEC-style probing of flash chips which are not compatible with the Common Flash Interface, but will use the common - CFI-targetted flash drivers for any chips which are identified which + CFI-targeted flash drivers for any chips which are identified which are in fact compatible in all but the probe method. This actually covers most AMD/Fujitsu-compatible chips and also non-CFI Intel chips. diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 092aef11120c..09cb7c8d93b4 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1247,12 +1247,12 @@ static int inval_cache_and_wait_for_operation( break; if (chip->erase_suspended && chip_state == FL_ERASING) { - /* Erase suspend occured while sleep: reset timeout */ + /* Erase suspend occurred while sleep: reset timeout */ timeo = reset_timeo; chip->erase_suspended = 0; } if (chip->write_suspended && chip_state == FL_WRITING) { - /* Write suspend occured while sleep: reset timeout */ + /* Write suspend occurred while sleep: reset timeout */ timeo = reset_timeo; chip->write_suspended = 0; } diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index f9a5331e9445..0b49266840b9 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -263,7 +263,7 @@ static void fixup_old_sst_eraseregion(struct mtd_info *mtd) struct cfi_private *cfi = map->fldrv_priv; /* - * These flashes report two seperate eraseblock regions based on the + * These flashes report two separate eraseblock regions based on the * sector_erase-size and block_erase-size, although they both operate on the * same memory. This is not allowed according to CFI, so we just pick the * sector_erase-size. @@ -611,8 +611,8 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) * * Note that anything more complicated than checking if no bits are toggling * (including checking DQ5 for an error status) is tricky to get working - * correctly and is therefore not done (particulary with interleaved chips - * as each chip must be checked independantly of the others). + * correctly and is therefore not done (particularly with interleaved chips + * as each chip must be checked independently of the others). */ static int __xipram chip_ready(struct map_info *map, unsigned long addr) { @@ -635,8 +635,8 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) * * Note that anything more complicated than checking if no bits are toggling * (including checking DQ5 for an error status) is tricky to get working - * correctly and is therefore not done (particulary with interleaved chips - * as each chip must be checked independantly of the others). + * correctly and is therefore not done (particularly with interleaved chips + * as each chip must be checked independently of the others). * */ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 6ae3d111e1e7..8e464054a631 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -1,6 +1,6 @@ /* * Common Flash Interface support: - * Generic utility functions not dependant on command set + * Generic utility functions not dependent on command set * * Copyright (C) 2002 Red Hat * Copyright (C) 2003 STMicroelectronics Limited diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 4e1be51cc122..ea832ea0e4aa 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -2075,7 +2075,7 @@ static inline int jedec_match( uint32_t base, } /* - * Make sure the ID's dissappear when the device is taken out of + * Make sure the ID's disappear when the device is taken out of * ID mode. The only time this should fail when it should succeed * is when the ID's are written as data to the same * addresses. For this rare and unfortunate case the chip diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index f29a6f9df6e7..97183c8c9e33 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -295,7 +295,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) dev->mtd.owner = THIS_MODULE; if (add_mtd_device(&dev->mtd)) { - /* Device didnt get added, so free the entry */ + /* Device didn't get added, so free the entry */ goto devinit_err; } list_add(&dev->list, &blkmtd_device_list); diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 719b2915dc3a..8b36fa77a195 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -90,7 +90,7 @@ static inline int DoC_WaitReady(void __iomem * docptr) return ret; } -/* For some reason the Millennium Plus seems to occassionally put itself +/* For some reason the Millennium Plus seems to occasionally put itself * into reset mode. For me this happens randomly, with no pattern that I * can detect. M-systems suggest always check this on any block level * operation and setting to normal mode if in reset mode. diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index a99838bb2dc0..37ef29a73ee4 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c @@ -109,7 +109,7 @@ for(ci=(n)-1;ci >=0;ci--)\ of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for example the polynomial representation of @^5 would be given by the binary representation of the integer "alpha_to[5]". - Similarily, index_of[] can be used as follows: + Similarly, index_of[] can be used as follows: As above, let @ represent the primitive element of GF(2^m) that is the root of the primitive polynomial p(x). In order to find the power of @ (alpha) that has the polynomial representation @@ -121,7 +121,7 @@ for(ci=(n)-1;ci >=0;ci--)\ NOTE: The element alpha_to[2^m-1] = 0 always signifying that the representation of "@^infinity" = 0 is (0,0,0,...,0). - Similarily, the element index_of[0] = A0 always signifying + Similarly, the element index_of[0] = A0 always signifying that the power of alpha which has the polynomial representation (0,0,...,0) is "infinity". diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index caf604167f03..4b829f97d56c 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c @@ -353,7 +353,7 @@ static inline int erase_block (__u32 offset) /* put the flash back into command mode */ write32 (DATA_TO_FLASH (READ_ARRAY),offset); - /* was the erase successfull? */ + /* was the erase successful? */ if ((status & STATUS_ERASE_ERR)) { printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",module_name,offset); @@ -508,7 +508,7 @@ static inline int write_dword (__u32 offset,__u32 x) /* put the flash back into command mode */ write32 (DATA_TO_FLASH (READ_ARRAY),offset); - /* was the write successfull? */ + /* was the write successful? */ if ((status & STATUS_PGM_ERR) || read32 (offset) != x) { printk (KERN_WARNING "%s: write error at address 0x%.8x.\n",module_name,offset); diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index ef0aba0ce58f..41b8cdcc64cb 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -351,7 +351,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, * Fixup routines for the V370PDC * PCI device ID 0x020011b0 * - * This function basicly kick starts the DRAM oboard the card and gets it + * This function basically kick starts the DRAM oboard the card and gets it * ready to be used. Before this is done the device reads VERY erratic, so * much that it can crash the Linux 2.2.x series kernels when a user cat's * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL @@ -540,7 +540,7 @@ static u32 fixup_pmc551(struct pci_dev *dev) /* * Check to make certain the DEVSEL is set correctly, this device - * has a tendancy to assert DEVSEL and TRDY when a write is performed + * has a tendency to assert DEVSEL and TRDY when a write is performed * to the memory when memory is read-only */ if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) { diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index 04fdfcca93f7..12679925b420 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c @@ -3,7 +3,7 @@ * erase, lock/unlock support for LPDDR flash memories * (C) 2008 Korolev Alexey * (C) 2008 Vasiliy Leonenko - * Many thanks to Roman Borisov for intial enabling + * Many thanks to Roman Borisov for initial enabling * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -171,7 +171,7 @@ static int wait_for_ready(struct map_info *map, struct flchip *chip, mutex_lock(&chip->mutex); } if (chip->erase_suspended || chip->write_suspended) { - /* Suspend has occured while sleep: reset timeout */ + /* Suspend has occurred while sleep: reset timeout */ timeo = reset_timeo; chip->erase_suspended = chip->write_suspended = 0; } diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index e5f645b775ad..23f551dc8ca8 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c @@ -42,7 +42,7 @@ * * Please note: * 1. The flash size given should be the largest flash size that can - * be accomodated. + * be accommodated. * * 2. The bus width must defined in clps_setup_flash. * @@ -58,7 +58,7 @@ #define BOOT_PARTITION_SIZE_KiB (16) #define PARAMS_PARTITION_SIZE_KiB (8) #define KERNEL_PARTITION_SIZE_KiB (4*128) -/* Use both remaing portion of first flash, and all of second flash */ +/* Use both remaining portion of first flash, and all of second flash */ #define ROOT_PARTITION_SIZE_KiB (3*128) + (8*128) static struct mtd_partition ceiva_partitions[] = { diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index b4ed81611918..f71343cd77cc 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -33,7 +33,7 @@ /* We split the flash chip up into four parts. - * 1: bootloader firts 128k (0x00000000 - 0x0001FFFF) size 0x020000 + * 1: bootloader first 128k (0x00000000 - 0x0001FFFF) size 0x020000 * 2: kernel 640k (0x00020000 - 0x000BFFFF) size 0x0A0000 * 3: compressed 1536k root ramdisk (0x000C0000 - 0x0023FFFF) size 0x180000 * 4: writeable diskpartition (jffs)(0x00240000 - 0x003FFFFF) size 0x1C0000 diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 917022948399..6799e75d74e0 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -497,7 +497,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; /* Request a memory window for PCMCIA. Some architeures can map windows - * upto the maximum that PCMCIA can support (64MiB) - this is ideal and + * up to the maximum that PCMCIA can support (64MiB) - this is ideal and * we aim for a window the size of the whole card - otherwise we try * smaller windows until we succeed */ diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c index acb13fa5001c..64aea6acd48e 100644 --- a/drivers/mtd/maps/pmcmsp-flash.c +++ b/drivers/mtd/maps/pmcmsp-flash.c @@ -3,7 +3,7 @@ * Config with both CFI and JEDEC device support. * * Basically physmap.c with the addition of partitions and - * an array of mapping info to accomodate more than one flash type per board. + * an array of mapping info to accommodate more than one flash type per board. * * Copyright 2005-2007 PMC-Sierra, Inc. * diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index 85c1e56309ec..4d8aaaf4bb76 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -197,7 +197,7 @@ static void sc520cdp_setup_par(void) } /* - ** Find the PARxx registers that are reponsible for activating + ** Find the PARxx registers that are responsible for activating ** ROMCS0, ROMCS1 and BOOTCS. Reprogram each of these with a ** new value from the table. */ diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index c08e140d40ed..0718dfb3ee64 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c @@ -63,7 +63,7 @@ static void __iomem *start_scan_addr; */ #ifdef CONFIG_MTD_PARTITIONS -/* Currently, TQM8xxL has upto 8MiB flash */ +/* Currently, TQM8xxL has up to 8MiB flash */ static unsigned long tqm8xxl_max_flash_size = 0x00800000; /* partition definition for first flash bank diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 1e74ad961040..3326615ad66b 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -129,7 +129,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) return ret; /* - * Here we could argubly set the cache state to STATE_CLEAN. + * Here we could arguably set the cache state to STATE_CLEAN. * However this could lead to inconsistency since we will not * be notified if this content is altered on the flash by other * means. Let's declare it empty and leave buffering tasks to diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 145b3d0dc0db..4c36ef66a46b 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -234,7 +234,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t * the data. For our userspace tools it is important * to dump areas with ecc errors ! * For kernel internal usage it also might return -EUCLEAN - * to signal the caller that a bitflip has occured and has + * to signal the caller that a bitflip has occurred and has * been corrected by the ECC algorithm. * Userspace software which accesses NAND this way * must be aware of the fact that it deals with NAND diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index a92054e945e1..edec457d361d 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -239,7 +239,7 @@ config MTD_NAND_BCM_UMI help This enables the NAND flash controller on the BCM UMI block. - No board specfic support is done by this driver, each board + No board specific support is done by this driver, each board must advertise a platform_device for the driver to attach. config MTD_NAND_BCM_UMI_HWCS diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index a067d090cb31..bc65bf71e1a2 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -228,7 +228,7 @@ static int __devinit ams_delta_init(struct platform_device *pdev) AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP); - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(ams_delta_mtd, 1)) { err = -ENXIO; goto out_mtd; diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 7c95da1f612c..0911cf03db80 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -176,7 +176,7 @@ static int __init autcpu12_init(void) */ this->options = NAND_USE_FLASH_BBT; - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(autcpu12_mtd, 1)) { err = -ENXIO; goto out_ior; diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 9f1b451005ca..71c35a0b9826 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -241,7 +241,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) /* Enable the following for a flash based bad block table */ this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(new_mtd, 1)) { err = -ENXIO; goto out_ior; diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 8c8d3c86c0e8..4633f094c510 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -724,7 +724,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) } /* This helper function setups the registers for ECC and whether or not - * the spare area will be transfered. */ + * the spare area will be transferred. */ static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, bool transfer_spare) { @@ -965,7 +965,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, if (ECC_ERROR_CORRECTABLE(err_correction_info)) { /* If err_byte is larger than ECC_SECTOR_SIZE, - * means error happend in OOB, so we ignore + * means error happened in OOB, so we ignore * it. It's no need for us to correct it * err_device is represented the NAND error * bits are happened in if there are more @@ -1109,7 +1109,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, } /* This is the callback that the NAND core calls to write a page without ECC. - * raw access is similiar to ECC page writes, so all the work is done in the + * raw access is similar to ECC page writes, so all the work is done in the * write_page() function above. */ static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index b7f8de7b2780..96c0b34ba8db 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -137,7 +137,7 @@ static struct rs_control *rs_decoder; * * Fabrice Bellard figured this out in the old docecc code. I added * some comments, improved a minor bit and converted it to make use - * of the generic Reed-Solomon libary. tglx + * of the generic Reed-Solomon library. tglx */ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) { @@ -400,7 +400,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - /* We cant' use dev_ready here, but at least we wait for the + /* We can't' use dev_ready here, but at least we wait for the * command to complete */ udelay(50); @@ -986,7 +986,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, dummy = ReadDOC(docptr, ECCConf); } - /* Error occured ? */ + /* Error occurred ? */ if (dummy & 0x80) { for (i = 0; i < 6; i++) { if (DoC_is_MillenniumPlus(doc)) @@ -1160,7 +1160,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio /* NOTE: The lines below modify internal variables of the NAND and MTD layers; variables with have already been configured by nand_scan. Unfortunately, we didn't know before this point what these values - should be. Thus, this code is somewhat dependant on the exact + should be. Thus, this code is somewhat dependent on the exact implementation of the NAND layer. */ if (mh->UnitSizeFactor != 0xff) { this->bbt_erase_shift += (0xff - mh->UnitSizeFactor); diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 7a13d42cbabd..537e380b8dcb 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -59,7 +59,7 @@ struct fsl_elbc_mtd { unsigned int fmr; /* FCM Flash Mode Register value */ }; -/* Freescale eLBC FCM controller infomation */ +/* Freescale eLBC FCM controller information */ struct fsl_elbc_fcm_ctrl { struct nand_hw_control controller; diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 205b10b9f9b9..0d45ef3883e8 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -335,7 +335,7 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) /* * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by - * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction upto + * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to * max of 8-bits) */ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, @@ -381,7 +381,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, /* * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by - * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction upto + * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to * max of 1-bit) */ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, @@ -408,10 +408,10 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, * @buf: buffer to store read data * @page: page number to read * - * This routine is needed for fsmc verison 8 as reading from NAND chip has to be + * This routine is needed for fsmc version 8 as reading from NAND chip has to be * performed in a strict sequence as follows: * data(512 byte) -> ecc(13 byte) - * After this read, fsmc hardware generates and reports error data bits(upto a + * After this read, fsmc hardware generates and reports error data bits(up to a * max of 8 bits) */ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, @@ -686,7 +686,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) } /* - * Scan to find existance of the device + * Scan to find existence of the device */ if (nand_scan_ident(&host->mtd, 1, NULL)) { ret = -ENXIO; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 85cfc061d41c..c54a4cbac6bc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1582,7 +1582,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } /** - * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc + * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc * @mtd: MTD device structure * @from: offset to read from * @len: number of bytes to read diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index a1e8b30078d9..af46428286fe 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -945,7 +945,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc rd2 = NULL; /* Per chip or per device ? */ chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; - /* Mirrored table avilable ? */ + /* Mirrored table available ? */ if (md) { if (td->pages[i] == -1 && md->pages[i] == -1) { writeops = 0x03; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 213181be0d9a..893d95bfea48 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -162,7 +162,7 @@ MODULE_PARM_DESC(bitflips, "Maximum number of random bit flips per page (z MODULE_PARM_DESC(gravepages, "Pages that lose data [: maximum reads (defaults to 3)]" " separated by commas e.g. 1401:2 means page 1401" " can be read only twice before failing"); -MODULE_PARM_DESC(rptwear, "Number of erases inbetween reporting wear, if not zero"); +MODULE_PARM_DESC(rptwear, "Number of erases between reporting wear, if not zero"); MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. " "The size is specified in erase blocks and as the exponent of a power of two" " e.g. 5 means a size of 32 erase blocks"); diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c index 8c0b69375224..a045a4a581b6 100644 --- a/drivers/mtd/nand/nomadik_nand.c +++ b/drivers/mtd/nand/nomadik_nand.c @@ -151,7 +151,7 @@ static int nomadik_nand_probe(struct platform_device *pdev) nand->options = pdata->options; /* - * Scan to find existance of the device + * Scan to find existence of the device */ if (nand_scan(&host->mtd, 1)) { ret = -ENXIO; diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 59efa829ef24..20bfe5f15afd 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -157,7 +157,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) /* Enable the following for a flash based bad block table */ chip->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(pasemi_nand_mtd, 1)) { err = -ENXIO; goto out_lpc; diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 317aff428e42..caf5a736340a 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -95,7 +95,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) goto out; } - /* Scan to find existance of the device */ + /* Scan to find existence of the device */ if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { err = -ENXIO; goto out; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index ab7f4c33ced6..ff0701276d65 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -184,7 +184,7 @@ struct pxa3xx_nand_info { static int use_dma = 1; module_param(use_dma, bool, 0444); -MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); +MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW"); /* * Default NAND flash controller configuration setup by the diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 6322d1fb5d62..cae2e013c986 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -185,7 +185,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) dbg_verbose("doing dma %s ", do_read ? "read" : "write"); - /* Set intial dma state: for reading first fill on board buffer, + /* Set initial dma state: for reading first fill on board buffer, from device, for writes first fill the buffer from memory*/ dev->dma_state = do_read ? DMA_INTERNAL : DMA_MEMORY; @@ -766,7 +766,7 @@ static irqreturn_t r852_irq(int irq, void *data) ret = IRQ_HANDLED; dev->card_detected = !!(card_status & R852_CARD_IRQ_INSERT); - /* we shouldn't recieve any interrupts if we wait for card + /* we shouldn't receive any interrupts if we wait for card to settle */ WARN_ON(dev->card_unstable); @@ -794,13 +794,13 @@ static irqreturn_t r852_irq(int irq, void *data) ret = IRQ_HANDLED; if (dma_status & R852_DMA_IRQ_ERROR) { - dbg("recieved dma error IRQ"); + dbg("received dma error IRQ"); r852_dma_done(dev, -EIO); complete(&dev->dma_done); goto out; } - /* recieved DMA interrupt out of nowhere? */ + /* received DMA interrupt out of nowhere? */ WARN_ON_ONCE(dev->dma_stage == 0); if (dev->dma_stage == 0) @@ -960,7 +960,7 @@ int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) &dev->card_detect_work, 0); - printk(KERN_NOTICE DRV_NAME ": driver loaded succesfully\n"); + printk(KERN_NOTICE DRV_NAME ": driver loaded successfully\n"); return 0; error10: diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 546c2f0eb2e8..81bbb5ee148d 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -78,7 +78,7 @@ static void start_translation(struct sh_flctl *flctl) static void timeout_error(struct sh_flctl *flctl, const char *str) { - dev_err(&flctl->pdev->dev, "Timeout occured in %s\n", str); + dev_err(&flctl->pdev->dev, "Timeout occurred in %s\n", str); } static void wait_completion(struct sh_flctl *flctl) diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index 4a8f367c295c..57cc80cd01a3 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c @@ -121,7 +121,7 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia) if (ret) return ret; - /* Bad block marker postion */ + /* Bad block marker position */ chip->badblockpos = 0x05; chip->badblockbits = 7; chip->block_markbad = sm_block_markbad; diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 38fb16771f85..14c578707824 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -4,7 +4,7 @@ * Slightly murky pre-git history of the driver: * * Copyright (c) Ian Molton 2004, 2005, 2008 - * Original work, independant of sharps code. Included hardware ECC support. + * Original work, independent of sharps code. Included hardware ECC support. * Hard ECC did not work for writes in the early revisions. * Copyright (c) Dirk Opfer 2005. * Modifications developed from sharps code but diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index f591f615d3f6..1fcb41adab07 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -608,7 +608,7 @@ static int omap2_onenand_enable(struct mtd_info *mtd) ret = regulator_enable(c->regulator); if (ret != 0) - dev_err(&c->pdev->dev, "cant enable regulator\n"); + dev_err(&c->pdev->dev, "can't enable regulator\n"); return ret; } @@ -620,7 +620,7 @@ static int omap2_onenand_disable(struct mtd_info *mtd) ret = regulator_disable(c->regulator); if (ret != 0) - dev_err(&c->pdev->dev, "cant disable regulator\n"); + dev_err(&c->pdev->dev, "can't disable regulator\n"); return ret; } diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c index 8b246061d511..5ef3bd547772 100644 --- a/drivers/mtd/onenand/onenand_sim.c +++ b/drivers/mtd/onenand/onenand_sim.c @@ -321,7 +321,7 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, continue; if (memcmp(dest + off, ffchars, this->subpagesize) && onenand_check_overwrite(dest + off, src + off, this->subpagesize)) - printk(KERN_ERR "over-write happend at 0x%08x\n", offset); + printk(KERN_ERR "over-write happened at 0x%08x\n", offset); memcpy(dest + off, src + off, this->subpagesize); } /* Fall through */ @@ -335,7 +335,7 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, dest = ONENAND_CORE_SPARE(flash, this, offset); if (memcmp(dest, ffchars, mtd->oobsize) && onenand_check_overwrite(dest, src, mtd->oobsize)) - printk(KERN_ERR "OOB: over-write happend at 0x%08x\n", + printk(KERN_ERR "OOB: over-write happened at 0x%08x\n", offset); memcpy(dest, src, mtd->oobsize); break; diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 2b0daae4018d..ed3d6cd2c6dc 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -540,7 +540,7 @@ static int sm_check_block(struct sm_ftl *ftl, int zone, int block) return -EIO; } - /* If the block is sliced (partialy erased usually) erase it */ + /* If the block is sliced (partially erased usually) erase it */ if (i == 2) { sm_erase_block(ftl, zone, block, 1); return 1; @@ -878,7 +878,7 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) return 0; } -/* Get and automaticly initialize an FTL mapping for one zone */ +/* Get and automatically initialize an FTL mapping for one zone */ struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num) { struct ftl_zone *zone; diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 11eb8ef12485..d2d12ab7def4 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -968,7 +968,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, * contains garbage because of a power cut during erase * operation. So we just schedule this PEB for erasure. * - * Besides, in case of NOR flash, we deliberatly + * Besides, in case of NOR flash, we deliberately * corrupt both headers because NOR flash erasure is * slow and can start from the end. */ diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 9e1c03eb97ae..5420f6de27df 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -399,7 +399,7 @@ static void el_timeout(struct net_device *dev) * as we may still be attempting to retrieve the last RX packet buffer. * * When a transmit times out we dump the card into control mode and just - * start again. It happens enough that it isnt worth logging. + * start again. It happens enough that it isn't worth logging. * * We avoid holding the spin locks when doing the packet load to the board. * The device is very slow, and its DMA mode is even slower. If we held the @@ -499,7 +499,7 @@ static netdev_tx_t el_start_xmit(struct sk_buff *skb, struct net_device *dev) * * Handle the ether interface interrupts. The 3c501 needs a lot more * hand holding than most cards. In particular we get a transmit interrupt - * with a collision error because the board firmware isnt capable of rewinding + * with a collision error because the board firmware isn't capable of rewinding * its own transmit buffer pointers. It can however count to 16 for us. * * On the receive side the card is also very dumb. It has no buffering to @@ -732,7 +732,7 @@ static void el_receive(struct net_device *dev) * el_reset: Reset a 3c501 card * @dev: The 3c501 card about to get zapped * - * Even resetting a 3c501 isnt simple. When you activate reset it loses all + * Even resetting a 3c501 isn't simple. When you activate reset it loses all * its configuration. You must hold the lock when doing this. The function * cannot take the lock itself as it is callable from the irq handler. */ diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index de579d043169..bc0d1a1c2e28 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -44,7 +44,7 @@ this for the 64K version would require a lot of heinous bank switching, which I'm sure not interested in doing. If you try to implement a bank switching version, you'll basically have to remember - what bank is enabled and do a switch everytime you access a memory + what bank is enabled and do a switch every time you access a memory location that's not current. You'll also have to remap pointers on the driver side, because it only knows about 16K of the memory. Anyone desperate or masochistic enough to try? diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 8c094bae8bf3..d9d056d207f3 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -51,7 +51,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter tx_csm != ap->tx_ret_csm) { printk(KERN_WARNING "%s: Transmitter is stuck, %08x\n", @@ -2564,7 +2564,7 @@ restart: /* * A TX-descriptor producer (an IRQ) might have gotten - * inbetween, making the ring free again. Since xmit is + * between, making the ring free again. Since xmit is * serialized, this is the only situation we have to * re-test. */ diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 2ca880b4c0db..88495c48a81d 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1398,7 +1398,7 @@ static void amd8111e_set_multicast_list(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0; lp->options &= ~OPTION_MULTICAST_ENABLE; amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF); - /* disable promiscous mode */ + /* disable promiscuous mode */ writel(PROM, lp->mmio + CMD2); return; } diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index f4744fc89768..65a78f965dd2 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -133,7 +133,7 @@ struct net_local { /* Run-time register bank 2 definitions. */ #define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */ #define TX_START 10 -#define COL16CNTL 11 /* Controll Reg for 16 collisions */ +#define COL16CNTL 11 /* Control Reg for 16 collisions */ #define MODE13 13 #define RX_CTRL 14 /* Configuration registers only on the '865A/B chips. */ diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 1ff001a8270c..b0a71e2f28a9 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -2509,7 +2509,7 @@ static struct pci_driver atl1e_driver = { .id_table = atl1e_pci_tbl, .probe = atl1e_probe, .remove = __devexit_p(atl1e_remove), - /* Power Managment Hooks */ + /* Power Management Hooks */ #ifdef CONFIG_PM .suspend = atl1e_suspend, .resume = atl1e_resume, diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index e637e9f28fd4..f46ee4546fdc 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1701,7 +1701,7 @@ static struct pci_driver atl2_driver = { .id_table = atl2_pci_tbl, .probe = atl2_probe, .remove = __devexit_p(atl2_remove), - /* Power Managment Hooks */ + /* Power Management Hooks */ .suspend = atl2_suspend, #ifdef CONFIG_PM .resume = atl2_resume, diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index e94a966af418..c48104b08861 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -597,7 +597,7 @@ static int bcm_enet_set_mac_address(struct net_device *dev, void *p) } /* - * Change rx mode (promiscous/allmulti) and update multicast list + * Change rx mode (promiscuous/allmulti) and update multicast list */ static void bcm_enet_set_multicast_list(struct net_device *dev) { diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 5a4a87e7c5ea..1e2d825bb94a 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1331,7 +1331,7 @@ err: /* * Uses MCC for this command as it may be called in BH context - * (mc == NULL) => multicast promiscous + * (mc == NULL) => multicast promiscuous */ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, struct net_device *netdev, struct be_dma_mem *mem) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a71163f1e34b..9a54c8b24ff9 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -708,7 +708,7 @@ static void be_set_multicast_list(struct net_device *netdev) goto done; } - /* BE was previously in promiscous mode; disable it */ + /* BE was previously in promiscuous mode; disable it */ if (adapter->promiscuous) { adapter->promiscuous = false; be_cmd_promiscuous_config(adapter, adapter->port_num, 0); diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h index 806b224a4c63..6cb89692f5c1 100644 --- a/drivers/net/bna/bna_hw.h +++ b/drivers/net/bna/bna_hw.h @@ -897,7 +897,7 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \ * Catapult RSS Table Base Offset Address * * Exists in RAD memory space. - * Each entry is 352 bits, but alligned on + * Each entry is 352 bits, but aligned on * 64 byte (512 bit) boundary. Accessed * 4 byte words, the whole entry can be * broken into 11 word accesses. diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index b7ff87b35fbb..e0fca701d2f3 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1220,7 +1220,7 @@ struct bnx2x { struct bnx2x_dcbx_port_params dcbx_port_params; int dcb_version; - /* DCBX Negotation results */ + /* DCBX Negotiation results */ struct dcbx_features dcbx_local_feat; u32 dcbx_error; u32 pending_max; diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index be503cc0a50b..dac1bf9cbbfa 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h @@ -3019,7 +3019,7 @@ struct tstorm_eth_mac_filter_config { /* - * common flag to indicate existance of TPA. + * common flag to indicate existence of TPA. */ struct tstorm_eth_tpa_exist { #if defined(__BIG_ENDIAN) diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index f2f367d4e74d..974ef2be36a5 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -2823,7 +2823,7 @@ static u16 bnx2x_wait_reset_complete(struct bnx2x *bp, struct link_params *params) { u16 cnt, ctrl; - /* Wait for soft reset to get cleared upto 1 sec */ + /* Wait for soft reset to get cleared up to 1 sec */ for (cnt = 0; cnt < 1000; cnt++) { bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl); @@ -4141,7 +4141,7 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, val = (1<<5); /* * Note that 2.5G works only when used with 1G - * advertisment + * advertisement */ } else val = (1<<5); @@ -4151,7 +4151,7 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) val |= (1<<7); - /* Note that 2.5G works only when used with 1G advertisment */ + /* Note that 2.5G works only when used with 1G advertisement */ if (phy->speed_cap_mask & (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) @@ -5232,14 +5232,14 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1); } else { - /* Force 1Gbps using autoneg with 1G advertisment */ + /* Force 1Gbps using autoneg with 1G advertisement */ /* Allow CL37 through CL73 */ DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n"); bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c); - /* Enable Full-Duplex advertisment on CL37 */ + /* Enable Full-Duplex advertisement on CL37 */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020); /* Enable CL37 AN */ @@ -6269,7 +6269,7 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, switch (actual_phy_selection) { case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: - /* Do nothing. Essentialy this is like the priority copper */ + /* Do nothing. Essentially this is like the priority copper */ break; case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER; @@ -7765,7 +7765,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); msleep(10); - /* The PHY reset is controled by GPIO 1 + /* The PHY reset is controlled by GPIO 1 * Hold it as vars low */ /* clear link led */ diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 32e64cc85d2c..a97a4a1c344f 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -3702,7 +3702,7 @@ static void bnx2x_eq_int(struct bnx2x *bp) if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE) hw_cons++; - /* This function may never run in parralel with itself for a + /* This function may never run in parallel with itself for a * specific bp, thus there is no need in "paired" read memory * barrier here. */ @@ -5089,7 +5089,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) /* Step 1: set zeroes to all ilt page entries with valid bit on * Step 2: set the timers first/last ilt entry to point * to the entire range to prevent ILT range error for 3rd/4th - * vnic (this code assumes existance of the vnic) + * vnic (this code assumes existence of the vnic) * * both steps performed by call to bnx2x_ilt_client_init_op() * with dummy TM client @@ -8685,7 +8685,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) E1H_FUNC_MAX * sizeof(struct drv_func_mb); /* * get mf configuration: - * 1. existance of MF configuration + * 1. existence of MF configuration * 2. MAC address must be legal (check only upper bytes) * for Switch-Independent mode; * OVLAN must be legal for Switch-Dependent mode @@ -8727,7 +8727,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) default: /* Unknown configuration: reset mf_config */ bp->mf_config[vn] = 0; - DP(NETIF_MSG_PROBE, "Unkown MF mode 0x%x\n", + DP(NETIF_MSG_PROBE, "Unknown MF mode 0x%x\n", val); } } @@ -9777,7 +9777,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, #endif - /* Configure interupt mode: try to enable MSI-X/MSI if + /* Configure interrupt mode: try to enable MSI-X/MSI if * needed, set bp->num_queues appropriately. */ bnx2x_set_int_mode(bp); diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 1c89f19a4425..1509a2318af9 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h @@ -175,9 +175,9 @@ the initial credit value; read returns the current value of the credit counter. Must be initialized to 1 at start-up. */ #define CCM_REG_CFC_INIT_CRD 0xd0204 -/* [RW 2] Auxillary counter flag Q number 1. */ +/* [RW 2] Auxiliary counter flag Q number 1. */ #define CCM_REG_CNT_AUX1_Q 0xd00c8 -/* [RW 2] Auxillary counter flag Q number 2. */ +/* [RW 2] Auxiliary counter flag Q number 2. */ #define CCM_REG_CNT_AUX2_Q 0xd00cc /* [RW 28] The CM header value for QM request (primary). */ #define CCM_REG_CQM_CCM_HDR_P 0xd008c @@ -457,13 +457,13 @@ #define CSDM_REG_AGG_INT_MODE_9 0xc21dc /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */ #define CSDM_REG_CFC_RSP_START_ADDR 0xc2008 -/* [RW 16] The maximum value of the competion counter #0 */ +/* [RW 16] The maximum value of the completion counter #0 */ #define CSDM_REG_CMP_COUNTER_MAX0 0xc201c -/* [RW 16] The maximum value of the competion counter #1 */ +/* [RW 16] The maximum value of the completion counter #1 */ #define CSDM_REG_CMP_COUNTER_MAX1 0xc2020 -/* [RW 16] The maximum value of the competion counter #2 */ +/* [RW 16] The maximum value of the completion counter #2 */ #define CSDM_REG_CMP_COUNTER_MAX2 0xc2024 -/* [RW 16] The maximum value of the competion counter #3 */ +/* [RW 16] The maximum value of the completion counter #3 */ #define CSDM_REG_CMP_COUNTER_MAX3 0xc2028 /* [RW 13] The start address in the internal RAM for the completion counters. */ @@ -851,7 +851,7 @@ #define IGU_REG_ATTN_MSG_ADDR_L 0x130120 /* [R 4] Debug: [3] - attention write done message is pending (0-no pending; * 1-pending). [2:0] = PFID. Pending means attention message was sent; but - * write done didnt receive. */ + * write done didn't receive. */ #define IGU_REG_ATTN_WRITE_DONE_PENDING 0x130030 #define IGU_REG_BLOCK_CONFIGURATION 0x130000 #define IGU_REG_COMMAND_REG_32LSB_DATA 0x130124 @@ -862,7 +862,7 @@ #define IGU_REG_CSTORM_TYPE_0_SB_CLEANUP 0x130200 /* [R 5] Debug: ctrl_fsm */ #define IGU_REG_CTRL_FSM 0x130064 -/* [R 1] data availble for error memory. If this bit is clear do not red +/* [R 1] data available for error memory. If this bit is clear do not red * from error_handling_memory. */ #define IGU_REG_ERROR_HANDLING_DATA_VALID 0x130130 /* [RW 11] Parity mask register #0 read/write */ @@ -3015,7 +3015,7 @@ block. Should be used for close the gates. */ #define PXP_REG_HST_DISCARD_DOORBELLS 0x1030a4 /* [R 1] debug only: '1' means this PSWHST is discarding doorbells. This bit - should update accoring to 'hst_discard_doorbells' register when the state + should update according to 'hst_discard_doorbells' register when the state machine is idle */ #define PXP_REG_HST_DISCARD_DOORBELLS_STATUS 0x1030a0 /* [RW 1] When 1; new internal writes arriving to the block are discarded. @@ -3023,7 +3023,7 @@ #define PXP_REG_HST_DISCARD_INTERNAL_WRITES 0x1030a8 /* [R 6] debug only: A bit mask for all PSWHST internal write clients. '1' means this PSWHST is discarding inputs from this client. Each bit should - update accoring to 'hst_discard_internal_writes' register when the state + update according to 'hst_discard_internal_writes' register when the state machine is idle. */ #define PXP_REG_HST_DISCARD_INTERNAL_WRITES_STATUS 0x10309c /* [WB 160] Used for initialization of the inbound interrupts memory */ @@ -3822,13 +3822,13 @@ #define TSDM_REG_AGG_INT_T_1 0x420bc /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */ #define TSDM_REG_CFC_RSP_START_ADDR 0x42008 -/* [RW 16] The maximum value of the competion counter #0 */ +/* [RW 16] The maximum value of the completion counter #0 */ #define TSDM_REG_CMP_COUNTER_MAX0 0x4201c -/* [RW 16] The maximum value of the competion counter #1 */ +/* [RW 16] The maximum value of the completion counter #1 */ #define TSDM_REG_CMP_COUNTER_MAX1 0x42020 -/* [RW 16] The maximum value of the competion counter #2 */ +/* [RW 16] The maximum value of the completion counter #2 */ #define TSDM_REG_CMP_COUNTER_MAX2 0x42024 -/* [RW 16] The maximum value of the competion counter #3 */ +/* [RW 16] The maximum value of the completion counter #3 */ #define TSDM_REG_CMP_COUNTER_MAX3 0x42028 /* [RW 13] The start address in the internal RAM for the completion counters. */ @@ -4284,13 +4284,13 @@ #define USDM_REG_AGG_INT_T_6 0xc40d0 /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */ #define USDM_REG_CFC_RSP_START_ADDR 0xc4008 -/* [RW 16] The maximum value of the competion counter #0 */ +/* [RW 16] The maximum value of the completion counter #0 */ #define USDM_REG_CMP_COUNTER_MAX0 0xc401c -/* [RW 16] The maximum value of the competion counter #1 */ +/* [RW 16] The maximum value of the completion counter #1 */ #define USDM_REG_CMP_COUNTER_MAX1 0xc4020 -/* [RW 16] The maximum value of the competion counter #2 */ +/* [RW 16] The maximum value of the completion counter #2 */ #define USDM_REG_CMP_COUNTER_MAX2 0xc4024 -/* [RW 16] The maximum value of the competion counter #3 */ +/* [RW 16] The maximum value of the completion counter #3 */ #define USDM_REG_CMP_COUNTER_MAX3 0xc4028 /* [RW 13] The start address in the internal RAM for the completion counters. */ @@ -4798,13 +4798,13 @@ #define XSDM_REG_AGG_INT_MODE_1 0x1661bc /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */ #define XSDM_REG_CFC_RSP_START_ADDR 0x166008 -/* [RW 16] The maximum value of the competion counter #0 */ +/* [RW 16] The maximum value of the completion counter #0 */ #define XSDM_REG_CMP_COUNTER_MAX0 0x16601c -/* [RW 16] The maximum value of the competion counter #1 */ +/* [RW 16] The maximum value of the completion counter #1 */ #define XSDM_REG_CMP_COUNTER_MAX1 0x166020 -/* [RW 16] The maximum value of the competion counter #2 */ +/* [RW 16] The maximum value of the completion counter #2 */ #define XSDM_REG_CMP_COUNTER_MAX2 0x166024 -/* [RW 16] The maximum value of the competion counter #3 */ +/* [RW 16] The maximum value of the completion counter #3 */ #define XSDM_REG_CMP_COUNTER_MAX3 0x166028 /* [RW 13] The start address in the internal RAM for the completion counters. */ diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index 118c28aa471e..b3bc7502868f 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -76,7 +76,7 @@ struct tlb_client_info { */ u32 tx_bytes; /* Each Client acumulates the BytesTx that * were tranmitted to it, and after each - * CallBack the LoadHistory is devided + * CallBack the LoadHistory is divided * by the balance interval */ u32 load_history; /* This field contains the amount of Bytes diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c index 80511167f35b..731aa1193770 100644 --- a/drivers/net/caif/caif_shmcore.c +++ b/drivers/net/caif/caif_shmcore.c @@ -591,7 +591,7 @@ int caif_shmcore_probe(struct shmdev_layer *pshm_dev) (NR_TX_BUF * TX_BUF_SZ + NR_RX_BUF * RX_BUF_SZ)) { pr_warn("ERROR, Amount of available" - " Phys. SHM cannot accomodate current SHM " + " Phys. SHM cannot accommodate current SHM " "driver configuration, Bailing out ...\n"); free_netdev(pshm_dev->pshm_netdev); return -ENOMEM; diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 20da1996d354..57e639373815 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -397,7 +397,7 @@ int cfspi_xmitlen(struct cfspi *cfspi) int pkts = 0; /* - * Decommit previously commited frames. + * Decommit previously committed frames. * skb_queue_splice_tail(&cfspi->chead,&cfspi->qhead) */ while (skb_peek(&cfspi->chead)) { diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c index 1b9943a4edab..b009e03cda9e 100644 --- a/drivers/net/caif/caif_spi_slave.c +++ b/drivers/net/caif/caif_spi_slave.c @@ -98,7 +98,7 @@ void cfspi_xfer(struct work_struct *work) cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT); - /* Copy commited SPI frames after the SPI indication. */ + /* Copy committed SPI frames after the SPI indication. */ ptr = (u8 *) cfspi->xfer.va_tx; ptr += SPI_IND_SZ; len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len); @@ -158,7 +158,7 @@ void cfspi_xfer(struct work_struct *work) cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE); - /* Signal that we are ready to recieve data. */ + /* Signal that we are ready to receive data. */ cfspi->dev->sig_xfer(true, cfspi->dev); cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE); diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 57d2ffbbb433..74efb5a2ad41 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -416,7 +416,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) stats->tx_bytes += cf->can_dlc; - /* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */ + /* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST); /* @@ -782,7 +782,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) reg_msr = at91_read(priv, AT91_MSR(mb)); if (likely(reg_msr & AT91_MSR_MRDY && ~reg_msr & AT91_MSR_MABT)) { - /* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */ + /* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST); dev->stats.tx_packets++; } diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 31552959aed7..7e5cc0bd913d 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -813,7 +813,7 @@ static int c_can_handle_state_change(struct net_device *dev, struct sk_buff *skb; struct can_berr_counter bec; - /* propogate the error condition to the CAN stack */ + /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) return 0; @@ -887,7 +887,7 @@ static int c_can_handle_bus_err(struct net_device *dev, if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) return 0; - /* propogate the error condition to the CAN stack */ + /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) return 0; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 102b16c6cc97..587fba48cdd9 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -274,7 +274,7 @@ static inline void ican3_set_page(struct ican3_dev *mod, unsigned int page) */ /* - * Recieve a message from the ICAN3 "old-style" firmware interface + * Receive a message from the ICAN3 "old-style" firmware interface * * LOCKING: must hold mod->lock * @@ -1050,7 +1050,7 @@ static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg) complete(&mod->termination_comp); break; default: - dev_err(mod->dev, "recieved an unknown inquiry response\n"); + dev_err(mod->dev, "received an unknown inquiry response\n"); break; } } @@ -1058,7 +1058,7 @@ static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg) static void ican3_handle_unknown_message(struct ican3_dev *mod, struct ican3_msg *msg) { - dev_warn(mod->dev, "recieved unknown message: spec 0x%.2x length %d\n", + dev_warn(mod->dev, "received unknown message: spec 0x%.2x length %d\n", msg->spec, le16_to_cpu(msg->len)); } @@ -1113,7 +1113,7 @@ static bool ican3_txok(struct ican3_dev *mod) } /* - * Recieve one CAN frame from the hardware + * Receive one CAN frame from the hardware * * CONTEXT: must be called from user context */ diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 74cd880c7e06..92feac68b66e 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -246,7 +246,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) out_be16(®s->tx.idr3_2, can_id); can_id >>= 16; - /* EFF_FLAGS are inbetween the IDs :( */ + /* EFF_FLAGS are between the IDs :( */ can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0) | MSCAN_EFF_FLAGS; } else { diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 0a8de01d52f7..a358ea9445a2 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -425,7 +425,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) cf->data[3] = ecc & ECC_SEG; break; } - /* Error occured during transmission? */ + /* Error occurred during transmission? */ if ((ecc & ECC_DIR) == 0) cf->data[2] |= CAN_ERR_PROT_TX; } diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h index 7ec9f4db3d52..afd7d85b6915 100644 --- a/drivers/net/can/softing/softing.h +++ b/drivers/net/can/softing/softing.h @@ -22,7 +22,7 @@ struct softing_priv { struct softing *card; struct { int pending; - /* variables wich hold the circular buffer */ + /* variables which hold the circular buffer */ int echo_put; int echo_get; } tx; diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index aeea9f9ff6e8..7a70709d5608 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -218,7 +218,7 @@ static int softing_handle_1(struct softing *card) ptr = buf; cmd = *ptr++; if (cmd == 0xff) - /* not quite usefull, probably the card has got out */ + /* not quite useful, probably the card has got out */ return 0; netdev = card->net[0]; if (cmd & CMD_BUS2) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 4d07f1ee7168..f7bbde9eb2cb 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -663,7 +663,7 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, struct can_frame *cf; struct sk_buff *skb; - /* propogate the error condition to the can stack */ + /* propagate the error condition to the can stack */ skb = alloc_can_err_skb(ndev, &cf); if (!skb) { if (printk_ratelimit()) diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index e75f1a876972..a72c7bfb4090 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -386,7 +386,7 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) break; } - /* Error occured during transmission? */ + /* Error occurred during transmission? */ if ((ecc & SJA1000_ECC_DIR) == 0) cf->data[2] |= CAN_ERR_PROT_TX; diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index dc53c831ea95..eb8b0e600282 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -284,7 +284,7 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, break; } - /* Error occured during transmission? */ + /* Error occurred during transmission? */ if (!(ecc & SJA1000_ECC_DIR)) cf->data[2] |= CAN_ERR_PROT_TX; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 3437613f0454..143a28c666af 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -51,7 +51,7 @@ * TX has 4 queues. currently these queues are used in a round-robin * fashion for load balancing. They can also be used for QoS. for that * to work, however, QoS information needs to be exposed down to the driver - * level so that subqueues get targetted to particular transmit rings. + * level so that subqueues get targeted to particular transmit rings. * alternatively, the queues can be configured via use of the all-purpose * ioctl. * @@ -5165,7 +5165,7 @@ err_out_free_res: pci_release_regions(pdev); err_write_cacheline: - /* Try to restore it in case the error occured after we + /* Try to restore it in case the error occurred after we * set it. */ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, orig_cacheline_size); diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h index faf4746a0f3e..b361424d5f57 100644 --- a/drivers/net/cassini.h +++ b/drivers/net/cassini.h @@ -772,7 +772,7 @@ #define RX_DEBUG_INTR_WRITE_PTR_MASK 0xC0000000 /* interrupt write pointer of the interrupt queue */ -/* flow control frames are emmitted using two PAUSE thresholds: +/* flow control frames are emitted using two PAUSE thresholds: * XOFF PAUSE uses pause time value pre-programmed in the Send PAUSE MAC reg * XON PAUSE uses a pause time of 0. granularity of threshold is 64bytes. * PAUSE thresholds defined in terms of FIFO occupancy and may be translated diff --git a/drivers/net/chelsio/mv88e1xxx.c b/drivers/net/chelsio/mv88e1xxx.c index 809047a99e96..71018a4fdf15 100644 --- a/drivers/net/chelsio/mv88e1xxx.c +++ b/drivers/net/chelsio/mv88e1xxx.c @@ -41,7 +41,7 @@ static void mdio_clear_bit(struct cphy *cphy, int reg, u32 bitval) * * PARAMS: cphy - Pointer to PHY instance data. * - * RETURN: 0 - Successfull reset. + * RETURN: 0 - Successful reset. * -1 - Timeout. */ static int mv88e1xxx_reset(struct cphy *cphy, int wait) diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 7dbb16d36fff..40c7b93ababc 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -293,7 +293,7 @@ static int pm3393_enable_port(struct cmac *cmac, int which) pm3393_enable(cmac, which); /* - * XXX This should be done by the PHY and preferrably not at all. + * XXX This should be done by the PHY and preferably not at all. * The PHY doesn't give us link status indication on its own so have * the link management code query it instead. */ diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index f778b15ad3fd..8754d4473042 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1662,7 +1662,7 @@ irqreturn_t t1_interrupt(int irq, void *data) * The code figures out how many entries the sk_buff will require in the * cmdQ and updates the cmdQ data structure with the state once the enqueue * has complete. Then, it doesn't access the global structure anymore, but - * uses the corresponding fields on the stack. In conjuction with a spinlock + * uses the corresponding fields on the stack. In conjunction with a spinlock * around that code, we can make the function reentrant without holding the * lock when we actually enqueue (which might be expensive, especially on * architectures with IO MMUs). diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/chelsio/vsc7326.c index 106a590f0d9a..b0cb388f5e12 100644 --- a/drivers/net/chelsio/vsc7326.c +++ b/drivers/net/chelsio/vsc7326.c @@ -566,7 +566,7 @@ static int mac_disable(struct cmac *mac, int which) for (i = 0; i <= 0x3a; ++i) vsc_write(mac->adapter, CRA(4, port, i), 0); - /* Clear sofware counters */ + /* Clear software counters */ memset(&mac->stats, 0, sizeof(struct cmac_statistics)); return 0; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index 80c2feeefec5..9d267d3a6892 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1383,7 +1383,7 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) spin_lock(&np->lock); /* Preempt protection */ switch (cmd) { /* The ioctls below should be considered obsolete but are */ - /* still present for compatability with old scripts/apps */ + /* still present for compatibility with old scripts/apps */ case SET_ETH_SPEED_10: /* 10 Mbps */ e100_set_speed(dev, 10); break; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index f9f6645b2e61..bfa2d56af1ee 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -199,7 +199,7 @@ static inline void refill_rspq(struct adapter *adapter, * need_skb_unmap - does the platform need unmapping of sk_buffs? * * Returns true if the platform needs sk_buff unmapping. The compiler - * optimizes away unecessary code if this returns true. + * optimizes away unnecessary code if this returns true. */ static inline int need_skb_unmap(void) { diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index d55db6b38e7b..c688421da9c7 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1386,11 +1386,11 @@ struct intr_info { * @reg: the interrupt status register to process * @mask: a mask to apply to the interrupt status * @acts: table of interrupt actions - * @stats: statistics counters tracking interrupt occurences + * @stats: statistics counters tracking interrupt occurrences * * A table driven interrupt handler that applies a set of masks to an * interrupt status word and performs the corresponding actions if the - * interrupts described by the mask have occured. The actions include + * interrupts described by the mask have occurred. The actions include * optionally printing a warning or alert message, and optionally * incrementing a stat counter. The table is terminated by an entry * specifying mask 0. Returns the number of fatal interrupt conditions. @@ -2783,7 +2783,7 @@ static void init_mtus(unsigned short mtus[]) { /* * See draft-mathis-plpmtud-00.txt for the values. The min is 88 so - * it can accomodate max size TCP/IP headers when SACK and timestamps + * it can accommodate max size TCP/IP headers when SACK and timestamps * are enabled and still have at least 8 bytes of payload. */ mtus[0] = 88; diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c index b9fd8a6f2cc4..d1ec111aebd8 100644 --- a/drivers/net/cxgb4/t4_hw.c +++ b/drivers/net/cxgb4/t4_hw.c @@ -883,7 +883,7 @@ struct intr_info { * * A table driven interrupt handler that applies a set of masks to an * interrupt status word and performs the corresponding actions if the - * interrupts described by the mask have occured. The actions include + * interrupts described by the mask have occurred. The actions include * optionally emitting a warning or alert message. The table is terminated * by an entry specifying mask 0. Returns the number of fatal interrupt * conditions. diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index 6aad64df4dcb..4661cbbd9bd9 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -2738,7 +2738,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, cfg_queues(adapter); /* - * Print a short notice on the existance and configuration of the new + * Print a short notice on the existence and configuration of the new * VF network device ... */ for_each_port(adapter, pidx) { diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c index e0b3d1bc2fdf..bb65121f581c 100644 --- a/drivers/net/cxgb4vf/sge.c +++ b/drivers/net/cxgb4vf/sge.c @@ -224,8 +224,8 @@ static inline bool is_buf_mapped(const struct rx_sw_desc *sdesc) /** * need_skb_unmap - does the platform need unmapping of sk_buffs? * - * Returns true if the platfrom needs sk_buff unmapping. The compiler - * optimizes away unecessary code if this returns true. + * Returns true if the platform needs sk_buff unmapping. The compiler + * optimizes away unnecessary code if this returns true. */ static inline int need_skb_unmap(void) { @@ -267,7 +267,7 @@ static inline unsigned int fl_cap(const struct sge_fl *fl) * * Tests specified Free List to see whether the number of buffers * available to the hardware has falled below our "starvation" - * threshhold. + * threshold. */ static inline bool fl_starving(const struct sge_fl *fl) { @@ -1149,7 +1149,7 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(credits < ETHTXQ_STOP_THRES)) { /* * After we're done injecting the Work Request for this - * packet, we'll be below our "stop threshhold" so stop the TX + * packet, we'll be below our "stop threshold" so stop the TX * Queue now and schedule a request for an SGE Egress Queue * Update message. The queue will get started later on when * the firmware processes this Work Request and sends us an diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index baca6bfcb089..807b6bb200eb 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -94,14 +94,14 @@ MODULE_VERSION(EMAC_MODULE_VERSION); static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* Configuration items */ -#define EMAC_DEF_PASS_CRC (0) /* Do not pass CRC upto frames */ +#define EMAC_DEF_PASS_CRC (0) /* Do not pass CRC up to frames */ #define EMAC_DEF_QOS_EN (0) /* EMAC proprietary QoS disabled */ #define EMAC_DEF_NO_BUFF_CHAIN (0) /* No buffer chain */ #define EMAC_DEF_MACCTRL_FRAME_EN (0) /* Discard Maccontrol frames */ #define EMAC_DEF_SHORT_FRAME_EN (0) /* Discard short frames */ #define EMAC_DEF_ERROR_FRAME_EN (0) /* Discard error frames */ -#define EMAC_DEF_PROM_EN (0) /* Promiscous disabled */ -#define EMAC_DEF_PROM_CH (0) /* Promiscous channel is 0 */ +#define EMAC_DEF_PROM_EN (0) /* Promiscuous disabled */ +#define EMAC_DEF_PROM_CH (0) /* Promiscuous channel is 0 */ #define EMAC_DEF_BCAST_EN (1) /* Broadcast enabled */ #define EMAC_DEF_BCAST_CH (0) /* Broadcast channel is 0 */ #define EMAC_DEF_MCAST_EN (1) /* Multicast enabled */ @@ -1013,7 +1013,7 @@ static void emac_rx_handler(void *token, int len, int status) return; } - /* recycle on recieve error */ + /* recycle on receive error */ if (status < 0) { ndev->stats.rx_errors++; goto recycle; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index f4d0922ec65b..dd70738eb2f4 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -160,7 +160,7 @@ static int e1000_get_settings(struct net_device *netdev, &adapter->link_duplex); ecmd->speed = adapter->link_speed; - /* unfortunatly FULL_DUPLEX != DUPLEX_FULL + /* unfortunately FULL_DUPLEX != DUPLEX_FULL * and HALF_DUPLEX != DUPLEX_HALF */ if (adapter->link_duplex == FULL_DUPLEX) diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index c70b23d52284..5c9a8403668b 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1026,7 +1026,7 @@ extern void __iomem *ce4100_gbe_mdio_base_virt; #define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */ #define E1000_MDPHYA 0x0003C /* PHY address - RW */ -#define E1000_MANC2H 0x05860 /* Managment Control To Host - RW */ +#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ #define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ #define E1000_GCR 0x05B00 /* PCI-Ex Control */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index bfab14092d2c..477e066a1cf0 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -205,7 +205,7 @@ static struct pci_driver e1000_driver = { .probe = e1000_probe, .remove = __devexit_p(e1000_remove), #ifdef CONFIG_PM - /* Power Managment Hooks */ + /* Power Management Hooks */ .suspend = e1000_suspend, .resume = e1000_resume, #endif diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index a39d4a4d871c..506a0a0043b3 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4886,7 +4886,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, if (skb->protocol == htons(ETH_P_IP)) tx_flags |= E1000_TX_FLAGS_IPV4; - /* if count is 0 then mapping error has occured */ + /* if count is 0 then mapping error has occurred */ count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); if (count) { e1000_tx_queue(adapter, tx_flags, count); diff --git a/drivers/net/enc28j60_hw.h b/drivers/net/enc28j60_hw.h index 1a0b20969f80..25b41de49f0e 100644 --- a/drivers/net/enc28j60_hw.h +++ b/drivers/net/enc28j60_hw.h @@ -303,7 +303,7 @@ /* maximum ethernet frame length */ #define MAX_FRAMELEN 1518 -/* Prefered half duplex: LEDA: Link status LEDB: Rx/Tx activity */ +/* Preferred half duplex: LEDA: Link status LEDB: Rx/Tx activity */ #define ENC28J60_LAMPS_MODE 0x3476 #endif diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index fb717be511f6..12d28e9d0cb7 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -13,7 +13,7 @@ This driver supports following cards : - ICL EtherTeam 16i - ICL EtherTeam 32 EISA - (Uses true 32 bit transfers rather than 16i compability mode) + (Uses true 32 bit transfers rather than 16i compatibility mode) Example Module usage: insmod eth16i.o io=0x2a0 mediatype=bnc diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index db0290f05bdf..a83dd312c3ac 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -542,7 +542,7 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id) /* Figure out what triggered the interrupt... * The tricky bit here is that the interrupt source bits get - * set in INT_SOURCE for an event irregardless of whether that + * set in INT_SOURCE for an event regardless of whether that * event is masked or not. Thus, in order to figure out what * triggered the interrupt, we need to remove the sources * for all events that are currently masked. This behaviour diff --git a/drivers/net/fec.h b/drivers/net/fec.h index ace318df4c8d..8b2c6d797e6d 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -97,11 +97,11 @@ struct bufdesc { * The following definitions courtesy of commproc.h, which where * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). */ -#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */ +#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */ #define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ #define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ #define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ -#define BD_SC_CM ((ushort)0x0200) /* Continous mode */ +#define BD_SC_CM ((ushort)0x0200) /* Continuous mode */ #define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ #define BD_SC_P ((ushort)0x0100) /* xmt preamble */ #define BD_SC_BR ((ushort)0x0020) /* Break received */ diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7b92897ca66b..d5ab4dad5051 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -440,7 +440,7 @@ union ring_type { #define NV_RX3_VLAN_TAG_PRESENT (1<<16) #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) -/* Miscelaneous hardware related defines: */ +/* Miscellaneous hardware related defines: */ #define NV_PCI_REGSZ_VER1 0x270 #define NV_PCI_REGSZ_VER2 0x2d4 #define NV_PCI_REGSZ_VER3 0x604 @@ -1488,7 +1488,7 @@ static int phy_init(struct net_device *dev) } } - /* some phys clear out pause advertisment on reset, set it back */ + /* some phys clear out pause advertisement on reset, set it back */ mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg); /* restart auto negotiation, power down phy */ @@ -2535,7 +2535,7 @@ static void nv_tx_timeout(struct net_device *dev) else nv_tx_done_optimized(dev, np->tx_ring_size); - /* save current HW postion */ + /* save current HW position */ if (np->tx_change_owner) put_tx.ex = np->tx_change_owner->first_tx_desc; else @@ -4053,7 +4053,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else if (ecmd->autoneg == AUTONEG_DISABLE) { /* Note: autonegotiation disable, speed 1000 intentionally - * forbidden - noone should need that. */ + * forbidden - no one should need that. */ if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) return -EINVAL; @@ -4103,7 +4103,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) adv |= ADVERTISE_100HALF; if (ecmd->advertising & ADVERTISED_100baseT_Full) adv |= ADVERTISE_100FULL; - if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */ + if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisements but disable tx pause */ adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) adv |= ADVERTISE_PAUSE_ASYM; @@ -4148,7 +4148,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) adv |= ADVERTISE_100FULL; np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE); - if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisments but disable tx pause */ + if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisements but disable tx pause */ adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE; } @@ -4449,7 +4449,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */ + if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisements but disable tx pause */ adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) adv |= ADVERTISE_PAUSE_ASYM; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index ec5d595ce2e2..b2fe7edefad9 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -1043,7 +1043,7 @@ enum gfar_errata { }; /* Struct stolen almost completely (and shamelessly) from the FCC enet source - * (Ok, that's not so true anymore, but there is a family resemblence) + * (Ok, that's not so true anymore, but there is a family resemblance) * The GFAR buffer descriptors track the ring buffers. The rx_bd_base * and tx_bd_base always point to the currently available buffer. * The dirty_tx tracks the current buffer that is being sent by the diff --git a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefile index 9def86704a91..104096070026 100644 --- a/drivers/net/hamradio/Makefile +++ b/drivers/net/hamradio/Makefile @@ -3,7 +3,7 @@ # # # 19971130 Moved the amateur radio related network drivers from -# drivers/net/ to drivers/hamradio for easier maintainance. +# drivers/net/ to drivers/hamradio for easier maintenance. # Joerg Reuter DL1BKE # # 20000806 Rewritten to use lists instead of if-statements. diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 7d9ced0738c5..96a98d2ff151 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -30,7 +30,7 @@ * 0.1 F1OAT 07.06.98 Add timer polling routine for channel arbitration * 0.2 F6FBB 08.06.98 Added delay after FPGA programming * 0.3 F6FBB 29.07.98 Delayed PTT implementation for dupmode=2 - * 0.4 F6FBB 30.07.98 Added TxTail, Slottime and Persistance + * 0.4 F6FBB 30.07.98 Added TxTail, Slottime and Persistence * 0.5 F6FBB 01.08.98 Shared IRQs, /proc/net and network statistics * 0.6 F6FBB 25.08.98 Added 1200Bds format * 0.7 F6FBB 12.09.98 Added to the kernel configuration diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 8e2c4601b5f5..8e10d2f6a5ad 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -180,8 +180,8 @@ struct hp100_private { u_int *page_vaddr_algn; /* Aligned virtual address of allocated page */ u_long whatever_offset; /* Offset to bus/phys/dma address */ - int rxrcommit; /* # Rx PDLs commited to adapter */ - int txrcommit; /* # Tx PDLs commited to adapter */ + int rxrcommit; /* # Rx PDLs committed to adapter */ + int txrcommit; /* # Tx PDLs committed to adapter */ }; /* @@ -716,7 +716,7 @@ static int __devinit hp100_probe1(struct net_device *dev, int ioaddr, * implemented/tested only with the lassen chip anyway... */ if (lp->mode == 1) { /* busmaster */ dma_addr_t page_baddr; - /* Get physically continous memory for TX & RX PDLs */ + /* Get physically continuous memory for TX & RX PDLs */ /* Conversion to new PCI API : * Pages are always aligned and zeroed, no need to it ourself. * Doc says should be OK for EISA bus as well - Jean II */ @@ -1596,7 +1596,7 @@ drop: /* clean_txring checks if packets have been sent by the card by reading * the TX_PDL register from the performance page and comparing it to the - * number of commited packets. It then frees the skb's of the packets that + * number of committed packets. It then frees the skb's of the packets that * obviously have been sent to the network. * * Needs the PERFORMANCE page selected. @@ -1617,7 +1617,7 @@ static void hp100_clean_txring(struct net_device *dev) #ifdef HP100_DEBUG if (donecount > MAX_TX_PDL) - printk("hp100: %s: Warning: More PDLs transmitted than commited to card???\n", dev->name); + printk("hp100: %s: Warning: More PDLs transmitted than committed to card???\n", dev->name); #endif for (; 0 != donecount; donecount--) { @@ -1765,7 +1765,7 @@ drop: * Receive Function (Non-Busmaster mode) * Called when an "Receive Packet" interrupt occurs, i.e. the receive * packet counter is non-zero. - * For non-busmaster, this function does the whole work of transfering + * For non-busmaster, this function does the whole work of transferring * the packet to the host memory and then up to higher layers via skb * and netif_rx. */ @@ -1892,7 +1892,7 @@ static void hp100_rx_bm(struct net_device *dev) /* RX_PKT_CNT states how many PDLs are currently formatted and available to * the cards BM engine */ if ((hp100_inw(RX_PKT_CNT) & 0x00ff) >= lp->rxrcommit) { - printk("hp100: %s: More packets received than commited? RX_PKT_CNT=0x%x, commit=0x%x\n", + printk("hp100: %s: More packets received than committed? RX_PKT_CNT=0x%x, commit=0x%x\n", dev->name, hp100_inw(RX_PKT_CNT) & 0x00ff, lp->rxrcommit); return; @@ -2256,7 +2256,7 @@ static irqreturn_t hp100_interrupt(int irq, void *dev_id) if (lp->mode != 1) /* non busmaster */ hp100_rx(dev); else if (!(val & HP100_RX_PDL_FILL_COMPL)) { - /* Shouldnt happen - maybe we missed a RX_PDL_FILL Interrupt? */ + /* Shouldn't happen - maybe we missed a RX_PDL_FILL Interrupt? */ hp100_rx_bm(dev); } } diff --git a/drivers/net/hp100.h b/drivers/net/hp100.h index e6ca128a5564..b60e96fe38b4 100644 --- a/drivers/net/hp100.h +++ b/drivers/net/hp100.h @@ -109,7 +109,7 @@ #define HP100_REG_MAC_CFG_2 0x0d /* RW: (8) Misc MAC functions */ #define HP100_REG_MAC_CFG_3 0x0e /* RW: (8) Misc MAC functions */ #define HP100_REG_MAC_CFG_4 0x0f /* R: (8) Misc MAC states */ -#define HP100_REG_DROPPED 0x10 /* R: (16),11:0 Pkts cant fit in mem */ +#define HP100_REG_DROPPED 0x10 /* R: (16),11:0 Pkts can't fit in mem */ #define HP100_REG_CRC 0x12 /* R: (8) Pkts with CRC */ #define HP100_REG_ABORT 0x13 /* R: (8) Aborted Tx pkts */ #define HP100_REG_TRAIN_REQUEST 0x14 /* RW: (16) Endnode MAC register. */ diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index 8ead6a96abaa..5f51bf7c9dc5 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c @@ -60,7 +60,7 @@ void tah_reset(struct platform_device *ofdev) printk(KERN_ERR "%s: reset timeout\n", ofdev->dev.of_node->full_name); - /* 10KB TAH TX FIFO accomodates the max MTU of 9000 */ + /* 10KB TAH TX FIFO accommodates the max MTU of 9000 */ out_be32(&p->mr, TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP | TAH_MR_DIG); diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 94d9969ec0bb..8ff68ae6b520 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -53,7 +53,7 @@ History: still work with 2.0.x.... Jan 28th, 2000 in Linux 2.2.13, the version.h file mysteriously didn't get - included. Added a workaround for this. Futhermore, it now + included. Added a workaround for this. Furthermore, it now not only compiles as a modules ;-) Jan 30th, 2000 newer kernels automatically probe more than one board, so the @@ -481,7 +481,7 @@ static void InitBoard(struct net_device *dev) if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > camcnt) rcrval |= RCREG_AMC; - /* promiscous mode ? */ + /* promiscuous mode ? */ if (dev->flags & IFF_PROMISC) rcrval |= RCREG_PRO; diff --git a/drivers/net/ibmlana.h b/drivers/net/ibmlana.h index aa3ddbdee4bb..accd5efc9c8a 100644 --- a/drivers/net/ibmlana.h +++ b/drivers/net/ibmlana.h @@ -90,7 +90,7 @@ typedef struct { #define RCREG_ERR 0x8000 /* accept damaged and collided pkts */ #define RCREG_RNT 0x4000 /* accept packets that are < 64 */ #define RCREG_BRD 0x2000 /* accept broadcasts */ -#define RCREG_PRO 0x1000 /* promiscous mode */ +#define RCREG_PRO 0x1000 /* promiscuous mode */ #define RCREG_AMC 0x0800 /* accept all multicasts */ #define RCREG_LB_NONE 0x0000 /* no loopback */ #define RCREG_LB_MAC 0x0200 /* MAC loopback */ diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 90c5e01e9235..ce8255fc3c52 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -181,7 +181,7 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) * address and must override the actual permanent MAC address. If an * alternate MAC address is fopund it is saved in the hw struct and * prgrammed into RAR0 and the cuntion returns success, otherwise the - * fucntion returns an error. + * function returns an error. **/ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) { @@ -982,7 +982,7 @@ out: } /** - * igb_get_speed_and_duplex_copper - Retreive current speed/duplex + * igb_get_speed_and_duplex_copper - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 6694bf3e5ad9..d639706eb3f6 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1421,7 +1421,7 @@ out: } /** - * igb_check_downshift - Checks whether a downshift in speed occured + * igb_check_downshift - Checks whether a downshift in speed occurred * @hw: pointer to the HW structure * * Success returns 0, Failure returns 1 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3d850af0cdda..0dfd1b93829e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -200,7 +200,7 @@ static struct pci_driver igb_driver = { .probe = igb_probe, .remove = __devexit_p(igb_remove), #ifdef CONFIG_PM - /* Power Managment Hooks */ + /* Power Management Hooks */ .suspend = igb_suspend, .resume = igb_resume, #endif @@ -2292,7 +2292,7 @@ static void igb_init_hw_timer(struct igb_adapter *adapter) /** * Scale the NIC clock cycle by a large factor so that * relatively small clock corrections can be added or - * substracted at each clock tick. The drawbacks of a large + * subtracted at each clock tick. The drawbacks of a large * factor are a) that the clock register overflows more quickly * (not such a big deal) and b) that the increment per tick has * to fit into 24 bits. As a result we need to use a shift of @@ -3409,7 +3409,7 @@ static void igb_set_rx_mode(struct net_device *netdev) } else { /* * Write addresses to the MTA, if the attempt fails - * then we should just turn on promiscous mode so + * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ count = igb_write_mc_addr_list(netdev); @@ -3423,7 +3423,7 @@ static void igb_set_rx_mode(struct net_device *netdev) /* * Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable - * unicast promiscous mode + * unicast promiscuous mode */ count = igb_write_uc_addr_list(netdev); if (count < 0) { @@ -4317,7 +4317,7 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, /* * count reflects descriptors mapped, if 0 or less then mapping error - * has occured and we need to rewind the descriptor queue + * has occurred and we need to rewind the descriptor queue */ count = igb_tx_map_adv(tx_ring, skb, first); if (!count) { @@ -5352,8 +5352,8 @@ static void igb_msg_task(struct igb_adapter *adapter) * The unicast table address is a register array of 32-bit registers. * The table is meant to be used in a way similar to how the MTA is used * however due to certain limitations in the hardware it is necessary to - * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscous - * enable bit to allow vlan tag stripping when promiscous mode is enabled + * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous + * enable bit to allow vlan tag stripping when promiscuous mode is enabled **/ static void igb_set_uta(struct igb_adapter *adapter) { diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 6ccc32fd7338..1d04ca6fdaea 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2227,7 +2227,7 @@ static netdev_tx_t igbvf_xmit_frame_ring_adv(struct sk_buff *skb, /* * count reflects descriptors mapped, if 0 then mapping error - * has occured and we need to rewind the descriptor queue + * has occurred and we need to rewind the descriptor queue */ count = igbvf_tx_map_adv(adapter, tx_ring, skb, first); diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index a5b0f0e194bb..58cd3202b48c 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -486,14 +486,14 @@ static int ipg_config_autoneg(struct net_device *dev) phyctrl = ipg_r8(PHY_CTRL); mac_ctrl_val = ipg_r32(MAC_CTRL); - /* Set flags for use in resolving auto-negotation, assuming + /* Set flags for use in resolving auto-negotiation, assuming * non-1000Mbps, half duplex, no flow control. */ fullduplex = 0; txflowcontrol = 0; rxflowcontrol = 0; - /* To accomodate a problem in 10Mbps operation, + /* To accommodate a problem in 10Mbps operation, * set a global flag if PHY running in 10Mbps mode. */ sp->tenmbpsmode = 0; @@ -846,7 +846,7 @@ static void init_tfdlist(struct net_device *dev) } /* - * Free all transmit buffers which have already been transfered + * Free all transmit buffers which have already been transferred * via DMA to the IPG. */ static void ipg_nic_txfree(struct net_device *dev) @@ -920,7 +920,7 @@ static void ipg_tx_timeout(struct net_device *dev) /* * For TxComplete interrupts, free all transmit - * buffers which have already been transfered via DMA + * buffers which have already been transferred via DMA * to the IPG. */ static void ipg_nic_txcleanup(struct net_device *dev) @@ -1141,13 +1141,13 @@ static int ipg_nic_rx_check_error(struct net_device *dev) /* Increment detailed receive error statistics. */ if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) { - IPG_DEBUG_MSG("RX FIFO overrun occured.\n"); + IPG_DEBUG_MSG("RX FIFO overrun occurred.\n"); sp->stats.rx_fifo_errors++; } if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) { - IPG_DEBUG_MSG("RX runt occured.\n"); + IPG_DEBUG_MSG("RX runt occurred.\n"); sp->stats.rx_length_errors++; } @@ -1156,7 +1156,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev) */ if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) { - IPG_DEBUG_MSG("RX alignment error occured.\n"); + IPG_DEBUG_MSG("RX alignment error occurred.\n"); sp->stats.rx_frame_errors++; } @@ -1421,12 +1421,12 @@ static int ipg_nic_rx(struct net_device *dev) /* Increment detailed receive error statistics. */ if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) { - IPG_DEBUG_MSG("RX FIFO overrun occured.\n"); + IPG_DEBUG_MSG("RX FIFO overrun occurred.\n"); sp->stats.rx_fifo_errors++; } if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) { - IPG_DEBUG_MSG("RX runt occured.\n"); + IPG_DEBUG_MSG("RX runt occurred.\n"); sp->stats.rx_length_errors++; } @@ -1436,7 +1436,7 @@ static int ipg_nic_rx(struct net_device *dev) */ if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) { - IPG_DEBUG_MSG("RX alignment error occured.\n"); + IPG_DEBUG_MSG("RX alignment error occurred.\n"); sp->stats.rx_frame_errors++; } @@ -1460,7 +1460,7 @@ static int ipg_nic_rx(struct net_device *dev) } } else { - /* Adjust the new buffer length to accomodate the size + /* Adjust the new buffer length to accommodate the size * of the received frame. */ skb_put(skb, framelen); @@ -1488,7 +1488,7 @@ static int ipg_nic_rx(struct net_device *dev) } /* - * If there are more RFDs to proces and the allocated amount of RFD + * If there are more RFDs to process and the allocated amount of RFD * processing time has expired, assert Interrupt Requested to make * sure we come back to process the remaining RFDs. */ @@ -1886,7 +1886,7 @@ static netdev_tx_t ipg_nic_hard_start_xmit(struct sk_buff *skb, /* Request TxComplete interrupts at an interval defined * by the constant IPG_FRAMESBETWEENTXCOMPLETES. * Request TxComplete interrupt for every frame - * if in 10Mbps mode to accomodate problem with 10Mbps + * if in 10Mbps mode to accommodate problem with 10Mbps * processing. */ if (sp->tenmbpsmode) @@ -2098,7 +2098,7 @@ static int ipg_nic_change_mtu(struct net_device *dev, int new_mtu) struct ipg_nic_private *sp = netdev_priv(dev); int err; - /* Function to accomodate changes to Maximum Transfer Unit + /* Function to accommodate changes to Maximum Transfer Unit * (or MTU) of IPG NIC. Cannot use default function since * the default will not allow for MTU > 1500 bytes. */ diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 92631eb6f6a3..872183f29ec4 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c @@ -76,7 +76,7 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info); static int ali_ircc_init_43(ali_chip_t *chip, chipio_t *info); static int ali_ircc_init_53(ali_chip_t *chip, chipio_t *info); -/* These are the currently known ALi sourth-bridge chipsets, the only one difference +/* These are the currently known ALi south-bridge chipsets, the only one difference * is that M1543C doesn't support HP HDSL-3600 */ static ali_chip_t chips[] = @@ -1108,7 +1108,7 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) outb(lcr, iobase+UART_LCR); /* Set 8N1 */ outb(fcr, iobase+UART_FCR); /* Enable FIFO's */ - /* without this, the conection will be broken after come back from FIR speed, + /* without this, the connection will be broken after come back from FIR speed, but with this, the SIR connection is harder to established */ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR); diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index f81d944fc360..174cafad2c1a 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -56,7 +56,7 @@ /* do_probe module parameter Enable this code */ /* Probe code is very useful for understanding how the hardware works */ /* Use it with various combinations of TT_LEN, RX_LEN */ -/* Strongly recomended, disable if the probe fails on your machine */ +/* Strongly recommended, disable if the probe fails on your machine */ /* and send me the output of dmesg */ #define USE_PROBE 1 #undef USE_PROBE diff --git a/drivers/net/irda/donauboe.h b/drivers/net/irda/donauboe.h index 77fcf4459161..d92d54e839b9 100644 --- a/drivers/net/irda/donauboe.h +++ b/drivers/net/irda/donauboe.h @@ -51,7 +51,7 @@ /* The documentation for this chip is allegedly released */ /* However I have not seen it, not have I managed to contact */ -/* anyone who has. HOWEVER the chip bears a striking resemblence */ +/* anyone who has. HOWEVER the chip bears a striking resemblance */ /* to the IrDA controller in the Toshiba RISC TMPR3922 chip */ /* the documentation for this is freely available at */ /* http://www.madingley.org/james/resources/toshoboe/TMPR3922.pdf */ diff --git a/drivers/net/irda/girbil-sir.c b/drivers/net/irda/girbil-sir.c index a31b8fa8aaa9..96cdecff349d 100644 --- a/drivers/net/irda/girbil-sir.c +++ b/drivers/net/irda/girbil-sir.c @@ -38,7 +38,7 @@ static int girbil_change_speed(struct sir_dev *dev, unsigned speed); /* Control register 1 */ #define GIRBIL_TXEN 0x01 /* Enable transmitter */ #define GIRBIL_RXEN 0x02 /* Enable receiver */ -#define GIRBIL_ECAN 0x04 /* Cancel self emmited data */ +#define GIRBIL_ECAN 0x04 /* Cancel self emitted data */ #define GIRBIL_ECHO 0x08 /* Echo control characters */ /* LED Current Register (0x2) */ diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index e4ea61944c22..d9267cb98a23 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -370,7 +370,7 @@ static void speed_bulk_callback(struct urb *urb) /* urb is now available */ //urb->status = 0; -> tested above - /* New speed and xbof is now commited in hardware */ + /* New speed and xbof is now committed in hardware */ self->new_speed = -1; self->new_xbofs = -1; @@ -602,7 +602,7 @@ static void write_bulk_callback(struct urb *urb) IRDA_DEBUG(1, "%s(), Changing speed now...\n", __func__); irda_usb_change_speed_xbofs(self); } else { - /* New speed and xbof is now commited in hardware */ + /* New speed and xbof is now committed in hardware */ self->new_speed = -1; self->new_xbofs = -1; /* Done, waiting for next packet */ diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index cc821de2c966..be52bfed66a9 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -588,7 +588,7 @@ static int mcs_speed_change(struct mcs_cb *mcs) mcs_get_reg(mcs, MCS_MODE_REG, &rval); - /* MINRXPW values recomended by MosChip */ + /* MINRXPW values recommended by MosChip */ if (mcs->new_speed <= 115200) { rval &= ~MCS_FIR; @@ -799,7 +799,7 @@ static void mcs_receive_irq(struct urb *urb) ret = usb_submit_urb(urb, GFP_ATOMIC); } -/* Transmit callback funtion. */ +/* Transmit callback function. */ static void mcs_send_irq(struct urb *urb) { struct mcs_cb *mcs = urb->context; @@ -811,7 +811,7 @@ static void mcs_send_irq(struct urb *urb) netif_wake_queue(ndev); } -/* Transmit callback funtion. */ +/* Transmit callback function. */ static netdev_tx_t mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev) { diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 559fe854d76d..7a963d4e6d06 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -716,7 +716,7 @@ static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info) int reg, com = 0; int pnp; - /* Read funtion enable register (FER) */ + /* Read function enable register (FER) */ outb(CFG_338_FER, cfg_base); reg = inb(cfg_base+1); diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h index 7ba7738759b9..32fa58211fad 100644 --- a/drivers/net/irda/nsc-ircc.h +++ b/drivers/net/irda/nsc-ircc.h @@ -135,7 +135,7 @@ #define LSR_TXRDY 0x20 /* Transmitter ready */ #define LSR_TXEMP 0x40 /* Transmitter empty */ -#define ASCR 0x07 /* Auxillary Status and Control Register */ +#define ASCR 0x07 /* Auxiliary Status and Control Register */ #define ASCR_RXF_TOUT 0x01 /* Rx FIFO timeout */ #define ASCR_FEND_INF 0x02 /* Frame end bytes in rx FIFO */ #define ASCR_S_EOT 0x04 /* Set end of transmission */ diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index c192c31e4c5c..001ed0a255f6 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -40,7 +40,7 @@ #define ICCR0_AME (1 << 7) /* Address match enable */ #define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */ -#define ICCR0_RIE (1 << 5) /* Recieve FIFO interrupt enable */ +#define ICCR0_RIE (1 << 5) /* Receive FIFO interrupt enable */ #define ICCR0_RXE (1 << 4) /* Receive enable */ #define ICCR0_TXE (1 << 3) /* Transmit enable */ #define ICCR0_TUS (1 << 2) /* Transmit FIFO underrun select */ @@ -483,7 +483,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) } if (icsr0 & ICSR0_EIF) { - /* An error in FIFO occured, or there is a end of frame */ + /* An error in FIFO occurred, or there is a end of frame */ pxa_irda_fir_irq_eif(si, dev, icsr0); } diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 1c1677cfea29..8800e1fe4129 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -1582,7 +1582,7 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) int iobase; int iir, lsr; - /* Already locked comming here in smsc_ircc_interrupt() */ + /* Already locked coming here in smsc_ircc_interrupt() */ /*spin_lock(&self->lock);*/ iobase = self->io.sir_base; diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 67c0ad42d818..fc896854e282 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -29,7 +29,7 @@ F02 Oct/28/02: Add SB device ID for 3147 and 3177. 2004-02-16: - Removed unneeded 'legacy' pci stuff. -- Make sure SIR mode is set (hw_init()) before calling mode-dependant stuff. +- Make sure SIR mode is set (hw_init()) before calling mode-dependent stuff. - On speed change from core, don't send SIR frame with new speed. Use current speed and change speeds later. - Make module-param dongle_id actually work. @@ -385,7 +385,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) self->io.dongle_id = dongle_id; /* The only value we must override it the baudrate */ - /* Maximum speeds and capabilities are dongle-dependant. */ + /* Maximum speeds and capabilities are dongle-dependent. */ switch( self->io.dongle_id ){ case 0x0d: self->qos.baud_rate.bits = diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index d66fab854bf1..a076eb125349 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -209,7 +209,7 @@ enum vlsi_pio_irintr { IRINTR_ACTEN = 0x80, /* activity interrupt enable */ IRINTR_ACTIVITY = 0x40, /* activity monitor (traffic detected) */ IRINTR_RPKTEN = 0x20, /* receive packet interrupt enable*/ - IRINTR_RPKTINT = 0x10, /* rx-packet transfered from fifo to memory finished */ + IRINTR_RPKTINT = 0x10, /* rx-packet transferred from fifo to memory finished */ IRINTR_TPKTEN = 0x08, /* transmit packet interrupt enable */ IRINTR_TPKTINT = 0x04, /* last bit of tx-packet+crc shifted to ir-pulser */ IRINTR_OE_EN = 0x02, /* UART rx fifo overrun error interrupt enable */ @@ -739,7 +739,7 @@ typedef struct vlsi_irda_dev { /* the remapped error flags we use for returning from frame * post-processing in vlsi_process_tx/rx() after it was completed * by the hardware. These functions either return the >=0 number - * of transfered bytes in case of success or the negative (-) + * of transferred bytes in case of success or the negative (-) * of the or'ed error flags. */ diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c index 41c529fac0ab..686a17aadef3 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ixgbe/ixgbe_dcb.c @@ -36,7 +36,7 @@ /** * ixgbe_ieee_credits - This calculates the ieee traffic class * credits from the configured bandwidth percentages. Credits - * are the smallest unit programable into the underlying + * are the smallest unit programmable into the underlying * hardware. The IEEE 802.1Qaz specification do not use bandwidth * groups so this is much simplified from the CEE case. */ diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index fec4c724c37a..327c8614198c 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -360,7 +360,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) return DCB_NO_HW_CHG; /* - * Only take down the adapter if an app change occured. FCoE + * Only take down the adapter if an app change occurred. FCoE * may shuffle tx rings in this case and this can not be done * without a reset currently. */ @@ -599,7 +599,7 @@ static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, break; /* The FCoE application priority may be changed multiple - * times in quick sucession with switches that build up + * times in quick succession with switches that build up * TLVs. To avoid creating uneeded device resets this * checks the actual HW configuration and clears * BIT_APP_UPCHG if a HW configuration change is not diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f17e4a7ee731..6f8adc7f5d7c 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -644,7 +644,7 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring, * @adapter: driver private struct * @index: reg idx of queue to query (0-127) * - * Helper function to determine the traffic index for a paticular + * Helper function to determine the traffic index for a particular * register index. * * Returns : a tc index for use in range 0-7, or 0-3 @@ -3556,7 +3556,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) } else { /* * Write addresses to the MTA, if the attempt fails - * then we should just turn on promiscous mode so + * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ hw->mac.ops.update_mc_addr_list(hw, netdev); @@ -3567,7 +3567,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) /* * Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable - * unicast promiscous mode + * unicast promiscuous mode */ count = ixgbe_write_uc_addr_list(netdev); if (count < 0) { @@ -4443,7 +4443,7 @@ static inline bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) } /* - * ixgbe_set_num_queues: Allocate queues for device, feature dependant + * ixgbe_set_num_queues: Allocate queues for device, feature dependent * @adapter: board private structure to initialize * * This is the top level queue allocation routine. The order here is very diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index f72f705f6183..df5b8aa4795d 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -1694,7 +1694,7 @@ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) } /** - * ixgbe_tn_check_overtemp - Checks if an overtemp occured. + * ixgbe_tn_check_overtemp - Checks if an overtemp occurred. * @hw: pointer to hardware structure * * Checks if the LASI temp alarm status was triggered due to overtemp diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c index f47e93fe32be..d9323c08f5c7 100644 --- a/drivers/net/ixgbe/ixgbe_x540.c +++ b/drivers/net/ixgbe/ixgbe_x540.c @@ -573,7 +573,7 @@ static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * - * Releases the SWFW semaphore throught the SW_FW_SYNC register + * Releases the SWFW semaphore through the SW_FW_SYNC register * for the specified function (CSR, PHY0, PHY1, EVM, Flash) **/ static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 054ab05b7c6a..05fa7c85deed 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -1925,7 +1925,7 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, } /* - * ixgbevf_set_num_queues: Allocate queues for device, feature dependant + * ixgbevf_set_num_queues: Allocate queues for device, feature dependent * @adapter: board private structure to initialize * * This is the top level queue allocation routine. The order here is very diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index efd44afeae83..f0d8346d0fa5 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c @@ -321,7 +321,7 @@ static void ks8842_reset_hw(struct ks8842_adapter *adapter) /* RX 2 kb high watermark */ ks8842_write16(adapter, 0, 0x1000, REG_QRFCR); - /* aggresive back off in half duplex */ + /* aggressive back off in half duplex */ ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1); /* enable no excessive collison drop */ diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 0fa4a9887ba2..bcd9ba68c9f2 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -141,7 +141,7 @@ static int msg_enable; * * All these calls issue SPI transactions to access the chip's registers. They * all require that the necessary lock is held to prevent accesses when the - * chip is busy transfering packet data (RX/TX FIFO accesses). + * chip is busy transferring packet data (RX/TX FIFO accesses). */ /** @@ -483,7 +483,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) * * This form of operation would require us to hold the SPI bus' * chipselect low during the entie transaction to avoid any - * reset to the data stream comming from the chip. + * reset to the data stream coming from the chip. */ for (; rxfc != 0; rxfc--) { @@ -634,7 +634,7 @@ static void ks8851_irq_work(struct work_struct *work) /** * calc_txlen - calculate size of message to send packet - * @len: Lenght of data + * @len: Length of data * * Returns the size of the TXFIFO message needed to send * this packet. @@ -1472,7 +1472,7 @@ static int ks8851_phy_reg(int reg) * @reg: The register to read. * * This call reads data from the PHY register specified in @reg. Since the - * device does not support all the MII registers, the non-existant values + * device does not support all the MII registers, the non-existent values * are always returned as zero. * * We return zero for unsupported registers as the MII code does not check diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index 2e2c69b24062..61631cace913 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -470,7 +470,7 @@ static int msg_enable; * * All these calls issue transactions to access the chip's registers. They * all require that the necessary lock is held to prevent accesses when the - * chip is busy transfering packet data (RX/TX FIFO accesses). + * chip is busy transferring packet data (RX/TX FIFO accesses). */ /** @@ -1364,7 +1364,7 @@ static int ks_phy_reg(int reg) * @reg: The register to read. * * This call reads data from the PHY register specified in @reg. Since the - * device does not support all the MII registers, the non-existant values + * device does not support all the MII registers, the non-existent values * are always returned as zero. * * We return zero for unsupported registers as the MII code does not check diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index da74db4a03d4..17b75e5f1b0a 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -35,7 +35,7 @@ Alexey Kuznetsov : use the 8390's six bit hash multicast filter. Paul Gortmaker : tweak ANK's above multicast changes a bit. Paul Gortmaker : update packet statistics for v2.1.x - Alan Cox : support arbitary stupid port mappings on the + Alan Cox : support arbitrary stupid port mappings on the 68K Macintosh. Support >16bit I/O spaces Paul Gortmaker : add kmod support for auto-loading of the 8390 module by all drivers that require it. @@ -121,7 +121,7 @@ static void __NS8390_init(struct net_device *dev, int startp); /* * SMP and the 8390 setup. * - * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is + * The 8390 isn't exactly designed to be multithreaded on RX/TX. There is * a page register that controls bank and packet buffer access. We guard * this with ei_local->page_lock. Nobody should assume or set the page other * than zero when the lock is not held. Lock holders must restore page 0 diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 3698824744cb..385a95311cd2 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -27,7 +27,7 @@ Credits: Thanks to Murphy Software BV for letting me write this in their time. - Well, actually, I get payed doing this... + Well, actually, I get paid doing this... (Also: see http://www.murphy.nl for murphy, and my homepage ~ard for more information on the Professional Workstation) diff --git a/drivers/net/meth.h b/drivers/net/meth.h index a78dc1ca8c29..5b145c6bad60 100644 --- a/drivers/net/meth.h +++ b/drivers/net/meth.h @@ -144,7 +144,7 @@ typedef struct rx_packet { /* Bits 22 through 28 are used to determine IPGR2 */ #define METH_REV_SHIFT 29 /* Bits 29 through 31 are used to determine the revision */ - /* 000: Inital revision */ + /* 000: Initial revision */ /* 001: First revision, Improved TX concatenation */ @@ -193,7 +193,7 @@ typedef struct rx_packet { /* 1: A TX message had the INT request bit set, the packet has been sent. */ #define METH_INT_TX_LINK_FAIL BIT(2) /* 0: No interrupt pending, 1: PHY has reported a link failure */ #define METH_INT_MEM_ERROR BIT(3) /* 0: No interrupt pending */ - /* 1: A memory error occurred durring DMA, DMA stopped, Fatal */ + /* 1: A memory error occurred during DMA, DMA stopped, Fatal */ #define METH_INT_TX_ABORT BIT(4) /* 0: No interrupt pending, 1: The TX aborted operation, DMA stopped, FATAL */ #define METH_INT_RX_THRESHOLD BIT(5) /* 0: No interrupt pending, 1: Selected receive threshold condition Valid */ #define METH_INT_RX_UNDERFLOW BIT(6) /* 0: No interrupt pending, 1: FIFO was empty, packet could not be queued */ diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index 9317b61a75b8..9276b1b25586 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -236,7 +236,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev) goto err_mr; } - /* Configure wich ports to start according to module parameters */ + /* Configure which ports to start according to module parameters */ mdev->port_cnt = 0; mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) mdev->port_cnt++; diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 4f158baa0246..77063f91c564 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -247,7 +247,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) priv->port); if (err) en_err(priv, "Failed enabling " - "promiscous mode\n"); + "promiscuous mode\n"); /* Disable port multicast filter (unconditionally) */ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, @@ -276,7 +276,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) } /* - * Not in promiscous mode + * Not in promiscuous mode */ if (priv->flags & MLX4_EN_FLAG_PROMISC) { @@ -292,14 +292,14 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn, priv->port); if (err) - en_err(priv, "Failed disabling promiscous mode\n"); + en_err(priv, "Failed disabling promiscuous mode\n"); /* Disable Multicast promisc */ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) { err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn, priv->port); if (err) - en_err(priv, "Failed disabling multicast promiscous mode\n"); + en_err(priv, "Failed disabling multicast promiscuous mode\n"); priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; } @@ -331,7 +331,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn, priv->port); if (err) - en_err(priv, "Failed disabling multicast promiscous mode\n"); + en_err(priv, "Failed disabling multicast promiscuous mode\n"); priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; } diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 05998ee297c9..cfd50bc49169 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -706,7 +706,7 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) } -/* Calculate the last offset position that accomodates a full fragment +/* Calculate the last offset position that accommodates a full fragment * (assuming fagment size = stride-align) */ static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align) { diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c index 9c91a92da705..191a8dcd8a93 100644 --- a/drivers/net/mlx4/en_selftest.c +++ b/drivers/net/mlx4/en_selftest.c @@ -149,7 +149,7 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf) netif_carrier_off(dev); retry_tx: - /* Wait untill all tx queues are empty. + /* Wait until all tx queues are empty. * there should not be any additional incoming traffic * since we turned the carrier off */ msleep(200); diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index 01feb8fd42ad..b229acf1855f 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -636,7 +636,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(!real_size)) goto tx_drop; - /* Allign descriptor to TXBB size */ + /* Align descriptor to TXBB size */ desc_size = ALIGN(real_size, TXBB_SIZE); nr_txbb = desc_size / TXBB_SIZE; if (unlikely(nr_txbb > MAX_DESC_TXBBS)) { diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c index e71372aa9cc4..279521aed826 100644 --- a/drivers/net/mlx4/mcg.c +++ b/drivers/net/mlx4/mcg.c @@ -222,7 +222,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, /* the given qpn is listed as a promisc qpn * we need to add it as a duplicate to this entry - * for future refernce */ + * for future references */ list_for_each_entry(dqp, &entry->duplicates, list) { if (qpn == dqp->qpn) return 0; /* qp is already duplicated */ diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index eca7d8596f87..8856659fb43c 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c @@ -172,7 +172,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap) } if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { - /* MAC already registered, increase refernce count */ + /* MAC already registered, increase references count */ ++table->refs[i]; goto out; } @@ -360,7 +360,7 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) if (table->refs[i] && (vlan == (MLX4_VLAN_MASK & be32_to_cpu(table->entries[i])))) { - /* Vlan already registered, increase refernce count */ + /* Vlan already registered, increase references count */ *index = i; ++table->refs[i]; goto out; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 673dc600c891..1446de59ae53 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3702,7 +3702,7 @@ abort: /* * This function determines the number of slices supported. - * The number slices is the minumum of the number of CPUS, + * The number slices is the minimum of the number of CPUS, * the number of MSI-X irqs supported, the number of slices * supported by the firmware */ diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index a761076b69c3..53aeea4b536e 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1009,7 +1009,7 @@ static int __devinit myri_sbus_probe(struct platform_device *op) /* Map in the MyriCOM register/localram set. */ if (mp->eeprom.cpuvers < CPUVERS_4_0) { - /* XXX Makes no sense, if control reg is non-existant this + /* XXX Makes no sense, if control reg is non-existent this * XXX driver cannot function at all... maybe pre-4.0 is * XXX only a valid version for PCI cards? Ask feldy... */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 2fd39630b1e5..aa2813e06d00 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -203,7 +203,7 @@ skbuff at an offset of "+2", 16-byte aligning the IP header. IIId. Synchronization Most operations are synchronized on the np->lock irq spinlock, except the -recieve and transmit paths which are synchronised using a combination of +receive and transmit paths which are synchronised using a combination of hardware descriptor ownership, disabling interrupts and NAPI poll scheduling. IVb. References @@ -726,7 +726,7 @@ static void move_int_phy(struct net_device *dev, int addr) * There are two addresses we must avoid: * - the address on the external phy that is used for transmission. * - the address that we want to access. User space can access phys - * on the mii bus with SIOCGMIIREG/SIOCSMIIREG, independant from the + * on the mii bus with SIOCGMIIREG/SIOCSMIIREG, independent from the * phy that is used for transmission. */ @@ -1982,7 +1982,7 @@ static void init_ring(struct net_device *dev) np->rx_head_desc = &np->rx_ring[0]; - /* Please be carefull before changing this loop - at least gcc-2.95.1 + /* Please be careful before changing this loop - at least gcc-2.95.1 * miscompiles it otherwise. */ /* Initialize all Rx descriptors. */ diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index d8bd73d7e296..dc1967c1f312 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -780,7 +780,7 @@ enum { /* * capabilities register, can be used to selectively enable/disable features - * for backward compability + * for backward compatibility */ #define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index a41b2cf4d917..6667e0667a88 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -512,7 +512,7 @@ static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group /* Packet Receiver * * The hardware supports linked lists of receive descriptors for - * which ownership is transfered back and forth by means of an + * which ownership is transferred back and forth by means of an * ownership bit. While the hardware does support the use of a * ring for receive descriptors, we only make use of a chain in * an attempt to reduce bus traffic under heavy load scenarios. @@ -1147,7 +1147,7 @@ again: #ifdef NS83820_VLAN_ACCEL_SUPPORT if(vlan_tx_tag_present(skb)) { /* fetch the vlan tag info out of the - * ancilliary data if the vlan code + * ancillary data if the vlan code * is using hw vlan acceleration */ short tag = vlan_tx_tag_get(skb); diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/pch_gbe/pch_gbe.h index e1e33c80fb25..bf126e76fabf 100644 --- a/drivers/net/pch_gbe/pch_gbe.h +++ b/drivers/net/pch_gbe/pch_gbe.h @@ -351,7 +351,7 @@ struct pch_gbe_functions { }; /** - * struct pch_gbe_mac_info - MAC infomation + * struct pch_gbe_mac_info - MAC information * @addr[6]: Store the MAC address * @fc: Mode of flow control * @fc_autoneg: Auto negotiation enable for flow control setting @@ -375,7 +375,7 @@ struct pch_gbe_mac_info { }; /** - * struct pch_gbe_phy_info - PHY infomation + * struct pch_gbe_phy_info - PHY information * @addr: PHY address * @id: PHY's identifier * @revision: PHY's revision @@ -393,7 +393,7 @@ struct pch_gbe_phy_info { /*! * @ingroup Gigabit Ether driver Layer * @struct pch_gbe_bus_info - * @brief Bus infomation + * @brief Bus information */ struct pch_gbe_bus_info { u8 type; @@ -404,7 +404,7 @@ struct pch_gbe_bus_info { /*! * @ingroup Gigabit Ether driver Layer * @struct pch_gbe_hw - * @brief Hardware infomation + * @brief Hardware information */ struct pch_gbe_hw { void *back; @@ -462,7 +462,7 @@ struct pch_gbe_tx_desc { /** - * struct pch_gbe_buffer - Buffer infomation + * struct pch_gbe_buffer - Buffer information * @skb: pointer to a socket buffer * @dma: DMA address * @time_stamp: time stamp @@ -477,7 +477,7 @@ struct pch_gbe_buffer { }; /** - * struct pch_gbe_tx_ring - tx ring infomation + * struct pch_gbe_tx_ring - tx ring information * @tx_lock: spinlock structs * @desc: pointer to the descriptor ring memory * @dma: physical address of the descriptor ring @@ -499,7 +499,7 @@ struct pch_gbe_tx_ring { }; /** - * struct pch_gbe_rx_ring - rx ring infomation + * struct pch_gbe_rx_ring - rx ring information * @desc: pointer to the descriptor ring memory * @dma: physical address of the descriptor ring * @size: length of descriptor ring in bytes diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c index c8c873b31a89..d2174a40d708 100644 --- a/drivers/net/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c @@ -21,7 +21,7 @@ #include "pch_gbe_api.h" /** - * pch_gbe_stats - Stats item infomation + * pch_gbe_stats - Stats item information */ struct pch_gbe_stats { char string[ETH_GSTRING_LEN]; diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 50986840c99c..2ef2f9cdefa6 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -1011,7 +1011,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, tmp_skb->len = skb->len; memcpy(&tmp_skb->data[ETH_HLEN + 2], &skb->data[ETH_HLEN], (skb->len - ETH_HLEN)); - /*-- Set Buffer infomation --*/ + /*-- Set Buffer information --*/ buffer_info->length = tmp_skb->len; buffer_info->dma = dma_map_single(&adapter->pdev->dev, tmp_skb->data, buffer_info->length, @@ -1540,7 +1540,7 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count; tx_ring->buffer_info = vzalloc(size); if (!tx_ring->buffer_info) { - pr_err("Unable to allocate memory for the buffer infomation\n"); + pr_err("Unable to allocate memory for the buffer information\n"); return -ENOMEM; } diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 1766dc4f07e1..c0f23376a462 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -214,7 +214,7 @@ static struct { { "SMC1211TX EZCard 10/100 (RealTek RTL8139)" }, /* { MPX5030, "Accton MPX5030 (RealTek RTL8139)" },*/ { "Delta Electronics 8139 10/100BaseTX" }, - { "Addtron Technolgy 8139 10/100BaseTX" }, + { "Addtron Technology 8139 10/100BaseTX" }, }; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 321b12f82645..81ac330f931d 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -950,7 +950,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) } /* Update statistics. - Suprisingly this need not be run single-threaded, but it effectively is. + Surprisingly this need not be run single-threaded, but it effectively is. The counters clear when read, so the adds must merely be atomic. */ static void update_stats(struct net_device *dev) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index d3cb77205863..3077d72e8222 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -780,7 +780,7 @@ module_exit(exit_axnet_cs); Alexey Kuznetsov : use the 8390's six bit hash multicast filter. Paul Gortmaker : tweak ANK's above multicast changes a bit. Paul Gortmaker : update packet statistics for v2.1.x - Alan Cox : support arbitary stupid port mappings on the + Alan Cox : support arbitrary stupid port mappings on the 68K Macintosh. Support >16bit I/O spaces Paul Gortmaker : add kmod support for auto-loading of the 8390 module by all drivers that require it. @@ -842,7 +842,7 @@ static void do_set_multicast_list(struct net_device *dev); /* * SMP and the 8390 setup. * - * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is + * The 8390 isn't exactly designed to be multithreaded on RX/TX. There is * a page register that controls bank and packet buffer access. We guard * this with ei_local->page_lock. Nobody should assume or set the page other * than zero when the lock is not held. Lock holders must restore page 0 diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 8a9ff5318923..108591756440 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1264,7 +1264,7 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb, /*====================================================================== - Handle a Tx anomolous event. Entered while in Window 2. + Handle a Tx anomalous event. Entered while in Window 2. ======================================================================*/ diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index aee3bb0358bf..768037602dff 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1651,7 +1651,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) /* * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit * starting until the packet is loaded. Strike one for reliability, lose - * one for latency - although on PCI this isnt a big loss. Older chips + * one for latency - although on PCI this isn't a big loss. Older chips * have FIFO's smaller than a packet, so you can't do this. * Turn on BCR18:BurstRdEn and BCR18:BurstWrEn. */ diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 993c52c82aeb..ff6129319b89 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -534,7 +534,7 @@ EXPORT_SYMBOL(phy_detach); /* Generic PHY support and helper functions */ /** - * genphy_config_advert - sanitize and advertise auto-negotation parameters + * genphy_config_advert - sanitize and advertise auto-negotiation parameters * @phydev: target phy_device struct * * Description: Writes MII_ADVERTISE with the appropriate values, @@ -683,7 +683,7 @@ int genphy_config_aneg(struct phy_device *phydev) return result; if (result == 0) { - /* Advertisment hasn't changed, but maybe aneg was never on to + /* Advertisement hasn't changed, but maybe aneg was never on to * begin with? Or maybe phy was isolated? */ int ctl = phy_read(phydev, MII_BMCR); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 9f6d670748d1..4609bc0e2f56 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1448,7 +1448,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) /* *check if we are on the last channel or - *we exceded the lenght of the data to + *we exceded the length of the data to *fragment */ if ((nfree <= 0) || (flen > len)) diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 4e6b72f57de8..2573f525f11c 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -178,7 +178,7 @@ ppp_print_buffer (const char *name, const __u8 *buf, int count) * way to fix this is to use a rwlock in the tty struct, but for now * we use a single global rwlock for all ttys in ppp line discipline. * - * FIXME: Fixed in tty_io nowdays. + * FIXME: Fixed in tty_io nowadays. */ static DEFINE_RWLOCK(disc_data_lock); diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 78c0e3c9b2b5..693aaef4e3ce 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -115,7 +115,7 @@ struct pppoe_net { * 2) Session stage (MAC and SID are known) * * Ethernet frames have a special tag for this but - * we use simplier approach based on session id + * we use simpler approach based on session id */ static inline bool stage_session(__be16 sid) { diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 5ecfa4b1e758..ffdf7349ef7a 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -632,7 +632,7 @@ static inline void gelic_card_enable_rxdmac(struct gelic_card *card) * @card: card structure * * gelic_card_disable_rxdmac terminates processing on the DMA controller by - * turing off DMA and issueing a force end + * turing off DMA and issuing a force end */ static inline void gelic_card_disable_rxdmac(struct gelic_card *card) { @@ -650,7 +650,7 @@ static inline void gelic_card_disable_rxdmac(struct gelic_card *card) * @card: card structure * * gelic_card_disable_txdmac terminates processing on the DMA controller by - * turing off DMA and issueing a force end + * turing off DMA and issuing a force end */ static inline void gelic_card_disable_txdmac(struct gelic_card *card) { diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h index 32521ae5e824..fadadf9097a3 100644 --- a/drivers/net/ps3_gelic_net.h +++ b/drivers/net/ps3_gelic_net.h @@ -117,7 +117,7 @@ enum gelic_descr_rx_error { GELIC_DESCR_RXDATAERR = 0x00020000, /* IP packet format error */ GELIC_DESCR_RXCALERR = 0x00010000, /* cariier extension length * error */ - GELIC_DESCR_RXCREXERR = 0x00008000, /* carrier extention error */ + GELIC_DESCR_RXCREXERR = 0x00008000, /* carrier extension error */ GELIC_DESCR_RXMLTCST = 0x00004000, /* multicast address frame */ /* bit 13..0 reserved */ }; diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 4a624a29393f..b5ae29d20f2e 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -814,7 +814,7 @@ static int gelic_wl_set_auth(struct net_device *netdev, * you will not decide suitable cipher from * its beacon. * You should have knowledge about the AP's - * cipher infomation in other method prior to + * cipher information in other method prior to * the association. */ if (!precise_ie()) diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 1b63c8aef121..89f7540d90f9 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -462,7 +462,7 @@ static u32 hash_function(unsigned char *mac_addr_orig) * pep - ETHERNET . * mac_addr - MAC address. * skip - if 1, skip this address.Used in case of deleting an entry which is a - * part of chain in the hash table.We cant just delete the entry since + * part of chain in the hash table.We can't just delete the entry since * that will break the chain.We need to defragment the tables time to * time. * rd - 0 Discard packet upon match. diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index 3362a661248c..73e234366a82 100644 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -770,7 +770,7 @@ enum { FM93C56A_WDS = 0x0, FM93C56A_ERASE = 0x3, FM93C56A_ERASE_ALL = 0x0, -/* Command Extentions */ +/* Command Extensions */ FM93C56A_WEN_EXT = 0x3, FM93C56A_WRITE_ALL_EXT = 0x1, FM93C56A_WDS_EXT = 0x0, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 49bfa5813068..5bb311945436 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -660,7 +660,7 @@ static void ql_disable_interrupts(struct ql_adapter *qdev) /* If we're running with multiple MSI-X vectors then we enable on the fly. * Otherwise, we may have multiple outstanding workers and don't want to * enable until the last one finishes. In this case, the irq_cnt gets - * incremented everytime we queue a worker and decremented everytime + * incremented every time we queue a worker and decremented every time * a worker finishes. Once it hits zero we enable the interrupt. */ u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr) @@ -3299,7 +3299,7 @@ msi: * will service it. An example would be if there are * 2 vectors (so 2 RSS rings) and 8 TX completion rings. * This would mean that vector 0 would service RSS ring 0 - * and TX competion rings 0,1,2 and 3. Vector 1 would + * and TX completion rings 0,1,2 and 3. Vector 1 would * service RSS ring 1 and TX completion rings 4,5,6 and 7. */ static void ql_set_tx_vect(struct ql_adapter *qdev) @@ -4152,7 +4152,7 @@ static int ql_change_rx_buffers(struct ql_adapter *qdev) int i, status; u32 lbq_buf_len; - /* Wait for an oustanding reset to complete. */ + /* Wait for an outstanding reset to complete. */ if (!test_bit(QL_ADAPTER_UP, &qdev->flags)) { int i = 3; while (i-- && !test_bit(QL_ADAPTER_UP, &qdev->flags)) { @@ -4281,7 +4281,7 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (ql_set_routing_reg (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 1)) { netif_err(qdev, hw, qdev->ndev, - "Failed to set promiscous mode.\n"); + "Failed to set promiscuous mode.\n"); } else { set_bit(QL_PROMISCUOUS, &qdev->flags); } @@ -4291,7 +4291,7 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (ql_set_routing_reg (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 0)) { netif_err(qdev, hw, qdev->ndev, - "Failed to clear promiscous mode.\n"); + "Failed to clear promiscuous mode.\n"); } else { clear_bit(QL_PROMISCUOUS, &qdev->flags); } diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index e3ebd90ae651..200a363c3bf5 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -535,7 +535,7 @@ static int r6040_rx(struct net_device *dev, int limit) /* RX dribble */ if (err & DSC_RX_ERR_DRI) dev->stats.rx_frame_errors++; - /* Buffer lenght exceeded */ + /* Buffer length exceeded */ if (err & DSC_RX_ERR_BUF) dev->stats.rx_length_errors++; /* Packet too long */ diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 356e74d20b80..337bdcd5abc9 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2353,7 +2353,7 @@ static int start_nic(struct s2io_nic *nic) if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { /* - * Dont see link state interrupts initally on some switches, + * Dont see link state interrupts initially on some switches, * so directly scheduling the link state task here. */ schedule_work(&nic->set_link_task); @@ -3563,7 +3563,7 @@ static void s2io_reset(struct s2io_nic *sp) } /* - * Clear spurious ECC interrupts that would have occured on + * Clear spurious ECC interrupts that would have occurred on * XFRAME II cards after reset. */ if (sp->device_type == XFRAME_II_DEVICE) { @@ -4065,7 +4065,7 @@ static int s2io_close(struct net_device *dev) * Description : * This function is the Tx entry point of the driver. S2IO NIC supports * certain protocol assist features on Tx side, namely CSO, S/G, LSO. - * NOTE: when device cant queue the pkt,just the trans_start variable will + * NOTE: when device can't queue the pkt,just the trans_start variable will * not be upadted. * Return value: * 0 on success & 1 on failure. diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 7d160306b651..2d144979f6f8 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -376,7 +376,7 @@ static const u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7}; /* Maintains Per FIFO related information. */ struct tx_fifo_config { #define MAX_AVAILABLE_TXDS 8192 - u32 fifo_len; /* specifies len of FIFO upto 8192, ie no of TxDLs */ + u32 fifo_len; /* specifies len of FIFO up to 8192, ie no of TxDLs */ /* Priority definition */ #define TX_FIFO_PRI_0 0 /*Highest */ #define TX_FIFO_PRI_1 1 diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 734fcfb52e85..d96b23769bd1 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -692,7 +692,7 @@ static int falcon_gmii_wait(struct efx_nic *efx) efx_oword_t md_stat; int count; - /* wait upto 50ms - taken max from datasheet */ + /* wait up to 50ms - taken max from datasheet */ for (count = 0; count < 5000; count++) { efx_reado(efx, &md_stat, FR_AB_MD_STAT); if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) { @@ -1221,7 +1221,7 @@ static int falcon_reset_sram(struct efx_nic *efx) return 0; } - } while (++count < 20); /* wait upto 0.4 sec */ + } while (++count < 20); /* wait up to 0.4 sec */ netif_err(efx, hw, efx->net_dev, "timed out waiting for SRAM reset\n"); return -ETIMEDOUT; diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 5e118f0d2479..d98479030ef2 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -453,7 +453,7 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc) * * There's a race here with efx_mcdi_rpc(), because we might receive * a REBOOT event *before* the request has been copied out. In polled - * mode (during startup) this is irrelevent, because efx_mcdi_complete() + * mode (during startup) this is irrelevant, because efx_mcdi_complete() * is ignored. In event mode, this condition is just an edge-case of * receiving a REBOOT event after posting the MCDI request. Did the mc * reboot before or after the copyout? The best we can do always is diff --git a/drivers/net/sfc/mcdi_pcol.h b/drivers/net/sfc/mcdi_pcol.h index b86a15f221ad..41fe06fa0600 100644 --- a/drivers/net/sfc/mcdi_pcol.h +++ b/drivers/net/sfc/mcdi_pcol.h @@ -103,7 +103,7 @@ * * If Code==CMDDONE, then the fields are further interpreted as: * - * - LEVEL==INFO Command succeded + * - LEVEL==INFO Command succeeded * - LEVEL==ERR Command failed * * 0 8 16 24 32 @@ -572,7 +572,7 @@ (4*(_numwords)) /* MC_CMD_SET_RAND_SEED: - * Set the 16byte seed for the MC psuedo-random generator + * Set the 16byte seed for the MC pseudo-random generator */ #define MC_CMD_SET_RAND_SEED 0x1a #define MC_CMD_SET_RAND_SEED_IN_LEN 16 @@ -1162,7 +1162,7 @@ #define MC_CMD_MAC_STATS_CMD_CLEAR_WIDTH 1 #define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_LBN 2 #define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_WIDTH 1 -/* Remaining PERIOD* fields only relevent when PERIODIC_CHANGE is set */ +/* Remaining PERIOD* fields only relevant when PERIODIC_CHANGE is set */ #define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_LBN 3 #define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_WIDTH 1 #define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_LBN 4 diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index ec3f740f5465..7e3c65b0c99f 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -449,7 +449,7 @@ void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa) struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u32 rmtadv; - /* The link partner capabilities are only relevent if the + /* The link partner capabilities are only relevant if the * link supports flow control autonegotiation */ if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) return; diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 215d5c51bfa0..9ffa9a6b55a0 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -670,7 +670,7 @@ struct efx_filter_state; * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0 * @fatal_irq_level: IRQ level (bit number) used for serious errors * @mtd_list: List of MTDs attached to the NIC - * @nic_data: Hardware dependant state + * @nic_data: Hardware dependent state * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, * @port_inhibited, efx_monitor() and efx_reconfigure_port() * @port_enabled: Port enabled indicator. diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 3a0cc63428ee..dd03bf619988 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -33,7 +33,7 @@ static char *sgiseeqstr = "SGI Seeq8003"; * with that in mind, I've decided to make this driver look completely like a * stupid Lance from a driver architecture perspective. Only difference is that * here our "ring buffer" looks and acts like a real Lance one does but is - * layed out like how the HPC DMA and the Seeq want it to. You'd be surprised + * laid out like how the HPC DMA and the Seeq want it to. You'd be surprised * how a stupid idea like this can pay off in performance, not to mention * making this driver 2,000 times easier to write. ;-) */ @@ -77,7 +77,7 @@ struct sgiseeq_tx_desc { }; /* - * Warning: This structure is layed out in a certain way because HPC dma + * Warning: This structure is laid out in a certain way because HPC dma * descriptors must be 8-byte aligned. So don't touch this without * some care. */ diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index e9e7a530552c..8a72a979ee71 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1875,7 +1875,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) if (ret) goto out_unregister; - /* print device infomation */ + /* print device information */ pr_info("Base address at 0x%x, %pM, IRQ %d.\n", (u32)ndev->base_addr, ndev->dev_addr, ndev->irq); diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 3406ed870917..b436e007eea0 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -93,7 +93,7 @@ enum sis190_registers { IntrStatus = 0x20, IntrMask = 0x24, IntrControl = 0x28, - IntrTimer = 0x2c, // unused (Interupt Timer) + IntrTimer = 0x2c, // unused (Interrupt Timer) PMControl = 0x30, // unused (Power Mgmt Control/Status) rsv2 = 0x34, // reserved ROMControl = 0x38, @@ -234,7 +234,7 @@ enum _DescStatusBit { RxSizeMask = 0x0000ffff /* * The asic could apparently do vlan, TSO, jumbo (sis191 only) and - * provide two (unused with Linux) Tx queues. No publically + * provide two (unused with Linux) Tx queues. No publicly * available documentation alas. */ }; diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 84d4167eee9a..cb317cd069ff 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1180,7 +1180,7 @@ sis900_init_rx_ring(struct net_device *net_dev) * * 630E equalizer workaround rule(Cyrus Huang 08/15) * PHY register 14h(Test) - * Bit 14: 0 -- Automatically dectect (default) + * Bit 14: 0 -- Automatically detect (default) * 1 -- Manually set Equalizer filter * Bit 13: 0 -- (Default) * 1 -- Speed up convergence of equalizer setting @@ -1192,7 +1192,7 @@ sis900_init_rx_ring(struct net_device *net_dev) * Then set equalizer value, and set Bit 14 to 1, Bit 9 to 0 * Link Off:Set Bit 13 to 1, Bit 14 to 0 * Calculate Equalizer value: - * When Link is ON and Bit 14 is 0, SIS900PHY will auto-dectect proper equalizer value. + * When Link is ON and Bit 14 is 0, SIS900PHY will auto-detect proper equalizer value. * When the equalizer is stable, this value is not a fixed value. It will be within * a small range(eg. 7~9). Then we get a minimum and a maximum value(eg. min=7, max=9) * 0 <= max <= 4 --> set equalizer to max @@ -1723,7 +1723,7 @@ static int sis900_rx(struct net_device *net_dev) rx_size = data_size - CRC_SIZE; #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - /* ``TOOLONG'' flag means jumbo packet recived. */ + /* ``TOOLONG'' flag means jumbo packet received. */ if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE) rx_status &= (~ ((unsigned int)TOOLONG)); #endif diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c index 8639a0884f5c..2fc5987b41dc 100644 --- a/drivers/net/skfp/ess.c +++ b/drivers/net/skfp/ess.c @@ -241,7 +241,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, != SMT_RDF_SUCCESS) || (sm->smt_tid != smc->ess.alloc_trans_id)) { - DB_ESS("ESS: Allocation Responce not accepted\n",0,0) ; + DB_ESS("ESS: Allocation Response not accepted\n",0,0) ; return fs; } @@ -393,7 +393,7 @@ static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhe * | T-NEG | * - - * - * T-NEG is discribed by the equation: + * T-NEG is described by the equation: * * (-) fddiMACT-NEG * T-NEG = ------------------- @@ -479,7 +479,7 @@ static void ess_send_response(struct s_smc *smc, struct smt_header *sm, void *p ; /* - * get and initialize the responce frame + * get and initialize the response frame */ if (sba_cmd == CHANGE_ALLOCATION) { if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY, @@ -578,7 +578,7 @@ static void ess_send_alc_req(struct s_smc *smc) } /* - * get and initialize the responce frame + * get and initialize the response frame */ if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST, sizeof(struct smt_sba_alc_req)))) diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index ca4e7bb6a5a8..a20ed1a98099 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c @@ -340,7 +340,7 @@ static void mac_counter_init(struct s_smc *smc) outpw(FM_A(FM_LCNTR),0) ; outpw(FM_A(FM_ECNTR),0) ; /* - * clear internal error counter stucture + * clear internal error counter structure */ ec = (u_long *)&smc->hw.fp.err_stats ; for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--) @@ -1262,8 +1262,8 @@ Function DOWNCALL/INTERN (SMT, fplustm.c) Para mode = 1 RX_ENABLE_ALLMULTI enable all multicasts 2 RX_DISABLE_ALLMULTI disable "enable all multicasts" - 3 RX_ENABLE_PROMISC enable promiscous - 4 RX_DISABLE_PROMISC disable promiscous + 3 RX_ENABLE_PROMISC enable promiscuous + 4 RX_DISABLE_PROMISC disable promiscuous 5 RX_ENABLE_NSA enable reception of NSA frames 6 RX_DISABLE_NSA disable reception of NSA frames diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h index f2f771d8be76..5a6c6122ccb0 100644 --- a/drivers/net/skfp/h/cmtdef.h +++ b/drivers/net/skfp/h/cmtdef.h @@ -19,7 +19,7 @@ /* * implementation specific constants - * MODIIFY THE FOLLWOING THREE DEFINES + * MODIIFY THE FOLLOWING THREE DEFINES */ #define AMDPLC /* if Amd PLC chip used */ #ifdef CONC @@ -456,7 +456,7 @@ struct s_plc { u_long soft_err ; /* error counter */ u_long parity_err ; /* error counter */ u_long ebuf_err ; /* error counter */ - u_long ebuf_cont ; /* continous error counter */ + u_long ebuf_cont ; /* continuous error counter */ u_long phyinv ; /* error counter */ u_long vsym_ctr ; /* error counter */ u_long mini_ctr ; /* error counter */ diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/skfp/h/fplustm.h index 6d738e1e2393..d43191ed938b 100644 --- a/drivers/net/skfp/h/fplustm.h +++ b/drivers/net/skfp/h/fplustm.h @@ -237,8 +237,8 @@ struct s_smt_fp { */ #define RX_ENABLE_ALLMULTI 1 /* enable all multicasts */ #define RX_DISABLE_ALLMULTI 2 /* disable "enable all multicasts" */ -#define RX_ENABLE_PROMISC 3 /* enable promiscous */ -#define RX_DISABLE_PROMISC 4 /* disable promiscous */ +#define RX_ENABLE_PROMISC 3 /* enable promiscuous */ +#define RX_DISABLE_PROMISC 4 /* disable promiscuous */ #define RX_ENABLE_NSA 5 /* enable reception of NSA frames */ #define RX_DISABLE_NSA 6 /* disable reception of NSA frames */ diff --git a/drivers/net/skfp/h/smc.h b/drivers/net/skfp/h/smc.h index 026a83b9f743..c774a95902f5 100644 --- a/drivers/net/skfp/h/smc.h +++ b/drivers/net/skfp/h/smc.h @@ -388,7 +388,7 @@ struct smt_config { u_long rmt_t_poll ; /* RMT : claim/beacon poller */ u_long rmt_dup_mac_behavior ; /* Flag for the beavior of SMT if * a Duplicate MAC Address was detected. - * FALSE: SMT will leave finaly the ring + * FALSE: SMT will leave finally the ring * TRUE: SMT will reinstert into the ring */ u_long mac_d_max ; /* MAC : D_Max timer value */ diff --git a/drivers/net/skfp/h/smt.h b/drivers/net/skfp/h/smt.h index 2976757a36fb..2030f9cbb24b 100644 --- a/drivers/net/skfp/h/smt.h +++ b/drivers/net/skfp/h/smt.h @@ -793,7 +793,7 @@ struct smt_rdf { } ; /* - * SBA Request Allocation Responce Frame + * SBA Request Allocation Response Frame */ struct smt_sba_alc_res { struct smt_header smt ; /* generic header */ diff --git a/drivers/net/skfp/h/supern_2.h b/drivers/net/skfp/h/supern_2.h index 5ba0b8306753..0b73690280f6 100644 --- a/drivers/net/skfp/h/supern_2.h +++ b/drivers/net/skfp/h/supern_2.h @@ -14,7 +14,7 @@ /* defines for AMD Supernet II chip set - the chips are refered to as + the chips are referred to as FPLUS Formac Plus PLC Physical Layer @@ -386,7 +386,7 @@ struct tx_queue { #define FM_MDISRCV (4<<8) /* disable receive function */ #define FM_MRES0 (5<<8) /* reserve */ #define FM_MLIMPROM (6<<8) /* limited-promiscuous mode */ -#define FM_MPROMISCOUS (7<<8) /* address detection : promiscous */ +#define FM_MPROMISCOUS (7<<8) /* address detection : promiscuous */ #define FM_SELSA 0x0800 /* select-short-address bit */ diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c index af5a755e269d..e26398b5a7dc 100644 --- a/drivers/net/skfp/hwmtm.c +++ b/drivers/net/skfp/hwmtm.c @@ -691,7 +691,7 @@ static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue) * interrupt service routine, handles the interrupt requests * generated by the FDDI adapter. * - * NOTE: The operating system dependent module must garantee that the + * NOTE: The operating system dependent module must guarantee that the * interrupts of the adapter are disabled when it calls fddi_isr. * * About the USE_BREAK_ISR mechanismn: diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c index 112d35b1bf0e..88d02d0a42c4 100644 --- a/drivers/net/skfp/pcmplc.c +++ b/drivers/net/skfp/pcmplc.c @@ -1680,7 +1680,7 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd) * Prevent counter from being wrapped after * hanging years in that interrupt. */ - plc->ebuf_cont++ ; /* Ebuf continous error */ + plc->ebuf_cont++ ; /* Ebuf continuous error */ } #ifdef SUPERNET_3 @@ -1717,8 +1717,8 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd) } #endif /* SUPERNET_3 */ } else { - /* Reset the continous error variable */ - plc->ebuf_cont = 0 ; /* reset Ebuf continous error */ + /* Reset the continuous error variable */ + plc->ebuf_cont = 0 ; /* reset Ebuf continuous error */ } if (cmd & PL_PHYINV) { /* physical layer invalid signal */ plc->phyinv++ ; diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c index 1e1bd0c201c8..08d94329c12f 100644 --- a/drivers/net/skfp/smt.c +++ b/drivers/net/skfp/smt.c @@ -219,7 +219,7 @@ void smt_emulate_token_ct(struct s_smc *smc, int mac_index) /* * Only when ring is up we will have a token count. The - * flag is unfortunatly a single instance value. This + * flag is unfortunately a single instance value. This * doesn't matter now, because we currently have only * one MAC instance. */ diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 507addcaffa3..51c0214ac25c 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -1038,7 +1038,7 @@ enum { PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ - PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */ + PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ @@ -1721,8 +1721,8 @@ enum { GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ - GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */ - GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */ + GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ @@ -2227,7 +2227,7 @@ enum { XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */ XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */ XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */ - XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occured */ + XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occurred */ XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */ XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */ XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */ diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2a91868788f7..ff8d262dc276 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -932,7 +932,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); - /* On chips without ram buffer, pause is controled by MAC level */ + /* On chips without ram buffer, pause is controlled by MAC level */ if (!(hw->flags & SKY2_HW_RAM_BUFFER)) { /* Pause threshold is scaled by 8 in bytes */ if (hw->chip_id == CHIP_ID_YUKON_FE_P && @@ -3255,7 +3255,7 @@ static void sky2_reset(struct sky2_hw *hw) /* Take device down (offline). * Equivalent to doing dev_stop() but this does not - * inform upper layers of the transistion. + * inform upper layers of the transition. */ static void sky2_detach(struct net_device *dev) { diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 6861b0e8db9a..0c6d10c5f053 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1194,7 +1194,7 @@ enum { PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ - PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */ + PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ @@ -1725,8 +1725,8 @@ enum { GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ - GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */ - GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */ + GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 68d48ab6eacf..5f53fbbf67be 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -921,7 +921,7 @@ static const char * chip_ids[ 16 ] = { * Hack Alert: Some setups just can't write 8 or 16 bits reliably when not * aligned to a 32 bit boundary. I tell you that does exist! * Fortunately the affected register accesses can be easily worked around - * since we can write zeroes to the preceeding 16 bits without adverse + * since we can write zeroes to the preceding 16 bits without adverse * effects and use a 32-bit access. * * Enforce it on any 32-bit capable setup for now. diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 1566259c1f27..c498b720b532 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1669,7 +1669,7 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op) } if (e2cmd & E2P_CMD_EPC_TIMEOUT_) { - SMSC_TRACE(DRV, "Error occured during eeprom operation"); + SMSC_TRACE(DRV, "Error occurred during eeprom operation"); return -EINVAL; } diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index b09ee1c319e8..4c92ad8be765 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -364,7 +364,7 @@ static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op) } if (e2cmd & E2P_CMD_EPC_TIMEOUT_) { - smsc_info(HW, "Error occured during eeprom operation"); + smsc_info(HW, "Error occurred during eeprom operation"); return -EINVAL; } diff --git a/drivers/net/stmmac/norm_desc.c b/drivers/net/stmmac/norm_desc.c index cd0cc76f7a1c..029c2a2cf524 100644 --- a/drivers/net/stmmac/norm_desc.c +++ b/drivers/net/stmmac/norm_desc.c @@ -67,7 +67,7 @@ static int ndesc_get_tx_len(struct dma_desc *p) /* This function verifies if each incoming frame has some errors * and, if required, updates the multicast statistics. - * In case of success, it returns csum_none becasue the device + * In case of success, it returns csum_none because the device * is not able to compute the csum in HW. */ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, struct dma_desc *p) diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index 8db88945b889..4943e975a731 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h @@ -185,7 +185,7 @@ #define BIGMAC_RXCFG_ENABLE 0x00000001 /* Enable the receiver */ #define BIGMAC_RXCFG_FIFO 0x0000000e /* Default rx fthresh... */ #define BIGMAC_RXCFG_PSTRIP 0x00000020 /* Pad byte strip enable */ -#define BIGMAC_RXCFG_PMISC 0x00000040 /* Enable promiscous mode */ +#define BIGMAC_RXCFG_PMISC 0x00000040 /* Enable promiscuous mode */ #define BIGMAC_RXCFG_DERR 0x00000080 /* Disable error checking */ #define BIGMAC_RXCFG_DCRCS 0x00000100 /* Disable CRC stripping */ #define BIGMAC_RXCFG_ME 0x00000200 /* Receive packets addressed to me */ diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index c1a344829b54..d3be735c4719 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1150,7 +1150,7 @@ static void gem_pcs_reinit_adv(struct gem *gp) val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO); writel(val, gp->regs + PCS_CFG); - /* Advertise all capabilities except assymetric + /* Advertise all capabilities except asymmetric * pause. */ val = readl(gp->regs + PCS_MIIADV); diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index 756b5bf3aa89..64f278360d89 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h @@ -223,7 +223,7 @@ /* BigMac receive config register. */ #define BIGMAC_RXCFG_ENABLE 0x00000001 /* Enable the receiver */ #define BIGMAC_RXCFG_PSTRIP 0x00000020 /* Pad byte strip enable */ -#define BIGMAC_RXCFG_PMISC 0x00000040 /* Enable promiscous mode */ +#define BIGMAC_RXCFG_PMISC 0x00000040 /* Enable promiscuous mode */ #define BIGMAC_RXCFG_DERR 0x00000080 /* Disable error checking */ #define BIGMAC_RXCFG_DCRCS 0x00000100 /* Disable CRC stripping */ #define BIGMAC_RXCFG_REJME 0x00000200 /* Reject packets addressed to me */ diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index b6eec8cea209..7ca51cebcddd 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -119,13 +119,13 @@ struct tc35815_regs { /* * Bit assignments */ -/* DMA_Ctl bit asign ------------------------------------------------------- */ +/* DMA_Ctl bit assign ------------------------------------------------------- */ #define DMA_RxAlign 0x00c00000 /* 1:Reception Alignment */ #define DMA_RxAlign_1 0x00400000 #define DMA_RxAlign_2 0x00800000 #define DMA_RxAlign_3 0x00c00000 #define DMA_M66EnStat 0x00080000 /* 1:66MHz Enable State */ -#define DMA_IntMask 0x00040000 /* 1:Interupt mask */ +#define DMA_IntMask 0x00040000 /* 1:Interrupt mask */ #define DMA_SWIntReq 0x00020000 /* 1:Software Interrupt request */ #define DMA_TxWakeUp 0x00010000 /* 1:Transmit Wake Up */ #define DMA_RxBigE 0x00008000 /* 1:Receive Big Endian */ @@ -134,11 +134,11 @@ struct tc35815_regs { #define DMA_PowrMgmnt 0x00001000 /* 1:Power Management */ #define DMA_DmBurst_Mask 0x000001fc /* DMA Burst size */ -/* RxFragSize bit asign ---------------------------------------------------- */ +/* RxFragSize bit assign ---------------------------------------------------- */ #define RxFrag_EnPack 0x00008000 /* 1:Enable Packing */ #define RxFrag_MinFragMask 0x00000ffc /* Minimum Fragment */ -/* MAC_Ctl bit asign ------------------------------------------------------- */ +/* MAC_Ctl bit assign ------------------------------------------------------- */ #define MAC_Link10 0x00008000 /* 1:Link Status 10Mbits */ #define MAC_EnMissRoll 0x00002000 /* 1:Enable Missed Roll */ #define MAC_MissRoll 0x00000400 /* 1:Missed Roll */ @@ -152,7 +152,7 @@ struct tc35815_regs { #define MAC_HaltImm 0x00000002 /* 1:Halt Immediate */ #define MAC_HaltReq 0x00000001 /* 1:Halt request */ -/* PROM_Ctl bit asign ------------------------------------------------------ */ +/* PROM_Ctl bit assign ------------------------------------------------------ */ #define PROM_Busy 0x00008000 /* 1:Busy (Start Operation) */ #define PROM_Read 0x00004000 /*10:Read operation */ #define PROM_Write 0x00002000 /*01:Write operation */ @@ -162,7 +162,7 @@ struct tc35815_regs { #define PROM_Addr_Ena 0x00000030 /*11xxxx:PROM Write enable */ /*00xxxx: disable */ -/* CAM_Ctl bit asign ------------------------------------------------------- */ +/* CAM_Ctl bit assign ------------------------------------------------------- */ #define CAM_CompEn 0x00000010 /* 1:CAM Compare Enable */ #define CAM_NegCAM 0x00000008 /* 1:Reject packets CAM recognizes,*/ /* accept other */ @@ -170,7 +170,7 @@ struct tc35815_regs { #define CAM_GroupAcc 0x00000002 /* 1:Multicast assept */ #define CAM_StationAcc 0x00000001 /* 1:unicast accept */ -/* CAM_Ena bit asign ------------------------------------------------------- */ +/* CAM_Ena bit assign ------------------------------------------------------- */ #define CAM_ENTRY_MAX 21 /* CAM Data entry max count */ #define CAM_Ena_Mask ((1<ifr_data, sizeof(data)); if (error) { - pr_err("cant copy from user\n"); + pr_err("can't copy from user\n"); RET(-EFAULT); } DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]); @@ -999,7 +999,7 @@ static inline void bdx_rxdb_free_elem(struct rxdb *db, int n) * * RxD fifo is smaller than RxF fifo by design. Upon high load, RxD will be * filled and packets will be dropped by nic without getting into host or - * cousing interrupt. Anyway, in that condition, host has no chance to proccess + * cousing interrupt. Anyway, in that condition, host has no chance to process * all packets, but dropping in nic is cheaper, since it takes 0 cpu cycles */ @@ -1200,8 +1200,8 @@ static void bdx_recycle_skb(struct bdx_priv *priv, struct rxd_desc *rxdd) RET(); } -/* bdx_rx_receive - recieves full packets from RXD fifo and pass them to OS - * NOTE: a special treatment is given to non-continous descriptors +/* bdx_rx_receive - receives full packets from RXD fifo and pass them to OS + * NOTE: a special treatment is given to non-continuous descriptors * that start near the end, wraps around and continue at the beginning. a second * part is copied right after the first, and then descriptor is interpreted as * normal. fifo has an extra space to allow such operations @@ -1584,9 +1584,9 @@ err_mem: } /* - * bdx_tx_space - calculates avalable space in TX fifo + * bdx_tx_space - calculates available space in TX fifo * @priv - NIC private structure - * Returns avaliable space in TX fifo in bytes + * Returns available space in TX fifo in bytes */ static inline int bdx_tx_space(struct bdx_priv *priv) { diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index b6ba8601e2b5..c5642fefc9e7 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -502,7 +502,7 @@ struct txd_desc { #define GMAC_RX_FILTER_ACRC 0x0010 /* accept crc error */ #define GMAC_RX_FILTER_AM 0x0008 /* accept multicast */ #define GMAC_RX_FILTER_AB 0x0004 /* accept broadcast */ -#define GMAC_RX_FILTER_PRM 0x0001 /* [0:1] promiscous mode */ +#define GMAC_RX_FILTER_PRM 0x0001 /* [0:1] promiscuous mode */ #define MAX_FRAME_AB_VAL 0x3fff /* 13:0 */ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 73c942d85f07..b8c5f35577e4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9712,7 +9712,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, eeprom->len += b_count; } - /* read bytes upto the last 4 byte boundary */ + /* read bytes up to the last 4 byte boundary */ pd = &data[eeprom->len]; for (i = 0; i < (len - (len & 3)); i += 4) { ret = tg3_nvram_read_be32(tp, offset + i, &val); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 73884b69b749..5e96706ad108 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2130,7 +2130,7 @@ #define MII_TG3_DSP_EXP96 0x0f96 #define MII_TG3_DSP_EXP97 0x0f97 -#define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ +#define MII_TG3_AUX_CTRL 0x18 /* auxiliary control register */ #define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010 #define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE 0x0020 @@ -2146,7 +2146,7 @@ #define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400 #define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000 -#define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */ +#define MII_TG3_AUX_STAT 0x19 /* auxiliary status register */ #define MII_TG3_AUX_STAT_LPASS 0x0004 #define MII_TG3_AUX_STAT_SPDMASK 0x0700 #define MII_TG3_AUX_STAT_10HALF 0x0100 diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 10800f16a231..8a3b191b195b 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -208,7 +208,7 @@ static void print_rx_state(struct net_device *dev) * passing/getting the next value from the nic. As with all requests * on this nic it has to be done in two stages, a) tell the nic which * memory address you want to access and b) pass/get the value from the nic. - * With the EEProm, you have to wait before and inbetween access a) and b). + * With the EEProm, you have to wait before and between access a) and b). * As this is only read at initialization time and the wait period is very * small we shouldn't have to worry about scheduling issues. */ diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 785ad1a2157b..2bedc0ace812 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -73,7 +73,7 @@ static void madgemc_setint(struct net_device *dev, int val); static irqreturn_t madgemc_interrupt(int irq, void *dev_id); /* - * These work around paging, however they don't guarentee you're on the + * These work around paging, however they don't guarantee you're on the * right page. */ #define SIFREADB(reg) (inb(dev->base_addr + ((reg<0x8)?reg:reg-0x8))) @@ -387,7 +387,7 @@ getout: * both with their own disadvantages... * * 1) Read in the SIFSTS register from the TMS controller. This - * is guarenteed to be accurate, however, there's a fairly + * is guaranteed to be accurate, however, there's a fairly * large performance penalty for doing so: the Madge chips * must request the register from the Eagle, the Eagle must * read them from its internal bus, and then take the route @@ -454,7 +454,7 @@ static irqreturn_t madgemc_interrupt(int irq, void *dev_id) } /* - * Set the card to the prefered ring speed. + * Set the card to the preferred ring speed. * * Unlike newer cards, the MC16/32 have their speed selection * circuit connected to the Madge ASICs and not to the TMS380 diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 63db5a6762ae..d9044aba7afa 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -393,7 +393,7 @@ static int smctr_alloc_shared_memory(struct net_device *dev) tp->rx_bdb_end[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0); /* Allocate MAC transmit buffers. - * MAC Tx Buffers doen't have to be on an ODD Boundry. + * MAC Tx Buffers doen't have to be on an ODD Boundary. */ tp->tx_buff_head[MAC_QUEUE] = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[MAC_QUEUE]); @@ -415,7 +415,7 @@ static int smctr_alloc_shared_memory(struct net_device *dev) /* Allocate Non-MAC transmit buffers. * ?? For maximum Netware performance, put Tx Buffers on - * ODD Boundry and then restore malloc to Even Boundrys. + * ODD Boundary and then restore malloc to Even Boundrys. */ smctr_malloc(dev, 1L); tp->tx_buff_head[NON_MAC_QUEUE] @@ -1311,7 +1311,7 @@ static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev) mem_used += sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE]; /* Allocate MAC transmit buffers. - * MAC transmit buffers don't have to be on an ODD Boundry. + * MAC transmit buffers don't have to be on an ODD Boundary. */ mem_used += tp->tx_buff_size[MAC_QUEUE]; @@ -1325,7 +1325,7 @@ static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev) /* Allocate Non-MAC transmit buffers. * For maximum Netware performance, put Tx Buffers on - * ODD Boundry,and then restore malloc to Even Boundrys. + * ODD Boundary,and then restore malloc to Even Boundrys. */ mem_used += 1L; mem_used += tp->tx_buff_size[NON_MAC_QUEUE]; @@ -3069,8 +3069,8 @@ static int smctr_load_node_addr(struct net_device *dev) * disabled.!? * * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask - * has any multi-cast or promiscous bits set, the receive_mask needs to - * be changed to clear the multi-cast or promiscous mode bits, the lobe_test + * has any multi-cast or promiscuous bits set, the receive_mask needs to + * be changed to clear the multi-cast or promiscuous mode bits, the lobe_test * run, and then the receive mask set back to its original value if the test * is successful. */ diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h index 60b30ee38dcb..e5a617c586c2 100644 --- a/drivers/net/tokenring/tms380tr.h +++ b/drivers/net/tokenring/tms380tr.h @@ -442,7 +442,7 @@ typedef struct { #define PASS_FIRST_BUF_ONLY 0x0100 /* Passes only first internal buffer * of each received frame; FrameSize * of RPLs must contain internal - * BUFFER_SIZE bits for promiscous mode. + * BUFFER_SIZE bits for promiscuous mode. */ #define ENABLE_FULL_DUPLEX_SELECTION 0x2000 /* Enable the use of full-duplex diff --git a/drivers/net/tsi108_eth.h b/drivers/net/tsi108_eth.h index 5a77ae6c5f36..5fee7d78dc6d 100644 --- a/drivers/net/tsi108_eth.h +++ b/drivers/net/tsi108_eth.h @@ -305,9 +305,9 @@ #define TSI108_TX_CRC (1 << 5) /* Generate CRC for this packet */ #define TSI108_TX_INT (1 << 14) /* Generate an IRQ after frag. processed */ #define TSI108_TX_RETRY (0xf << 16) /* 4 bit field indicating num. of retries */ -#define TSI108_TX_COL (1 << 20) /* Set if a collision occured */ -#define TSI108_TX_LCOL (1 << 24) /* Set if a late collision occured */ -#define TSI108_TX_UNDER (1 << 25) /* Set if a FIFO underrun occured */ +#define TSI108_TX_COL (1 << 20) /* Set if a collision occurred */ +#define TSI108_TX_LCOL (1 << 24) /* Set if a late collision occurred */ +#define TSI108_TX_UNDER (1 << 25) /* Set if a FIFO underrun occurred */ #define TSI108_TX_RLIM (1 << 26) /* Set if the retry limit was reached */ #define TSI108_TX_OK (1 << 30) /* Set if the frame TX was successful */ #define TSI108_TX_OWN (1 << 31) /* Set if the device owns the descriptor */ @@ -332,7 +332,7 @@ typedef struct { #define TSI108_RX_RUNT (1 << 4)/* Packet is less than minimum size */ #define TSI108_RX_HASH (1 << 7)/* Hash table match */ #define TSI108_RX_BAD (1 << 8) /* Bad frame */ -#define TSI108_RX_OVER (1 << 9) /* FIFO overrun occured */ +#define TSI108_RX_OVER (1 << 9) /* FIFO overrun occurred */ #define TSI108_RX_TRUNC (1 << 11) /* Packet truncated due to excess length */ #define TSI108_RX_CRC (1 << 12) /* Packet had a CRC error */ #define TSI108_RX_INT (1 << 13) /* Generate an IRQ after frag. processed */ diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 4dbd493b996b..efaa1d69b720 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -79,7 +79,7 @@ every usable DECchip board, I pinched Donald's 'next_module' field to link my modules together. - Upto 15 EISA cards can be supported under this driver, limited primarily + Up to 15 EISA cards can be supported under this driver, limited primarily by the available IRQ lines. I have checked different configurations of multiple depca, EtherWORKS 3 cards and de4x5 cards and have not found a problem yet (provided you have at least depca.c v0.38) ... @@ -517,7 +517,7 @@ struct mii_phy { u_int mci; /* 21142 MII Connector Interrupt info */ }; -#define DE4X5_MAX_PHY 8 /* Allow upto 8 attached PHY devices per board */ +#define DE4X5_MAX_PHY 8 /* Allow up to 8 attached PHY devices per board */ struct sia_phy { u_char mc; /* Media Code */ @@ -1436,7 +1436,7 @@ de4x5_sw_reset(struct net_device *dev) /* Poll for setup frame completion (adapter interrupts are disabled now) */ - for (j=0, i=0;(i<500) && (j==0);i++) { /* Upto 500ms delay */ + for (j=0, i=0;(i<500) && (j==0);i++) { /* Up to 500ms delay */ mdelay(1); if ((s32)le32_to_cpu(lp->tx_ring[lp->tx_new].status) >= 0) j=1; } diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 7064e035757a..fb07f48910ae 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -1224,7 +1224,7 @@ static void dmfe_timer(unsigned long data) /* If chip reports that link is failed it could be because external - PHY link status pin is not conected correctly to chip + PHY link status pin is not connected correctly to chip To be sure ask PHY too. */ diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 3031ed9c4a1a..296486bf0956 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -115,7 +115,7 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) 0x02, /* phy reset sequence length */ 0x01, 0x00, /* phy reset sequence */ 0x00, 0x78, /* media capabilities */ - 0x00, 0xe0, /* nway advertisment */ + 0x00, 0xe0, /* nway advertisement */ 0x00, 0x05, /* fdx bit map */ 0x00, 0x06 /* ttm bit map */ }; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 7fa5ec2de942..82653cb07857 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -846,7 +846,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) if(typhoon_num_free_tx(txRing) < (numDesc + 2)) { netif_stop_queue(dev); - /* A Tx complete IRQ could have gotten inbetween, making + /* A Tx complete IRQ could have gotten between, making * the ring free again. Only need to recheck here, since * Tx is serialized. */ diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 055b87ab4f07..d12fcad145e9 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -80,7 +80,7 @@ struct ucc_geth { frames) received that were between 128 (Including FCS length==4) and 255 octets */ u32 txok; /* Total number of octets residing in frames - that where involved in successfull + that where involved in successful transmission */ u16 txcf; /* Total number of PAUSE control frames transmitted by this MAC */ @@ -759,7 +759,7 @@ struct ucc_geth_hardware_statistics { frames) received that were between 128 (Including FCS length==4) and 255 octets */ u32 txok; /* Total number of octets residing in frames - that where involved in successfull + that where involved in successful transmission */ u16 txcf; /* Total number of PAUSE control frames transmitted by this MAC */ diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index 5f3b97668e63..555284761313 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -190,7 +190,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* * EEM packet header format: - * b0..14: EEM type dependant (Data or Command) + * b0..14: EEM type dependent (Data or Command) * b15: bmType */ header = get_unaligned_le16(skb->data); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 7dc84971f26f..ad0298f9b5f9 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1221,7 +1221,7 @@ static void kaweth_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (!kaweth) { - dev_warn(&intf->dev, "unregistering non-existant device\n"); + dev_warn(&intf->dev, "unregistering non-existent device\n"); return; } netdev = kaweth->net; diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 5e7f069eab53..eb5d75df5d5d 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1861,7 +1861,7 @@ static void rhine_restart_tx(struct net_device *dev) { u32 intr_status; /* - * If new errors occured, we need to sort them out before doing Tx. + * If new errors occurred, we need to sort them out before doing Tx. * In that case the ISR will be back here RSN anyway. */ intr_status = get_intr_status(dev); @@ -1887,7 +1887,7 @@ static void rhine_restart_tx(struct net_device *dev) { /* This should never happen */ if (debug > 1) printk(KERN_WARNING "%s: rhine_restart_tx() " - "Another error occured %8.8x.\n", + "Another error occurred %8.8x.\n", dev->name, intr_status); } diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 0d6fec6b7d93..4fe051753842 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -292,7 +292,7 @@ VELOCITY_PARAM(DMA_length, "DMA length"); /* IP_byte_align[] is used for IP header DWORD byte aligned 0: indicate the IP header won't be DWORD byte aligned.(Default) . 1: indicate the IP header will be DWORD byte aligned. - In some enviroment, the IP header should be DWORD byte aligned, + In some environment, the IP header should be DWORD byte aligned, or the packet will be droped when we receive it. (eg: IPVS) */ VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned"); @@ -1994,7 +1994,7 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb) * @dev: network device * * Replace the current skb that is scheduled for Rx processing by a - * shorter, immediatly allocated skb, if the received packet is small + * shorter, immediately allocated skb, if the received packet is small * enough. This function returns a negative value if the received * packet is too big or if memory is exhausted. */ diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index cc14b4a75048..0d47c3a05307 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -892,7 +892,7 @@ vmxnet3_prepare_tso(struct sk_buff *skb, * Transmits a pkt thru a given tq * Returns: * NETDEV_TX_OK: descriptors are setup successfully - * NETDEV_TX_OK: error occured, the pkt is dropped + * NETDEV_TX_OK: error occurred, the pkt is dropped * NETDEV_TX_BUSY: tx ring is full, queue is stopped * * Side-effects: @@ -2685,7 +2685,7 @@ vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac) * Enable MSIx vectors. * Returns : * 0 on successful enabling of required vectors, - * VMXNET3_LINUX_MIN_MSIX_VECT when only minumum number of vectors required + * VMXNET3_LINUX_MIN_MSIX_VECT when only minimum number of vectors required * could be enabled. * number of vectors which can be enabled otherwise (this number is smaller * than VMXNET3_LINUX_MIN_MSIX_VECT) diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index e74e4b42592d..401bebf59502 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c @@ -187,7 +187,7 @@ vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action, VXGE_HW_DEF_DEVICE_POLL_MILLIS); /* The __vxge_hw_device_register_poll can udelay for a significant - * amount of time, blocking other proccess from the CPU. If it delays + * amount of time, blocking other process from the CPU. If it delays * for ~5secs, a NMI error can occur. A way around this is to give up * the processor via msleep, but this is not allowed is under lock. * So, only allow it to sleep for ~4secs if open. Otherwise, delay for diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 395423aeec00..aff68c1118d4 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -2282,7 +2282,7 @@ vxge_alarm_msix_handle(int irq, void *dev_id) VXGE_HW_VPATH_MSIX_ACTIVE) + VXGE_ALARM_MSIX_ID; for (i = 0; i < vdev->no_of_vpath; i++) { - /* Reduce the chance of loosing alarm interrupts by masking + /* Reduce the chance of losing alarm interrupts by masking * the vector. A pending bit will be set if an alarm is * generated and on unmask the interrupt will be fired. */ @@ -2788,7 +2788,7 @@ static int vxge_open(struct net_device *dev) } /* Enable vpath to sniff all unicast/multicast traffic that not - * addressed to them. We allow promiscous mode for PF only + * addressed to them. We allow promiscuous mode for PF only */ val64 = 0; @@ -2890,7 +2890,7 @@ out0: return ret; } -/* Loop throught the mac address list and delete all the entries */ +/* Loop through the mac address list and delete all the entries */ static void vxge_free_mac_add_list(struct vxge_vpath *vpath) { @@ -2957,7 +2957,7 @@ static int do_vxge_close(struct net_device *dev, int do_io) val64); } - /* Remove the function 0 from promiscous mode */ + /* Remove the function 0 from promiscuous mode */ vxge_hw_mgmt_reg_write(vdev->devh, vxge_hw_mgmt_reg_type_mrpcim, 0, diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index 8674f331311c..2638b8d97b8f 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c @@ -1111,7 +1111,7 @@ void vxge_hw_channel_dtr_free(struct __vxge_hw_channel *channel, void *dtrh) * vxge_hw_channel_dtr_count * @channel: Channel handle. Obtained via vxge_hw_channel_open(). * - * Retreive number of DTRs available. This function can not be called + * Retrieve number of DTRs available. This function can not be called * from data path. ring_initial_replenishi() is the only user. */ int vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel) @@ -2060,7 +2060,7 @@ enum vxge_hw_status vxge_hw_vpath_promisc_enable( vpath = vp->vpath; - /* Enable promiscous mode for function 0 only */ + /* Enable promiscuous mode for function 0 only */ if (!(vpath->hldev->access_rights & VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) return VXGE_HW_OK; diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 9d9dfda4c7ab..6c2fc0b72af5 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h @@ -681,7 +681,7 @@ struct vxge_hw_xmac_aggr_stats { * @rx_red_discard: Count of received frames that are discarded because of RED * (Random Early Discard). * @rx_xgmii_ctrl_err_cnt: Maintains a count of unexpected or misplaced control - * characters occuring between times of normal data transmission + * characters occurring between times of normal data transmission * (i.e. not included in RX_XGMII_DATA_ERR_CNT). This counter is * incremented when either - * 1) The Reconciliation Sublayer (RS) is expecting one control diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 10bafd59f9c3..6fb6f8e667d0 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -329,7 +329,7 @@ static int startmicrocode(struct cosa_data *cosa, int address); static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len); static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id); -/* Auxilliary functions */ +/* Auxiliary functions */ static int get_wait_data(struct cosa_data *cosa); static int put_wait_data(struct cosa_data *cosa, int data); static int puthexnumber(struct cosa_data *cosa, int number); diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 4578e5b4b411..acb9ea830628 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -56,7 +56,7 @@ * IV. Notes * The current error (XDU, RFO) recovery code is untested. * So far, RDO takes his RX channel down and the right sequence to enable it - * again is still a mistery. If RDO happens, plan a reboot. More details + * again is still a mystery. If RDO happens, plan a reboot. More details * in the code (NB: as this happens, TX still works). * Don't mess the cables during operation, especially on DTE ports. I don't * suggest it for DCE either but at least one can get some messages instead @@ -1065,7 +1065,7 @@ static int dscc4_open(struct net_device *dev) /* * Due to various bugs, there is no way to reliably reset a - * specific port (manufacturer's dependant special PCI #RST wiring + * specific port (manufacturer's dependent special PCI #RST wiring * apart: it affects all ports). Thus the device goes in the best * silent mode possible at dscc4_close() time and simply claims to * be up if it's opened again. It still isn't possible to change @@ -1230,9 +1230,9 @@ static inline int dscc4_check_clock_ability(int port) * scaling. Of course some rounding may take place. * - no high speed mode (40Mb/s). May be trivial to do but I don't have an * appropriate external clocking device for testing. - * - no time-slot/clock mode 5: shameless lazyness. + * - no time-slot/clock mode 5: shameless laziness. * - * The clock signals wiring can be (is ?) manufacturer dependant. Good luck. + * The clock signals wiring can be (is ?) manufacturer dependent. Good luck. * * BIG FAT WARNING: if the device isn't provided enough clocking signal, it * won't pass the init sequence. For example, straight back-to-back DTE without diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index 48edc5f4dac8..e817583e6ec5 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -15,7 +15,7 @@ * The hardware does the bus handling to avoid the need for delays between * touching control registers. * - * Port B isnt wired (why - beats me) + * Port B isn't wired (why - beats me) * * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa */ diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 6c571e198835..f1e1643dc3eb 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -178,7 +178,7 @@ * * The resulting average clock frequency (assuming 33.333 MHz oscillator) is: * freq = 66.666 MHz / (A + (B + 1) / (C + 1)) - * minumum freq = 66.666 MHz / (A + 1) + * minimum freq = 66.666 MHz / (A + 1) * maximum freq = 66.666 MHz / A * * Example: A = 2, B = 2, C = 7, CLOCK_CR register = 2 << 22 | 2 << 12 | 7 @@ -230,7 +230,7 @@ #define PKT_PIPE_MODE_WRITE 0x57 /* HDLC packet status values - desc->status */ -#define ERR_SHUTDOWN 1 /* stop or shutdown occurrance */ +#define ERR_SHUTDOWN 1 /* stop or shutdown occurrence */ #define ERR_HDLC_ALIGN 2 /* HDLC alignment error */ #define ERR_HDLC_FCS 3 /* HDLC Frame Check Sum error */ #define ERR_RXFREE_Q_EMPTY 4 /* RX-free queue became empty while receiving diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 70feb84df670..b7f2358d23be 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -24,7 +24,7 @@ * * Linux driver notes: * Linux uses the device struct lmc_private to pass private information - * arround. + * around. * * The initialization portion of this driver (the lmc_reset() and the * lmc_dec_reset() functions, as well as the led controls and the diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h index 65d01978e784..01ad45218d19 100644 --- a/drivers/net/wan/lmc/lmc_var.h +++ b/drivers/net/wan/lmc/lmc_var.h @@ -180,7 +180,7 @@ struct lmc___ctl { /* - * Carefull, look at the data sheet, there's more to this + * Careful, look at the data sheet, there's more to this * structure than meets the eye. It should probably be: * * struct tulip_desc_t { @@ -380,7 +380,7 @@ struct lmc___softc { /* CSR6 settings */ #define OPERATION_MODE 0x00000200 /* Full Duplex */ #define PROMISC_MODE 0x00000040 /* Promiscuous Mode */ -#define RECIEVE_ALL 0x40000000 /* Recieve All */ +#define RECIEVE_ALL 0x40000000 /* Receive All */ #define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames */ /* Dec control registers CSR6 as well */ @@ -398,7 +398,7 @@ struct lmc___softc { #define TULIP_CMD_RECEIVEALL 0x40000000L /* (RW) Receivel all frames? */ #define TULIP_CMD_MUSTBEONE 0x02000000L /* (RW) Must Be One (21140) */ #define TULIP_CMD_TXTHRSHLDCTL 0x00400000L /* (RW) Transmit Threshold Mode (21140) */ -#define TULIP_CMD_STOREFWD 0x00200000L /* (RW) Store and Foward (21140) */ +#define TULIP_CMD_STOREFWD 0x00200000L /* (RW) Store and Forward (21140) */ #define TULIP_CMD_NOHEARTBEAT 0x00080000L /* (RW) No Heartbeat (21140) */ #define TULIP_CMD_PORTSELECT 0x00040000L /* (RW) Post Select (100Mb) (21140) */ #define TULIP_CMD_FULLDUPLEX 0x00000200L /* (RW) Full Duplex Mode */ diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index 93956861ea21..0806232e0f8f 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -542,7 +542,7 @@ static void z8530_dma_tx(struct z8530_channel *chan) z8530_tx(chan); return; } - /* This shouldnt occur in DMA mode */ + /* This shouldn't occur in DMA mode */ printk(KERN_ERR "DMA tx - bogus event!\n"); z8530_tx(chan); } @@ -1219,7 +1219,7 @@ static const char *z8530_type_name[]={ * @io: the port value in question * * Describe a Z8530 in a standard format. We must pass the I/O as - * the port offset isnt predictable. The main reason for this function + * the port offset isn't predictable. The main reason for this function * is to try and get a common format of report. */ @@ -1588,7 +1588,7 @@ static void z8530_rx_done(struct z8530_channel *c) unsigned long flags; /* - * Complete this DMA. Neccessary to find the length + * Complete this DMA. Necessary to find the length */ flags=claim_dma_lock(); @@ -1657,7 +1657,7 @@ static void z8530_rx_done(struct z8530_channel *c) * fifo length for this. Thus we want to flip to the new * buffer and then mess around copying and allocating * things. For the current case it doesn't matter but - * if you build a system where the sync irq isnt blocked + * if you build a system where the sync irq isn't blocked * by the kernel IRQ disable then you need only block the * sync IRQ for the RT_LOCK area. * diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index 12b84ed0e38a..727d728649b7 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -378,7 +378,7 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, * the device's state as sometimes we need to do a link-renew (the BS * wants us to renew a DHCP lease, for example). * - * In fact, doc says that everytime we get a link-up, we should do a + * In fact, doc says that every time we get a link-up, we should do a * DHCP negotiation... */ static @@ -675,7 +675,7 @@ void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code) * - the ack message wasn't formatted correctly * * The returned skb has been allocated with wimax_msg_to_user_alloc(), - * it contains the reponse in a netlink attribute and is ready to be + * it contains the response in a netlink attribute and is ready to be * passed up to user space with wimax_msg_to_user_send(). To access * the payload and its length, use wimax_msg_{data,len}() on the skb. * diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 65bc334ed57b..47cae7150bc1 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -654,7 +654,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) if (result == -EUCLEAN) { /* * We come here because the reset during operational mode - * wasn't successully done and need to proceed to a bus + * wasn't successfully done and need to proceed to a bus * reset. For the dev_reset_handle() to be able to handle * the reset event later properly, we restore boot_mode back * to the state before previous reset. ie: just like we are @@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(i2400m_error_recovery); * Alloc the command and ack buffers for boot mode * * Get the buffers needed to deal with boot mode messages. These - * buffers need to be allocated before the sdio recieve irq is setup. + * buffers need to be allocated before the sdio receive irq is setup. */ static int i2400m_bm_buf_alloc(struct i2400m *i2400m) diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 8b55a5b14152..85dadd5bf4be 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -54,7 +54,7 @@ * endpoint and read from it in the notification endpoint. In SDIO we * talk to it via the write address and read from the read address. * - * Upon entrance to boot mode, the device sends (preceeded with a few + * Upon entrance to boot mode, the device sends (preceded with a few * zero length packets (ZLPs) on the notification endpoint in USB) a * reboot barker (4 le32 words with the same value). We ack it by * sending the same barker to the device. The device acks with a @@ -1589,7 +1589,7 @@ int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags) i2400m->fw_name = fw_name; ret = i2400m_fw_bootstrap(i2400m, fw, flags); release_firmware(fw); - if (ret >= 0) /* firmware loaded succesfully */ + if (ret >= 0) /* firmware loaded successfully */ break; i2400m->fw_name = NULL; } diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index eb80243e22df..6650fde99e1d 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -105,14 +105,14 @@ static inline void edc_init(struct edc *edc) * * @edc: pointer to error density counter. * @max_err: maximum number of errors we can accept over the timeframe - * @timeframe: lenght of the timeframe (in jiffies). + * @timeframe: length of the timeframe (in jiffies). * * Returns: !0 1 if maximum acceptable errors per timeframe has been * exceeded. 0 otherwise. * * This is way to determine if the number of acceptable errors per time * period has been exceeded. It is not accurate as there are cases in which - * this scheme will not work, for example if there are periodic occurences + * this scheme will not work, for example if there are periodic occurrences * of errors that straddle updates to the start time. This scheme is * sufficient for our usage. * @@ -204,7 +204,7 @@ enum { * usb_autopm_get/put_interface() barriers when executing * commands. See doc in i2400mu_suspend() for more information. * - * @rx_size_auto_shrink: if true, the rx_size is shrinked + * @rx_size_auto_shrink: if true, the rx_size is shrunk * automatically based on the average size of the received * transactions. This allows the receive code to allocate smaller * chunks of memory and thus reduce pressure on the memory diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 030cbfd31704..5eacc653a94d 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -526,7 +526,7 @@ struct i2400m_barker_db; * * @barker: barker type that the device uses; this is initialized by * i2400m_is_boot_barker() the first time it is called. Then it - * won't change during the life cycle of the device and everytime + * won't change during the life cycle of the device and every time * a boot barker is received, it is just verified for it being the * same. * @@ -928,7 +928,7 @@ extern void i2400m_report_tlv_rf_switches_status( struct i2400m *, const struct i2400m_tlv_rf_switches_status *); /* - * Helpers for firmware backwards compability + * Helpers for firmware backwards compatibility * * As we aim to support at least the firmware version that was * released with the previous kernel/driver release, some code will be diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 94742e1eafe0..2edd8fe1c1f3 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -166,7 +166,7 @@ void i2400m_wake_tx_work(struct work_struct *ws) d_fnstart(3, dev, "(ws %p i2400m %p skb %p)\n", ws, i2400m, skb); result = -EINVAL; if (skb == NULL) { - dev_err(dev, "WAKE&TX: skb dissapeared!\n"); + dev_err(dev, "WAKE&TX: skb disappeared!\n"); goto out_put; } /* If we have, somehow, lost the connection after this was diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c index 9e02b90b0080..b0dba35a8ad2 100644 --- a/drivers/net/wimax/i2400m/op-rfkill.c +++ b/drivers/net/wimax/i2400m/op-rfkill.c @@ -27,7 +27,7 @@ * - report changes in the HW RF Kill switch [with * wimax_rfkill_{sw,hw}_report(), which happens when we detect those * indications coming through hardware reports]. We also do it on - * initialization to let the stack know the intial HW state. + * initialization to let the stack know the initial HW state. * * - implement indications from the stack to change the SW RF Kill * switch (coming from sysfs, the wimax stack or user space). @@ -73,7 +73,7 @@ int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state) * Generic Netlink will call this function when a message is sent from * userspace to change the software RF-Kill switch status. * - * This function will set the device's sofware RF-Kill switch state to + * This function will set the device's software RF-Kill switch state to * match what is requested. * * NOTE: the i2400m has a strict state machine; we can only set the diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 844133b44af0..2f94a872101f 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c @@ -349,7 +349,7 @@ error_no_waiter: * * For reports: We can't clone the original skb where the data is * because we need to send this up via netlink; netlink has to add - * headers and we can't overwrite what's preceeding the payload...as + * headers and we can't overwrite what's preceding the payload...as * it is another message. So we just dup them. */ static @@ -425,7 +425,7 @@ error_check: * * As in i2400m_rx_ctl(), we can't clone the original skb where the * data is because we need to send this up via netlink; netlink has to - * add headers and we can't overwrite what's preceeding the + * add headers and we can't overwrite what's preceding the * payload...as it is another message. So we just dup them. */ static diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c index 3f819efc06b5..4b30ed11d785 100644 --- a/drivers/net/wimax/i2400m/tx.c +++ b/drivers/net/wimax/i2400m/tx.c @@ -149,7 +149,7 @@ * (with a moved message header to make sure it is size-aligned to * 16), TAIL room that was unusable (and thus is marked with a message * header that says 'skip this') and at the head of the buffer, an - * imcomplete message with a couple of payloads. + * incomplete message with a couple of payloads. * * N ___________________________________________________ * | | @@ -819,7 +819,7 @@ EXPORT_SYMBOL_GPL(i2400m_tx); * the FIF that is ready for transmission. * * It sets the state in @i2400m to indicate the bus-specific driver is - * transfering that message (i2400m->tx_msg_size). + * transferring that message (i2400m->tx_msg_size). * * Once the transfer is completed, call i2400m_tx_msg_sent(). * diff --git a/drivers/net/wimax/i2400m/usb-fw.c b/drivers/net/wimax/i2400m/usb-fw.c index b58ec56b86f8..1fda46c55eb3 100644 --- a/drivers/net/wimax/i2400m/usb-fw.c +++ b/drivers/net/wimax/i2400m/usb-fw.c @@ -169,7 +169,7 @@ retry: * * Command can be a raw command, which requires no preparation (and * which might not even be following the command format). Checks that - * the right amount of data was transfered. + * the right amount of data was transferred. * * To satisfy USB requirements (no onstack, vmalloc or in data segment * buffers), we copy the command to i2400m->bm_cmd_buf and send it from diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c index a26483a812a5..e3257681e360 100644 --- a/drivers/net/wimax/i2400m/usb-rx.c +++ b/drivers/net/wimax/i2400m/usb-rx.c @@ -58,7 +58,7 @@ * a zillion reads; by serializing, we are throttling. * * - RX data processing can get heavy enough so that it is not - * appropiate for doing it in the USB callback; thus we run it in a + * appropriate for doing it in the USB callback; thus we run it in a * process context. * * We provide a read buffer of an arbitrary size (short of a page); if diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c index c65b9979f87e..ac357acfb3e9 100644 --- a/drivers/net/wimax/i2400m/usb-tx.c +++ b/drivers/net/wimax/i2400m/usb-tx.c @@ -168,7 +168,7 @@ retry: /* * Get the next TX message in the TX FIFO and send it to the device * - * Note we exit the loop if i2400mu_tx() fails; that funtion only + * Note we exit the loop if i2400mu_tx() fails; that function only * fails on hard error (failing to tx a buffer not being one of them, * see its doc). * diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 57a79b0475f6..4e5c7a11f04a 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1884,7 +1884,7 @@ static int airo_open(struct net_device *dev) { /* Make sure the card is configured. * Wireless Extensions may postpone config changes until the card * is open (to pipeline changes and speed-up card setup). If - * those changes are not yet commited, do it now - Jean II */ + * those changes are not yet committed, do it now - Jean II */ if (test_bit(FLAG_COMMIT, &ai->flags)) { disable_MAC(ai, 1); writeConfigRid(ai, 1); @@ -1992,7 +1992,7 @@ static int mpi_send_packet (struct net_device *dev) /* * Magic, the cards firmware needs a length count (2 bytes) in the host buffer * right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen - * is immediatly after it. ------------------------------------------------ + * is immediately after it. ------------------------------------------------ * |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA| * ------------------------------------------------ */ @@ -2006,7 +2006,7 @@ static int mpi_send_packet (struct net_device *dev) sizeof(wifictlhdr8023) + 2 ; /* - * Firmware automaticly puts 802 header on so + * Firmware automatically puts 802 header on so * we don't need to account for it in the length */ if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && @@ -2531,7 +2531,7 @@ static int mpi_init_descriptors (struct airo_info *ai) /* * We are setting up three things here: * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid. - * 2) Map PCI memory for issueing commands. + * 2) Map PCI memory for issuing commands. * 3) Allocate memory (shared) to send and receive ethernet frames. */ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci) @@ -3947,7 +3947,7 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { if ( max_tries == -1 ) { airo_print_err(ai->dev->name, - "Max tries exceeded when issueing command"); + "Max tries exceeded when issuing command"); if (IN4500(ai, COMMAND) & COMMAND_BUSY) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); return ERROR; @@ -4173,7 +4173,7 @@ done: } /* Note, that we are using BAP1 which is also used by transmit, so - * make sure this isnt called when a transmit is happening */ + * make sure this isn't called when a transmit is happening */ static int PC4500_writerid(struct airo_info *ai, u16 rid, const void *pBuf, int len, int lock) { @@ -4776,7 +4776,7 @@ static int proc_stats_rid_open( struct inode *inode, if (!statsLabels[i]) continue; if (j+strlen(statsLabels[i])+16>4096) { airo_print_warn(apriv->dev->name, - "Potentially disasterous buffer overflow averted!"); + "Potentially disastrous buffer overflow averted!"); break; } j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index b761fec0d721..ccc2edaaeda0 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -974,7 +974,7 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (ar->rx_failover_missing <= 0) { /* * nested ar9170_rx call! - * termination is guranteed, even when the + * termination is guaranteed, even when the * combined frame also have a element with * a bad tag. */ diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index 0dbfcf79ac96..aa8d06ba1ee4 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -424,7 +424,7 @@ static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz) /* * initialize some phy regs from eeprom values in modal_header[] - * acc. to band and bandwith + * acc. to band and bandwidth */ static int ar9170_init_phy_from_eeprom(struct ar9170 *ar, bool is_2ghz, bool is_40mhz) diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h index d0a664039c87..034015397093 100644 --- a/drivers/net/wireless/ath/ath5k/ani.h +++ b/drivers/net/wireless/ath/ath5k/ani.h @@ -27,7 +27,7 @@ #define ATH5K_ANI_RSSI_THR_HIGH 40 #define ATH5K_ANI_RSSI_THR_LOW 7 -/* maximum availabe levels */ +/* maximum available levels */ #define ATH5K_ANI_MAX_FIRSTEP_LVL 2 #define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 4d7f21ee111c..349a5963931b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1953,7 +1953,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) #define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3 /* We use FUDGE to make sure the next TBTT is ahead of the current TU. - * Since we later substract AR5K_TUNE_SW_BEACON_RESP (10) in the timer + * Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer * configuration we need to make sure it is bigger than that. */ if (bc_tsf == -1) { @@ -1971,7 +1971,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) intval |= AR5K_BEACON_RESET_TSF; } else if (bc_tsf > hw_tsf) { /* - * beacon received, SW merge happend but HW TSF not yet updated. + * beacon received, SW merge happened but HW TSF not yet updated. * not possible to reconfigure timers yet, but next time we * receive a beacon with the same BSSID, the hardware will * automatically update the TSF and then we need to reconfigure @@ -2651,7 +2651,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, synchronize_irq(sc->irq); stop_tasklets(sc); - /* Save ani mode and disable ANI durring + /* Save ani mode and disable ANI during * reset. If we don't we might get false * PHY error interrupts. */ ani_mode = ah->ah_sc->ani_state.ani_mode; diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 16b44ff7dd3e..a8fcc94269f7 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -51,7 +51,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, /* * Validate input * - Zero retries don't make sense. - * - A zero rate will put the HW into a mode where it continously sends + * - A zero rate will put the HW into a mode where it continuously sends * noise on the channel, so it is important to avoid this. */ if (unlikely(tx_tries0 == 0)) { @@ -190,7 +190,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* * Validate input * - Zero retries don't make sense. - * - A zero rate will put the HW into a mode where it continously sends + * - A zero rate will put the HW into a mode where it continuously sends * noise on the channel, so it is important to avoid this. */ if (unlikely(tx_tries0 == 0)) { @@ -300,7 +300,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, /* * Rates can be 0 as long as the retry count is 0 too. * A zero rate and nonzero retry count will put the HW into a mode where - * it continously sends noise on the channel, so it is important to + * it continuously sends noise on the channel, so it is important to * avoid this. */ if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || @@ -342,7 +342,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, \***********************/ /* - * Proccess the tx status descriptor on 5210/5211 + * Process the tx status descriptor on 5210/5211 */ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, struct ath5k_desc *desc, struct ath5k_tx_status *ts) @@ -394,7 +394,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, } /* - * Proccess a tx status descriptor on 5212 + * Process a tx status descriptor on 5212 */ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, struct ath5k_desc *desc, struct ath5k_tx_status *ts) @@ -519,7 +519,7 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, } /* - * Proccess the rx status descriptor on 5210/5211 + * Process the rx status descriptor on 5210/5211 */ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, struct ath5k_desc *desc, struct ath5k_rx_status *rs) @@ -602,7 +602,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, } /* - * Proccess the rx status descriptor on 5212 + * Process the rx status descriptor on 5212 */ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, struct ath5k_desc *desc, diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index b6561f785c6e..efb672cb31e4 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1080,7 +1080,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) * * To recreate the curves we read here the points and interpolate * later. Note that in most cases only 2 (higher and lower) curves are - * used (like RF5112) but vendors have the oportunity to include all + * used (like RF5112) but vendors have the opportunity to include all * 4 curves on eeprom. The final curve (higher power) has an extra * point for better accuracy like RF5112. */ @@ -1302,7 +1302,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) /* * Pd gain 0 is not the last pd gain * so it only has 2 pd points. - * Continue wih pd gain 1. + * Continue with pd gain 1. */ pcinfo->pwr_i[1] = (val >> 10) & 0x1f; diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 66598a0d1df0..3c44689a700b 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -57,7 +57,7 @@ static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) *csz = (int)u8tmp; /* - * This check was put in to avoid "unplesant" consequences if + * This check was put in to avoid "unpleasant" consequences if * the bootrom has not fully initialized all PCI devices. * Sometimes the cache line size register is not set */ diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index a702817daf72..d9b3f828455a 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -472,7 +472,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) } /* - * The AR5210 uses promiscous mode to detect radar activity + * The AR5210 uses promiscuous mode to detect radar activity */ if (ah->ah_version == AR5K_AR5210 && (filter & AR5K_RX_FILTER_RADARERR)) { @@ -706,8 +706,8 @@ ath5k_check_timer_win(int a, int b, int window, int intval) * The need for this function arises from the fact that we have 4 separate * HW timer registers (TIMER0 - TIMER3), which are closely related to the * next beacon target time (NBTT), and that the HW updates these timers - * seperately based on the current TSF value. The hardware increments each - * timer by the beacon interval, when the local TSF coverted to TU is equal + * separately based on the current TSF value. The hardware increments each + * timer by the beacon interval, when the local TSF converted to TU is equal * to the value stored in the timer. * * The reception of a beacon with the same BSSID can update the local HW TSF diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 62ce2f4e8605..55441913344d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -335,11 +335,11 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, * http://madwifi-project.org/ticket/1659 * with various measurements and diagrams * - * TODO: Deal with power drops due to probes by setting an apropriate + * TODO: Deal with power drops due to probes by setting an appropriate * tx power on the probe packets ! Make this part of the calibration process. */ -/* Initialize ah_gain durring attach */ +/* Initialize ah_gain during attach */ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) { /* Initialize the gain optimization values */ @@ -1049,7 +1049,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, \**************************/ /* - * Convertion needed for RF5110 + * Conversion needed for RF5110 */ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) { @@ -1088,7 +1088,7 @@ static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, } /* - * Convertion needed for 5111 + * Conversion needed for 5111 */ static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, struct ath5k_athchan_2ghz *athchan) @@ -2201,7 +2201,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax, /* * Get the surrounding per-channel power calibration piers * for a given frequency so that we can interpolate between - * them and come up with an apropriate dataset for our current + * them and come up with an appropriate dataset for our current * channel. */ static void @@ -2618,7 +2618,7 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah) /* * Set the gain boundaries and create final Power to PDADC table * - * We can have up to 4 pd curves, we need to do a simmilar process + * We can have up to 4 pd curves, we need to do a similar process * as we do for RF5112. This time we don't have an edge_flag but we * set the gain boundaries on a separate register. */ @@ -2826,13 +2826,13 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, u32 target = channel->center_freq; int pdg, i; - /* Get surounding freq piers for this channel */ + /* Get surrounding freq piers for this channel */ ath5k_get_chan_pcal_surrounding_piers(ah, channel, &pcinfo_L, &pcinfo_R); /* Loop over pd gain curves on - * surounding freq piers by index */ + * surrounding freq piers by index */ for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { /* Fill curves in reverse order @@ -2923,7 +2923,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, } /* Interpolate between curves - * of surounding freq piers to + * of surrounding freq piers to * get the final curve for this * pd gain. Re-use tmpL for interpolation * output */ @@ -2947,7 +2947,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, /* Fill min and max power levels for this * channel by interpolating the values on - * surounding channels to complete the dataset */ + * surrounding channels to complete the dataset */ ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, (s16) pcinfo_L->freq, (s16) pcinfo_R->freq, @@ -3179,7 +3179,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, /* FIXME: TPC scale reduction */ - /* Get surounding channels for per-rate power table + /* Get surrounding channels for per-rate power table * calibration */ ath5k_get_rate_pcal_data(ah, channel, &rate_info); diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index e1c9abd8c879..d12b827033c1 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -132,8 +132,8 @@ * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). - * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i - * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what + * So SNAPPEDBCRVALID should also stand for "snapped BCR -values- valid", so i + * renamed it to SNAPSHOTSVALID to make more sense. I really have no idea what * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. */ #define AR5K_BSR 0x002c /* Register Address */ @@ -283,7 +283,7 @@ */ #define AR5K_ISR 0x001c /* Register Address [5210] */ #define AR5K_PISR 0x0080 /* Register Address [5211+] */ -#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */ +#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly received */ #define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ #define AR5K_ISR_RXERR 0x00000004 /* Receive error */ #define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ @@ -372,12 +372,12 @@ /* * Interrupt Mask Registers * - * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary + * As with ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. */ #define AR5K_IMR 0x0020 /* Register Address [5210] */ #define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ -#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/ +#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly received*/ #define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ #define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ #define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ @@ -895,7 +895,7 @@ #define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ #define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ #define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ -#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/ +#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even with pending interrupts*/ #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ #define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ #define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index ffcf44a4058b..106c0b06cf55 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -142,7 +142,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) /** * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios - * @ah: atheros hardware stucture + * @ah: atheros hardware structure * @chan: * * For the external AR2133/AR5133 radios, takes the MHz channel value and set diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 4a9271802991..6eadf975ae48 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3240,7 +3240,7 @@ static int ar9300_compress_decision(struct ath_hw *ah, eep = ar9003_eeprom_struct_find_by_id(reference); if (eep == NULL) { ath_dbg(common, ATH_DBG_EEPROM, - "cant find reference eeprom struct %d\n", + "can't find reference eeprom struct %d\n", reference); return -1; } diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index c41ab8c30161..62e139a30a74 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -360,7 +360,7 @@ ret: * HTC Messages are handled directly here and the obtained SKB * is freed. * - * Sevice messages (Data, WMI) passed to the corresponding + * Service messages (Data, WMI) passed to the corresponding * endpoint RX handlers, which have to free the SKB. */ void ath9k_htc_rx_msg(struct htc_target *htc_handle, diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e83128c50f7b..9c65459be100 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -44,7 +44,7 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) *csz = (int)u8tmp; /* - * This check was put in to avoid "unplesant" consequences if + * This check was put in to avoid "unpleasant" consequences if * the bootrom has not fully initialized all PCI devices. * Sometimes the cache line size register is not set */ diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a3241cd089b1..4c0d36a6980f 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -792,7 +792,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; } else { - /* Set the choosen rate. No RTS for first series entry. */ + /* Set the chosen rate. No RTS for first series entry. */ ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, rix, 0); } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 26734e53b37f..88fa7fdffd05 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -628,8 +628,8 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, (u32)ATH_AMPDU_LIMIT_MAX); /* - * h/w can accept aggregates upto 16 bit lengths (65535). - * The IE, however can hold upto 65536, which shows up here + * h/w can accept aggregates up to 16 bit lengths (65535). + * The IE, however can hold up to 65536, which shows up here * as zero. Ignore 65536 since we are constrained by hw. */ if (tid->an->maxampdu) diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index c6a5fae634a0..c01c43d8e61b 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -161,7 +161,7 @@ struct carl9170_sta_tid { * Naturally: The higher the limit, the faster the device CAN send. * However, even a slight over-commitment at the wrong time and the * hardware is doomed to send all already-queued frames at suboptimal - * rates. This in turn leads to an enourmous amount of unsuccessful + * rates. This in turn leads to an enormous amount of unsuccessful * retries => Latency goes up, whereas the throughput goes down. CRASH! */ #define CARL9170_NUM_TX_LIMIT_HARD ((AR9170_TXQ_DEPTH * 3) / 2) diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index b6b0de600506..b6ae0e179c8d 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -427,7 +427,7 @@ static u32 carl9170_def_val(u32 reg, bool is_2ghz, bool is_40mhz) /* * initialize some phy regs from eeprom values in modal_header[] - * acc. to band and bandwith + * acc. to band and bandwidth */ static int carl9170_init_phy_from_eeprom(struct ar9170 *ar, bool is_2ghz, bool is_40mhz) diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 84866a4b8350..ec21ea9fd8d5 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -849,7 +849,7 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) /* * nested carl9170_rx_stream call! * - * termination is guranteed, even when the + * termination is guaranteed, even when the * combined frame also have an element with * a bad tag. */ diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index f82c400be288..2fb53d067512 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -430,7 +430,7 @@ static void carl9170_usb_rx_complete(struct urb *urb) * The system is too slow to cope with * the enormous workload. We have simply * run out of active rx urbs and this - * unfortunatly leads to an unpredictable + * unfortunately leads to an unpredictable * device. */ diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index 183c28281385..cc11d66f15bc 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c @@ -86,7 +86,7 @@ * IFRAME-01: 0110 * * An easy eye-inspeciton of this already should tell you that this frame - * will not pass our check. This is beacuse the bssid_mask tells the + * will not pass our check. This is because the bssid_mask tells the * hardware to only look at the second least significant bit and the * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB * as 1, which does not match 0. diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index f828f294ba89..0e1b8793c864 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -268,7 +268,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, } /* - * If a country IE has been recieved check its rule for this + * If a country IE has been received check its rule for this * channel first before enabling active scan. The passive scan * would have been enforced by the initial processing of our * custom regulatory domain. @@ -476,7 +476,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; } else { /* - * This gets applied in the case of the absense of CRDA, + * This gets applied in the case of the absence of CRDA, * it's our own custom world regulatory domain, similar to * cfg80211's but we enable passive scanning. */ diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 46e382ed46aa..39a11e8af4fa 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -439,7 +439,7 @@ static u8 mac_reader[] = { }; struct atmel_private { - void *card; /* Bus dependent stucture varies for PCcard */ + void *card; /* Bus dependent structure varies for PCcard */ int (*present_callback)(void *); /* And callback which uses it */ char firmware_id[32]; AtmelFWType firmware_type; @@ -3895,7 +3895,7 @@ static int reset_atmel_card(struct net_device *dev) This routine is also responsible for initialising some hardware-specific fields in the atmel_private structure, - including a copy of the firmware's hostinfo stucture + including a copy of the firmware's hostinfo structure which is the route into the rest of the firmware datastructures. */ struct atmel_private *priv = netdev_priv(dev); diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index c96e19da2949..05263516c113 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -99,7 +99,7 @@ static void atmel_detach(struct pcmcia_device *link) } /* Call-back function to interrogate PCMCIA-specific information - about the current existance of the card */ + about the current existence of the card */ static int card_present(void *arg) { struct pcmcia_device *link = (struct pcmcia_device *)arg; diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index bd4cb75b6ca3..229f4388f790 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -648,7 +648,7 @@ struct b43_request_fw_context { char errors[B43_NR_FWTYPES][128]; /* Temporary buffer for storing the firmware name. */ char fwname[64]; - /* A fatal error occured while requesting. Firmware reqest + /* A fatal error occurred while requesting. Firmware reqest * can not continue, as any other reqest will also fail. */ int fatal_failure; }; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 57eb5b649730..d59b0168c14a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4010,7 +4010,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev) b43_mac_enable(dev); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); - /* Start maintainance work */ + /* Start maintenance work */ b43_periodic_tasks_setup(dev); b43_leds_init(dev); diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h index 8569fdd4c6be..5413c906a3e7 100644 --- a/drivers/net/wireless/b43/phy_g.h +++ b/drivers/net/wireless/b43/phy_g.h @@ -164,7 +164,7 @@ struct b43_phy_g { /* Current Interference Mitigation mode */ int interfmode; /* Stack of saved values from the Interference Mitigation code. - * Each value in the stack is layed out as follows: + * Each value in the stack is laid out as follows: * bit 0-11: offset * bit 12-15: register ID * bit 16-32: value diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 001e841f118c..e789a89f1047 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -703,7 +703,7 @@ #define B43_NPHY_CHAN_ESTHANG B43_PHY_N(0x21D) /* Channel estimate hang */ #define B43_NPHY_FINERX2_CGC B43_PHY_N(0x221) /* Fine RX 2 clock gate control */ #define B43_NPHY_FINERX2_CGC_DECGC 0x0008 /* Decode gated clocks */ -#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */ +#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power control init */ #define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */ #define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0 #define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */ diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index c81b2f53b0c5..23583be1ee0b 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -488,7 +488,7 @@ struct b43legacy_phy { /* Current Interference Mitigation mode */ int interfmode; /* Stack of saved values from the Interference Mitigation code. - * Each value in the stack is layed out as follows: + * Each value in the stack is laid out as follows: * bit 0-11: offset * bit 12-15: register ID * bit 16-32: value diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 18d63f57777d..3d05dc15c6b8 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -2359,7 +2359,7 @@ int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], } -/* Translate our list of Access Points & Stations to a card independant +/* Translate our list of Access Points & Stations to a card independent * format that the Wireless Tools will understand - Jean II */ int prism2_ap_translate_scan(struct net_device *dev, struct iw_request_info *info, char *buffer) diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h index 655ceeba9612..334e2d0b8e11 100644 --- a/drivers/net/wireless/hostap/hostap_ap.h +++ b/drivers/net/wireless/hostap/hostap_ap.h @@ -114,7 +114,7 @@ struct sta_info { * has passed since last received frame from the station, a nullfunc data * frame is sent to the station. If this frame is not acknowledged and no other * frames have been received, the station will be disassociated after - * AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after + * AP_DISASSOC_DELAY. Similarly, a the station will be deauthenticated after * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with * max inactivity timer. */ #define AP_MAX_INACTIVITY_SEC (5 * 60) diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 6038633ef361..12de46407c71 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -1945,7 +1945,7 @@ static char * __prism2_translate_scan(local_info_t *local, } -/* Translate scan data returned from the card to a card independant +/* Translate scan data returned from the card to a card independent * format that the Wireless Tools will understand - Jean II */ static inline int prism2_translate_scan(local_info_t *local, struct iw_request_info *info, @@ -2043,7 +2043,7 @@ static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, * until results are ready for various reasons. * First, managing wait queues is complex and racy * (there may be multiple simultaneous callers). - * Second, we grab some rtnetlink lock before comming + * Second, we grab some rtnetlink lock before coming * here (in dev_ioctl()). * Third, the caller can wait on the Wireless Event * - Jean II */ diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 1c66b3c1030d..88dc6a52bdf1 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -853,7 +853,7 @@ struct local_info { struct work_struct comms_qual_update; /* RSSI to dBm adjustment (for RX descriptor fields) */ - int rssi_to_dBm; /* substract from RSSI to get approximate dBm value */ + int rssi_to_dBm; /* subtract from RSSI to get approximate dBm value */ /* BSS list / protected by local->lock */ struct list_head bss_list; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 4b97f918daff..44307753587d 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -63,7 +63,7 @@ When data is sent to the firmware, the first TBD is used to indicate to the firmware if a Command or Data is being sent. If it is Command, all of the command information is contained within the physical address referred to by the TBD. If it is Data, the first TBD indicates the type of data packet, number -of fragments, etc. The next TBD then referrs to the actual packet location. +of fragments, etc. The next TBD then refers to the actual packet location. The Tx flow cycle is as follows: diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 160881f234cc..42c3fe37af64 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -1181,7 +1181,7 @@ static void ipw_led_shutdown(struct ipw_priv *priv) /* * The following adds a new attribute to the sysfs representation * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/) - * used for controling the debug level. + * used for controlling the debug level. * * See the level definitions in ipw for details. */ @@ -3763,7 +3763,7 @@ static int ipw_queue_tx_init(struct ipw_priv *priv, q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL); if (!q->txb) { - IPW_ERROR("vmalloc for auxilary BD structures failed\n"); + IPW_ERROR("vmalloc for auxiliary BD structures failed\n"); return -ENOMEM; } @@ -5581,7 +5581,7 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, return 0; } - /* Verify privacy compatability */ + /* Verify privacy compatibility */ if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " @@ -5808,7 +5808,7 @@ static int ipw_best_network(struct ipw_priv *priv, return 0; } - /* Verify privacy compatability */ + /* Verify privacy compatibility */ if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " @@ -8184,7 +8184,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, static int is_network_packet(struct ipw_priv *priv, struct libipw_hdr_4addr *header) { - /* Filter incoming packets to determine if they are targetted toward + /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */ @@ -8340,9 +8340,9 @@ static void ipw_handle_mgmt_packet(struct ipw_priv *priv, } /* - * Main entry function for recieving a packet with 80211 headers. This + * Main entry function for receiving a packet with 80211 headers. This * should be called when ever the FW has notified us that there is a new - * skb in the recieve queue. + * skb in the receive queue. */ static void ipw_rx(struct ipw_priv *priv) { @@ -8683,7 +8683,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) * functions defined in ipw_main to provide the HW interaction. * * The exception to this is the use of the ipw_get_ordinal() - * function used to poll the hardware vs. making unecessary calls. + * function used to poll the hardware vs. making unnecessary calls. * */ @@ -10419,7 +10419,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, memset(&dummystats, 0, sizeof(dummystats)); - /* Filtering of fragment chains is done agains the first fragment */ + /* Filtering of fragment chains is done against the first fragment */ hdr = (void *)txb->fragments[0]->data; if (libipw_is_management(le16_to_cpu(hdr->frame_control))) { if (filter & IPW_PROM_NO_MGMT) diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 0de1b1893220..e5ad76cd77da 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -925,7 +925,7 @@ drop_free: static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; /* -* Make ther structure we read from the beacon packet has +* Make the structure we read from the beacon packet to have * the right values */ static int libipw_verify_qos_info(struct libipw_qos_information_element diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index d418b647be80..1c3a8cb186bf 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -1030,7 +1030,7 @@ int iwl_legacy_apm_init(struct iwl_priv *priv) /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s - * NOTE: This is no-op for 3945 (non-existant bit) + * NOTE: This is no-op for 3945 (non-existent bit) */ iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); diff --git a/drivers/net/wireless/iwlegacy/iwl-fh.h b/drivers/net/wireless/iwlegacy/iwl-fh.h index 4e20c7e5c883..6e6091816e36 100644 --- a/drivers/net/wireless/iwlegacy/iwl-fh.h +++ b/drivers/net/wireless/iwlegacy/iwl-fh.h @@ -436,7 +436,7 @@ * @finished_rb_num [0:11] - Indicates the index of the current RB * in which the last frame was written to * @finished_fr_num [0:11] - Indicates the index of the RX Frame - * which was transfered + * which was transferred */ struct iwl_rb_status { __le16 closed_rb_num; diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c index 60f597f796ca..353234a02c6d 100644 --- a/drivers/net/wireless/iwlegacy/iwl-scan.c +++ b/drivers/net/wireless/iwlegacy/iwl-scan.c @@ -143,7 +143,7 @@ static void iwl_legacy_do_scan_abort(struct iwl_priv *priv) IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret); iwl_legacy_force_scan_end(priv); } else - IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n"); + IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n"); } /** diff --git a/drivers/net/wireless/iwlegacy/iwl-sta.c b/drivers/net/wireless/iwlegacy/iwl-sta.c index 47c9da3834ea..66f0fb2bbe00 100644 --- a/drivers/net/wireless/iwlegacy/iwl-sta.c +++ b/drivers/net/wireless/iwlegacy/iwl-sta.c @@ -110,7 +110,7 @@ static int iwl_legacy_process_add_sta_resp(struct iwl_priv *priv, /* * XXX: The MAC address in the command buffer is often changed from * the original sent to the device. That is, the MAC address - * written to the command buffer often is not the same MAC adress + * written to the command buffer often is not the same MAC address * read from the command buffer when the command returns. This * issue has not yet been resolved and this debugging is left to * observe the problem. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index b5cb3be0eb4b..ed0148d714de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -69,7 +69,7 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) if (!priv->_agn.ict_tbl_vir) return -ENOMEM; - /* align table to PAGE_SIZE boundry */ + /* align table to PAGE_SIZE boundary */ priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE); IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6c30fa652e27..bafbe57c9602 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1040,7 +1040,7 @@ int iwl_apm_init(struct iwl_priv *priv) /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s - * NOTE: This is no-op for 3945 (non-existant bit) + * NOTE: This is no-op for 3945 (non-existent bit) */ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 55b8370bc6d4..474009a244d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -436,7 +436,7 @@ * @finished_rb_num [0:11] - Indicates the index of the current RB * in which the last frame was written to * @finished_fr_num [0:11] - Indicates the index of the RX Frame - * which was transfered + * which was transferred */ struct iwl_rb_status { __le16 closed_rb_num; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 3a4d9e6b0421..914c77e44588 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -143,7 +143,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret); iwl_force_scan_end(priv); } else - IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n"); + IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n"); } /** diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index 907ac890997c..1cabcb39643f 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -57,7 +57,7 @@ * This is due to the fact the host talks exclusively * to the UMAC and so there needs to be a special UMAC * command for talking to the LMAC. - * This is how a wifi command is layed out: + * This is how a wifi command is laid out: * ------------------------ * | iwm_udma_out_wifi_hdr | * ------------------------ @@ -72,7 +72,7 @@ * Those commands are handled by the device's bootrom, * and are typically sent when the UMAC and the LMAC * are not yet available. - * * This is how a non-wifi command is layed out: + * * This is how a non-wifi command is laid out: * --------------------------- * | iwm_udma_out_nonwifi_hdr | * --------------------------- diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c index 3216621fc55a..be98074c0608 100644 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ b/drivers/net/wireless/iwmc3200wifi/tx.c @@ -197,7 +197,7 @@ int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb) spin_lock(&iwm->tx_credit.lock); if (!iwm_tx_credit_ok(iwm, id, nb)) { - IWM_DBG_TX(iwm, DBG, "No credit avaliable for pool[%d]\n", id); + IWM_DBG_TX(iwm, DBG, "No credit available for pool[%d]\n", id); ret = -ENOSPC; goto out; } diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index 60fd1afe89ac..1453eec82a99 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -70,7 +70,7 @@ rdrf These commands are used to read the MAC, BBP and RF registers from the card. These commands take one parameter that specifies the offset location that is to be read. This parameter must be specified in - hexadecimal (its possible to preceed preceding the number with a "0x"). + hexadecimal (its possible to precede preceding the number with a "0x"). Path: /sys/kernel/debug/libertas_wireless/ethX/registers/ @@ -84,7 +84,7 @@ wrrf These commands are used to write the MAC, BBP and RF registers in the card. These commands take two parameters that specify the offset location and the value that is to be written. This parameters must - be specified in hexadecimal (its possible to preceed the number + be specified in hexadecimal (its possible to precede the number with a "0x"). Usage: diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 30ef0351bfc4..5caa2ac14d61 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -1350,7 +1350,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, * we remove all keys like in the WPA/WPA2 setup, * we just don't set RSN. * - * Therefore: fall-throught + * Therefore: fall-through */ case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index fc8121190d38..8712cb213f2f 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -913,7 +913,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out3; } - /* Clear any interrupt cause that happend while sending + /* Clear any interrupt cause that happened while sending * firmware/initializing card */ if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); if_cs_enable_ints(card); diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index 8b1417d3b71b..d2ac1dcd7e2e 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h @@ -66,7 +66,7 @@ #define IF_SPI_HOST_INT_CTRL_REG 0x40 /* Host interrupt controller reg */ #define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */ -#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */ +#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interrupt status reg */ #define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */ #define IF_SPI_CARD_INT_STATUS_MASK_REG 0x50 /* Card interrupt status mask */ diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 56f439d58013..f4f4257a9d67 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -62,7 +62,7 @@ MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler"); * an intersection to occur but each device will still use their * respective regulatory requested domains. Subsequent radios will * use the resulting intersection. - * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We acomplish + * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We accomplish * this by using a custom beacon-capable regulatory domain for the first * radio. All other device world roam. * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index b4772c1c6135..3c7877a7c31c 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -1031,7 +1031,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, else buf.tsc[4] = 0x10; - /* Wait upto 100ms for tx queue to empty */ + /* Wait up to 100ms for tx queue to empty */ for (k = 100; k > 0; k--) { udelay(1000); ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY, diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 356e6bb443a6..a946991989c6 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -465,7 +465,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, if (slot < 0) { /* - * The device supports the choosen algorithm, but the + * The device supports the chosen algorithm, but the * firmware does not provide enough key slots to store * all of them. * But encryption offload for outgoing frames is always diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7ecc0bda57b3..6d9204fef90b 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -287,7 +287,7 @@ static void p54spi_power_on(struct p54s_priv *priv) enable_irq(gpio_to_irq(p54spi_gpio_irq)); /* - * need to wait a while before device can be accessed, the lenght + * need to wait a while before device can be accessed, the length * is just a guess */ msleep(10); diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index d44f8e20cce0..266d45bf86f5 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -113,7 +113,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes * and add WDS address information */ if (likely(((long) skb->data & 0x03) | init_wds)) { - /* get the number of bytes to add and re-allign */ + /* get the number of bytes to add and re-align */ offset = (4 - (long) skb->data) & 0x03; offset += init_wds ? 6 : 0; @@ -342,7 +342,7 @@ islpci_eth_receive(islpci_private *priv) priv->pci_map_rx_address[index], MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - /* update the skb structure and allign the buffer */ + /* update the skb structure and align the buffer */ skb_put(skb, size); if (offset) { /* shift the buffer allocation offset bytes to get the right frame */ diff --git a/drivers/net/wireless/rayctl.h b/drivers/net/wireless/rayctl.h index 49d9b267bc0f..d7646f299bd3 100644 --- a/drivers/net/wireless/rayctl.h +++ b/drivers/net/wireless/rayctl.h @@ -578,7 +578,7 @@ struct tx_msg { UCHAR var[1]; }; -/****** ECF Receive Control Stucture (RCS) Area at Shared RAM offset 0x0800 */ +/****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800 */ /* Structures for command specific parameters (rcs.var) */ struct rx_packet_cmd { UCHAR rx_data_ptr[2]; diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 70b9abbdeb9e..8fbc5fa965e0 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -616,7 +616,7 @@ * READ_CONTROL: 0 write BBP, 1 read BBP * BUSY: ASIC is busy executing BBP commands * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks - * BBP_RW_MODE: 0 serial, 1 paralell + * BBP_RW_MODE: 0 serial, 1 parallel */ #define BBP_CSR_CFG 0x101c #define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2ee6cebb9b25..dbf74d07d947 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1518,7 +1518,7 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, if (rf->channel > 14) { /* * When TX power is below 0, we should increase it by 7 to - * make it a positive value (Minumum value is -7). + * make it a positive value (Minimum value is -7). * However this means that values between 0 and 7 have * double meaning, and we should set a 7DBm boost flag. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a3940d7300a4..7f10239f56a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -484,13 +484,13 @@ struct rt2x00intf_conf { enum nl80211_iftype type; /* - * TSF sync value, this is dependant on the operation type. + * TSF sync value, this is dependent on the operation type. */ enum tsf_sync sync; /* - * The MAC and BSSID addressess are simple array of bytes, - * these arrays are little endian, so when sending the addressess + * The MAC and BSSID addresses are simple array of bytes, + * these arrays are little endian, so when sending the addresses * to the drivers, copy the it into a endian-signed variable. * * Note that all devices (except rt2500usb) have 32 bits @@ -1131,7 +1131,7 @@ void rt2x00queue_stop_queue(struct data_queue *queue); * @drop: True to drop all pending frames. * * This function will flush the queue. After this call - * the queue is guarenteed to be empty. + * the queue is guaranteed to be empty. */ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index e7f67d5eda52..9416e36de29e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -60,7 +60,7 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, * Note that when NULL is passed as address we will send * 00:00:00:00:00 to the device to clear the address. * This will prevent the device being confused when it wants - * to ACK frames or consideres itself associated. + * to ACK frames or considers itself associated. */ memset(conf.mac, 0, sizeof(conf.mac)); if (mac) diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 5e9074bf2b8e..3f5688fbf3f7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -237,7 +237,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, } /* - * NOTE: Always count the payload as transfered, + * NOTE: Always count the payload as transferred, * even when alignment was set to zero. This is required * for determining the correct offset for the ICV data. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 5d6e0b83151f..063ebcce97f8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -51,7 +51,7 @@ * [rt2x00dump header][hardware descriptor][ieee802.11 frame] * * rt2x00dump header: The description of the dumped frame, as well as - * additional information usefull for debugging. See &rt2x00dump_hdr. + * additional information useful for debugging. See &rt2x00dump_hdr. * hardware descriptor: Descriptor that was used to receive or transmit * the frame. * ieee802.11 frame: The actual frame that was received or transmitted. diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index c975b0a12e95..29abfdeb0b65 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -283,7 +283,7 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) /** * While scanning, link tuning is disabled. By default * the most sensitive settings will be used to make sure - * that all beacons and probe responses will be recieved + * that all beacons and probe responses will be received * during the scan. */ if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4b3c70eeef1f..4358051bfe1a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -546,7 +546,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, } /* - * When DMA allocation is required we should guarentee to the + * When DMA allocation is required we should guarantee to the * driver that the DMA is aligned to a 4-byte boundary. * However some drivers require L2 padding to pad the payload * rather then the header. This could be a requirement for @@ -689,7 +689,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, spin_unlock_irqrestore(&queue->index_lock, irqflags); /* - * Start from the TX done pointer, this guarentees that we will + * Start from the TX done pointer, this guarantees that we will * send out all frames in the correct order. */ if (index_start < index_end) { @@ -883,7 +883,7 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) } /* - * Check if driver supports flushing, we can only guarentee + * Check if driver supports flushing, we can only guarantee * full support for flushing if the driver is able * to cancel all pending frames (drop = true). */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 0c8b0c699679..217861f8d95f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -344,8 +344,8 @@ struct txentry_desc { * only be touched after the device has signaled it is done with it. * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting * for the signal to start sending. - * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured - * while transfering the data to the hardware. No TX status report will + * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occurred + * while transferring the data to the hardware. No TX status report will * be expected from the hardware. * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and * returned. It is now waiting for the status reporting before the @@ -365,7 +365,7 @@ enum queue_entry_flags { * @flags: Entry flags, see &enum queue_entry_flags. * @queue: The data queue (&struct data_queue) to which this entry belongs. * @skb: The buffer which is currently being transmitted (for TX queue), - * or used to directly recieve data in (for RX queue). + * or used to directly receive data in (for RX queue). * @entry_idx: The entry index number. * @priv_data: Private data belonging to this queue entry. The pointer * points to data specific to a particular driver and queue type. @@ -388,7 +388,7 @@ struct queue_entry { * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is * owned by the hardware then the queue is considered to be full. * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been - * transfered to the hardware. + * transferred to the hardware. * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by * the hardware and for which we need to run the txdone handler. If this * entry is not owned by the hardware the queue is considered to be empty. @@ -627,7 +627,7 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) } /** - * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports + * rt2x00queue_status_timeout - Check if a timeout occurred for STATUS reports * @queue: Queue to check. */ static inline int rt2x00queue_status_timeout(struct data_queue *queue) @@ -637,7 +637,7 @@ static inline int rt2x00queue_status_timeout(struct data_queue *queue) } /** - * rt2x00queue_timeout - Check if a timeout occured for DMA transfers + * rt2x00queue_timeout - Check if a timeout occurred for DMA transfers * @queue: Queue to check. */ static inline int rt2x00queue_dma_timeout(struct data_queue *queue) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index fbe735f5b352..36f388f97d65 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -173,7 +173,7 @@ static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) /* * If the transfer to hardware succeeded, it does not mean the * frame was send out correctly. It only means the frame - * was succesfully pushed to the hardware, we have no + * was successfully pushed to the hardware, we have no * way to determine the transmission status right now. * (Only indirectly by looking at the failed TX counters * in the register). diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 6aaf51fc7ad8..e11c759ac9ed 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -400,7 +400,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue); * @rt2x00dev: Pointer to &struct rt2x00_dev * * Check the health of the USB communication and determine - * if timeouts have occured. If this is the case, this function + * if timeouts have occurred. If this is the case, this function * will reset all communication to restore functionality again. */ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index bb0c781f4a1b..0d7d93e1d398 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -520,7 +520,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *because hw will nerver use hw_rate *when tcb_desc->use_driver_rate = false *so we never set highest N rate here, - *and N rate will all be controled by FW + *and N rate will all be controlled by FW *when tcb_desc->use_driver_rate = false */ if (rtlmac->ht_enable) { diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9cd7703c2a30..5938f6ee21e4 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -395,7 +395,7 @@ static void rtl_pci_init_aspm(struct ieee80211_hw *hw) * 0 - Disable ASPM, * 1 - Enable ASPM without Clock Req, * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, + * 3 - Always Enable ASPM with Clock Req, * 4 - Always Enable ASPM without Clock Req. * set defult to RTL8192CE:3 RTL8192E:2 * */ diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index 3336ca999dfd..d26f957981ad 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -179,7 +179,7 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, } /* - *If a country IE has been recieved check its rule for this + *If a country IE has been received check its rule for this *channel first before enabling active scan. The passive scan *would have been enforced by the initial processing of our *custom regulatory domain. diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 01226f8e70f9..07db95ff9bc5 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1555,7 +1555,7 @@ struct rtl_priv { /*************************************** - Bluetooth Co-existance Related + Bluetooth Co-existence Related ****************************************/ enum bt_ant_num { diff --git a/drivers/net/wireless/wl1251/cmd.c b/drivers/net/wireless/wl1251/cmd.c index 0ade4bd617c0..81f164bc4888 100644 --- a/drivers/net/wireless/wl1251/cmd.c +++ b/drivers/net/wireless/wl1251/cmd.c @@ -104,7 +104,7 @@ int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer) * @wl: wl struct * @id: acx id * @buf: buffer for the response, including all headers, must work with dma - * @len: lenght of buf + * @len: length of buf */ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len) { diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/wl1251/rx.c index c1b3b3f03da2..6af35265c900 100644 --- a/drivers/net/wireless/wl1251/rx.c +++ b/drivers/net/wireless/wl1251/rx.c @@ -179,7 +179,7 @@ static void wl1251_rx_body(struct wl1251 *wl, rx_buffer = skb_put(skb, length); wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); - /* The actual lenght doesn't include the target's alignment */ + /* The actual length doesn't include the target's alignment */ skb->len = desc->length - PLCP_HEADER_LENGTH; fc = (u16 *)skb->data; diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index f0aa7ab97bf7..96324336f936 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -359,7 +359,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) * @wl: wl struct * @id: acx id * @buf: buffer for the response, including all headers, must work with dma - * @len: lenght of buf + * @len: length of buf */ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) { diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 856a8a2fff4f..8a8323896eec 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -497,7 +497,7 @@ struct conf_rx_settings { #define CONF_TX_RATE_RETRY_LIMIT 10 /* - * Rates supported for data packets when operating as AP. Note the absense + * Rates supported for data packets when operating as AP. Note the absence * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop * one. The rate dropped is not mandatory under any operating mode. */ @@ -572,7 +572,7 @@ enum conf_tx_ac { CONF_TX_AC_BK = 1, /* background */ CONF_TX_AC_VI = 2, /* video */ CONF_TX_AC_VO = 3, /* voice */ - CONF_TX_AC_CTS2SELF = 4, /* fictious AC, follows AC_VO */ + CONF_TX_AC_CTS2SELF = 4, /* fictitious AC, follows AC_VO */ CONF_TX_AC_ANY_TID = 0x1f }; @@ -1169,7 +1169,7 @@ struct conf_memory_settings { /* * Minimum required free tx memory blocks in order to assure optimum - * performence + * performance * * Range: 0-120 */ @@ -1177,7 +1177,7 @@ struct conf_memory_settings { /* * Minimum required free rx memory blocks in order to assure optimum - * performence + * performance * * Range: 0-120 */ diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index c1aac8292089..00c771ea70bf 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -94,7 +94,7 @@ static inline int wl1271_translate_addr(struct wl1271 *wl, int addr) * translated region. * * The translated regions occur next to each other in physical device - * memory, so just add the sizes of the preceeding address regions to + * memory, so just add the sizes of the preceding address regions to * get the offset to the new region. * * Currently, only the two first regions are addressed, and the diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 3e5befe4d03b..fc08f36fe1f5 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -290,7 +290,7 @@ static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest, * \ \- IEEE 802.11 -/ \-------------- len --------------/ * \-struct wl3501_80211_tx_hdr--/ \-------- Ethernet Frame -------/ * - * Return = Postion in Card + * Return = Position in Card */ static u16 wl3501_get_tx_buffer(struct wl3501_card *this, u16 len) { @@ -1932,7 +1932,7 @@ static int wl3501_config(struct pcmcia_device *link) this->base_addr = dev->base_addr; if (!wl3501_get_flash_mac_addr(this)) { - printk(KERN_WARNING "%s: Cant read MAC addr in flash ROM?\n", + printk(KERN_WARNING "%s: Can't read MAC addr in flash ROM?\n", dev->name); unregister_netdev(dev); goto failed; diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c index 0597d862fbd2..e36117486c91 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -169,7 +169,7 @@ static int rf2959_init_hw(struct zd_rf *rf) { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, /* { CR91, 0x18 }, */ - /* should solve continous CTS frame problems */ + /* should solve continuous CTS frame problems */ { CR91, 0x00 }, { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c index 9e74eb1b67d5..ba0a0ccb1fa0 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c @@ -353,7 +353,7 @@ static int uw2453_init_hw(struct zd_rf *rf) }; static const u32 rv[] = { - UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */ + UW2453_REGWRITE(4, 0x2b), /* configure receiver gain */ UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */ UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */ UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */ diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index 2642af4ee491..372572c0adc6 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -786,7 +786,7 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg) * @reg: register number to write to * @val: value to write to the register number specified by reg * - * This fucntion waits till the device is ready to accept a new MDIO + * This function waits till the device is ready to accept a new MDIO * request and then writes the val to the MDIO Write Data register. */ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg, diff --git a/drivers/net/znet.c b/drivers/net/znet.c index ae07b3dfbcc1..ec2800ff8d42 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -652,7 +652,7 @@ static irqreturn_t znet_interrupt(int irq, void *dev_id) dev->stats.tx_errors++; /* Transceiver may be stuck if cable - * was removed while emiting a + * was removed while emitting a * packet. Flip it off, then on to * reset it. This is very empirical, * but it seems to work. */ diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index c9db49c10f45..8b63a691a9ed 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -676,7 +676,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, early_init_dt_check_for_initrd(node); - /* Retreive command line */ + /* Retrieve command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index dcd7857784f2..d35e300b0ad1 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -136,7 +136,7 @@ EXPORT_SYMBOL(of_phy_find_device); * @hndlr: Link state callback for the network device * @iface: PHY data interface type * - * Returns a pointer to the phy_device if successfull. NULL otherwise + * Returns a pointer to the phy_device if successful. NULL otherwise */ struct phy_device *of_phy_connect(struct net_device *dev, struct device_node *phy_np, diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 1062b8ffe244..246a92f677e4 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -141,7 +141,7 @@ struct pdcspath_attribute paths_attr_##_name = { \ * @entry: A pointer to an allocated pdcspath_entry. * * The general idea is that you don't read from the Stable Storage every time - * you access the files provided by the facilites. We store a copy of the + * you access the files provided by the facilities. We store a copy of the * content of the stable storage WRT various paths in these structs. We read * these structs when reading the files, and we will write to these structs when * writing to the files, and only then write them back to the Stable Storage. @@ -213,7 +213,7 @@ pdcspath_store(struct pdcspath_entry *entry) /* addr, devpath and count must be word aligned */ if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) { - printk(KERN_ERR "%s: an error occured when writing to PDC.\n" + printk(KERN_ERR "%s: an error occurred when writing to PDC.\n" "It is likely that the Stable Storage data has been corrupted.\n" "Please check it carefully upon next reboot.\n", __func__); WARN_ON(1); diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index 855f389eea40..d92185a5523b 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -142,7 +142,7 @@ config PARPORT_AX88796 the AX88796 network controller chip. This code is also available as a module (say M), called parport_ax88796. - The driver is not dependant on the AX88796 network driver, and + The driver is not dependent on the AX88796 network driver, and should not interfere with the networking functions of the chip. config PARPORT_1284 diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index 8901ecf6e037..f9fd4b33a546 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c @@ -355,7 +355,7 @@ int parport_negotiate (struct parport *port, int mode) return 0; } - /* Go to compability forward idle mode */ + /* Go to compatibility forward idle mode */ if (port->ieee1284.mode != IEEE1284_MODE_COMPAT) parport_ieee1284_terminate (port); diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 8d62fb76cd41..a3755ffc03d4 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -1488,7 +1488,7 @@ static void __devinit winbond_check(int io, int key) outb(key, io); outb(key, io); /* Write Magic Sequence to EFER, extended - funtion enable register */ + function enable register */ outb(0x20, io); /* Write EFIR, extended function index register */ devid = inb(io + 1); /* Read EFDR, extended function data register */ outb(0x21, io); @@ -1527,7 +1527,7 @@ static void __devinit winbond_check2(int io, int key) x_oldid = inb(io + 2); outb(key, io); /* Write Magic Byte to EFER, extended - funtion enable register */ + function enable register */ outb(0x20, io + 2); /* Write EFIR, extended function index register */ devid = inb(io + 2); /* Read EFDR, extended function data register */ outb(0x21, io + 1); @@ -1569,7 +1569,7 @@ static void __devinit smsc_check(int io, int key) outb(key, io); outb(key, io); /* Write Magic Sequence to EFER, extended - funtion enable register */ + function enable register */ outb(0x0d, io); /* Write EFIR, extended function index register */ oldid = inb(io + 1); /* Read EFDR, extended function data register */ outb(0x0e, io); diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 3bc72d18b121..8f3faf343f75 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -351,7 +351,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) * To handle different BIOS behavior, we look for _OSC on a root * bridge preferentially (according to PCI fw spec). Later for * OSHP within the scope of the hotplug controller and its parents, - * upto the host bridge under which this controller exists. + * up to the host bridge under which this controller exists. */ handle = acpi_find_root_bridge_handle(pdev); if (handle) { diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e610cfe4f07b..2f67e9bc2f96 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -585,7 +585,7 @@ static void remove_bridge(acpi_handle handle) /* * On root bridges with hotplug slots directly underneath (ie, - * no p2p bridge inbetween), we call cleanup_bridge(). + * no p2p bridge between), we call cleanup_bridge(). * * The else clause cleans up root bridges that either had no * hotplug slots at all, or had a p2p bridge underneath. diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index ef7411c660b9..758adb5f47fd 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -290,7 +290,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes, * @dn: device node of slot * * This subroutine will register a hotplugable slot with the - * PCI hotplug infrastructure. This routine is typicaly called + * PCI hotplug infrastructure. This routine is typically called * during boot time, if the hotplug slots are present at boot time, * or is called later, by the dlpar add code, if the slot is * being dynamically added during runtime. diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 7da3bef60d87..505c1c7075f0 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2265,7 +2265,7 @@ int __init init_dmars(void) /* * TBD: * we could share the same root & context tables - * amoung all IOMMU's. Need to Split it later. + * among all IOMMU's. Need to Split it later. */ ret = iommu_alloc_root_entry(iommu); if (ret) { diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index a22557b20283..3607faf28a4d 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -289,7 +289,7 @@ int free_irte(int irq) * source validation type */ #define SVT_NO_VERIFY 0x0 /* no verification is required */ -#define SVT_VERIFY_SID_SQ 0x1 /* verify using SID and SQ fiels */ +#define SVT_VERIFY_SID_SQ 0x1 /* verify using SID and SQ fields */ #define SVT_VERIFY_BUS 0x2 /* verify bus of request-id */ /* diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c index 7914951ef29a..9606e599a475 100644 --- a/drivers/pci/iova.c +++ b/drivers/pci/iova.c @@ -391,7 +391,7 @@ reserve_iova(struct iova_domain *iovad, break; } - /* We are here either becasue this is the first reserver node + /* We are here either because this is the first reserver node * or need to insert remaining non overlap addr range */ iova = __insert_new_range(iovad, pfn_lo, pfn_hi); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index a8a277a2e0d0..f8deb3e380a2 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -645,7 +645,7 @@ pci_adjust_legacy_attr(struct pci_bus *b, enum pci_mmap_state mmap_type) * a per-bus basis. This routine creates the files and ties them into * their associated read, write and mmap files from pci-sysfs.c * - * On error unwind, but don't propogate the error to the caller + * On error unwind, but don't propagate the error to the caller * as it is ok to set up the PCI bus without these files. */ void pci_create_legacy_files(struct pci_bus *b) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bd80f6378463..5129ed6d8fa7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -263,7 +263,7 @@ static void quirk_vialatency(struct pci_dev *dev) * This happens to include the IDE controllers.... * * VIA only apply this fix when an SB Live! is present but under - * both Linux and Windows this isnt enough, and we have seen + * both Linux and Windows this isn't enough, and we have seen * corruption without SB Live! but with things like 3 UDMA IDE * controllers. So we ignore that bit of the VIA recommendation.. */ @@ -2680,7 +2680,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0020, quirk_hotplug_bridge); * This is a quirk for the Ricoh MMC controller found as a part of * some mulifunction chips. - * This is very similiar and based on the ricoh_mmc driver written by + * This is very similar and based on the ricoh_mmc driver written by * Philip Langdale. Thank you for these magic sequences. * * These chips implement the four main memory card controllers (SD, MMC, MS, xD) diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index fc7906eaf228..3e447d0387b7 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -54,7 +54,7 @@ static struct pccard_operations i82092aa_operations = { .set_mem_map = i82092aa_set_mem_map, }; -/* The card can do upto 4 sockets, allocate a structure for each of them */ +/* The card can do up to 4 sockets, allocate a structure for each of them */ struct socket_info { int number; diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 42fbf1a75576..fe77e8223841 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -173,7 +173,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, c = p_dev->function_config; if (!(c->state & CONFIG_LOCKED)) { - dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); + dev_dbg(&p_dev->dev, "Configuration isn't't locked\n"); mutex_unlock(&s->ops_mutex); return -EACCES; } diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c index 25afe637c657..c21888eebb58 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/pxa2xx_lubbock.c @@ -187,7 +187,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, * We need to hack around the const qualifier as * well to keep this ugly workaround localized and * not force it to the rest of the code. Barf bags - * avaliable in the seat pocket in front of you! + * available in the seat pocket in front of you! */ ((socket_state_t *)state)->Vcc = 50; ((socket_state_t *)state)->Vpp = 50; diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index 9ffa97d0b16c..a71789486cdf 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -691,7 +691,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) /* * those are either single or dual slot CB with additional functions * like 1394, smartcard reader, etc. check the TIEALL flag for them - * the TIEALL flag binds the IRQ of all functions toghether. + * the TIEALL flag binds the IRQ of all functions together. * we catch the single slot variants later. */ sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c index 6c12db503161..c2f4bd8013b5 100644 --- a/drivers/platform/x86/intel_mid_thermal.c +++ b/drivers/platform/x86/intel_mid_thermal.c @@ -202,7 +202,7 @@ static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp) if (ret) return ret; - /* Shift bits to accomodate the lower two data bits */ + /* Shift bits to accommodate the lower two data bits */ adc_val = (data << 2); addr++; diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 4a651f69e17c..bc00693d0c79 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -320,7 +320,7 @@ void pnp_remove_card_device(struct pnp_dev *dev) * pnp_request_card_device - Searches for a PnP device under the specified card * @clink: pointer to the card link, cannot be NULL * @id: pointer to a PnP ID structure that explains the rules for finding the device - * @from: Starting place to search from. If NULL it will start from the begining. + * @from: Starting place to search from. If NULL it will start from the beginning. */ struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from) @@ -369,7 +369,7 @@ err_out: /** * pnp_release_card_device - call this when the driver no longer needs the device - * @dev: pointer to the PnP device stucture + * @dev: pointer to the PnP device structure */ void pnp_release_card_device(struct pnp_dev *dev) { diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index 8591f6ab1b35..b859d16cf78c 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -219,7 +219,7 @@ void pnpbios_print_status(const char *module, u16 status) module); break; case PNP_HARDWARE_ERROR: - printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", + printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occurred\n", module); break; default: diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig index f0d3376b58ba..258ca596e1bc 100644 --- a/drivers/pps/Kconfig +++ b/drivers/pps/Kconfig @@ -35,7 +35,7 @@ config NTP_PPS depends on PPS && !NO_HZ help This option adds support for direct in-kernel time - syncronization using an external PPS signal. + synchronization using an external PPS signal. It doesn't work on tickless systems at the moment. diff --git a/drivers/ps3/ps3-lpm.c b/drivers/ps3/ps3-lpm.c index 8000985d0e8c..643697f71390 100644 --- a/drivers/ps3/ps3-lpm.c +++ b/drivers/ps3/ps3-lpm.c @@ -919,7 +919,7 @@ EXPORT_SYMBOL_GPL(ps3_disable_pm); * @offset: Offset in bytes from the start of the trace buffer. * @buf: Copy destination. * @count: Maximum count of bytes to copy. - * @bytes_copied: Pointer to a variable that will recieve the number of + * @bytes_copied: Pointer to a variable that will receive the number of * bytes copied to @buf. * * On error @buf will contain any successfully copied trace buffer data @@ -974,7 +974,7 @@ EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb); * @offset: Offset in bytes from the start of the trace buffer. * @buf: A __user copy destination. * @count: Maximum count of bytes to copy. - * @bytes_copied: Pointer to a variable that will recieve the number of + * @bytes_copied: Pointer to a variable that will receive the number of * bytes copied to @buf. * * On error @buf will contain any successfully copied trace buffer data @@ -1074,7 +1074,7 @@ EXPORT_SYMBOL_GPL(ps3_disable_pm_interrupts); /** * ps3_lpm_open - Open the logical performance monitor device. - * @tb_type: Specifies the type of trace buffer lv1 sould use for this lpm + * @tb_type: Specifies the type of trace buffer lv1 should use for this lpm * instance, specified by one of enum ps3_lpm_tb_type. * @tb_cache: Optional user supplied buffer to use as the trace buffer cache. * If NULL, the driver will allocate and manage an internal buffer. diff --git a/drivers/ps3/ps3-sys-manager.c b/drivers/ps3/ps3-sys-manager.c index d37c445f0eda..1b98367110c4 100644 --- a/drivers/ps3/ps3-sys-manager.c +++ b/drivers/ps3/ps3-sys-manager.c @@ -80,7 +80,7 @@ static void __maybe_unused _dump_sm_header( * * Currently all messages received from the system manager are either * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header - * + 16 bytes payload = 32 bytes). This knowlege is used to simplify + * + 16 bytes payload = 32 bytes). This knowledge is used to simplify * the logic. */ diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 3a59d5f018d3..ee893581d4b7 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -295,7 +295,7 @@ static int __devinit rio_add_device(struct rio_dev *rdev) } /** - * rio_enable_rx_tx_port - enable input reciever and output transmitter of + * rio_enable_rx_tx_port - enable input receiver and output transmitter of * given port * @port: Master port associated with the RIO network * @local: local=1 select local port otherwise a far device is reached diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 3ffc6979d164..0fae51c4845a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1313,7 +1313,7 @@ static int _regulator_enable(struct regulator_dev *rdev) return -EINVAL; /* Query before enabling in case configuration - * dependant. */ + * dependent. */ ret = _regulator_get_enable_time(rdev); if (ret >= 0) { delay = ret; diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index a8f4ecfb0843..daff7fd0e95c 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -262,7 +262,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, if (err) { dev_warn(max8952->dev, "VID0/1 gpio invalid: " - "DVS not avilable.\n"); + "DVS not available.\n"); max8952->vid0 = 0; max8952->vid1 = 0; /* Mark invalid */ diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8ec6b069a7f5..23719f0acbf6 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -454,7 +454,7 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable); * @rtc: pointer to the rtc device * * This function is called when an AIE, UIE or PIE mode interrupt - * has occured (or been emulated). + * has occurred (or been emulated). * * Triggers the registered irq_task function callback. */ diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 518a76ec71ca..e39b77a4609a 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -60,7 +60,7 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, /* * The Calendar Alarm register does not have a field for * the year - so these will return an invalid value. When an - * alarm is set, at91_alarm_year wille store the current year. + * alarm is set, at91_alarm_year will store the current year. */ tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */ tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */ diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index ca9cff85ab8a..a0fc4cf42abf 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -20,9 +20,9 @@ * write would be discarded and things quickly fall apart. * * To keep this delay from significantly degrading performance (we, in theory, - * would have to sleep for up to 1 second everytime we wanted to write a + * would have to sleep for up to 1 second every time we wanted to write a * register), we only check the write pending status before we start to issue - * a new write. We bank on the idea that it doesnt matter when the sync + * a new write. We bank on the idea that it doesn't matter when the sync * happens so long as we don't attempt another write before it does. The only * time userspace would take this penalty is when they try and do multiple * operations right after another ... but in this case, they need to take the diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index ec8701ce99f9..ae16250c762f 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -240,7 +240,7 @@ static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) spin_lock_init(&rtc->lock); /* - * The RTC is on a seperate power domain and can keep it's state + * The RTC is on a separate power domain and can keep it's state * across a chip power cycle. If the RTC has never been previously * setup, then set it up now for the first time. */ diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 9aae49139a0a..b00aad2620d4 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -573,7 +573,7 @@ static int x1205_probe(struct i2c_client *client, i2c_set_clientdata(client, rtc); - /* Check for power failures and eventualy enable the osc */ + /* Check for power failures and eventually enable the osc */ if ((err = x1205_get_status(client, &sr)) == 0) { if (sr & X1205_SR_RTCF) { dev_err(&client->dev, diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 1654a24817be..87a0cf160fe5 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -2207,7 +2207,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) * DASD_3990_ERP_CONTROL_CHECK * * DESCRIPTION - * Does a generic inspection if a control check occured and sets up + * Does a generic inspection if a control check occurred and sets up * the related error recovery procedure * * PARAMETER @@ -2250,7 +2250,7 @@ dasd_3990_erp_inspect(struct dasd_ccw_req *erp) struct dasd_ccw_req *erp_new = NULL; char *sense; - /* if this problem occured on an alias retry on base */ + /* if this problem occurred on an alias retry on base */ erp_new = dasd_3990_erp_inspect_alias(erp); if (erp_new) return erp_new; @@ -2282,7 +2282,7 @@ dasd_3990_erp_inspect(struct dasd_ccw_req *erp) * DASD_3990_ERP_ADD_ERP * * DESCRIPTION - * This funtion adds an additional request block (ERP) to the head of + * This function adds an additional request block (ERP) to the head of * the given cqr (or erp). * For a command mode cqr the erp is initialized as an default erp * (retry TIC). diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index cb6a67bc89ff..42e1bf35f689 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -302,7 +302,7 @@ dasd_parse_keyword( char *parsestring ) { /* * Try to interprete the first element on the comma separated parse string * as a device number or a range of devices. If the interpretation is - * successfull, create the matching dasd_devmap entries and return a pointer + * successful, create the matching dasd_devmap entries and return a pointer * to the residual string. * If interpretation fails or in case of an error, return an error code. */ diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 459f2cbe80fc..db8005d9f2fd 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2858,7 +2858,7 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, /* * struct PFX_eckd_data has up to 2 byte as extended parameter * this is needed for write full track and has to be mentioned - * seperately + * separately * add 8 instead of 2 to keep 8 byte boundary */ pfx_datasize = sizeof(struct PFX_eckd_data) + 8; diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 4c023761946f..e21a5c39ef20 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -604,7 +604,7 @@ __raw3270_size_device(struct raw3270 *rp) /* * To determine the size of the 3270 device we need to do: * 1) send a 'read partition' data stream to the device - * 2) wait for the attn interrupt that preceeds the query reply + * 2) wait for the attn interrupt that precedes the query reply * 3) do a read modified to get the query reply * To make things worse we have to cope with intervention * required (3270 device switched to 'stand-by') and command diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index e090a307fdee..87cd0ab242de 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -139,7 +139,7 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) /* * If the tape isn't terminated yet, do it now. And since we then * are at the end of the tape there wouldn't be anything to read - * anyways. So we return immediatly. + * anyways. So we return immediately. */ if(device->required_tapemarks) { return tape_std_terminate_write(device); diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index d33554df2b06..2db1482b406e 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -328,7 +328,7 @@ tty3270_write_callback(struct raw3270_request *rq, void *data) tp = (struct tty3270 *) rq->view; if (rq->rc != 0) { - /* Write wasn't successfull. Refresh all. */ + /* Write wasn't successful. Refresh all. */ tp->update_flags = TTY_UPDATE_ALL; tty3270_set_timer(tp, 1); } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index a845695ac314..6084103672b5 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -318,7 +318,7 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err) /** * ccw_device_notify() - inform the device's driver about an event - * @cdev: device for which an event occured + * @cdev: device for which an event occurred * @event: event that occurred * * Returns: @@ -688,7 +688,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event) (scsw_stctl(&cdev->private->irb.scsw) & SCSW_STCTL_STATUS_PEND)) { /* * No final status yet or final status not yet delivered - * to the device driver. Can't do path verfication now, + * to the device driver. Can't do path verification now, * delay until final status was delivered. */ cdev->private->flags.doverify = 1; diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 88ebd114735b..9688f3985b07 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -76,7 +76,7 @@ struct ica_z90_status { /** * Large random numbers are pulled in 4096 byte chunks from the crypto cards - * and stored in a page. Be carefull when increasing this buffer due to size + * and stored in a page. Be careful when increasing this buffer due to size * limitations for AP requests. */ #define ZCRYPT_RNG_BUFFER_SIZE 4096 diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 9feb62febb3d..da8aa75bb20b 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -779,7 +779,7 @@ claw_irq_handler(struct ccw_device *cdev, case CLAW_START_WRITE: if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { dev_info(&cdev->dev, - "%s: Unit Check Occured in " + "%s: Unit Check Occurred in " "write channel\n", dev->name); clear_bit(0, (void *)&p_ch->IO_active); if (p_ch->irb->ecw[0] & 0x80) { diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 8c921fc3511a..2d602207541b 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -184,7 +184,7 @@ static void ctcmpc_chx_resend(fsm_instance *, int, void *); static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg); /** - * Check return code of a preceeding ccw_device call, halt_IO etc... + * Check return code of a preceding ccw_device call, halt_IO etc... * * ch : The channel, the error belongs to. * Returns the error code (!= 0) to inspect. diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 7fbc4adbb6d5..49d1cfc3217e 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1123,7 +1123,7 @@ list_modified: list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){ switch (ipm->ipm_state) { case LCS_IPM_STATE_SET_REQUIRED: - /* del from ipm_list so noone else can tamper with + /* del from ipm_list so no one else can tamper with * this entry */ list_del_init(&ipm->list); spin_unlock_irqrestore(&card->ipm_lock, flags); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 10a3a3b4dd3e..85cc53117ea6 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1107,7 +1107,7 @@ static int qeth_setup_card(struct qeth_card *card) INIT_LIST_HEAD(card->ip_tbd_list); INIT_LIST_HEAD(&card->cmd_waiter_list); init_waitqueue_head(&card->wait_q); - /* intial options */ + /* initial options */ qeth_set_intial_options(card); /* IP address takeover */ INIT_LIST_HEAD(&card->ipato.entries); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index a0e05ef65924..8512b5c0ef82 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1083,7 +1083,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) } break; case FSF_SBAL_MISMATCH: - /* should never occure, avoided in zfcp_fsf_send_els */ + /* should never occur, avoided in zfcp_fsf_send_els */ /* fall through */ default: req->status |= ZFCP_STATUS_FSFREQ_ERROR; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 8da5ed644c2b..98e97d90835b 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -391,7 +391,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q)) goto failed_qdio; - /* set index of first avalable SBALS / number of available SBALS */ + /* set index of first available SBALS / number of available SBALS */ qdio->req_q_idx = 0; atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status); diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index e8566224fe4b..6b4678a7900a 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -13,7 +13,7 @@ * TODO: Erase/program both banks of a 8MB SIMM. * * It is anticipated that programming an OS Flash will be a routine - * procedure. In the same time it is exeedingly dangerous because + * procedure. In the same time it is exceedingly dangerous because * a user can program its OBP flash with OS image and effectively * kill the machine. * diff --git a/drivers/sbus/char/max1617.h b/drivers/sbus/char/max1617.h index 0bb09c286cb4..cd30819a0a30 100644 --- a/drivers/sbus/char/max1617.h +++ b/drivers/sbus/char/max1617.h @@ -6,7 +6,7 @@ #define MAX1617_CPU_TEMP 0x01 /* Processor die temp in C */ #define MAX1617_STATUS 0x02 /* Chip status bits */ -/* Read-only versions of changable registers. */ +/* Read-only versions of changeable registers. */ #define MAX1617_RD_CFG_BYTE 0x03 /* Config register */ #define MAX1617_RD_CVRATE_BYTE 0x04 /* Temp conversion rate */ #define MAX1617_RD_AMB_HIGHLIM 0x05 /* Ambient high limit */ diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 3343824855d0..040f7214e5b7 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -61,7 +61,7 @@ static twa_message_type twa_aen_table[] = { {0x0000, "AEN queue empty"}, {0x0001, "Controller reset occurred"}, {0x0002, "Degraded unit detected"}, - {0x0003, "Controller error occured"}, + {0x0003, "Controller error occurred"}, {0x0004, "Background rebuild failed"}, {0x0005, "Background rebuild done"}, {0x0006, "Incomplete unit detected"}, diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 8b9f9d17e7fe..49dcf03c631a 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -8,7 +8,7 @@ Copyright (C) 1999-2010 3ware Inc. - Kernel compatiblity By: Andre Hedrick + Kernel compatibility By: Andre Hedrick Non-Copyright (C) 2000 Andre Hedrick This program is free software; you can redistribute it and/or modify diff --git a/drivers/scsi/53c700.scr b/drivers/scsi/53c700.scr index a064a092c604..ec822e3b7a27 100644 --- a/drivers/scsi/53c700.scr +++ b/drivers/scsi/53c700.scr @@ -31,7 +31,7 @@ ABSOLUTE StatusAddress = 0 ; Addr to receive status return ABSOLUTE ReceiveMsgAddress = 0 ; Addr to receive msg ; ; This is the magic component for handling scatter-gather. Each of the -; SG components is preceeded by a script fragment which moves the +; SG components is preceded by a script fragment which moves the ; necessary amount of data and jumps to the next SG segment. The final ; SG segment jumps back to . However, this address is the first SG script ; segment. diff --git a/drivers/scsi/53c700_d.h_shipped b/drivers/scsi/53c700_d.h_shipped index 0b42a51257f2..aa623da333c8 100644 --- a/drivers/scsi/53c700_d.h_shipped +++ b/drivers/scsi/53c700_d.h_shipped @@ -34,7 +34,7 @@ ABSOLUTE StatusAddress = 0 ; Addr to receive status return ABSOLUTE ReceiveMsgAddress = 0 ; Addr to receive msg ; ; This is the magic component for handling scatter-gather. Each of the -; SG components is preceeded by a script fragment which moves the +; SG components is preceded by a script fragment which moves the ; necessary amount of data and jumps to the next SG segment. The final ; SG segment jumps back to . However, this address is the first SG script ; segment. diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index e40cdfb7541f..dcd716d68600 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -2509,7 +2509,7 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); - /* Setup our STATE so we know what happend when + /* Setup our STATE so we know what happened when the wheels fall off. */ currSCCB->Sccb_scsistat = SELECT_ST; @@ -2900,7 +2900,7 @@ static void FPT_SendMsg(unsigned long port, unsigned char message) * * Function: FPT_sdecm * - * Description: Determine the proper responce to the message from the + * Description: Determine the proper response to the message from the * target device. * *---------------------------------------------------------------------*/ diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index e7cd2fcbe036..165e4dd865d9 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1198,12 +1198,12 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) */ if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) { - int transfered; + int transferred; if (!hostdata->connected) panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno); - transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); + transferred = (hostdata->dmalen - NCR5380_dma_residual(instance)); hostdata->connected->SCp.this_residual -= transferred; hostdata->connected->SCp.ptr += transferred; hostdata->dmalen = 0; @@ -1563,7 +1563,7 @@ failed: * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transfered or exit + * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. @@ -1800,7 +1800,7 @@ static int do_abort(struct Scsi_Host *host) { * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transfered or exit + * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 118ce83a737c..061995741444 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -747,8 +747,8 @@ char * get_container_type(unsigned tindex) * Arguments: [1] pointer to void [1] int * * Purpose: Sets SCSI inquiry data strings for vendor, product - * and revision level. Allows strings to be set in platform dependant - * files instead of in OS dependant driver source. + * and revision level. Allows strings to be set in platform dependent + * files instead of in OS dependent driver source. */ static void setinqstr(struct aac_dev *dev, void *data, int tindex) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 29ab00016b78..ffb587817efc 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1259,7 +1259,7 @@ struct aac_dev #define CACHE_UNSTABLE 2 /* - * Lets the client know at which level the data was commited on + * Lets the client know at which level the data was committed on * a write request */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index dd7ad3ba2dad..e7d0d47b9185 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -421,7 +421,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) return -EBUSY; /* - * There are 5 cases with the wait and reponse requested flags. + * There are 5 cases with the wait and response requested flags. * The only invalid cases are if the caller requests to wait and * does not request a response and if the caller does not want a * response and the Fib is not allocated from pool. If a response diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 081c6de92bc5..bfd618a69499 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -4544,7 +4544,7 @@ AscMemWordCopyPtrToLram(PortAddr iop_base, ushort s_addr, * Copy 4 bytes to LRAM. * * The source data is assumed to be in little-endian order in memory - * and is maintained in little-endian order when writen to LRAM. + * and is maintained in little-endian order when written to LRAM. */ static void AscMemDWordCopyPtrToLram(PortAddr iop_base, diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index d058f1ab82b5..1c10b796c1a2 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -461,7 +461,7 @@ static int aha1740_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *) /* The Adaptec Spec says the card is so fast that the loops will only be executed once in the code below. Even if this was true with the fastest processors when the spec was - written, it doesn't seem to be true with todays fast + written, it doesn't seem to be true with today's fast processors. We print a warning if the code is executed more often than LOOPCNT_WARN. If this happens, it should be investigated. If the count reaches LOOPCNT_MAX, we assume diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 95ee50385188..9b059422aacb 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -473,7 +473,7 @@ struct hardware_scb { * o A residual has occurred if SG_FULL_RESID is set in sgptr, * or residual_sgptr does not have SG_LIST_NULL set. * - * o We are transfering the last segment if residual_datacnt has + * o We are transferring the last segment if residual_datacnt has * the SG_LAST_SEG flag set. * * Host: @@ -516,7 +516,7 @@ struct hardware_scb { */ /* - * Definition of a scatter/gather element as transfered to the controller. + * Definition of a scatter/gather element as transferred to the controller. * The aic7xxx chips only support a 24bit length. We use the top byte of * the length to store additional address bits and a flag to indicate * that a given segment terminates the transfer. This gives us an diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg index 0666c22ab55b..7e12c31ccfda 100644 --- a/drivers/scsi/aic7xxx/aic79xx.reg +++ b/drivers/scsi/aic7xxx/aic79xx.reg @@ -305,7 +305,7 @@ register HS_MAILBOX { } /* - * Sequencer Interupt Status + * Sequencer Interrupt Status */ register SEQINTSTAT { address 0x00C @@ -685,7 +685,7 @@ register DCHRXMSG0 { } /* - * CMC Recieve Message 0 + * CMC Receive Message 0 */ register CMCRXMSG0 { address 0x090 @@ -696,7 +696,7 @@ register CMCRXMSG0 { } /* - * Overlay Recieve Message 0 + * Overlay Receive Message 0 */ register OVLYRXMSG0 { address 0x090 @@ -732,7 +732,7 @@ register DCHRXMSG1 { } /* - * CMC Recieve Message 1 + * CMC Receive Message 1 */ register CMCRXMSG1 { address 0x091 @@ -742,7 +742,7 @@ register CMCRXMSG1 { } /* - * Overlay Recieve Message 1 + * Overlay Receive Message 1 */ register OVLYRXMSG1 { address 0x091 @@ -777,7 +777,7 @@ register DCHRXMSG2 { } /* - * CMC Recieve Message 2 + * CMC Receive Message 2 */ register CMCRXMSG2 { address 0x092 @@ -787,7 +787,7 @@ register CMCRXMSG2 { } /* - * Overlay Recieve Message 2 + * Overlay Receive Message 2 */ register OVLYRXMSG2 { address 0x092 @@ -816,7 +816,7 @@ register DCHRXMSG3 { } /* - * CMC Recieve Message 3 + * CMC Receive Message 3 */ register CMCRXMSG3 { address 0x093 @@ -826,7 +826,7 @@ register CMCRXMSG3 { } /* - * Overlay Recieve Message 3 + * Overlay Receive Message 3 */ register OVLYRXMSG3 { address 0x093 @@ -1249,7 +1249,7 @@ register TARGPCISTAT { /* * LQ Packet In - * The last LQ Packet recieved + * The last LQ Packet received */ register LQIN { address 0x020 @@ -2573,7 +2573,7 @@ register IOPDNCTL { } /* - * Shaddow Host Address. + * Shadow Host Address. */ register SHADDR { address 0x060 @@ -3983,7 +3983,7 @@ scratch_ram { /* * The maximum amount of time to wait, when interrupt coalescing - * is enabled, before issueing a CMDCMPLT interrupt for a completed + * is enabled, before issuing a CMDCMPLT interrupt for a completed * command. */ INT_COALESCING_TIMER { diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index 2fb78e35a9e5..3a36d9362a10 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq @@ -567,7 +567,7 @@ BEGIN_CRITICAL; shr SELOID, 4, SCB_SCSIID; /* * If we want to send a message to the device, ensure - * we are selecting with atn irregardless of our packetized + * we are selecting with atn regardless of our packetized * agreement. Since SPI4 only allows target reset or PPR * messages if this is a packetized connection, the change * to our negotiation table entry for this selection will @@ -960,7 +960,7 @@ p_status_okay: * This is done to allow the host to send messages outside of an identify * sequence while protecting the seqencer from testing the MK_MESSAGE bit * on an SCB that might not be for the current nexus. (For example, a - * BDR message in responce to a bad reselection would leave us pointed to + * BDR message in response to a bad reselection would leave us pointed to * an SCB that doesn't have anything to do with the current target). * * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, @@ -1507,7 +1507,7 @@ service_fifo: * If the other FIFO needs loading, then it * must not have claimed the S/G cache yet * (SG_CACHE_AVAIL would have been cleared in - * the orginal FIFO mode and we test this above). + * the original FIFO mode and we test this above). * Return to the idle loop so we can process the * FIFO not currently on the bus first. */ @@ -1521,7 +1521,7 @@ idle_sgfetch_okay: idle_sgfetch_start: /* * We fetch a "cacheline aligned" and sized amount of data - * so we don't end up referencing a non-existant page. + * so we don't end up referencing a non-existent page. * Cacheline aligned is in quotes because the kernel will * set the prefetch amount to a reasonable level if the * cacheline size is unknown. @@ -1551,7 +1551,7 @@ idle_sg_avail: test DFSTATUS, PRELOAD_AVAIL jz return; /* * On the A, preloading a segment before HDMAENACK - * comes true can clobber the shaddow address of the + * comes true can clobber the shadow address of the * first segment in the S/G FIFO. Wait until it is * safe to proceed. */ @@ -2004,10 +2004,10 @@ pkt_handle_xfer: * Defer handling of this NONPACKREQ until we * can be sure it pertains to this FIFO. SAVEPTRS * will not be asserted if the NONPACKREQ is for us, - * so we must simulate it if shaddow is valid. If - * shaddow is not valid, keep running this FIFO until we + * so we must simulate it if shadow is valid. If + * shadow is not valid, keep running this FIFO until we * have satisfied the transfer by loading segments and - * waiting for either shaddow valid or last_seg_done. + * waiting for either shadow valid or last_seg_done. */ test MDFFSTAT, SHVALID jnz pkt_saveptrs; pkt_service_fifo: @@ -2171,7 +2171,7 @@ pkt_status_check_nonpackreq: /* * The unexpected nonpkt phase handler assumes that any * data channel use will have a FIFO reference count. It - * turns out that the status handler doesn't need a refernce + * turns out that the status handler doesn't need a references * count since the status received flag, and thus completion * processing, cannot be set until the handler is finished. * We increment the count here to make the nonpkt handler diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 3233bf564435..5f8617dd43bb 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -562,7 +562,7 @@ ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) } #endif -/*********************** Miscelaneous Support Functions ***********************/ +/*********************** Miscellaneous Support Functions ***********************/ /* * Return pointers to the transfer negotiation information * for the specified our_id/remote_id pair. @@ -599,7 +599,7 @@ void ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) { /* - * Write low byte first to accomodate registers + * Write low byte first to accommodate registers * such as PRGMCNT where the order maters. */ ahd_outb(ahd, port, value & 0xFF); @@ -2067,7 +2067,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) * that requires host assistance for completion. * While handling the message phase(s), we will be * notified by the sequencer after each byte is - * transfered so we can track bus phase changes. + * transferred so we can track bus phase changes. * * If this is the first time we've seen a HOST_MSG_LOOP * interrupt, initialize the state of the host message @@ -2487,7 +2487,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) /* * Although the driver does not care about the * 'Selection in Progress' status bit, the busy - * LED does. SELINGO is only cleared by a successfull + * LED does. SELINGO is only cleared by a successful * selection, so we must manually clear it to insure * the LED turns off just incase no future successful * selections occur (e.g. no devices on the bus). @@ -3548,7 +3548,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP); ahd_outb(ahd, SIMODE1, simode1); /* - * SCSIINT seems to glitch occassionally when + * SCSIINT seems to glitch occasionally when * the interrupt masks are restored. Clear SCSIINT * one more time so that only persistent errors * are seen as a real interrupt. @@ -3838,7 +3838,7 @@ ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, /* * Update the bitmask of targets for which the controller should - * negotiate with at the next convenient oportunity. This currently + * negotiate with at the next convenient opportunity. This currently * means the next time we send the initial identify messages for * a new transaction. */ @@ -4200,7 +4200,7 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, /* * During packetized transfers, the target will - * give us the oportunity to send command packets + * give us the opportunity to send command packets * without us asserting attention. */ if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0) @@ -5651,7 +5651,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) /* * Requeue all tagged commands for this target - * currently in our posession so they can be + * currently in our possession so they can be * converted to untagged commands. */ ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb), @@ -6245,7 +6245,7 @@ ahd_shutdown(void *arg) /* * Reset the controller and record some information about it * that is only available just after a reset. If "reinit" is - * non-zero, this reset occured after initial configuration + * non-zero, this reset occurred after initial configuration * and the caller requests that the chip be fully reinitialized * to a runable state. Chip interrupts are *not* enabled after * a reinitialization. The caller must enable interrupts via @@ -6495,7 +6495,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) } /* - * Note that we were successfull + * Note that we were successful */ return (0); @@ -7079,7 +7079,7 @@ ahd_init(struct ahd_softc *ahd) return (ENOMEM); /* - * Verify that the compiler hasn't over-agressively + * Verify that the compiler hasn't over-aggressively * padded important structures. */ if (sizeof(struct hardware_scb) != 64) @@ -10087,7 +10087,7 @@ ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, return (error); /* - * Write the data. If we don't get throught the loop at + * Write the data. If we don't get through the loop at * least once, the arguments were invalid. */ retval = EINVAL; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 25d066624476..7d48700257a7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1441,7 +1441,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev, usertags = ahd_linux_user_tagdepth(ahd, devinfo); if (!was_queuing) { /* - * Start out agressively and allow our + * Start out aggressively and allow our * dynamic queue depth algorithm to take * care of the rest. */ diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 17444bc18bca..f695774645c1 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -440,7 +440,7 @@ struct hardware_scb { * o A residual has occurred if SG_FULL_RESID is set in sgptr, * or residual_sgptr does not have SG_LIST_NULL set. * - * o We are transfering the last segment if residual_datacnt has + * o We are transferring the last segment if residual_datacnt has * the SG_LAST_SEG flag set. * * Host: @@ -494,7 +494,7 @@ struct hardware_scb { */ /* - * Definition of a scatter/gather element as transfered to the controller. + * Definition of a scatter/gather element as transferred to the controller. * The aic7xxx chips only support a 24bit length. We use the top byte of * the length to store additional address bits and a flag to indicate * that a given segment terminates the transfer. This gives us an diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg index 9a96e55da39a..ba0b411d03e2 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.reg +++ b/drivers/scsi/aic7xxx/aic7xxx.reg @@ -351,7 +351,7 @@ register SSTAT2 { address 0x00d access_mode RO field OVERRUN 0x80 - field SHVALID 0x40 /* Shaddow Layer non-zero */ + field SHVALID 0x40 /* Shadow Layer non-zero */ field EXP_ACTIVE 0x10 /* SCSI Expander Active */ field CRCVALERR 0x08 /* CRC doesn't match (U3 only) */ field CRCENDERR 0x04 /* No terminal CRC packet (U3 only) */ diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq index 5a4cfc954a9f..e60041e8f2d1 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.seq +++ b/drivers/scsi/aic7xxx/aic7xxx.seq @@ -57,10 +57,10 @@ PREFIX = "ahc_" * a later time. This problem cannot be resolved by holding a single entry * in scratch ram since a reconnecting target can request sense and this will * create yet another SCB waiting for selection. The solution used here is to - * use byte 27 of the SCB as a psuedo-next pointer and to thread a list + * use byte 27 of the SCB as a pseudo-next pointer and to thread a list * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to - * this list everytime a request sense occurs or after completing a non-tagged + * this list every time a request sense occurs or after completing a non-tagged * command for which a second SCB has been queued. The sequencer will * automatically consume the entries. */ @@ -752,7 +752,7 @@ idle_loop: /* * We fetch a "cacheline aligned" and sized amount of data - * so we don't end up referencing a non-existant page. + * so we don't end up referencing a non-existent page. * Cacheline aligned is in quotes because the kernel will * set the prefetch amount to a reasonable level if the * cacheline size is unknown. @@ -1485,7 +1485,7 @@ p_status_okay: * This is done to allow the host to send messages outside of an identify * sequence while protecting the seqencer from testing the MK_MESSAGE bit * on an SCB that might not be for the current nexus. (For example, a - * BDR message in responce to a bad reselection would leave us pointed to + * BDR message in response to a bad reselection would leave us pointed to * an SCB that doesn't have anything to do with the current target). * * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, @@ -1999,7 +1999,7 @@ if ((ahc->flags & AHC_TARGETROLE) != 0) { * from out to in, wait an additional data release delay before continuing. */ change_phase: - /* Wait for preceeding I/O session to complete. */ + /* Wait for preceding I/O session to complete. */ test SCSISIGI, ACKI jnz .; /* Change the phase */ diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index e021b4812d58..dc28b0a91b22 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -427,7 +427,7 @@ ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index) } #endif -/*********************** Miscelaneous Support Functions ***********************/ +/*********************** Miscellaneous Support Functions ***********************/ /* * Determine whether the sequencer reported a residual * for this SCB/transaction. @@ -1243,7 +1243,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) * that requires host assistance for completion. * While handling the message phase(s), we will be * notified by the sequencer after each byte is - * transfered so we can track bus phase changes. + * transferred so we can track bus phase changes. * * If this is the first time we've seen a HOST_MSG_LOOP * interrupt, initialize the state of the host message @@ -1487,7 +1487,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) scbptr, ahc_inb(ahc, ARG_1), ahc->scb_data->hscbs[scbptr].tag); ahc_dump_card_state(ahc); - panic("for saftey"); + panic("for safety"); break; } case OUT_OF_RANGE: @@ -1733,7 +1733,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) /* * Although the driver does not care about the * 'Selection in Progress' status bit, the busy - * LED does. SELINGO is only cleared by a successfull + * LED does. SELINGO is only cleared by a successful * selection, so we must manually clear it to insure * the LED turns off just incase no future successful * selections occur (e.g. no devices on the bus). @@ -1943,7 +1943,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) if (lastphase != P_BUSFREE) { /* * Renegotiate with this device at the - * next oportunity just in case this busfree + * next opportunity just in case this busfree * is due to a negotiation mismatch with the * device. */ @@ -2442,7 +2442,7 @@ ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, /* * Update the bitmask of targets for which the controller should - * negotiate with at the next convenient oportunity. This currently + * negotiate with at the next convenient opportunity. This currently * means the next time we send the initial identify messages for * a new transaction. */ @@ -4131,7 +4131,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) /* * Requeue all tagged commands for this target - * currently in our posession so they can be + * currently in our possession so they can be * converted to untagged commands. */ ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb), @@ -4581,7 +4581,7 @@ ahc_shutdown(void *arg) /* * Reset the controller and record some information about it * that is only available just after a reset. If "reinit" is - * non-zero, this reset occured after initial configuration + * non-zero, this reset occurred after initial configuration * and the caller requests that the chip be fully reinitialized * to a runable state. Chip interrupts are *not* enabled after * a reinitialization. The caller must enable interrupts via @@ -4899,7 +4899,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) ahc->next_queued_scb = ahc_get_scb(ahc); /* - * Note that we were successfull + * Note that we were successful */ return (0); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 4a359bb307c6..c6251bb4f438 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -294,7 +294,7 @@ static uint32_t aic7xxx_extended; * dubious at best. To my knowledge, this option has never actually * solved a PCI parity problem, but on certain machines with broken PCI * chipset configurations where stray PCI transactions with bad parity are - * the norm rather than the exception, the error messages can be overwelming. + * the norm rather than the exception, the error messages can be overwhelming. * It's included in the driver for completeness. * 0 = Shut off PCI parity check * non-0 = reverse polarity pci parity checking @@ -1318,7 +1318,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, usertags = ahc_linux_user_tagdepth(ahc, devinfo); if (!was_queuing) { /* - * Start out agressively and allow our + * Start out aggressively and allow our * dynamic queue depth algorithm to take * care of the rest. */ diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 2b11a4272364..6917b4f5ac9e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -789,7 +789,7 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; - /* Remeber how the card was setup in case there is no SEEPROM */ + /* Remember how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { ahc_pause(ahc); if ((ahc->features & AHC_ULTRA2) != 0) @@ -860,7 +860,7 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) } /* - * We cannot perform ULTRA speeds without the presense + * We cannot perform ULTRA speeds without the presence * of the external precision resistor. */ if ((ahc->features & AHC_ULTRA) != 0) { @@ -969,7 +969,7 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) } /* - * Test for the presense of external sram in an + * Test for the presence of external sram in an * "unshared" configuration. */ static int diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y index e4064433842e..f1586a437906 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y @@ -803,7 +803,7 @@ macro_arglist: | macro_arglist ',' T_ARG { if ($1 == 0) { - stop("Comma without preceeding argument in arg list", + stop("Comma without preceding argument in arg list", EX_DATAERR); /* NOTREACHED */ } @@ -1319,8 +1319,8 @@ code: ; /* - * This grammer differs from the one in the aic7xxx - * reference manual since the grammer listed there is + * This grammar differs from the one in the aic7xxx + * reference manual since the grammar listed there is * ambiguous and causes a shift/reduce conflict. * It also seems more logical as the "immediate" * argument is listed as the second arg like the @@ -1799,7 +1799,7 @@ format_3_instr(int opcode, symbol_ref_t *src, instr = seq_alloc(); f3_instr = &instr->format.format3; if (address->symbol == NULL) { - /* 'dot' referrence. Use the current instruction pointer */ + /* 'dot' reference. Use the current instruction pointer */ addr = instruction_ptr + address->offset; } else if (address->symbol->type == UNINITIALIZED) { /* forward reference */ diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y index ff46aa6801bf..708326df0766 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y @@ -115,7 +115,7 @@ macro_arglist: | macro_arglist ',' T_ARG { if ($1 == 0) { - stop("Comma without preceeding argument in arg list", + stop("Comma without preceding argument in arg list", EX_DATAERR); /* NOTREACHED */ } diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 4ff60a08df0f..5b212f0df898 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -905,7 +905,7 @@ struct aic_dev_data { * problems with architectures I can't test on (because I don't have one, * such as the Alpha based systems) which happen to give faults for * non-aligned memory accesses, care was taken to align this structure - * in a way that gauranteed all accesses larger than 8 bits were aligned + * in a way that guaranteed all accesses larger than 8 bits were aligned * on the appropriate boundary. It's also organized to try and be more * cache line efficient. Be careful when changing this lest you might hurt * overall performance and bring down the wrath of the masses. @@ -1180,7 +1180,7 @@ static int aic7xxx_pci_parity = 0; * the card's registers in a hex dump format tailored to each model of * controller. * - * NOTE: THE CONTROLLER IS LEFT IN AN UNUSEABLE STATE BY THIS OPTION. + * NOTE: THE CONTROLLER IS LEFT IN AN UNUSABLE STATE BY THIS OPTION. * YOU CANNOT BOOT UP WITH THIS OPTION, IT IS FOR DEBUGGING PURPOSES * ONLY */ @@ -3467,7 +3467,7 @@ aic7xxx_reset_current_bus(struct aic7xxx_host *p) /* Turn off the bus' current operations, after all, we shouldn't have any * valid commands left to cause a RSELI and SELO once we've tossed the * bus away with this reset, so we might as well shut down the sequencer - * until the bus is restarted as oppossed to saving the current settings + * until the bus is restarted as opposed to saving the current settings * and restoring them (which makes no sense to me). */ /* Turn on the bus reset. */ @@ -4070,7 +4070,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) aic_dev->max_q_depth = aic_dev->temp_q_depth = 1; /* * We set this command up as a bus device reset. However, we have - * to clear the tag type as it's causing us problems. We shouldnt + * to clear the tag type as it's causing us problems. We shouldn't * have to worry about any other commands being active, since if * the device is refusing tagged commands, this should be the * first tagged command sent to the device, however, we do have @@ -9748,7 +9748,7 @@ skip_pci_controller: } /* - * We are commited now, everything has been checked and this card + * We are committed now, everything has been checked and this card * has been found, now we just set it up */ @@ -9906,7 +9906,7 @@ skip_pci_controller: * 2: All PCI controllers with BIOS_ENABLED next, according to BIOS * address, going from lowest to highest. * 3: Remaining VLB/EISA controllers going in slot order. - * 4: Remaining PCI controllers, going in PCI device order (reversable) + * 4: Remaining PCI controllers, going in PCI device order (reversible) */ { diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.seq b/drivers/scsi/aic7xxx_old/aic7xxx.seq index 1565be9ebd49..823ff2873229 100644 --- a/drivers/scsi/aic7xxx_old/aic7xxx.seq +++ b/drivers/scsi/aic7xxx_old/aic7xxx.seq @@ -51,7 +51,7 @@ * use byte 27 of the SCB as a pseudo-next pointer and to thread a list * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to - * this list everytime a request sense occurs or after completing a non-tagged + * this list every time a request sense occurs or after completing a non-tagged * command for which a second SCB has been queued. The sequencer will * automatically consume the entries. */ @@ -696,7 +696,7 @@ p_status: * This is done to allow the hsot to send messages outside of an identify * sequence while protecting the seqencer from testing the MK_MESSAGE bit * on an SCB that might not be for the current nexus. (For example, a - * BDR message in responce to a bad reselection would leave us pointed to + * BDR message in response to a bad reselection would leave us pointed to * an SCB that doesn't have anything to do with the current target). * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, * bus device reset). @@ -716,8 +716,8 @@ p_mesgout_identify: } else { and SINDEX,0x7,SCB_TCL; /* lun */ } - and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */ - or SINDEX,A; /* or in disconnect privledge */ + and A,DISCENB,SCB_CONTROL; /* mask off disconnect privilege */ + or SINDEX,A; /* or in disconnect privilege */ or SINDEX,MSG_IDENTIFYFLAG; p_mesgout_mk_message: test SCB_CONTROL,MK_MESSAGE jz p_mesgout_tag; diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h index 40273a747d29..dd6cc8008b16 100644 --- a/drivers/scsi/aic94xx/aic94xx_reg_def.h +++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h @@ -2134,7 +2134,7 @@ * The host accesses this scratch in a different manner from the * link sequencer. The sequencer has to use LSEQ registers * LmSCRPAGE and LmMnSCRPAGE to access the scratch memory. A flat -* mapping of the scratch memory is avaliable for software +* mapping of the scratch memory is available for software * convenience and to prevent corruption while the sequencer is * running. This memory is mapped onto addresses 800h - 9FFh. * diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index ec166726b314..c454e44cf51c 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -100,7 +100,7 @@ */ #define TIMEOUT_TIME 10 /* - * Define this if you want to have verbose explaination of SCSI + * Define this if you want to have verbose explanation of SCSI * status/messages. */ #undef CONFIG_ACORNSCSI_CONSTANTS @@ -1561,7 +1561,7 @@ void acornscsi_message(AS_Host *host) /* * If we were negociating sync transfer, we don't yet know if * this REJECT is for the sync transfer or for the tagged queue/wide - * transfer. Re-initiate sync transfer negociation now, and if + * transfer. Re-initiate sync transfer negotiation now, and if * we got a REJECT in response to SDTR, then it'll be set to DONE. */ if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) diff --git a/drivers/scsi/arm/acornscsi.h b/drivers/scsi/arm/acornscsi.h index 8d2172a0b351..01bc715a3aec 100644 --- a/drivers/scsi/arm/acornscsi.h +++ b/drivers/scsi/arm/acornscsi.h @@ -223,8 +223,8 @@ typedef enum { * Synchronous transfer state */ typedef enum { /* Synchronous transfer state */ - SYNC_ASYNCHRONOUS, /* don't negociate synchronous transfers*/ - SYNC_NEGOCIATE, /* start negociation */ + SYNC_ASYNCHRONOUS, /* don't negotiate synchronous transfers*/ + SYNC_NEGOCIATE, /* start negotiation */ SYNC_SENT_REQUEST, /* sent SDTR message */ SYNC_COMPLETED, /* received SDTR reply */ } syncxfer_t; @@ -322,7 +322,7 @@ typedef struct acornscsi_hostdata { /* per-device info */ struct { unsigned char sync_xfer; /* synchronous transfer (SBIC value) */ - syncxfer_t sync_state; /* sync xfer negociation state */ + syncxfer_t sync_state; /* sync xfer negotiation state */ unsigned char disconnect_ok:1; /* device can disconnect */ } device[8]; unsigned long busyluns[64 / sizeof(unsigned long)];/* array of bits indicating LUNs busy */ diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c index 2836fe248df9..a750aa72b8ef 100644 --- a/drivers/scsi/arm/arxescsi.c +++ b/drivers/scsi/arm/arxescsi.c @@ -228,7 +228,7 @@ static const char *arxescsi_info(struct Scsi_Host *host) * Params : buffer - a buffer to write information to * start - a pointer into this buffer set by this routine to the start * of the required information. - * offset - offset into information that we have read upto. + * offset - offset into information that we have read up to. * length - length of buffer * host_no - host number to return information for * inout - 0 for reading, 1 for writing. diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index c9902b5c1f2b..547987b86384 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -344,7 +344,7 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) * Params : buffer - a buffer to write information to * start - a pointer into this buffer set by this routine to the start * of the required information. - * offset - offset into information that we have read upto. + * offset - offset into information that we have read up to. * length - length of buffer * host_no - host number to return information for * inout - 0 for reading, 1 for writing. diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index d8435132f461..edfd12b48c28 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -429,7 +429,7 @@ eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) * Params : buffer - a buffer to write information to * start - a pointer into this buffer set by this routine to the start * of the required information. - * offset - offset into information that we have read upto. + * offset - offset into information that we have read up to. * length - length of buffer * host_no - host number to return information for * inout - 0 for reading, 1 for writing. diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index 2b2ce21e227e..e85c40b6e19b 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -2119,7 +2119,7 @@ request_sense: * executed, unless a target connects to us. */ if (info->reqSCpnt) - printk(KERN_WARNING "scsi%d.%c: loosing request command\n", + printk(KERN_WARNING "scsi%d.%c: losing request command\n", info->host->host_no, '0' + SCpnt->device->id); info->reqSCpnt = SCpnt; } @@ -2294,7 +2294,7 @@ static int fas216_noqueue_command_lck(struct scsi_cmnd *SCpnt, * If we don't have an IRQ, then we must poll the card for * it's interrupt, and use that to call this driver's * interrupt routine. That way, we keep the command - * progressing. Maybe we can add some inteligence here + * progressing. Maybe we can add some intelligence here * and go to sleep if we know that the device is going * to be some time (eg, disconnected). */ diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h index f30f8d659dc4..84b7127c0121 100644 --- a/drivers/scsi/arm/fas216.h +++ b/drivers/scsi/arm/fas216.h @@ -203,11 +203,11 @@ typedef enum { } fasdmatype_t; typedef enum { - neg_wait, /* Negociate with device */ - neg_inprogress, /* Negociation sent */ - neg_complete, /* Negociation complete */ - neg_targcomplete, /* Target completed negociation */ - neg_invalid /* Negociation not supported */ + neg_wait, /* Negotiate with device */ + neg_inprogress, /* Negotiation sent */ + neg_complete, /* Negotiation complete */ + neg_targcomplete, /* Target completed negotiation */ + neg_invalid /* Negotiation not supported */ } neg_t; #define MAGIC 0x441296bdUL diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index e2297b4c1b9e..9274c0677b9c 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -232,7 +232,7 @@ powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) * Params : buffer - a buffer to write information to * start - a pointer into this buffer set by this routine to the start * of the required information. - * offset - offset into information that we have read upto. + * offset - offset into information that we have read up to. * length - length of buffer * inout - 0 for reading, 1 for writing. * Returns : length of data written to buffer. diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 88b2928b4d3b..ea439f93ed81 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -464,7 +464,7 @@ static void free_all_tags(void) * * Parameters: Scsi_Cmnd *cmd * The command to work on. The first scatter buffer's data are - * assumed to be already transfered into ptr/this_residual. + * assumed to be already transferred into ptr/this_residual. */ static void merge_contiguous_buffers(Scsi_Cmnd *cmd) @@ -1720,7 +1720,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes are transfered or exit + * maximum number of bytes, 0 if all bytes are transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. @@ -1911,7 +1911,7 @@ static int do_abort(struct Scsi_Host *host) * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transfered or exit + * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 76029d570beb..7e6eca4a125e 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1228,7 +1228,7 @@ TCM_5: /* isolation complete.. */ printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ i = 15; j = mbuf[0]; - if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ + if ((j & 0x20) != 0) { /* bit5=1:ID up to 7 */ i = 7; } if ((j & 0x06) == 0) { /* IDvalid? */ diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 5218de4ab35a..fbd1dc2c15f7 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -877,7 +877,7 @@ struct be_all_if_id { */ #define CXN_KILLED_PDU_SIZE_EXCEEDS_DSL 3 /* Connection got invalidated * internally - * due to a recieved PDU + * due to a received PDU * size > DSL */ #define CXN_KILLED_BURST_LEN_MISMATCH 4 /* Connection got invalidated @@ -886,7 +886,7 @@ struct be_all_if_id { * FBL/MBL. */ #define CXN_KILLED_AHS_RCVD 5 /* Connection got invalidated - * internally due to a recieved + * internally due to a received * PDU Hdr that has * AHS */ #define CXN_KILLED_HDR_DIGEST_ERR 6 /* Connection got invalidated @@ -899,12 +899,12 @@ struct be_all_if_id { * pdu hdr */ #define CXN_KILLED_STALE_ITT_TTT_RCVD 8 /* Connection got invalidated - * internally due to a recieved + * internally due to a received * ITT/TTT that does not belong * to this Connection */ #define CXN_KILLED_INVALID_ITT_TTT_RCVD 9 /* Connection got invalidated - * internally due to recieved + * internally due to received * ITT/TTT value > Max * Supported ITTs/TTTs */ @@ -936,21 +936,21 @@ struct be_all_if_id { * index. */ #define CXN_KILLED_OVER_RUN_RESIDUAL 16 /* Command got invalidated - * internally due to recived + * internally due to received * command has residual * over run bytes. */ #define CXN_KILLED_UNDER_RUN_RESIDUAL 17 /* Command got invalidated - * internally due to recived + * internally due to received * command has residual under * run bytes. */ #define CMD_KILLED_INVALID_STATSN_RCVD 18 /* Command got invalidated - * internally due to a recieved + * internally due to a received * PDU has an invalid StatusSN */ #define CMD_KILLED_INVALID_R2T_RCVD 19 /* Command got invalidated - * internally due to a recieved + * internally due to a received * an R2T with some invalid * fields in it */ @@ -973,7 +973,7 @@ struct be_all_if_id { */ #define CMD_CXN_KILLED_INVALID_DATASN_RCVD 24 /* Command got invalidated * internally due to a - * recieved PDU has an invalid + * received PDU has an invalid * DataSN */ #define CXN_INVALIDATE_NOTIFY 25 /* Connection invalidation diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 1cd5c8b0618d..91838c51fb76 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -355,7 +355,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec) /* * ERR_PSS bit needs to be cleared as well in case * interrups are shared so driver's interrupt handler is - * still called eventhough it is already masked out. + * still called even though it is already masked out. */ curr_value = readl( bfa->ioc.ioc_regs.pss_err_status_reg); diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 648c84176722..207f598877c7 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -145,7 +145,7 @@ struct bfa_fw_io_stats_s { u32 ioh_data_oor_event; /* Data out of range */ u32 ioh_ro_ooo_event; /* Relative offset out of range */ u32 ioh_cpu_owned_event; /* IOH hit -iost owned by f/w */ - u32 ioh_unexp_frame_event; /* unexpected frame recieved + u32 ioh_unexp_frame_event; /* unexpected frame received * count */ u32 ioh_err_int; /* IOH error int during data-phase * for scsi write @@ -566,8 +566,8 @@ struct bfa_itnim_iostats_s { u32 input_reqs; /* Data in-bound requests */ u32 output_reqs; /* Data out-bound requests */ u32 io_comps; /* Total IO Completions */ - u32 wr_throughput; /* Write data transfered in bytes */ - u32 rd_throughput; /* Read data transfered in bytes */ + u32 wr_throughput; /* Write data transferred in bytes */ + u32 rd_throughput; /* Read data transferred in bytes */ u32 iocomp_ok; /* Slowpath IO completions */ u32 iocomp_underrun; /* IO underrun */ diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index 8e764fae8dc9..bf0067e0fd0d 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -315,7 +315,7 @@ struct fc_plogi_csp_s { query_dbc:1, hg_supp:1; #endif - __be16 rxsz; /* recieve data_field size */ + __be16 rxsz; /* receive data_field size */ __be16 conseq; __be16 ro_bitmap; __be32 e_d_tov; diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index f674f9318629..9b43ca4b6778 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -1033,7 +1033,7 @@ bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, /* - * Lookup for a vport withing a fabric given its pwwn + * Lookup for a vport within a fabric given its pwwn */ struct bfa_fcs_vport_s * bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn) diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 0fd63168573f..61cdce4bd913 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -705,7 +705,7 @@ enum rport_event { RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ - RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */ + RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continuously */ }; /* diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 43fa986bb586..1d6be8c14473 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -1149,7 +1149,7 @@ bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi, } else { /* * For a base port, we should first register the HBA - * atribute. The HBA attribute also contains the base + * attribute. The HBA attribute also contains the base * port registration. */ bfa_sm_set_state(fdmi, diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 1d34921f88bf..16d9a5f61c18 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -1035,7 +1035,7 @@ bfa_fcxp_free(struct bfa_fcxp_s *fcxp) * @param[in] rport BFA rport pointer. Could be left NULL for WKA rports * @param[in] vf_id virtual Fabric ID * @param[in] lp_tag lport tag - * @param[in] cts use Continous sequence + * @param[in] cts use Continuous sequence * @param[in] cos fc Class of Service * @param[in] reqlen request length, does not include FCHS length * @param[in] fchs fc Header Pointer. The header content will be copied @@ -5022,7 +5022,7 @@ bfa_uf_start(struct bfa_s *bfa) } /* - * Register handler for all unsolicted recieve frames. + * Register handler for all unsolicted receive frames. * * @param[in] bfa BFA instance * @param[in] ufrecv receive handler function diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 331ad992a581..5902a45c080f 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -127,7 +127,7 @@ struct bfa_fcxp_req_info_s { * rport nexus is established */ struct fchs_s fchs; /* request FC header structure */ - u8 cts; /* continous sequence */ + u8 cts; /* continuous sequence */ u8 class; /* FC class for the request/response */ u16 max_frmsz; /* max send frame size */ u16 vf_id; /* vsan tag if applicable */ diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 44524cf55d33..0fd510a01561 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1278,7 +1278,7 @@ bfad_setup_intr(struct bfad_s *bfad) * interrupts into one vector, so even if we * can try to request less vectors, we don't * know how to associate interrupt events to - * vectors. Linux doesn't dupicate vectors + * vectors. Linux doesn't duplicate vectors * in the MSIX table for this case. */ diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h index 69d031d98469..97a61b4d81b7 100644 --- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h +++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h @@ -898,7 +898,7 @@ struct fcoe_confqe { /* - * FCoE conection data base + * FCoE connection data base */ struct fcoe_conn_db { #if defined(__BIG_ENDIAN) diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c index 7a11a255157f..52c358427ce2 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/drivers/scsi/bnx2fc/bnx2fc_els.c @@ -397,7 +397,7 @@ void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req, &els_req->req_flags)) { BNX2FC_ELS_DBG("Timer context finished processing this " "els - 0x%x\n", els_req->xid); - /* This IO doesnt receive cleanup completion */ + /* This IO doesn't receive cleanup completion */ kref_put(&els_req->refcount, bnx2fc_cmd_release); return; } diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index d3fc302c241a..1decefbf32e3 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -1273,7 +1273,7 @@ static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req) bnx2fc_cmd_release); /* timer hold */ rc = bnx2fc_initiate_abts(cmd); - /* abts shouldnt fail in this context */ + /* abts shouldn't fail in this context */ WARN_ON(rc != SUCCESS); } else printk(KERN_ERR PFX "lun_rst: abts already in" @@ -1308,7 +1308,7 @@ static void bnx2fc_tgt_reset_cmpl(struct bnx2fc_cmd *io_req) kref_put(&io_req->refcount, bnx2fc_cmd_release); /* timer hold */ rc = bnx2fc_initiate_abts(cmd); - /* abts shouldnt fail in this context */ + /* abts shouldn't fail in this context */ WARN_ON(rc != SUCCESS); } else diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index 7cc05e4e82d5..a2e3830bd268 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -395,7 +395,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport, rp = rport->dd_data; if (rport->port_id == FC_FID_DIR_SERV) { /* - * bnx2fc_rport structure doesnt exist for + * bnx2fc_rport structure doesn't exist for * directory server. * We should not come here, as lport will * take care of fabric login diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 1da34c019b8a..f0b89513faed 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -173,7 +173,7 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) /** * bnx2i_get_rq_buf - copy RQ buffer contents to driver buffer - * @conn: iscsi connection on which RQ event occured + * @conn: iscsi connection on which RQ event occurred * @ptr: driver buffer to which RQ buffer contents is to * be copied * @len: length of valid data inside RQ buf diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 0a20fd5f7102..9267844519c9 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -262,9 +262,9 @@ struct cxgbi_skb_tx_cb { enum cxgbi_skcb_flags { SKCBF_TX_NEED_HDR, /* packet needs a header */ SKCBF_RX_COALESCED, /* received whole pdu */ - SKCBF_RX_HDR, /* recieved pdu header */ - SKCBF_RX_DATA, /* recieved pdu payload */ - SKCBF_RX_STATUS, /* recieved ddp status */ + SKCBF_RX_HDR, /* received pdu header */ + SKCBF_RX_DATA, /* received pdu payload */ + SKCBF_RX_STATUS, /* received ddp status */ SKCBF_RX_DATA_DDPD, /* pdu payload ddp'd */ SKCBF_RX_HCRC_ERR, /* header digest error */ SKCBF_RX_DCRC_ERR, /* data digest error */ diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index b0f8523e665f..b10b3841535c 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -235,7 +235,7 @@ struct ScsiReqBlk { u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ - size_t total_xfer_length; /* Total number of bytes remaining to be transfered */ + size_t total_xfer_length; /* Total number of bytes remaining to be transferred */ size_t request_length; /* Total number of bytes in this request */ /* * The sense buffer handling function, request_sense, uses @@ -1774,7 +1774,7 @@ static void dc395x_handle_interrupt(struct AdapterCtlBlk *acb, dc395x_statev(acb, srb, &scsi_status); /* - * if there were any exception occured scsi_status + * if there were any exception occurred scsi_status * will be modify to bus free phase new scsi_status * transfer out from ... previous dc395x_statev */ @@ -1954,11 +1954,11 @@ static void sg_verify_length(struct ScsiReqBlk *srb) static void sg_update_list(struct ScsiReqBlk *srb, u32 left) { u8 idx; - u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ + u32 xferred = srb->total_xfer_length - left; /* bytes transferred */ struct SGentry *psge = srb->segment_x + srb->sg_index; dprintkdbg(DBG_0, - "sg_update_list: Transfered %i of %i bytes, %i remain\n", + "sg_update_list: Transferred %i of %i bytes, %i remain\n", xferred, srb->total_xfer_length, left); if (xferred == 0) { /* nothing to update since we did not transfer any data */ @@ -1990,7 +1990,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) /* - * We have transfered a single byte (PIO mode?) and need to update + * We have transferred a single byte (PIO mode?) and need to update * the count of bytes remaining (total_xfer_length) and update the sg * entry to either point to next byte in the current sg entry, or of * already at the end to point to the start of the next sg entry @@ -2029,7 +2029,7 @@ static void cleanup_after_transfer(struct AdapterCtlBlk *acb, /* - * Those no of bytes will be transfered w/ PIO through the SCSI FIFO + * Those no of bytes will be transferred w/ PIO through the SCSI FIFO * Seems to be needed for unknown reasons; could be a hardware bug :-( */ #define DC395x_LASTPIO 4 @@ -2256,7 +2256,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, DC395x_read32(acb, TRM_S1040_DMA_CXCNT), srb->total_xfer_length, d_left_counter); #if DC395x_LASTPIO - /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */ + /* KG: Less than or equal to 4 bytes can not be transferred via DMA, it seems. */ if (d_left_counter && srb->total_xfer_length <= DC395x_LASTPIO) { size_t left_io = srb->total_xfer_length; diff --git a/drivers/scsi/dc395x.h b/drivers/scsi/dc395x.h index b38360e5fe4f..fbf35e37701e 100644 --- a/drivers/scsi/dc395x.h +++ b/drivers/scsi/dc395x.h @@ -617,7 +617,7 @@ struct ScsiInqData #define NTC_DO_SEND_START 0x08 /* Send start command SPINUP */ #define NTC_DO_DISCONNECT 0x04 /* Enable SCSI disconnect */ #define NTC_DO_SYNC_NEGO 0x02 /* Sync negotiation */ -#define NTC_DO_PARITY_CHK 0x01 /* (it sould define at NAC) */ +#define NTC_DO_PARITY_CHK 0x01 /* (it should define at NAC) */ /* Parity check enable */ /************************************************************************/ diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 7cae0bc85390..42fe52902add 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -541,7 +541,7 @@ static int alua_check_sense(struct scsi_device *sdev, * * Evaluate the Target Port Group State. * Returns SCSI_DH_DEV_OFFLINED if the path is - * found to be unuseable. + * found to be unusable. */ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) { @@ -620,7 +620,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) break; case TPGS_STATE_OFFLINE: case TPGS_STATE_UNAVAILABLE: - /* Path unuseable for unavailable/offline */ + /* Path unusable for unavailable/offline */ err = SCSI_DH_DEV_OFFLINED; break; default: diff --git a/drivers/scsi/dpt/sys_info.h b/drivers/scsi/dpt/sys_info.h index a90c4cb8ea8b..a4aa1c31ff72 100644 --- a/drivers/scsi/dpt/sys_info.h +++ b/drivers/scsi/dpt/sys_info.h @@ -79,9 +79,9 @@ typedef struct { #endif - uSHORT cylinders; /* Upto 1024 */ - uCHAR heads; /* Upto 255 */ - uCHAR sectors; /* Upto 63 */ + uSHORT cylinders; /* Up to 1024 */ + uCHAR heads; /* Up to 255 */ + uCHAR sectors; /* Up to 63 */ #ifdef __cplusplus diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index 53925ac178fd..0eb4fe6a4c8a 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -63,7 +63,7 @@ * ep:[y|n] eisa_probe=[1|0] CONFIG_EISA defined * pp:[y|n] pci_probe=[1|0] CONFIG_PCI defined * - * The default action is to perform probing if the corrisponding + * The default action is to perform probing if the corresponding * bus is configured and to skip probing otherwise. * * + If pci_probe is in effect and a list of I/O ports is specified diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index c93f007e702f..9d38be2a41f9 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -656,7 +656,7 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, * If non-FIP, we may have gotten an SID by accepting an FLOGI * from a point-to-point connection. Switch to using * the source mac based on the SID. The destination - * MAC in this case would have been set by receving the + * MAC in this case would have been set by receiving the * FLOGI. */ if (fip->state == FIP_ST_NON_FIP) { @@ -1876,7 +1876,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, * fcoe_ctlr_vn_rport_callback - Event handler for rport events. * @lport: The lport which is receiving the event * @rdata: remote port private data - * @event: The event that occured + * @event: The event that occurred * * Locking Note: The rport lock must not be held when calling this function. */ diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 69b7aa54f43f..643f6d500fe7 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -174,7 +174,7 @@ Future Domain sold DOS BIOS source for $250 and the UN*X driver source was $750, but these required a non-disclosure agreement, so even if I could have afforded them, they would *not* have been useful for writing this - publically distributable driver. Future Domain technical support has + publicly distributable driver. Future Domain technical support has provided some information on the phone and have sent a few useful FAXs. They have been much more helpful since they started to recognize that the word "Linux" refers to an operating system :-). diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 2b48d79bad94..3c53c3478ee7 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -411,7 +411,7 @@ int fnic_rq_cmpl_handler(struct fnic *fnic, int rq_work_to_do) err = vnic_rq_fill(&fnic->rq[i], fnic_alloc_rq_frame); if (err) shost_printk(KERN_ERR, fnic->lport->host, - "fnic_alloc_rq_frame cant alloc" + "fnic_alloc_rq_frame can't alloc" " frame\n"); } tot_rq_work_done += cur_work_done; diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 22d02404d15f..538b31c2cf58 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1123,7 +1123,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id) fc_lun.scsi_lun, io_req)) { /* * Revert the cmd state back to old state, if - * it hasnt changed in between. This cmd will get + * it hasn't changed in between. This cmd will get * aborted later by scsi_eh, or cleaned up during * lun reset */ @@ -1208,7 +1208,7 @@ void fnic_terminate_rport_io(struct fc_rport *rport) fc_lun.scsi_lun, io_req)) { /* * Revert the cmd state back to old state, if - * it hasnt changed in between. This cmd will get + * it hasn't changed in between. This cmd will get * aborted later by scsi_eh, or cleaned up during * lun reset */ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 427a56d3117e..81182badfeb1 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -566,7 +566,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, * @dst: buffer to read into * @len: buffer length * - * Perform a psuedo DMA mode read from an NCR53C400 or equivalent + * Perform a pseudo DMA mode read from an NCR53C400 or equivalent * controller */ @@ -650,7 +650,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, * @dst: buffer to read into * @len: buffer length * - * Perform a psuedo DMA mode read from an NCR53C400 or equivalent + * Perform a pseudo DMA mode read from an NCR53C400 or equivalent * controller */ diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 120a0625a7b5..d969855ac64a 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -895,7 +895,7 @@ typedef struct { u8 ldr_no; /* log. drive no. */ u8 rw_attribs; /* r/w attributes */ u8 cluster_type; /* cluster properties */ - u8 media_changed; /* Flag:MOUNT/UNMOUNT occured */ + u8 media_changed; /* Flag:MOUNT/UNMOUNT occurred */ u32 start_sec; /* start sector */ } hdr[MAX_LDRIVES]; /* host drives */ struct { diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 2ce26eb7a1ec..50bb54150a78 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -300,7 +300,7 @@ static int __devinit gvp11_probe(struct zorro_dev *z, /* * Rumors state that some GVP ram boards use the same product * code as the SCSI controllers. Therefore if the board-size - * is not 64KB we asume it is a ram board and bail out. + * is not 64KB we assume it is a ram board and bail out. */ if (zorro_resource_len(z) != 0x10000) return -ENODEV; diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 99aa0e5699bc..26cd9d1d7571 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -3,7 +3,7 @@ * * (The IMM is the embedded controller in the ZIP Plus drive.) * - * My unoffical company acronym list is 21 pages long: + * My unofficial company acronym list is 21 pages long: * FLA: Four letter acronym with built in facility for * future expansion to five letters. */ diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 9627d062e16b..dd741bcd6ccd 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -242,7 +242,7 @@ static u8 i91udftNvRam[64] = static u8 initio_rate_tbl[8] = /* fast 20 */ { - /* nanosecond devide by 4 */ + /* nanosecond divide by 4 */ 12, /* 50ns, 20M */ 18, /* 75ns, 13.3M */ 25, /* 100ns, 10M */ @@ -1917,7 +1917,7 @@ static int int_initio_scsi_rst(struct initio_host * host) } /** - * int_initio_scsi_resel - Reselection occured + * int_initio_scsi_resel - Reselection occurred * @host: InitIO host adapter * * A SCSI reselection event has been signalled and the interrupt diff --git a/drivers/scsi/initio.h b/drivers/scsi/initio.h index e58af9e95506..219b901bdc25 100644 --- a/drivers/scsi/initio.h +++ b/drivers/scsi/initio.h @@ -116,7 +116,7 @@ typedef struct { #define TUL_SBusId 0x89 /* 09 R SCSI BUS ID */ #define TUL_STimeOut 0x8A /* 0A W Sel/Resel Time Out Register */ #define TUL_SIdent 0x8A /* 0A R Identify Message Register */ -#define TUL_SAvail 0x8A /* 0A R Availiable Counter Register */ +#define TUL_SAvail 0x8A /* 0A R Available Counter Register */ #define TUL_SData 0x8B /* 0B R/W SCSI data in/out */ #define TUL_SFifo 0x8C /* 0C R/W FIFO */ #define TUL_SSignal 0x90 /* 10 R/W SCSI signal in/out */ @@ -389,7 +389,7 @@ struct scsi_ctrl_blk { /* Bit Definition for status */ #define SCB_RENT 0x01 #define SCB_PEND 0x02 -#define SCB_CONTIG 0x04 /* Contigent Allegiance */ +#define SCB_CONTIG 0x04 /* Contingent Allegiance */ #define SCB_SELECT 0x08 #define SCB_BUSY 0x10 #define SCB_DONE 0x20 diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index b2511acd39bd..218f71a8726e 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -137,7 +137,7 @@ /* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ /* - Fix sort order of 7k */ /* - Remove 3 unused "inline" functions */ -/* 7.12.xx - Use STATIC functions whereever possible */ +/* 7.12.xx - Use STATIC functions wherever possible */ /* - Clean up deprecated MODULE_PARM calls */ /* 7.12.05 - Remove Version Matching per IBM request */ /*****************************************************************************/ @@ -1665,7 +1665,7 @@ ips_flash_copperhead(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb) int datasize; /* Trombone is the only copperhead that can do packet flash, but only - * for firmware. No one said it had to make sence. */ + * for firmware. No one said it had to make sense. */ if (IPS_IS_TROMBONE(ha) && pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE) { if (ips_usrcmd(ha, pt, scb)) return IPS_SUCCESS; diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 4e49fbcfe8af..f2df0593332b 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -1193,7 +1193,7 @@ typedef struct { #define IPS_VER_SEBRING "7.12.02" #define IPS_VER_KEYWEST "7.12.02" -/* Compatability IDs for various adapters */ +/* Compatibility IDs for various adapters */ #define IPS_COMPAT_UNKNOWN "" #define IPS_COMPAT_CURRENT "KW710" #define IPS_COMPAT_SERVERAID1 "2.25.01" diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index a860452a8f71..3df985305f69 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -295,7 +295,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment); /* * We may not have been able to send data because the conn - * is getting stopped. libiscsi will know so propogate err + * is getting stopped. libiscsi will know so propagate err * for it to do the right thing. */ if (rc == -EAGAIN) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 28231badd9e6..77035a746f60 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1042,7 +1042,7 @@ static void fc_exch_set_addr(struct fc_exch *ep, } /** - * fc_seq_els_rsp_send() - Send an ELS response using infomation from + * fc_seq_els_rsp_send() - Send an ELS response using information from * the existing sequence/exchange. * @fp: The received frame * @els_cmd: The ELS command to be sent @@ -1153,7 +1153,7 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) * fc_exch_send_ba_rjt() - Send BLS Reject * @rx_fp: The frame being rejected * @reason: The reason the frame is being rejected - * @explan: The explaination for the rejection + * @explan: The explanation for the rejection * * This is for rejecting BA_ABTS only. */ diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index b1b03af158bf..5b799a37ad09 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -870,7 +870,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) fsp->scsi_resid = ntohl(rp_ex->fr_resid); /* * The cmnd->underflow is the minimum number of - * bytes that must be transfered for this + * bytes that must be transferred for this * command. Provided a sense condition is not * present, make sure the actual amount * transferred is at least the underflow value @@ -1306,7 +1306,7 @@ static int fc_lun_reset(struct fc_lport *lport, struct fc_fcp_pkt *fsp, } /** - * fc_tm_done() - Task Managment response handler + * fc_tm_done() - Task Management response handler * @seq: The sequence that the response is on * @fp: The response frame * @arg: The FCP packet the response is for diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 8c08b210001d..906bbcad0e2d 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -52,7 +52,7 @@ * while making the callback. To ensure that the rport is not free'd while * processing the callback the rport callbacks are serialized through a * single-threaded workqueue. An rport would never be free'd while in a - * callback handler becuase no other rport work in this queue can be executed + * callback handler because no other rport work in this queue can be executed * at the same time. * * When discovery succeeds or fails a callback is made to the lport as @@ -163,7 +163,7 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) * fc_lport_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rdata: private remote port data - * @event: The event that occured + * @event: The event that occurred * * Locking Note: The rport lock should not be held when calling * this function. @@ -379,7 +379,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) /** * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. - * @lport: Fibre Channel local port recieving the RLIR + * @lport: Fibre Channel local port receiving the RLIR * @fp: The RLIR request frame * * Locking Note: The lport lock is expected to be held before calling @@ -396,7 +396,7 @@ static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) /** * fc_lport_recv_echo_req() - Handle received ECHO request - * @lport: The local port recieving the ECHO + * @lport: The local port receiving the ECHO * @fp: ECHO request frame * * Locking Note: The lport lock is expected to be held before calling @@ -432,7 +432,7 @@ static void fc_lport_recv_echo_req(struct fc_lport *lport, /** * fc_lport_recv_rnid_req() - Handle received Request Node ID data request - * @lport: The local port recieving the RNID + * @lport: The local port receiving the RNID * @fp: The RNID request frame * * Locking Note: The lport lock is expected to be held before calling @@ -491,7 +491,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, /** * fc_lport_recv_logo_req() - Handle received fabric LOGO request - * @lport: The local port recieving the LOGO + * @lport: The local port receiving the LOGO * @fp: The LOGO request frame * * Locking Note: The lport lock is exected to be held before calling @@ -771,7 +771,7 @@ EXPORT_SYMBOL(fc_lport_set_local_id); /** * fc_lport_recv_flogi_req() - Receive a FLOGI request - * @lport: The local port that recieved the request + * @lport: The local port that received the request * @rx_fp: The FLOGI frame * * A received FLOGI request indicates a point-to-point connection. @@ -858,7 +858,7 @@ out: * if an rport should handle the request. * * Locking Note: This function should not be called with the lport - * lock held becuase it will grab the lock. + * lock held because it will grab the lock. */ static void fc_lport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) @@ -925,7 +925,7 @@ struct fc4_prov fc_lport_els_prov = { * @fp: The frame the request is in * * Locking Note: This function should not be called with the lport - * lock held becuase it may grab the lock. + * lock held because it may grab the lock. */ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index f3f693b772ac..874e29d9533f 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -240,7 +240,7 @@ static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req, disc_resp, DISCOVER_RESP_SIZE); if (res) return res; - /* This is detecting a failure to transmit inital + /* This is detecting a failure to transmit initial * dev to host FIS as described in section G.5 of * sas-2 r 04b */ dr = &((struct smp_resp *)disc_resp)->disc; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 4e0faa00b96f..17d789325f40 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4515,7 +4515,7 @@ static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL) * Description: * This function is called by the transport after the @fc_vport's symbolic name * has been changed. This function re-registers the symbolic name with the - * switch to propogate the change into the fabric if the vport is active. + * switch to propagate the change into the fabric if the vport is active. **/ static void lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 793b9f1131fb..77b2871d96b7 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1939,7 +1939,7 @@ out: * @rxxri: Receive exchange id * @len: Number of data bytes * - * This function allocates and posts a data buffer of sufficient size to recieve + * This function allocates and posts a data buffer of sufficient size to receive * an unsolicted CT command. **/ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index a753581509d6..3d967741c708 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -908,7 +908,7 @@ lpfc_debugfs_dumpData_open(struct inode *inode, struct file *file) if (!debug) goto out; - /* Round to page boundry */ + /* Round to page boundary */ printk(KERN_ERR "9059 BLKGRD: %s: _dump_buf_data=0x%p\n", __func__, _dump_buf_data); debug->buffer = _dump_buf_data; @@ -938,7 +938,7 @@ lpfc_debugfs_dumpDif_open(struct inode *inode, struct file *file) if (!debug) goto out; - /* Round to page boundry */ + /* Round to page boundary */ printk(KERN_ERR "9060 BLKGRD: %s: _dump_buf_dif=0x%p file=%s\n", __func__, _dump_buf_dif, file->f_dentry->d_name.name); debug->buffer = _dump_buf_dif; @@ -2158,7 +2158,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) debugfs_create_dir(name, phba->hba_debugfs_root); if (!vport->vport_debugfs_root) { lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "0417 Cant create debugfs\n"); + "0417 Can't create debugfs\n"); goto debug_failed; } atomic_inc(&phba->debugfs_vport_count); @@ -2211,7 +2211,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) vport, &lpfc_debugfs_op_nodelist); if (!vport->debug_nodelist) { lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "0409 Cant create debugfs nodelist\n"); + "0409 Can't create debugfs nodelist\n"); goto debug_failed; } diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 735028fedda5..d34b69f9cdb1 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -102,7 +102,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) phba->pport->port_state); /* CLEAR_LA should re-enable link attention events and - * we should then imediately take a LATT event. The + * we should then immediately take a LATT event. The * LATT processing should call lpfc_linkdown() which * will cleanup any left over in-progress discovery * events. @@ -1599,7 +1599,7 @@ out: * This routine is the completion callback function for issuing the Port * Login (PLOGI) command. For PLOGI completion, there must be an active * ndlp on the vport node list that matches the remote node ID from the - * PLOGI reponse IOCB. If such ndlp does not exist, the PLOGI is simply + * PLOGI response IOCB. If such ndlp does not exist, the PLOGI is simply * ignored and command IOCB released. The PLOGI response IOCB status is * checked for error conditons. If there is error status reported, PLOGI * retry shall be attempted by invoking the lpfc_els_retry() routine. diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 154c715fb3af..301498301a8f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -739,7 +739,7 @@ lpfc_do_work(void *p) /* * This is only called to handle FC worker events. Since this a rare - * occurance, we allocate a struct lpfc_work_evt structure here instead of + * occurrence, we allocate a struct lpfc_work_evt structure here instead of * embedding it in the IOCB. */ int @@ -1348,7 +1348,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) int rc; spin_lock_irq(&phba->hbalock); - /* If the FCF is not availabe do nothing. */ + /* If the FCF is not available do nothing. */ if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) { phba->hba_flag &= ~(FCF_TS_INPROG | FCF_RR_INPROG); spin_unlock_irq(&phba->hbalock); @@ -1538,7 +1538,7 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, /* * If user did not specify any addressing mode, or if the - * prefered addressing mode specified by user is not supported + * preferred addressing mode specified by user is not supported * by FCF, allow fabric to pick the addressing mode. */ *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, @@ -1553,7 +1553,7 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, FCFCNCT_AM_SPMA) ? LPFC_FCF_SPMA : LPFC_FCF_FPMA; /* - * If the user specified a prefered address mode, use the + * If the user specified a preferred address mode, use the * addr mode only if FCF support the addr_mode. */ else if ((conn_entry->conn_rec.flags & FCFCNCT_AM_VALID) && @@ -3117,7 +3117,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * back at reg login state so this * mbox needs to be ignored becase * there is another reg login in - * proccess. + * process. */ spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; @@ -4477,7 +4477,7 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) if ((vport->fc_flag & FC_RSCN_MODE) && !(vport->fc_flag & FC_NDISC_ACTIVE)) { if (lpfc_rscn_payload_check(vport, did)) { - /* If we've already recieved a PLOGI from this NPort + /* If we've already received a PLOGI from this NPort * we don't need to try to discover it again. */ if (ndlp->nlp_flag & NLP_RCV_PLOGI) @@ -4493,7 +4493,7 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) } else ndlp = NULL; } else { - /* If we've already recieved a PLOGI from this NPort, + /* If we've already received a PLOGI from this NPort, * or we are already in the process of discovery on it, * we don't need to try to discover it again. */ @@ -5756,7 +5756,7 @@ lpfc_read_fcoe_param(struct lpfc_hba *phba, * @size: Size of the data buffer. * @rec_type: Record type to be searched. * - * This function searches config region data to find the begining + * This function searches config region data to find the beginning * of the record specified by record_type. If record found, this * function return pointer to the record else return NULL. */ diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index e6ebe516cfbb..505f88443b5c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -4466,7 +4466,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) } /** - * lpfc_init_api_table_setup - Set up init api fucntion jump table + * lpfc_init_api_table_setup - Set up init api function jump table * @phba: The hba struct for which this call is being executed. * @dev_grp: The HBA PCI-Device group number. * @@ -4850,7 +4850,7 @@ out_free_mem: * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ int @@ -5730,7 +5730,7 @@ lpfc_destroy_bootstrap_mbox(struct lpfc_hba *phba) * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ static int @@ -5835,7 +5835,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ static int @@ -5894,7 +5894,7 @@ lpfc_setup_endian_order(struct lpfc_hba *phba) * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ static int @@ -6189,7 +6189,7 @@ out_error: * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ static void @@ -6253,7 +6253,7 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba) * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ int @@ -6498,7 +6498,7 @@ out_error: * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ void @@ -6543,7 +6543,7 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba) * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory **/ static int lpfc_sli4_cq_event_pool_create(struct lpfc_hba *phba) @@ -6704,7 +6704,7 @@ lpfc_sli4_cq_event_release_all(struct lpfc_hba *phba) * * Return codes * 0 - successful - * -ENOMEM - No availble memory + * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ int diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index dba32dfdb59b..fbab9734e9b4 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1834,7 +1834,7 @@ lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox) * @fcf_index: index to fcf table. * * This routine routine allocates and constructs non-embedded mailbox command - * for reading a FCF table entry refered by @fcf_index. + * for reading a FCF table entry referred by @fcf_index. * * Return: pointer to the mailbox command constructed if successful, otherwise * NULL. diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h index f3cfbe2ce986..f2b1bbcb196f 100644 --- a/drivers/scsi/lpfc/lpfc_nl.h +++ b/drivers/scsi/lpfc/lpfc_nl.h @@ -50,7 +50,7 @@ * and subcategory. The event type must come first. * The subcategory further defines the data that follows in the rest * of the payload. Each category will have its own unique header plus - * any addtional data unique to the subcategory. + * any additional data unique to the subcategory. * The payload sent via the fc transport is one-way driver->application. */ diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 52b35159fc35..0d92d4205ea6 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -658,7 +658,7 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) return 0; } /** - * lpfc_release_rpi - Release a RPI by issueing unreg_login mailbox cmd. + * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd. * @phba : Pointer to lpfc_hba structure. * @vport: Pointer to lpfc_vport structure. * @rpi : rpi to be release. diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2b962b020cfb..fe7cc84e773b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -577,7 +577,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) iocb->un.fcpi64.bdl.addrHigh = 0; iocb->ulpBdeCount = 0; iocb->ulpLe = 0; - /* fill in responce BDE */ + /* fill in response BDE */ iocb->unsli3.fcp_ext.rbde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; iocb->unsli3.fcp_ext.rbde.tus.f.bdeSize = @@ -1217,10 +1217,10 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) (2 * sizeof(struct ulp_bde64))); data_bde->addrHigh = putPaddrHigh(physaddr); data_bde->addrLow = putPaddrLow(physaddr); - /* ebde count includes the responce bde and data bpl */ + /* ebde count includes the response bde and data bpl */ iocb_cmd->unsli3.fcp_ext.ebde_count = 2; } else { - /* ebde count includes the responce bde and data bdes */ + /* ebde count includes the response bde and data bdes */ iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1); } } else { @@ -2380,7 +2380,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, } /* * The cmnd->underflow is the minimum number of bytes that must - * be transfered for this command. Provided a sense condition + * be transferred for this command. Provided a sense condition * is not present, make sure the actual amount transferred is at * least the underflow value or fail. */ @@ -2873,7 +2873,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, } /** - * lpfc_scsi_api_table_setup - Set up scsi api fucntion jump table + * lpfc_scsi_api_table_setup - Set up scsi api function jump table * @phba: The hba struct for which this call is being executed. * @dev_grp: The HBA PCI-Device group number. * diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index 5932273870a5..ce645b20a6ad 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h @@ -130,7 +130,7 @@ struct lpfc_scsi_buf { dma_addr_t nonsg_phys; /* Non scatter-gather physical address. */ /* - * data and dma_handle are the kernel virutal and bus address of the + * data and dma_handle are the kernel virtual and bus address of the * dma-able buffer containing the fcp_cmd, fcp_rsp and a scatter * gather bde list that supports the sg_tablesize value. */ diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4746dcd756dd..dacabbe0a586 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2817,7 +2817,7 @@ void lpfc_poll_eratt(unsigned long ptr) * This function is called from the interrupt context when there is a ring * event for the fcp ring. The caller does not hold any lock. * The function processes each response iocb in the response ring until it - * finds an iocb with LE bit set and chains all the iocbs upto the iocb with + * finds an iocb with LE bit set and chains all the iocbs up to the iocb with * LE bit set. The function will call the completion handler of the command iocb * if the response iocb indicates a completion for a command iocb or it is * an abort completion. The function will call lpfc_sli_process_unsol_iocb @@ -5117,7 +5117,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) /* Setting state unknown so lpfc_sli_abort_iocb_ring * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing - * it to fail all oustanding SCSI IO. + * it to fail all outstanding SCSI IO. */ spin_lock_irq(&phba->pport->work_port_lock); phba->pport->work_port_events &= ~WORKER_MBOX_TMO; @@ -6031,7 +6031,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) } /** - * lpfc_mbox_api_table_setup - Set up mbox api fucntion jump table + * lpfc_mbox_api_table_setup - Set up mbox api function jump table * @phba: The hba struct for which this call is being executed. * @dev_grp: The HBA PCI-Device group number. * @@ -6847,7 +6847,7 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, } /** - * lpfc_sli_api_table_setup - Set up sli api fucntion jump table + * lpfc_sli_api_table_setup - Set up sli api function jump table * @phba: The hba struct for which this call is being executed. * @dev_grp: The HBA PCI-Device group number. * @@ -7521,7 +7521,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_dmabuf *mp, *next_mp; struct list_head *slp = &pring->postbufq; - /* Search postbufq, from the begining, looking for a match on tag */ + /* Search postbufq, from the beginning, looking for a match on tag */ spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { if (mp->buffer_tag == tag) { @@ -7565,7 +7565,7 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_dmabuf *mp, *next_mp; struct list_head *slp = &pring->postbufq; - /* Search postbufq, from the begining, looking for a match on phys */ + /* Search postbufq, from the beginning, looking for a match on phys */ spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { if (mp->phys == phys) { @@ -8438,7 +8438,7 @@ lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *phba) * for possible error attention events. The caller must hold the hostlock * with spin_lock_irq(). * - * This fucntion returns 1 when there is Error Attention in the Host Attention + * This function returns 1 when there is Error Attention in the Host Attention * Register and returns 0 otherwise. **/ static int @@ -8491,7 +8491,7 @@ unplug_err: * for possible error attention events. The caller must hold the hostlock * with spin_lock_irq(). * - * This fucntion returns 1 when there is Error Attention in the Host Attention + * This function returns 1 when there is Error Attention in the Host Attention * Register and returns 0 otherwise. **/ static int @@ -8581,7 +8581,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) * This function is called from timer soft interrupt context to check HBA's * error attention register bit for error attention events. * - * This fucntion returns 1 when there is Error Attention in the Host Attention + * This function returns 1 when there is Error Attention in the Host Attention * Register and returns 0 otherwise. **/ int @@ -9684,7 +9684,7 @@ out: * @cq: Pointer to the completion queue. * @wcqe: Pointer to a completion queue entry. * - * This routine process a slow-path work-queue or recieve queue completion queue + * This routine process a slow-path work-queue or receive queue completion queue * entry. * * Return: true if work posted to worker thread, otherwise false. @@ -12971,7 +12971,7 @@ lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba, * record and processing it one at a time starting from the @fcf_index * for initial FCF discovery or fast FCF failover rediscovery. * - * Return 0 if the mailbox command is submitted sucessfully, none 0 + * Return 0 if the mailbox command is submitted successfully, none 0 * otherwise. **/ int @@ -13032,7 +13032,7 @@ fail_fcf_scan: * This routine is invoked to read an FCF record indicated by @fcf_index * and to use it for FLOGI roundrobin FCF failover. * - * Return 0 if the mailbox command is submitted sucessfully, none 0 + * Return 0 if the mailbox command is submitted successfully, none 0 * otherwise. **/ int @@ -13078,7 +13078,7 @@ fail_fcf_read: * This routine is invoked to read an FCF record indicated by @fcf_index to * determine whether it's eligible for FLOGI roundrobin failover list. * - * Return 0 if the mailbox command is submitted sucessfully, none 0 + * Return 0 if the mailbox command is submitted successfully, none 0 * otherwise. **/ int diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index c212694a9714..f2684dd09ed0 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -284,7 +284,7 @@ mega_query_adapter(adapter_t *adapter) adapter->host->max_id = 16; /* max targets per channel */ - adapter->host->max_lun = 7; /* Upto 7 luns for non disk devices */ + adapter->host->max_lun = 7; /* Up to 7 luns for non disk devices */ adapter->host->cmd_per_lun = max_cmd_per_lun; @@ -3734,7 +3734,7 @@ mega_m_to_n(void __user *arg, nitioctl_t *uioc) * check is the application conforms to NIT. We do not have to do much * in that case. * We exploit the fact that the signature is stored in the very - * begining of the structure. + * beginning of the structure. */ if( copy_from_user(signature, arg, 7) ) diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index 853411911b2e..9a7897f8ca43 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h @@ -532,9 +532,9 @@ struct uioctl_t { /* * struct mcontroller is used to pass information about the controllers in the - * system. Its upto the application how to use the information. We are passing + * system. Its up to the application how to use the information. We are passing * as much info about the cards as possible and useful. Before issuing the - * call to find information about the cards, the applicaiton needs to issue a + * call to find information about the cards, the application needs to issue a * ioctl first to find out the number of controllers in the system. */ #define MAX_CONTROLLERS 32 @@ -804,7 +804,7 @@ typedef struct { unsigned long base; void __iomem *mmio_base; - /* mbox64 with mbox not aligned on 16-byte boundry */ + /* mbox64 with mbox not aligned on 16-byte boundary */ mbox64_t *una_mbox64; dma_addr_t una_mbox64_dma; diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h index ce2487a888ed..e01c6f7c2cac 100644 --- a/drivers/scsi/megaraid/mbox_defs.h +++ b/drivers/scsi/megaraid/mbox_defs.h @@ -660,7 +660,7 @@ typedef struct { * @lparam : logical drives parameters * @span : span * - * 8-LD logical drive with upto 8 spans + * 8-LD logical drive with up to 8 spans */ typedef struct { logdrv_param_t lparam; @@ -673,7 +673,7 @@ typedef struct { * @lparam : logical drives parameters * @span : span * - * 8-LD logical drive with upto 4 spans + * 8-LD logical drive with up to 4 spans */ typedef struct { logdrv_param_t lparam; @@ -720,7 +720,7 @@ typedef struct { * @ldrv : logical drives information * @pdrv : physical drives information * - * Disk array for 8LD logical drives with upto 8 spans + * Disk array for 8LD logical drives with up to 8 spans */ typedef struct { uint8_t numldrv; @@ -737,7 +737,7 @@ typedef struct { * @ldrv : logical drives information * @pdrv : physical drives information * - * Disk array for 8LD logical drives with upto 4 spans + * Disk array for 8LD logical drives with up to 4 spans */ typedef struct { uint8_t numldrv; diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 5708cb27d078..1dba32870b4c 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -2689,7 +2689,7 @@ megaraid_reset_handler(struct scsi_cmnd *scp) (MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i)); } - // bailout if no recovery happended in reset time + // bailout if no recovery happened in reset time if (adapter->outstanding_cmds == 0) { break; } @@ -3452,7 +3452,7 @@ megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) * megaraid_mbox_setup_device_map - manage device ids * @adapter : Driver's soft state * - * Manange the device ids to have an appropraite mapping between the kernel + * Manange the device ids to have an appropriate mapping between the kernel * scsi addresses and megaraid scsi and logical drive addresses. We export * scsi devices on their actual addresses, whereas the logical drives are * exported on a virtual scsi channel. @@ -3973,7 +3973,7 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data) * NOTE: The commands issuance functionality is not generalized and * implemented in context of "get ld map" command only. If required, the * command issuance logical can be trivially pulled out and implemented as a - * standalone libary. For now, this should suffice since there is no other + * standalone library. For now, this should suffice since there is no other * user of this interface. * * Return 0 on success. diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 635b228c3ead..046dcc672ec1 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1347,7 +1347,7 @@ struct megasas_instance { struct timer_list io_completion_timer; struct list_head internal_reset_pending_q; - /* Ptr to hba specfic information */ + /* Ptr to hba specific information */ void *ctrl_context; u8 msi_flag; struct msix_entry msixentry; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index bbd10c81fd9c..66d4cea4df98 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -1698,7 +1698,7 @@ void megasas_do_ocr(struct megasas_instance *instance) * megasas_wait_for_outstanding - Wait for all outstanding cmds * @instance: Adapter soft state * - * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to + * This function waits for up to MEGASAS_RESET_WAIT_TIME seconds for FW to * complete all its outstanding commands. Returns error if one or more IOs * are pending after this time period. It also marks the controller dead. */ diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h index 20e6b8869341..165454d52591 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h @@ -21,7 +21,7 @@ * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO * Control field Task Attribute flags. - * Moved LUN field defines to mpi2.h becasue they are + * Moved LUN field defines to mpi2.h because they are * common to many structures. * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to * Query Asynchronous Event. diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 5e001ffd4c13..3346357031e9 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -925,7 +925,7 @@ _base_interrupt(int irq, void *bus_id) } /** - * mpt2sas_base_release_callback_handler - clear interupt callback handler + * mpt2sas_base_release_callback_handler - clear interrupt callback handler * @cb_idx: callback index * * Return nothing. @@ -1113,7 +1113,7 @@ _base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc) * @ioc: per adapter object * * Check to see if card is capable of MSIX, and set number - * of avaliable msix vectors + * of available msix vectors */ static int _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) @@ -1595,7 +1595,7 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle) /** - * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware + * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware * @ioc: per adapter object * @smid: system request message index * @@ -2599,7 +2599,7 @@ _base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout, int_status = readl(&ioc->chip->HostInterruptStatus); if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " - "successfull count(%d), timeout(%d)\n", ioc->name, + "successful count(%d), timeout(%d)\n", ioc->name, __func__, count, timeout)); return 0; } @@ -2640,7 +2640,7 @@ _base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout, int_status = readl(&ioc->chip->HostInterruptStatus); if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " - "successfull count(%d), timeout(%d)\n", ioc->name, + "successful count(%d), timeout(%d)\n", ioc->name, __func__, count, timeout)); return 0; } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { @@ -2688,7 +2688,7 @@ _base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout, doorbell_reg = readl(&ioc->chip->Doorbell); if (!(doorbell_reg & MPI2_DOORBELL_USED)) { dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " - "successfull count(%d), timeout(%d)\n", ioc->name, + "successful count(%d), timeout(%d)\n", ioc->name, __func__, count, timeout)); return 0; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index 6afd67b324fe..6861244249a3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c @@ -93,7 +93,7 @@ struct config_request{ * @mpi_reply: reply message frame * Context: none. * - * Function for displaying debug info helpfull when debugging issues + * Function for displaying debug info helpful when debugging issues * in this module. */ static void diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index e92b77af5484..1c6d2b405eef 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -116,7 +116,7 @@ _ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) * @mpi_reply: reply message frame * Context: none. * - * Function for displaying debug info helpfull when debugging issues + * Function for displaying debug info helpful when debugging issues * in this module. */ static void diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 6ceb7759bfe5..d2064a0533ae 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -397,7 +397,7 @@ _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle, * @is_raid: [flag] 1 = raid object, 0 = sas object * * Determines whether this device should be first reported device to - * to scsi-ml or sas transport, this purpose is for persistant boot device. + * to scsi-ml or sas transport, this purpose is for persistent boot device. * There are primary, alternate, and current entries in bios page 2. The order * priority is primary, alternate, then current. This routine saves * the corresponding device object and is_raid flag in the ioc object. @@ -2671,10 +2671,10 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, * @handle: device handle * Context: interrupt time. * - * This code is to initiate the device removal handshake protocal + * This code is to initiate the device removal handshake protocol * with controller firmware. This function will issue target reset * using high priority request queue. It will send a sas iounit - * controll request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. + * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. * * This is designed to send muliple task management request at the same * time to the fifo. If the fifo is full, we will append the request, @@ -2749,9 +2749,9 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) * @reply: reply message frame(lower 32bit addr) * Context: interrupt time. * - * This is the sas iounit controll completion routine. + * This is the sas iounit control completion routine. * This code is part of the code to initiate the device removal - * handshake protocal with controller firmware. + * handshake protocol with controller firmware. * * Return 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. @@ -2878,8 +2878,8 @@ _scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, * * This is the target reset completion routine. * This code is part of the code to initiate the device removal - * handshake protocal with controller firmware. - * It will send a sas iounit controll request (MPI2_SAS_OP_REMOVE_DEVICE) + * handshake protocol with controller firmware. + * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE) * * Return 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. @@ -2984,7 +2984,7 @@ _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid) * * This routine added to better handle cable breaker. * - * This handles the case where driver recieves multiple expander + * This handles the case where driver receives multiple expander * add and delete events in a single shot. When there is a delete event * the routine will void any pending add events waiting in the event queue. * @@ -3511,7 +3511,7 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data) #ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** - * _scsih_scsi_ioc_info - translated non-successfull SCSI_IO request + * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request * @ioc: per adapter object * @scmd: pointer to scsi command object * @mpi_reply: reply mf payload returned from firmware @@ -5138,7 +5138,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, unsigned long flags; int r; - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primative: " + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: " "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, event_data->PortWidth)); dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 46cc3825638d..835d8d66e696 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -2679,7 +2679,7 @@ static struct script script0 __initdata = { }/*-------------------------< RESEL_TAG >-------------------*/,{ /* ** Read IDENTIFY + SIMPLE + TAG using a single MOVE. - ** Agressive optimization, is'nt it? + ** Aggressive optimization, is'nt it? ** No need to test the SIMPLE TAG message, since the ** driver only supports conformant devices for tags. ;-) */ diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 6b8b021400f8..f6a50c98c36f 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -1288,7 +1288,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id) nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", nsp32_read4(base, SAVED_SACK_CNT)); - scsi_set_resid(SCpnt, 0); /* all data transfered! */ + scsi_set_resid(SCpnt, 0); /* all data transferred! */ } /* @@ -1630,7 +1630,7 @@ static int nsp32_busfree_occur(struct scsi_cmnd *SCpnt, unsigned short execph) /* * If SAVEDSACKCNT == 0, it means SavedDataPointer is - * come after data transfering. + * come after data transferring. */ if (s_sacklen > 0) { /* @@ -1785,7 +1785,7 @@ static void nsp32_adjust_busfree(struct scsi_cmnd *SCpnt, unsigned int s_sacklen the head element of the sg. restlen is correctly calculated. */ } - /* calculate the rest length for transfering */ + /* calculate the rest length for transferring */ restlen = sentlen - s_sacklen; /* update adjusting current SG table entry */ diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index 9565acf1aa72..c0221829069c 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -507,7 +507,7 @@ typedef struct _nsp32_lunt { /* * SCSI TARGET/LUN definition */ -#define NSP32_HOST_SCSIID 7 /* SCSI initiator is everytime defined as 7 */ +#define NSP32_HOST_SCSIID 7 /* SCSI initiator is every time defined as 7 */ #define MAX_TARGET 8 #define MAX_LUN 8 /* XXX: In SPI3, max number of LUN is 64. */ diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 521e2182d45b..58f5be4740e9 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -1366,7 +1366,7 @@ error: /* The values below are based on the OnStream frame payload size of 32K == 2**15, * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions - * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1. + * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1. */ #define OSST_FRAME_SHIFT 6 #define OSST_SECTOR_SHIFT 9 @@ -3131,7 +3131,7 @@ static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** } #if DEBUG if (debugging) - printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n", + printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n", name, offset, transfer, blks); #endif @@ -3811,7 +3811,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo if (transfer == 0) { printk(KERN_WARNING - "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n", + "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n", name, count, STp->block_size < 1024? STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k'); diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h index 11d26c57f3f8..b4fea98ba276 100644 --- a/drivers/scsi/osst.h +++ b/drivers/scsi/osst.h @@ -413,7 +413,7 @@ typedef struct os_dat_s { * AUX */ typedef struct os_aux_s { - __be32 format_id; /* hardware compability AUX is based on */ + __be32 format_id; /* hardware compatibility AUX is based on */ char application_sig[4]; /* driver used to write this media */ __be32 hdwr; /* reserved */ __be32 update_frame_cntr; /* for configuration frame */ diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index be3f33d31a99..54bdf6d85c6d 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -742,7 +742,7 @@ static void nsp_pio_read(struct scsi_cmnd *SCpnt) res = nsp_fifo_count(SCpnt) - ocount; //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount, res); - if (res == 0) { /* if some data avilable ? */ + if (res == 0) { /* if some data available ? */ if (stat == BUSPHASE_DATA_IN) { /* phase changed? */ //nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", SCpnt->SCp.this_residual); continue; diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 18b6c55cd08c..8b7db1e53c10 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -339,7 +339,7 @@ update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) /** * bar4_shift - function is called to shift BAR base address - * @pm8001_ha : our hba card infomation + * @pm8001_ha : our hba card information * @shiftValue : shifting value in memory bar. */ static int bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index 833a5201eda4..909132041c07 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h @@ -209,7 +209,7 @@ struct pio_setup_fis { /* * brief the data structure of SATA Completion Response - * use to discribe the sata task response (64 bytes) + * use to describe the sata task response (64 bytes) */ struct sata_completion_resp { __le32 tag; @@ -951,7 +951,7 @@ struct set_dev_state_resp { #define PCIE_EVENT_INTERRUPT 0x003044 #define PCIE_ERROR_INTERRUPT_ENABLE 0x003048 #define PCIE_ERROR_INTERRUPT 0x00304C -/* signature defintion for host scratch pad0 register */ +/* signature definition for host scratch pad0 register */ #define SPC_SOFT_RESET_SIGNATURE 0x252acbcd /* Signature for Soft Reset */ diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index bdb6b27dedd6..aa05e661d113 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -445,7 +445,7 @@ struct fw_control_info { struct fw_control_ex { struct fw_control_info *fw_control; void *buffer;/* keep buffer pointer to be - freed when the responce comes*/ + freed when the response comes*/ void *virtAddr;/* keep virtual address of the data */ void *usrAddr;/* keep virtual address of the user data */ diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index bcf858e88c64..96d5ad0c1e42 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -213,7 +213,7 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev) * pmcraid_slave_configure - Configures a SCSI device * @scsi_dev: scsi device struct * - * This fucntion is executed by SCSI mid layer just after a device is first + * This function is executed by SCSI mid layer just after a device is first * scanned (i.e. it has responded to an INQUIRY). For VSET resources, the * timeout value (default 30s) will be over-written to a higher value (60s) * and max_sectors value will be over-written to 512. It also sets queue depth @@ -2122,7 +2122,7 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance) * * This function executes most of the steps required for IOA reset. This gets * called by user threads (modprobe/insmod/rmmod) timer, tasklet and midlayer's - * 'eh_' thread. Access to variables used for controling the reset sequence is + * 'eh_' thread. Access to variables used for controlling the reset sequence is * synchronized using host lock. Various functions called during reset process * would make use of a single command block, pointer to which is also stored in * adapter instance structure. @@ -2994,7 +2994,7 @@ static int pmcraid_abort_complete(struct pmcraid_cmd *cancel_cmd) /* If the abort task is not timed out we will get a Good completion * as sense_key, otherwise we may get one the following responses - * due to subsquent bus reset or device reset. In case IOASC is + * due to subsequent bus reset or device reset. In case IOASC is * NR_SYNC_REQUIRED, set sync_reqd flag for the corresponding resource */ if (ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET || @@ -3933,7 +3933,7 @@ static long pmcraid_ioctl_passthrough( /* if abort task couldn't find the command i.e it got * completed prior to aborting, return good completion. - * if command got aborted succesfully or there was IOA + * if command got aborted successfully or there was IOA * reset due to abort task itself getting timedout then * return -ETIMEDOUT */ @@ -5932,7 +5932,7 @@ static int __devinit pmcraid_probe( * However, firmware supports 64-bit streaming DMA buffers, whereas * coherent buffers are to be 32-bit. Since pci_alloc_consistent always * returns memory within 4GB (if not, change this logic), coherent - * buffers are within firmware acceptible address ranges. + * buffers are within firmware acceptable address ranges. */ if ((sizeof(dma_addr_t) == 4) || pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index 4db210d93947..34e4c915002e 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -1024,7 +1024,7 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { /* - * pmcraid_ioctl_header - definition of header structure that preceeds all the + * pmcraid_ioctl_header - definition of header structure that precedes all the * buffers given as ioctl arguments. * * .signature : always ASCII string, "PMCRAID" diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 5dec684bf010..8ba5744c267e 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -78,7 +78,7 @@ - Clean up vchan handling Rev 3.23.33 July 3, 2003, Jes Sorensen - Don't define register access macros before define determining MMIO. - This just happend to work out on ia64 but not elsewhere. + This just happened to work out on ia64 but not elsewhere. - Don't try and read from the card while it is in reset as it won't respond and causes an MCA Rev 3.23.32 June 23, 2003, Jes Sorensen diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 6c51c0a35b9e..ee20353c8550 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2086,7 +2086,7 @@ struct ct_sns_pkt { }; /* - * SNS command structures -- for 2200 compatability. + * SNS command structures -- for 2200 compatibility. */ #define RFT_ID_SNS_SCMD_LEN 22 #define RFT_ID_SNS_CMD_SIZE 60 diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 631fefc8482d..f5ba09c8a663 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -539,7 +539,7 @@ struct sts_entry_24xx { * If DIF Error is set in comp_status, these additional fields are * defined: * &data[10] : uint8_t report_runt_bg[2]; - computed guard - * &data[12] : uint8_t actual_dif[8]; - DIF Data recieved + * &data[12] : uint8_t actual_dif[8]; - DIF Data received * &data[20] : uint8_t expected_dif[8]; - DIF Data computed */ }; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d17ed9a94a0c..712518d05128 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -414,7 +414,7 @@ skip_rio: "marked OFFLINE!\n"); vha->flags.online = 0; } else { - /* Check to see if MPI timeout occured */ + /* Check to see if MPI timeout occurred */ if ((mbx & MBX_3) && (ha->flags.port0)) set_bit(MPI_RESET_NEEDED, &vha->dpc_flags); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7a7c0ecfe7dd..34893397ac84 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -303,7 +303,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occured. " + "Mailbox command timeout occurred. " "Scheduling ISP " "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); @@ -321,7 +321,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occured. " + "Mailbox command timeout occurred. " "Issuing ISP abort.\n"); set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); @@ -3789,7 +3789,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mcp->mb[20] = LSW(MSD(mreq->send_dma)); mcp->mb[21] = MSW(MSD(mreq->send_dma)); - /* recieve data address */ + /* receive data address */ mcp->mb[16] = LSW(mreq->rcv_dma); mcp->mb[17] = MSW(mreq->rcv_dma); mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 76ec876e6b21..455fe134d31d 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2598,7 +2598,7 @@ qla82xx_calc_dsd_lists(uint16_t dsds) * qla82xx_start_scsi() - Send a SCSI command to the ISP * @sp: command to send to the ISP * - * Returns non-zero if a failure occured, else zero. + * Returns non-zero if a failure occurred, else zero. */ int qla82xx_start_scsi(srb_t *sp) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 75a966c94860..aa7747529165 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1046,7 +1046,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) eh_bus_reset_done: qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__, - (ret == FAILED) ? "failed" : "succeded"); + (ret == FAILED) ? "failed" : "succeeded"); return ret; } @@ -1136,7 +1136,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) eh_host_reset_lock: qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, - (ret == FAILED) ? "failed" : "succeded"); + (ret == FAILED) ? "failed" : "succeeded"); return ret; } @@ -3902,7 +3902,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha) continue; if (atomic_read(&other_pdev->enable_cnt)) { DEBUG17(qla_printk(KERN_INFO, ha, - "Found PCI func availabe and enabled at 0x%x\n", + "Found PCI func available and enabled at 0x%x\n", fn)); pci_dev_put(other_pdev); break; diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index c1f8d1b150f7..4757878d59dd 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -182,7 +182,7 @@ struct srb { uint16_t flags; /* (1) Status flags. */ #define SRB_DMA_VALID BIT_3 /* DMA Buffer mapped. */ -#define SRB_GOT_SENSE BIT_4 /* sense data recieved. */ +#define SRB_GOT_SENSE BIT_4 /* sense data received. */ uint8_t state; /* (1) Status flags. */ #define SRB_NO_QUEUE_STATE 0 /* Request is in between states */ diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index bbb2e903d38a..48e2241ddaf4 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -1338,7 +1338,7 @@ exit_init_hba: } DEBUG2(printk("scsi%ld: initialize adapter: %s\n", ha->host_no, - status == QLA_ERROR ? "FAILED" : "SUCCEDED")); + status == QLA_ERROR ? "FAILED" : "SUCCEEDED")); return status; } diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h index b3831bd29479..945cc328f57f 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/drivers/scsi/qla4xxx/ql4_nvram.h @@ -28,7 +28,7 @@ #define FM93C56A_ERASE 0x3 #define FM93C56A_ERASE_ALL 0x0 -/* Command Extentions */ +/* Command Extensions */ #define FM93C56A_WEN_EXT 0x3 #define FM93C56A_WRITE_ALL_EXT 0x1 #define FM93C56A_WDS_EXT 0x0 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index a4acb0dd7beb..230ba097d28c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1213,7 +1213,7 @@ recover_ha_init_adapter: clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no, - status == QLA_ERROR ? "FAILED" : "SUCCEDED")); + status == QLA_ERROR ? "FAILED" : "SUCCEEDED")); return status; } @@ -2110,7 +2110,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Abort command - %s\n", - ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed"); + ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed"); return ret; } @@ -2278,7 +2278,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) return_status = SUCCESS; ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n", - return_status == FAILED ? "FAILED" : "SUCCEDED"); + return_status == FAILED ? "FAILED" : "SUCCEEDED"); return return_status; } @@ -2492,7 +2492,7 @@ qla4xxx_pci_slot_reset(struct pci_dev *pdev) /* Initialize device or resume if in suspended state */ rc = pci_enable_device(pdev); if (rc) { - ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable " + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Can't re-enable " "device after reset\n", ha->host_no, __func__); goto exit_slot_reset; } diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index fa5758cbdedb..6888b2ca5bfc 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2454,7 +2454,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (devip) { - /* make this slot avaliable for re-use */ + /* make this slot available for re-use */ devip->used = 0; sdp->hostdata = NULL; } diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index a2ed201885ae..26a8a45584ef 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -499,7 +499,7 @@ scsi_netlink_init(void) SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, THIS_MODULE); if (!scsi_nl_sock) { - printk(KERN_ERR "%s: register of recieve handler failed\n", + printk(KERN_ERR "%s: register of receive handler failed\n", __func__); netlink_unregister_notifier(&scsi_netlink_notifier); return; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index f67282058ba1..8bca8c25ba69 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -93,7 +93,7 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, /* * The blk helpers are used to the READ/WRITE requests - * transfering data from a initiator point of view. Since + * transferring data from a initiator point of view. Since * we are in target mode we want the opposite. */ rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2941d2d92c94..fdf3fa639056 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2378,7 +2378,7 @@ fc_flush_devloss(struct Scsi_Host *shost) * fc_remove_host - called to terminate any fc_transport-related elements for a scsi host. * @shost: Which &Scsi_Host * - * This routine is expected to be called immediately preceeding the + * This routine is expected to be called immediately preceding the * a driver's call to scsi_remove_host(). * * WARNING: A driver utilizing the fc_transport, which fails to call @@ -2458,7 +2458,7 @@ static void fc_terminate_rport_io(struct fc_rport *rport) } /** - * fc_starget_delete - called to delete the scsi decendents of an rport + * fc_starget_delete - called to delete the scsi descendants of an rport * @work: remote port to be operated on. * * Deletes target and all sdevs. diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b61ebec6bca7..bd0806e64e85 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1055,7 +1055,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * @arg: this is third argument given to ioctl(2) system call. * Often contains a pointer. * - * Returns 0 if successful (some ioctls return postive numbers on + * Returns 0 if successful (some ioctls return positive numbers on * success as well). Returns a negated errno value in case of error. * * Note: most ioctls are forward onto the block subsystem or further diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index aefadc6a1607..95019c747cc1 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -567,7 +567,7 @@ static const struct block_device_operations sr_bdops = .revalidate_disk = sr_block_revalidate_disk, /* * No compat_ioctl for now because sr_block_ioctl never - * seems to pass arbitary ioctls down to host drivers. + * seems to pass arbitrary ioctls down to host drivers. */ }; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 4f0e5485ffde..07eaef1c722b 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -467,7 +467,7 @@ static void free_all_tags( void ) * * Parameters: struct scsi_cmnd *cmd * The command to work on. The first scatter buffer's data are - * assumed to be already transfered into ptr/this_residual. + * assumed to be already transferred into ptr/this_residual. */ static void merge_contiguous_buffers(struct scsi_cmnd *cmd) @@ -1717,7 +1717,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd, * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes are transfered or exit + * maximum number of bytes, 0 if all bytes are transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. @@ -1904,7 +1904,7 @@ static int do_abort (struct Scsi_Host *host) * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transfered or exit + * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c index 190107ae120b..012c86edd59f 100644 --- a/drivers/scsi/sym53c416.c +++ b/drivers/scsi/sym53c416.c @@ -774,7 +774,7 @@ static int sym53c416_host_reset(Scsi_Cmnd *SCpnt) /* printk("sym53c416_reset\n"); */ base = SCpnt->device->host->io_port; - /* search scsi_id - fixme, we shouldnt need to iterate for this! */ + /* search scsi_id - fixme, we shouldn't need to iterate for this! */ for(i = 0; i < host_index && scsi_id == -1; i++) if(hosts[i].base == base) scsi_id = hosts[i].scsi_id; diff --git a/drivers/scsi/sym53c8xx_2/sym_fw1.h b/drivers/scsi/sym53c8xx_2/sym_fw1.h index 7b08d6caaa99..63952ee300b5 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw1.h +++ b/drivers/scsi/sym53c8xx_2/sym_fw1.h @@ -1449,7 +1449,7 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = { PADDR_B (msg_weird_seen), /* * We donnot handle extended messages from SCRIPTS. - * Read the amount of data correponding to the + * Read the amount of data corresponding to the * message length and call the C code. */ SCR_COPY (1), diff --git a/drivers/scsi/sym53c8xx_2/sym_fw2.h b/drivers/scsi/sym53c8xx_2/sym_fw2.h index ae1fb179b88e..c87d72443a16 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw2.h +++ b/drivers/scsi/sym53c8xx_2/sym_fw2.h @@ -1326,7 +1326,7 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = { PADDR_B (msg_weird_seen), /* * We donnot handle extended messages from SCRIPTS. - * Read the amount of data correponding to the + * Read the amount of data corresponding to the * message length and call the C code. */ SCR_STORE_REL (scratcha, 1), diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 2c3e89ddf069..d92fe4037e94 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -2457,7 +2457,7 @@ static void sym_int_ma (struct sym_hcb *np) } /* - * The data in the dma fifo has not been transfered to + * The data in the dma fifo has not been transferred to * the target -> add the amount to the rest * and clear the data. * Check the sstat2 register in case of wide transfer. @@ -5094,7 +5094,7 @@ fail: } /* - * Lun control block deallocation. Returns the number of valid remaing LCBs + * Lun control block deallocation. Returns the number of valid remaining LCBs * for the target. */ int sym_free_lcb(struct sym_hcb *np, u_char tn, u_char ln) diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c index 883cac10daf9..6f9af0de7ec3 100644 --- a/drivers/scsi/sym53c8xx_2/sym_malloc.c +++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c @@ -50,7 +50,7 @@ * from the SCRIPTS code. In addition, cache line alignment * is guaranteed for power of 2 cache line size. * - * This allocator has been developped for the Linux sym53c8xx + * This allocator has been developed for the Linux sym53c8xx * driver, since this O/S does not provide naturally aligned * allocations. * It has the advantage of allowing the driver to use private diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 5f697e0bd009..4468ae3610f7 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -1843,7 +1843,7 @@ check_setup_args(char *key, int *flags, int *val, char *buf) * * The original driver used to rely on a fixed sx_table, containing periods * for (only) the lower limits of the respective input-clock-frequency ranges - * (8-10/12-15/16-20 MHz). Although it seems, that no problems ocurred with + * (8-10/12-15/16-20 MHz). Although it seems, that no problems occurred with * this setting so far, it might be desirable to adjust the transfer periods * closer to the really attached, possibly 25% higher, input-clock, since * - the wd33c93 may really use a significant shorter period, than it has diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index db451ae0a368..9ee0afef2d16 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -837,7 +837,7 @@ static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed) } } - /* Take the lock, then check we didnt get beaten, if so try again */ + /* Take the lock, then check we didn't get beaten, if so try again */ spin_lock_irqsave(&scbpool_lock, flags); if (freescbs < needed) { spin_unlock_irqrestore(&scbpool_lock, flags); diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c index 04113e5304a0..1e824fb1649b 100644 --- a/drivers/sfi/sfi_core.c +++ b/drivers/sfi/sfi_core.c @@ -515,7 +515,7 @@ void __init sfi_init_late(void) } /* - * The reason we put it here becasue we need wait till the /sys/firmware + * The reason we put it here because we need wait till the /sys/firmware * is setup, then our interface can be registered in /sys/firmware/sfi */ core_initcall(sfi_sysfs_init); diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 5a4e0afb9ad6..5825370bad25 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -661,7 +661,7 @@ static void readwriter(struct pl022 *pl022) { /* - * The FIFO depth is different inbetween primecell variants. + * The FIFO depth is different between primecell variants. * I believe filling in too much in the FIFO might cause * errons in 8bit wide transfers on ARM variants (just 8 words * FIFO, means only 8x8 = 64 bits in FIFO) at least. @@ -722,7 +722,7 @@ static void readwriter(struct pl022 *pl022) * This inner reader takes care of things appearing in the RX * FIFO as we're transmitting. This will happen a lot since the * clock starts running when you put things into the TX FIFO, - * and then things are continously clocked into the RX FIFO. + * and then things are continuously clocked into the RX FIFO. */ while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) && (pl022->rx < pl022->rx_end)) { @@ -842,7 +842,7 @@ static void dma_callback(void *data) unmap_free_dma_scatter(pl022); - /* Update total bytes transfered */ + /* Update total bytes transferred */ msg->actual_length += pl022->cur_transfer->len; if (pl022->cur_transfer->cs_change) pl022->cur_chip-> @@ -1224,7 +1224,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) "number of bytes on a 16bit bus?)\n", (u32) (pl022->rx - pl022->rx_end)); } - /* Update total bytes transfered */ + /* Update total bytes transferred */ msg->actual_length += pl022->cur_transfer->len; if (pl022->cur_transfer->cs_change) pl022->cur_chip-> @@ -1415,11 +1415,11 @@ static void do_polling_transfer(struct pl022 *pl022) SSP_CR1(pl022->virtbase)); dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); - /* FIXME: insert a timeout so we don't hang here indefinately */ + /* FIXME: insert a timeout so we don't hang here indefinitely */ while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) readwriter(pl022); - /* Update total byte transfered */ + /* Update total byte transferred */ message->actual_length += pl022->cur_transfer->len; if (pl022->cur_transfer->cs_change) pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); @@ -2129,7 +2129,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) "probe - problem registering spi master\n"); goto err_spi_register; } - dev_dbg(dev, "probe succeded\n"); + dev_dbg(dev, "probe succeeded\n"); /* * Disable the silicon block pclk and any voltage domain and just * power it up and clock it when it's needed @@ -2184,7 +2184,7 @@ pl022_remove(struct amba_device *adev) spi_unregister_master(pl022->master); spi_master_put(pl022->master); amba_set_drvdata(adev, NULL); - dev_dbg(&adev->dev, "remove succeded\n"); + dev_dbg(&adev->dev, "remove succeeded\n"); return 0; } diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index 3c9ade69643f..b50563d320e1 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c @@ -480,7 +480,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw) au1xxx_dbdma_stop(hw->dma_rx_ch); au1xxx_dbdma_stop(hw->dma_tx_ch); - /* get number of transfered bytes */ + /* get number of transferred bytes */ hw->rx_count = hw->len - au1xxx_get_dma_residue(hw->dma_rx_ch); hw->tx_count = hw->len - au1xxx_get_dma_residue(hw->dma_tx_ch); diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 9a6196461b27..b1a4b9f503ae 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c @@ -345,7 +345,7 @@ static void int_error_stop(struct dw_spi *dws, const char *msg) void dw_spi_xfer_done(struct dw_spi *dws) { - /* Update total byte transfered return count actual bytes read */ + /* Update total byte transferred return count actual bytes read */ dws->cur_msg->actual_length += dws->len; /* Move to next transfer */ diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h index fb0bce564844..b23e452adaf7 100644 --- a/drivers/spi/dw_spi.h +++ b/drivers/spi/dw_spi.h @@ -46,7 +46,7 @@ #define SPI_INT_RXFI (1 << 4) #define SPI_INT_MSTI (1 << 5) -/* TX RX interrupt level threshhold, max can be 256 */ +/* TX RX interrupt level threshold, max can be 256 */ #define SPI_INT_THRESHOLD 32 enum dw_ssi_type { diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c index 0ba35df9a6df..d3570071e98f 100644 --- a/drivers/spi/ep93xx_spi.c +++ b/drivers/spi/ep93xx_spi.c @@ -512,7 +512,7 @@ static int ep93xx_spi_read_write(struct ep93xx_spi *espi) * * This function processes one SPI transfer given in @t. Function waits until * transfer is complete (may sleep) and updates @msg->status based on whether - * transfer was succesfully processed or not. + * transfer was successfully processed or not. */ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, struct spi_message *msg, diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index a429b01d0285..9c74aad6be93 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -700,7 +700,7 @@ static void int_transfer_complete(struct driver_data *drv_data) if (!pxa25x_ssp_comp(drv_data)) write_SSTO(0, reg); - /* Update total byte transfered return count actual bytes read */ + /* Update total byte transferred return count actual bytes read */ drv_data->cur_msg->actual_length += drv_data->len - (drv_data->rx_end - drv_data->rx); @@ -759,7 +759,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) /* * PXA25x_SSP has no timeout, set up rx threshould for the - * remaing RX bytes. + * remaining RX bytes. */ if (pxa25x_ssp_comp(drv_data)) { diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 34bb17f03019..82b9a428c323 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -957,7 +957,7 @@ EXPORT_SYMBOL_GPL(spi_sync); * drivers may DMA directly into and out of the message buffers. * * This call should be used by drivers that require exclusive access to the - * SPI bus. It has to be preceeded by a spi_bus_lock call. The SPI bus must + * SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must * be released by a spi_bus_unlock call when the exclusive access is over. * * It returns zero on success, else a negative error code. diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index a28462486df8..bdb7289a1d22 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -905,7 +905,7 @@ static void bfin_spi_pump_transfers(unsigned long data) "IO write error!\n"); message->state = ERROR_STATE; } else { - /* Update total byte transfered */ + /* Update total byte transferred */ message->actual_length += drv_data->len_in_bytes; /* Move to next transfer of this msg */ message->state = bfin_spi_next_transfer(drv_data); diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c index 900e921ab80e..496f895a0024 100644 --- a/drivers/spi/spi_fsl_espi.c +++ b/drivers/spi/spi_fsl_espi.c @@ -474,7 +474,7 @@ static int fsl_espi_setup(struct spi_device *spi) mpc8xxx_spi = spi_master_get_devdata(spi->master); reg_base = mpc8xxx_spi->reg_base; - hw_mode = cs->hw_mode; /* Save orginal settings */ + hw_mode = cs->hw_mode; /* Save original settings */ cs->hw_mode = mpc8xxx_spi_read_reg( ®_base->csmode[spi->chip_select]); /* mask out bits we are going to set */ diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index a467b20baac8..6f34963b3c64 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -670,7 +670,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, ssb_printk(KERN_ERR PFX "No SPROM available!\n"); return -ENODEV; } - if (bus->chipco.dev) { /* can be unavailible! */ + if (bus->chipco.dev) { /* can be unavailable! */ /* * get SPROM offset: SSB_SPROM_BASE1 except for * chipcommon rev >= 31 or chip ID is 0x4312 and diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 4f7cc8d13277..5f34d7a3e3a5 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c @@ -185,7 +185,7 @@ bool ssb_is_sprom_available(struct ssb_bus *bus) /* this routine differs from specs as we do not access SPROM directly on PCMCIA */ if (bus->bustype == SSB_BUSTYPE_PCI && - bus->chipco.dev && /* can be unavailible! */ + bus->chipco.dev && /* can be unavailable! */ bus->chipco.dev->id.revision >= 31) return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM; diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c index c6488e0d1305..41223f953589 100644 --- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c +++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c @@ -237,7 +237,7 @@ static int CreditsAvailableCallback(void *pContext, int Credits, bool CreditIRQE pProt->CreditsCurrentSeek)); if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) { - /* we have enough credits to fullfill at least 1 packet waiting in the queue */ + /* we have enough credits to fulfill at least 1 packet waiting in the queue */ pProt->CreditsCurrentSeek = 0; pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS; doPendingSends = true; @@ -285,7 +285,7 @@ static void FailureCallback(void *pContext, int Status) { struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; - /* target assertion occured */ + /* target assertion occurred */ NotifyTransportFailure(pProt, Status); } @@ -507,7 +507,7 @@ static int HCIUartMessagePending(void *pContext, u8 LookAheadBytes[], int ValidB } while (false); - /* check if we need to disable the reciever */ + /* check if we need to disable the receiver */ if (status || blockRecv) { DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC); } diff --git a/drivers/staging/ath6kl/include/aggr_recv_api.h b/drivers/staging/ath6kl/include/aggr_recv_api.h index 67a058492c4d..5ead58d5febd 100644 --- a/drivers/staging/ath6kl/include/aggr_recv_api.h +++ b/drivers/staging/ath6kl/include/aggr_recv_api.h @@ -72,7 +72,7 @@ aggr_process_bar(void *cntxt, u8 tid, u16 seq_no); * This event is to initiate/modify the receive side window. * Target will send WMI_ADDBA_REQ_EVENTID event to host - to setup * recv re-ordering queues. Target will negotiate ADDBA with peer, - * and indicate via this event after succesfully completing the + * and indicate via this event after successfully completing the * negotiation. This happens in two situations: * 1. Initial setup of aggregation * 2. Renegotiation of current recv window. diff --git a/drivers/staging/ath6kl/include/common/a_hci.h b/drivers/staging/ath6kl/include/common/a_hci.h index 08cb013090be..379d65224e3a 100644 --- a/drivers/staging/ath6kl/include/common/a_hci.h +++ b/drivers/staging/ath6kl/include/common/a_hci.h @@ -124,7 +124,7 @@ #define PAL_NUM_COMPL_DATA_BLOCK_EVENT 0x48 #define PAL_SHORT_RANGE_MODE_CHANGE_COMPL_EVENT 0x4C #define PAL_AMP_STATUS_CHANGE_EVENT 0x4D -/*======== End of PAL events definiton =================*/ +/*======== End of PAL events definition =================*/ /*======== Timeouts (not part of HCI cmd, but input to PAL engine) =========*/ @@ -430,7 +430,7 @@ typedef struct hci_event_hw_err_t { u8 hw_err_code; } POSTPACK HCI_EVENT_HW_ERR; -/* Flush occured event */ +/* Flush occurred event */ /* Qos Violation event */ typedef struct hci_event_handle_t { u8 event_code; diff --git a/drivers/staging/ath6kl/include/common/dbglog.h b/drivers/staging/ath6kl/include/common/dbglog.h index 3a3d00da0b81..b7a123086ccf 100644 --- a/drivers/staging/ath6kl/include/common/dbglog.h +++ b/drivers/staging/ath6kl/include/common/dbglog.h @@ -44,7 +44,7 @@ extern "C" { #define DBGLOG_MODULEID_NUM_MAX 16 /* Upper limit is width of mask */ /* - * Please ensure that the definition of any new module intrduced is captured + * Please ensure that the definition of any new module introduced is captured * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The * structure is required for the parser to correctly pick up the values for * different modules. diff --git a/drivers/staging/ath6kl/include/common/epping_test.h b/drivers/staging/ath6kl/include/common/epping_test.h index 5c40d8a2229d..7027fac8f37e 100644 --- a/drivers/staging/ath6kl/include/common/epping_test.h +++ b/drivers/staging/ath6kl/include/common/epping_test.h @@ -92,7 +92,7 @@ typedef PREPACK struct { #define EPPING_CMD_RESET_RECV_CNT 2 /* reset recv count */ #define EPPING_CMD_CAPTURE_RECV_CNT 3 /* fetch recv count, 4-byte count returned in CmdBuffer_t */ #define EPPING_CMD_NO_ECHO 4 /* non-echo packet test (tx-only) */ -#define EPPING_CMD_CONT_RX_START 5 /* continous RX packets, parameters are in CmdBuffer_h */ +#define EPPING_CMD_CONT_RX_START 5 /* continuous RX packets, parameters are in CmdBuffer_h */ #define EPPING_CMD_CONT_RX_STOP 6 /* stop continuous RX packet transmission */ /* test command parameters may be no more than 8 bytes */ diff --git a/drivers/staging/ath6kl/include/common/ini_dset.h b/drivers/staging/ath6kl/include/common/ini_dset.h index 8bfc75940c8f..a9e05fa0f659 100644 --- a/drivers/staging/ath6kl/include/common/ini_dset.h +++ b/drivers/staging/ath6kl/include/common/ini_dset.h @@ -31,7 +31,7 @@ */ typedef enum { #if defined(AR6002_REV4) || defined(AR6003) -/* Add these definitions for compatability */ +/* Add these definitions for compatibility */ #define WHAL_INI_DATA_ID_BB_RFGAIN_LNA1 WHAL_INI_DATA_ID_BB_RFGAIN #define WHAL_INI_DATA_ID_BB_RFGAIN_LNA2 WHAL_INI_DATA_ID_BB_RFGAIN WHAL_INI_DATA_ID_NULL =0, diff --git a/drivers/staging/ath6kl/include/common/testcmd.h b/drivers/staging/ath6kl/include/common/testcmd.h index 9ca1f2ac2cbf..7d94aee508b3 100644 --- a/drivers/staging/ath6kl/include/common/testcmd.h +++ b/drivers/staging/ath6kl/include/common/testcmd.h @@ -43,8 +43,8 @@ typedef enum { PN15_PATTERN }TX_DATA_PATTERN; -/* Continous tx - mode : TCMD_CONT_TX_OFF - Disabling continous tx +/* Continuous tx + mode : TCMD_CONT_TX_OFF - Disabling continuous tx TCMD_CONT_TX_SINE - Enable continuous unmodulated tx TCMD_CONT_TX_FRAME- Enable continuous modulated tx freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g) diff --git a/drivers/staging/ath6kl/include/common/wmi.h b/drivers/staging/ath6kl/include/common/wmi.h index c645af373442..4e6343485362 100644 --- a/drivers/staging/ath6kl/include/common/wmi.h +++ b/drivers/staging/ath6kl/include/common/wmi.h @@ -1568,8 +1568,8 @@ typedef PREPACK struct { switch to ps-poll mode default = 3 */ - u32 scoContStompMax; /* max number of continous stomp allowed in opt mode. - if excedded switch to pspoll mode + u32 scoContStompMax; /* max number of continuous stomp allowed in opt mode. + if exceeded switch to pspoll mode default = 3 */ u32 scoMinlowRateMbps; /* Low rate threshold */ @@ -2084,7 +2084,7 @@ typedef PREPACK struct { /* * BSS INFO HDR version 2.0 * With 6 bytes HTC header and 6 bytes of WMI header - * WMI_BSS_INFO_HDR cannot be accomodated in the removed 802.11 management + * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management * header space. * - Reduce the ieMask to 2 bytes as only two bit flags are used * - Remove rssi and compute it on the host. rssi = snr - 95 @@ -2911,7 +2911,7 @@ typedef PREPACK struct { u8 pktID; /* packet ID to identify parent packet */ u8 rateIdx; /* rate index on successful transmission */ u8 ackFailures; /* number of ACK failures in tx attempt */ -#if 0 /* optional params currently ommitted. */ +#if 0 /* optional params currently omitted. */ u32 queueDelay; // usec delay measured Tx Start time - host delivery time u32 mediaDelay; // usec delay measured ACK rx time - host delivery time #endif diff --git a/drivers/staging/ath6kl/include/common/wmix.h b/drivers/staging/ath6kl/include/common/wmix.h index 5ebb8285d135..36acba66d49f 100644 --- a/drivers/staging/ath6kl/include/common/wmix.h +++ b/drivers/staging/ath6kl/include/common/wmix.h @@ -191,7 +191,7 @@ typedef PREPACK struct { } POSTPACK WMIX_GPIO_INTR_ACK_CMD; /* - * Target informs Host of GPIO interrupts that have ocurred since the + * Target informs Host of GPIO interrupts that have occurred since the * last WMIX_GIPO_INTR_ACK_CMD was received. Additional information -- * the current GPIO input values is provided -- in order to support * use of a GPIO interrupt as a Data Valid signal for other GPIO pins. diff --git a/drivers/staging/ath6kl/include/htc_api.h b/drivers/staging/ath6kl/include/htc_api.h index 1bc2488788ab..4fb767559f82 100644 --- a/drivers/staging/ath6kl/include/htc_api.h +++ b/drivers/staging/ath6kl/include/htc_api.h @@ -209,7 +209,7 @@ struct htc_endpoint_credit_dist { typedef enum _HTC_CREDIT_DIST_REASON { HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed send operations (MANDATORY) resulting in credit reports */ - HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occured (OPTIONAL) */ + HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occurred (OPTIONAL) */ HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */ HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by the distribution function */ @@ -253,7 +253,7 @@ struct htc_endpoint_stats { u32 RxPacketsBundled; /* count of recv packets received in a bundle */ u32 RxBundleLookAheads; /* count of number of bundled lookaheads */ u32 RxBundleIndFromHdr; /* count of the number of bundle indications from the HTC header */ - u32 RxAllocThreshHit; /* count of the number of times the recv allocation threshhold was hit */ + u32 RxAllocThreshHit; /* count of the number of times the recv allocation threshold was hit */ u32 RxAllocThreshBytes; /* total number of bytes */ }; @@ -391,7 +391,7 @@ int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket); +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void HTCStop(HTC_HANDLE HTCHandle); /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Destory HTC service + @desc: Destroy HTC service @function name: HTCDestroy @input: HTCHandle @output: diff --git a/drivers/staging/ath6kl/miscdrv/credit_dist.c b/drivers/staging/ath6kl/miscdrv/credit_dist.c index ae54e1f48e50..33fa0209026d 100644 --- a/drivers/staging/ath6kl/miscdrv/credit_dist.c +++ b/drivers/staging/ath6kl/miscdrv/credit_dist.c @@ -341,7 +341,7 @@ static void SeekCredits(struct common_credit_state_info *pCredInfo, credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); if (credits >= pEPDist->TxCreditsSeek) { - /* we found some to fullfill the seek request */ + /* we found some to fulfill the seek request */ break; } @@ -364,8 +364,8 @@ static void SeekCredits(struct common_credit_state_info *pCredInfo, if ((pCurEpDist->TxCreditsAssigned - need) >= pCurEpDist->TxCreditsMin) { /* the current one has been allocated more than it's minimum and it - * has enough credits assigned above it's minimum to fullfill our need - * try to take away just enough to fullfill our need */ + * has enough credits assigned above it's minimum to fulfill our need + * try to take away just enough to fulfill our need */ ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned - need); diff --git a/drivers/staging/ath6kl/os/linux/ar6000_android.c b/drivers/staging/ath6kl/os/linux/ar6000_android.c index c96f6e9c99c6..4aa75ee2cb13 100644 --- a/drivers/staging/ath6kl/os/linux/ar6000_android.c +++ b/drivers/staging/ath6kl/os/linux/ar6000_android.c @@ -372,7 +372,7 @@ void android_ar6k_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bo } } if (needWake) { - /* keep host wake up if there is any event and packate comming in*/ + /* keep host wake up if there is any event and packate coming in*/ if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c index 27cb02dfad3c..97d6ce63b5c0 100644 --- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c +++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c @@ -520,7 +520,7 @@ dbglog_parse_debug_logs(s8 *datap, u32 len) int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar) { - u32 data[8]; /* Should be able to accomodate struct dbglog_buf_s */ + u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */ u32 address; u32 length; u32 dropped; @@ -2063,7 +2063,7 @@ ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs) * - In case of surprise removal, the hcd already frees up the pending * for the device and hence there is no need to unregister the function * driver inorder to get these requests. For planned removal, the function - * driver has to explictly unregister itself to have the hcd return all the + * driver has to explicitly unregister itself to have the hcd return all the * pending requests before the data structures for the devices are freed up. * Note that as per the current implementation, the function driver will * end up releasing all the devices since there is no API to selectively @@ -2982,7 +2982,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev) /* If target is not associated */ if( (!ar->arConnected && !bypasswmi) #ifdef CONFIG_HOST_TCMD_SUPPORT - /* TCMD doesnt support any data, free the buf and return */ + /* TCMD doesn't support any data, free the buf and return */ || (ar->arTargetMode == AR6000_TCMD_MODE) #endif ) { @@ -6393,7 +6393,7 @@ static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID e /* * Add support for adding and removing a virtual adapter for soft AP. * Some OS requires different adapters names for station and soft AP mode. - * To support these requirement, create and destory a netdevice instance + * To support these requirement, create and destroy a netdevice instance * when the AP mode is operational. A full fledged support for virual device * is not implemented. Rather a virtual interface is created and is linked * with the existing physical device instance during the operation of the diff --git a/drivers/staging/ath6kl/wmi/wmi.c b/drivers/staging/ath6kl/wmi/wmi.c index 0ddaee21f9d7..a00bf0a59871 100644 --- a/drivers/staging/ath6kl/wmi/wmi.c +++ b/drivers/staging/ath6kl/wmi/wmi.c @@ -4867,7 +4867,7 @@ wmi_set_country(struct wmi_t *wmip, u8 *countryCode) #ifdef CONFIG_HOST_TCMD_SUPPORT /* WMI layer doesn't need to know the data type of the test cmd. This would be beneficial for customers like Qualcomm, who might - have different test command requirements from differnt manufacturers + have different test command requirements from different manufacturers */ int wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len) diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h index 32909e2938d5..20cca24ff5f0 100644 --- a/drivers/staging/bcm/Adapter.h +++ b/drivers/staging/bcm/Adapter.h @@ -412,7 +412,7 @@ struct _MINI_ADAPTER // this to keep track of the Tx and Rx MailBox Registers. atomic_t CurrNumFreeTxDesc; - // to keep track the no of byte recieved + // to keep track the no of byte received USHORT PrevNumRecvDescs; USHORT CurrNumRecvDescs; UINT u32TotalDSD; @@ -527,7 +527,7 @@ struct _MINI_ADAPTER BOOLEAN bStatusWrite; UINT uiNVMDSDSize; UINT uiVendorExtnFlag; - //it will always represent choosed DSD at any point of time. + //it will always represent chosen DSD at any point of time. // Generally it is Active DSD but in case of NVM RD/WR it might be different. UINT ulFlashCalStart; ULONG ulFlashControlSectionStart; @@ -546,10 +546,10 @@ struct _MINI_ADAPTER PFLASH_CS_INFO psFlashCSInfo ; PFLASH2X_VENDORSPECIFIC_INFO psFlash2xVendorInfo; UINT uiFlashBaseAdd; //Flash start address - UINT uiActiveISOOffset; //Active ISO offset choosen before f/w download + UINT uiActiveISOOffset; //Active ISO offset chosen before f/w download FLASH2X_SECTION_VAL eActiveISO; //Active ISO section val - FLASH2X_SECTION_VAL eActiveDSD; //Active DSD val choosen before f/w download - UINT uiActiveDSDOffsetAtFwDld; //For accessing Active DSD choosen before f/w download + FLASH2X_SECTION_VAL eActiveDSD; //Active DSD val chosen before f/w download + UINT uiActiveDSDOffsetAtFwDld; //For accessing Active DSD chosen before f/w download UINT uiFlashLayoutMajorVersion ; UINT uiFlashLayoutMinorVersion; BOOLEAN bAllDSDWriteAllow ; diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 9be184f143e5..c0ee95a71343 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -384,7 +384,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter,stConvergenceSLT } if(psfCSType->cCPacketClassificationRule.u8Protocol == 0) { - //we didnt get protocol field filled in by the BS + //we didn't get protocol field filled in by the BS pstClassifierEntry->ucProtocolLength=0; } else @@ -879,7 +879,7 @@ static VOID CopyToAdapter( register PMINI_ADAPTER Adapter, /**sfAuthorizedSet.u8TrafficIndicationPreference); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Recieved : 0x%X",pstAddIndication->sfAuthorizedSet.u8TotalClassifiers); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received : 0x%X",pstAddIndication->sfAuthorizedSet.u8TotalClassifiers); nCurClassifierCnt = pstAddIndication->sfAuthorizedSet.u8TotalClassifiers; @@ -1305,7 +1305,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference : 0x%02X", pstAddIndication->sfAdmittedSet.u8TrafficIndicationPreference); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Recieved : 0x%X",pstAddIndication->sfAdmittedSet.u8TotalClassifiers); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received : 0x%X",pstAddIndication->sfAdmittedSet.u8TotalClassifiers); nCurClassifierCnt = pstAddIndication->sfAdmittedSet.u8TotalClassifiers; @@ -1502,7 +1502,7 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TrafficIndicationPreference : 0x%X", pstAddIndication->sfActiveSet.u8TrafficIndicationPreference); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Recieved : 0x%X",pstAddIndication->sfActiveSet.u8TotalClassifiers); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received : 0x%X",pstAddIndication->sfActiveSet.u8TotalClassifiers); nCurClassifierCnt = pstAddIndication->sfActiveSet.u8TotalClassifiers; @@ -1696,7 +1696,7 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *p //No Special handling send the message as it is return 1; } - // For DSA_REQ, only upto "psfAuthorizedSet" parameter should be accessed by driver! + // For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver! pstAddIndication=kmalloc(sizeof(*pstAddIndication), GFP_KERNEL); if(NULL==pstAddIndication) @@ -1788,7 +1788,7 @@ static inline stLocalSFAddIndicationAlt BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage "); /* //Need to Allocate memory to contain the SUPER Large structures - //Our driver cant create these structures on Stack :( + //Our driver can't create these structures on Stack :( */ pstAddIndicationDest=kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL); @@ -1957,7 +1957,7 @@ INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) { /* //Need to Allocate memory to contain the SUPER Large structures - //Our driver cant create these structures on Stack + //Our driver can't create these structures on Stack */ Adapter->caDsxReqResp=kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL); if(!Adapter->caDsxReqResp) diff --git a/drivers/staging/bcm/HostMIBSInterface.h b/drivers/staging/bcm/HostMIBSInterface.h index f17a4f13474c..e34531b638e8 100644 --- a/drivers/staging/bcm/HostMIBSInterface.h +++ b/drivers/staging/bcm/HostMIBSInterface.h @@ -62,7 +62,7 @@ typedef struct _S_MIBS_HOST_INFO ULONG NumDesUsed; ULONG CurrNumFreeDesc; ULONG PrevNumFreeDesc; - // to keep track the no of byte recieved + // to keep track the no of byte received ULONG PrevNumRcevBytes; ULONG CurrNumRcevBytes; diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c index 91b6fbe33c91..5b4fd372ec36 100644 --- a/drivers/staging/bcm/IPv6Protocol.c +++ b/drivers/staging/bcm/IPv6Protocol.c @@ -287,7 +287,7 @@ static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Head for(uiLoopIndex=0;uiLoopIndexstSrcIpAddress.ulIpv6Mask[uiLoopIndex]); @@ -340,7 +340,7 @@ static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Hea for(uiLoopIndex=0;uiLoopIndexstDestIpAddress.ulIpv6Mask[uiLoopIndex]); diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c index bf5c0ad86610..96fa4ead7930 100644 --- a/drivers/staging/bcm/InterfaceIdleMode.c +++ b/drivers/staging/bcm/InterfaceIdleMode.c @@ -11,7 +11,7 @@ Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context Return: BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful. - Other - If an error occured. + Other - If an error occurred. */ @@ -26,7 +26,7 @@ Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context Return: BCM_STATUS_SUCCESS - If Idle mode response related HW configuration was successful. - Other - If an error occured. + Other - If an error occurred. */ /* diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c index 220ff922bdcf..67719d57256d 100644 --- a/drivers/staging/bcm/InterfaceIsr.c +++ b/drivers/staging/bcm/InterfaceIsr.c @@ -80,8 +80,8 @@ static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) } case -EINPROGRESS: { - //This situation may happend when URBunlink is used. for detail check usb_unlink_urb documentation. - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occured... something very bad is going on"); + //This situation may happened when URBunlink is used. for detail check usb_unlink_urb documentation. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occurred... something very bad is going on"); break ; //return; } diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c index 533f8ebe0f84..806ef5d18522 100644 --- a/drivers/staging/bcm/InterfaceRx.c +++ b/drivers/staging/bcm/InterfaceRx.c @@ -34,7 +34,7 @@ GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter) return pRcb; } -/*this is receive call back - when pkt avilable for receive (BULK IN- end point)*/ +/*this is receive call back - when pkt available for receive (BULK IN- end point)*/ static void read_bulk_callback(struct urb *urb) { struct sk_buff *skb = NULL; @@ -123,7 +123,7 @@ static void read_bulk_callback(struct urb *urb) if((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) || (!(pLeader->Status >= 0x20 && pLeader->Status <= 0x3F))) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Recived control pkt..."); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt..."); *(PUSHORT)skb->data = pLeader->Status; memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer + (sizeof(LEADER)), pLeader->PLength); @@ -142,7 +142,7 @@ static void read_bulk_callback(struct urb *urb) * Data Packet, Format a proper Ethernet Header * and give it to the stack */ - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt..."); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt..."); skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES); memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(LEADER), pLeader->PLength); skb->dev = Adapter->dev; @@ -151,7 +151,7 @@ static void read_bulk_callback(struct urb *urb) skb_put (skb, pLeader->PLength + ETH_HLEN); Adapter->PackInfo[QueueIndex].uiTotalRxBytes+=pLeader->PLength; Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes+= pLeader->PLength; - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt of len :0x%X", pLeader->PLength); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength); if(netif_running(Adapter->dev)) { @@ -237,7 +237,7 @@ Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context Return: TRUE - If Rx was successful. - Other - If an error occured. + Other - If an error occurred. */ BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter) diff --git a/drivers/staging/bcm/Ioctl.h b/drivers/staging/bcm/Ioctl.h index e4f8eb70be1e..f859cf1c47b0 100644 --- a/drivers/staging/bcm/Ioctl.h +++ b/drivers/staging/bcm/Ioctl.h @@ -241,7 +241,7 @@ typedef struct bulkwrmbuffer typedef enum _FLASH2X_SECTION_VAL { - NO_SECTION_VAL = 0, //no section is choosen when absolute offset is given for RD/WR + NO_SECTION_VAL = 0, //no section is chosen when absolute offset is given for RD/WR ISO_IMAGE1, ISO_IMAGE2, DSD0, diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index f4cf41c0e46b..a55d4228e8e0 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -213,7 +213,7 @@ static VOID CheckAndSendPacketFromIndex(PMINI_ADAPTER Adapter, PacketInfo *psSF) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", psSF->uiCurrentTokenCount, iPacketLen); - //this part indicates that becuase of non-availability of the tokens + //this part indicates that because of non-availability of the tokens //pkt has not been send out hence setting the pending flag indicating the host to send it out //first next iteration . psSF->uiPendedLast = TRUE; diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index d624f35d0551..c5003b62234c 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -602,7 +602,7 @@ VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) Adapter->LinkStatus=LINKUP_DONE; Adapter->bPHSEnabled = *(pucBuffer+3); Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Recieved In LinkUp Ack : %x \n",Adapter->bPHSEnabled); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x \n",Adapter->bPHSEnabled); if((FALSE == Adapter->bShutStatus)&& (FALSE == Adapter->IdleMode)) { @@ -1153,7 +1153,7 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) /* * 1. If the LED Settings fails, do not stop and do the Firmware download. - * 2. This init would happend only if the cfg file is present, else + * 2. This init would happened only if the cfg file is present, else * call from the ioctl context. */ @@ -1185,7 +1185,7 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) status = PropagateCalParamsFromFlashToMemory(ps_adapter); if(status) { - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propogation of Cal param failed .." ); + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propagation of Cal param failed .." ); goto OUT; } } diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c index feade9451b2e..c97020f0fb6a 100644 --- a/drivers/staging/bcm/Qos.c +++ b/drivers/staging/bcm/Qos.c @@ -727,7 +727,7 @@ static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct s BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID); - /* In case FW didn't recieve the TLV, the priority field should be ignored */ + /* In case FW didn't receive the TLV, the priority field should be ignored */ if(pstClassifierRule->usValidityBitMap & (1<eNwpktEthFrameType!=eEth802QVLANFrame) diff --git a/drivers/staging/bcm/cntrl_SignalingInterface.h b/drivers/staging/bcm/cntrl_SignalingInterface.h index 890778450a86..ab131806e2c9 100644 --- a/drivers/staging/bcm/cntrl_SignalingInterface.h +++ b/drivers/staging/bcm/cntrl_SignalingInterface.h @@ -21,7 +21,7 @@ #define VENDOR_PHS_PARAM_LENGTH 10 #define MAX_NUM_ACTIVE_BS 10 #define AUTH_TOKEN_LENGTH 10 -#define NUM_HARQ_CHANNELS 16 //Changed from 10 to 16 to accomodate all HARQ channels +#define NUM_HARQ_CHANNELS 16 //Changed from 10 to 16 to accommodate all HARQ channels #define VENDOR_CLASSIFIER_PARAM_LENGTH 1 //Changed the size to 1 byte since we dnt use it #define VENDOR_SPECIF_QOS_PARAM 1 #define VENDOR_PHS_PARAM_LENGTH 10 @@ -109,13 +109,13 @@ typedef struct _stPhsRuleSI { B_UINT8 u8PHSI; /** PHSF Length Of The Service Flow*/ B_UINT8 u8PHSFLength; - /** String of bytes containing header information to be supressed by the sending CS and reconstructed by the receiving CS*/ + /** String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS*/ B_UINT8 u8PHSF[MAX_PHS_LENGTHS]; /** PHSM Length Of The Service Flow*/ B_UINT8 u8PHSMLength; /** PHS Mask for the SF*/ B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; - /** 8bit Total number of bytes to be supressed for the Service Flow*/ + /** 8bit Total number of bytes to be suppressed for the Service Flow*/ B_UINT8 u8PHSS; /** 8bit Indicates whether or not Packet Header contents need to be verified prior to supression */ B_UINT8 u8PHSV; diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index c7292373a65f..4da5b7b54a1a 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -313,7 +313,7 @@ INT ReadMacAddressFromNVM(PMINI_ADAPTER Adapter) // uiNumBytes - Number of bytes to be read from the EEPROM. // // Returns: -// OSAL_STATUS_SUCCESS - if EEPROM read is successfull. +// OSAL_STATUS_SUCCESS - if EEPROM read is successful. // - if failed. //----------------------------------------------------------------------------- @@ -431,7 +431,7 @@ INT BeceemEEPROMBulkRead( // uiNumBytes - Number of bytes to be read from the FLASH. // // Returns: -// OSAL_STATUS_SUCCESS - if FLASH read is successfull. +// OSAL_STATUS_SUCCESS - if FLASH read is successful. // - if failed. //----------------------------------------------------------------------------- @@ -1174,7 +1174,7 @@ static INT BeceemFlashBulkWrite( if(NULL == pTempBuff) goto BeceemFlashBulkWrite_EXIT; // -// check if the data to be written is overlapped accross sectors +// check if the data to be written is overlapped across sectors // if(uiOffset+uiNumBytes < uiSectBoundary) { @@ -1390,7 +1390,7 @@ static INT BeceemFlashBulkWriteStatus( goto BeceemFlashBulkWriteStatus_EXIT; // -// check if the data to be written is overlapped accross sectors +// check if the data to be written is overlapped across sectors // if(uiOffset+uiNumBytes < uiSectBoundary) { @@ -2020,7 +2020,7 @@ INT BeceemEEPROMBulkWrite( // uiNumBytes - Number of bytes to be read from the NVM. // // Returns: -// OSAL_STATUS_SUCCESS - if NVM read is successfull. +// OSAL_STATUS_SUCCESS - if NVM read is successful. // - if failed. //----------------------------------------------------------------------------- @@ -2083,7 +2083,7 @@ INT BeceemNVMRead( // uiNumBytes - Number of bytes to be written.. // // Returns: -// OSAL_STATUS_SUCCESS - if NVM write is successfull. +// OSAL_STATUS_SUCCESS - if NVM write is successful. // - if failed. //----------------------------------------------------------------------------- @@ -2218,7 +2218,7 @@ INT BeceemNVMWrite( // uiSectorSize - sector size // // Returns: -// OSAL_STATUS_SUCCESS - if NVM write is successfull. +// OSAL_STATUS_SUCCESS - if NVM write is successful. // - if failed. //----------------------------------------------------------------------------- @@ -2430,7 +2430,7 @@ INT BcmInitNVM(PMINI_ADAPTER ps_adapter) *Input Parameter: * Adapter data structure *Return Value : -* 0. means sucess; +* 0. means success; */ /***************************************************************************/ @@ -2998,7 +2998,7 @@ INT BcmGetSectionValStartOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlas /* * Considering all the section for which end offset can be calculated or directly given * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section - * endoffset can't be calculated or given in CS Stucture. + * endoffset can't be calculated or given in CS Structure. */ INT SectStartOffset = 0 ; @@ -3173,7 +3173,7 @@ INT BcmGetSectionValEndOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2 * @uiNumBytes : Number of Bytes for Read * * Return value:- -* return true on sucess and STATUS_FAILURE on fail. +* return true on success and STATUS_FAILURE on fail. */ INT BcmFlash2xBulkRead( @@ -3241,7 +3241,7 @@ INT BcmFlash2xBulkRead( * @uiNumBytes : Number of Bytes for Write * * Return value:- -* return true on sucess and STATUS_FAILURE on fail. +* return true on success and STATUS_FAILURE on fail. * */ @@ -3308,7 +3308,7 @@ INT BcmFlash2xBulkWrite( * @Adapter :-Drivers private Data Structure * * Return Value:- -* Return STATUS_SUCESS if get sucess in setting the right DSD else negaive error code +* Return STATUS_SUCESS if get success in setting the right DSD else negaive error code * **/ static INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) @@ -3384,7 +3384,7 @@ static INT BcmGetActiveISO(PMINI_ADAPTER Adapter) * @uiOffset : Offset provided in the Flash * * Return Value:- -* Sucess:-TRUE , offset is writable +* Success:-TRUE , offset is writable * Failure:-FALSE, offset is RO * **/ @@ -3441,7 +3441,7 @@ static INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) @Adapter:-Driver private Data Structure * * Return value:- -* Sucess:- STATUS_SUCESS +* Success:- STATUS_SUCESS * Failure:- negative error code **/ @@ -3783,7 +3783,7 @@ INT BcmSetActiveSection(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectV // This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. // We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO // by user - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happend, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); SectImagePriority = htonl(0x1); Status = BcmFlash2xBulkWrite(Adapter, &SectImagePriority, @@ -3853,7 +3853,7 @@ INT BcmSetActiveSection(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectV // This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. // We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD // by user - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happend, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); SectImagePriority = htonl(0x1); Status = BcmFlash2xBulkWrite(Adapter, @@ -4119,7 +4119,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) MAX_RW_SIZE); IsThisHeaderSector = FALSE ; } - //substracting the written Data + //subtracting the written Data uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ; } @@ -4250,7 +4250,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) IsThisHeaderSector = FALSE ; } - //substracting the written Data + //subtracting the written Data uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ; } @@ -4268,7 +4268,7 @@ BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header @eFlash2xSectionVal :- Flash section val which has header Return Value :- - Sucess :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS + Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS Failure :-Return negative error code @@ -4301,7 +4301,7 @@ BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has @eFlashSectionVal :- Flash section val which has header Return Value :- - Sucess :- If Section is present and writable write the sig and return STATUS_SUCCESS + Success :- If Section is present and writable write the sig and return STATUS_SUCCESS Failure :-Return negative error code **/ @@ -4504,7 +4504,7 @@ BcmCopySection :- This API is used to copy the One section in another. Both sect in case of numofBytes equal zero complete section will be copied. Return Values- - Sucess : Return STATUS_SUCCESS + Success : Return STATUS_SUCCESS Faillure :- return negative error code **/ @@ -4621,7 +4621,7 @@ SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header S @uiOffset :- Flash offset that has to be written. Return value :- - Sucess :- On sucess return STATUS_SUCCESS + Success :- On success return STATUS_SUCCESS Faillure :- Return negative error code **/ @@ -4634,7 +4634,7 @@ INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) UINT uiSectAlignAddr = 0; UINT sig = 0; - //making the offset sector alligned + //making the offset sector aligned uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); @@ -4643,7 +4643,7 @@ INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD0)- Adapter->uiSectorSize)) { - //offset from the sector boundry having the header map + //offset from the sector boundary having the header map offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize; HeaderSizeToProtect = sizeof(DSD_HEADER); bHasHeader = TRUE ; @@ -4697,7 +4697,7 @@ BcmDoChipSelect : This will selcet the appropriate chip for writing. @Adapater :- Bcm Driver Private Data Structure OutPut:- - Select the Appropriate chip and retrn status Sucess + Select the Appropriate chip and retrn status Success **/ static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) { @@ -5086,7 +5086,7 @@ static INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSect { if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence cant Corrupt signature"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Corrupt signature"); return SECTOR_IS_NOT_WRITABLE; } } @@ -5155,7 +5155,7 @@ static INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSect if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence cant Corrupt signature"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Corrupt signature"); return SECTOR_IS_NOT_WRITABLE; } diff --git a/drivers/staging/brcm80211/README b/drivers/staging/brcm80211/README index 99e67669f26b..f8facb0786ec 100644 --- a/drivers/staging/brcm80211/README +++ b/drivers/staging/brcm80211/README @@ -71,7 +71,7 @@ the driver. The devices use a single worldwide regulatory domain, with channels passive operation. Transmission on those channels is suppressed until appropriate other traffic is observed on those channels. -Within the driver, we use the ficticious country code "X2" to represent this +Within the driver, we use the fictitious country code "X2" to represent this worldwide regulatory domain. There is currently no interface to configure a different domain. diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 65313fa0cf4a..71c3571ee143 100644 --- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -264,7 +264,7 @@ extern SDIOH_API_RC sdioh_disable_func_intr(void) } #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ -/* Configure callback to client when we recieve client interrupt */ +/* Configure callback to client when we receive client interrupt */ extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) { diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c index cbfa1c1b7059..1cf6c5dc2bb7 100644 --- a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c +++ b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c @@ -46,7 +46,7 @@ extern int sdioh_mmc_irq(int irq); #include #endif -/* Customer specific Host GPIO defintion */ +/* Customer specific Host GPIO definition */ static int dhd_oob_gpio_num = -1; /* GG 19 */ module_param(dhd_oob_gpio_num, int, 0644); diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c index 02c6d446934c..dd0375793875 100644 --- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c @@ -478,7 +478,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) dhd_set_packet_filter(1, dhd); /* if dtim skip setup as default force it - * to wake each thrid dtim + * to wake each third dtim * for better power saving. * Note that side effect is chance to miss BC/MC * packet diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c index 106627040db0..464f52af1315 100644 --- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c @@ -3659,7 +3659,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) * control pkt receives. * Later we use buffer-poll for data as well * as control packets. - * This is required becuase dhd receives full + * This is required because dhd receives full * frame in gSPI unlike SDIO. * After the frame is received we have to * distinguish whether it is data @@ -3744,7 +3744,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) bus->dhd->rx_errors++; dhd_os_sdunlock_rxq(bus->dhd); /* Force retry w/normal header read. - * Don't attemp NAK for + * Don't attempt NAK for * gSPI */ dhdsdio_rxfail(bus, true, diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c index 774b4e916b29..c1b07ae31674 100644 --- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c +++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c @@ -1079,7 +1079,7 @@ static int ieee_hw_init(struct ieee80211_hw *hw) */ hw->max_rates = 2; /* Primary rate and 1 fallback rate */ - hw->channel_change_time = 7 * 1000; /* channel change time is dependant on chip and band */ + hw->channel_change_time = 7 * 1000; /* channel change time is dependent on chip and band */ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); hw->rate_control_algorithm = "minstrel_ht"; diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c index c6cdcd940956..f00865957881 100644 --- a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c +++ b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c @@ -89,7 +89,7 @@ u32 wl_ampdu_dbg = /* structure to hold tx fifo information and pre-loading state * counters specific to tx underflows of ampdus * some counters might be redundant with the ones in wlc or ampdu structures. - * This allows to maintain a specific state independantly of + * This allows to maintain a specific state independently of * how often and/or when the wlc counters are updated. */ typedef struct wlc_fifo_info { @@ -265,7 +265,7 @@ static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb) scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu; - /* go back to legacy size if some preloading is occuring */ + /* go back to legacy size if some preloading is occurring */ for (i = 0; i < NUM_FFPLD_FIFO; i++) { if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR) scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY; @@ -406,7 +406,7 @@ static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid) /* compute a new dma xfer rate for max_mpdu @ max mcs. This is the minimum dma rate that - can acheive no unferflow condition for the current mpdu size. + can achieve no unferflow condition for the current mpdu size. */ /* note : we divide/multiply by 100 to avoid integer overflows */ fifo->dmaxferrate = diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c index 5a96dc3cdb36..4b6e181c7dc9 100644 --- a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c +++ b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c @@ -1915,7 +1915,7 @@ void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw) phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi); - /* Specfic reset sequence required for NPHY rev 3 and 4 */ + /* Specific reset sequence required for NPHY rev 3 and 4 */ if (WLCISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && NREV_LE(wlc_hw->band->phyrev, 4)) { /* Set the PHY bandwidth */ diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c index 639b5d7c9603..717fced45801 100644 --- a/drivers/staging/brcm80211/brcmsmac/wlc_main.c +++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.c @@ -8295,7 +8295,7 @@ wlc_txflowcontrol_prio_isset(struct wlc_info *wlc, struct wlc_txq_info *q, return (q->stopped & prio_mask) == prio_mask; } -/* propogate the flow control to all interfaces using the given tx queue */ +/* propagate the flow control to all interfaces using the given tx queue */ void wlc_txflowcontrol(struct wlc_info *wlc, struct wlc_txq_info *qi, bool on, int prio) { @@ -8462,7 +8462,7 @@ static void wlc_txq_free(struct wlc_info *wlc, struct wlc_txq_info *qi) } /* - * Flag 'scan in progress' to withold dynamic phy calibration + * Flag 'scan in progress' to withhold dynamic phy calibration */ void wlc_scan_start(struct wlc_info *wlc) { diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_rate.c b/drivers/staging/brcm80211/brcmsmac/wlc_rate.c index 0cfa36023cf1..d284f1ac49cc 100644 --- a/drivers/staging/brcm80211/brcmsmac/wlc_rate.c +++ b/drivers/staging/brcm80211/brcmsmac/wlc_rate.c @@ -332,7 +332,7 @@ wlc_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs, return false; } -/* caluclate the rate of a rx'd frame and return it as a ratespec */ +/* calculate the rate of a rx'd frame and return it as a ratespec */ ratespec_t BCMFASTPATH wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp) { int phy_type; diff --git a/drivers/staging/brcm80211/include/bcmsrom_fmt.h b/drivers/staging/brcm80211/include/bcmsrom_fmt.h index ae2bff828607..4768968f910a 100644 --- a/drivers/staging/brcm80211/include/bcmsrom_fmt.h +++ b/drivers/staging/brcm80211/include/bcmsrom_fmt.h @@ -103,7 +103,7 @@ #define SROM_CRCREV 63 -/* SROM Rev 4: Reallocate the software part of the srom to accomodate +/* SROM Rev 4: Reallocate the software part of the srom to accommodate * MIMO features. It assumes up to two PCIE functions and 440 bytes * of useable srom i.e. the useable storage in chips with OTP that * implements hardware redundancy. diff --git a/drivers/staging/brcm80211/include/hndsoc.h b/drivers/staging/brcm80211/include/hndsoc.h index 9747cc46ca96..6435686b329f 100644 --- a/drivers/staging/brcm80211/include/hndsoc.h +++ b/drivers/staging/brcm80211/include/hndsoc.h @@ -181,7 +181,7 @@ * conventions for the use the flash space: */ -/* Minumum amount of flash we support */ +/* Minimum amount of flash we support */ #define FLASH_MIN 0x00020000 /* Minimum flash size */ /* A boot/binary may have an embedded block that describes its size */ diff --git a/drivers/staging/brcm80211/util/bcmotp.c b/drivers/staging/brcm80211/util/bcmotp.c index ba71c108b366..17991212a22d 100644 --- a/drivers/staging/brcm80211/util/bcmotp.c +++ b/drivers/staging/brcm80211/util/bcmotp.c @@ -213,7 +213,7 @@ static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off) return (int)st; } -/* Calculate max HW/SW region byte size by substracting fuse region and checksum size, +/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size, * osizew is oi->wsize (OTP size - GU size) in words */ static int ipxotp_max_rgnsz(si_t *sih, int osizew) @@ -229,7 +229,7 @@ static int ipxotp_max_rgnsz(si_t *sih, int osizew) ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; break; default: - ASSERT(0); /* Don't konw about this chip */ + ASSERT(0); /* Don't know about this chip */ } return ret; diff --git a/drivers/staging/brcm80211/util/bcmsrom.c b/drivers/staging/brcm80211/util/bcmsrom.c index eca35b94e96c..850bfa6593e0 100644 --- a/drivers/staging/brcm80211/util/bcmsrom.c +++ b/drivers/staging/brcm80211/util/bcmsrom.c @@ -1859,7 +1859,7 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count) /* * Apply CRC over SROM content regardless SROM is present or not, - * and use variable sromrev's existance in flash to decide + * and use variable sromrev's existence in flash to decide * if we should return an error when CRC fails or read SROM variables * from flash. */ diff --git a/drivers/staging/brcm80211/util/hnddma.c b/drivers/staging/brcm80211/util/hnddma.c index 8a81eb997f99..be339feae77d 100644 --- a/drivers/staging/brcm80211/util/hnddma.c +++ b/drivers/staging/brcm80211/util/hnddma.c @@ -1179,7 +1179,7 @@ static void BCMFASTPATH dma64_txreclaim(dma_info_t *di, txd_range_t range) (range == HNDDMA_RANGE_ALL) ? "all" : ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : - "transfered"))); + "transferred"))); if (di->txin == di->txout) return; @@ -1549,7 +1549,7 @@ static int BCMFASTPATH dma64_txfast(dma_info_t *di, struct sk_buff *p0, * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be * transmitted as noted by the hardware "CurrDescr" pointer. * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be - * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. + * transferred by the DMA as noted by the hardware "ActiveDescr" pointer. * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and * return associated packet regardless of the value of hardware pointers. */ @@ -1563,7 +1563,7 @@ static void *BCMFASTPATH dma64_getnexttxp(dma_info_t *di, txd_range_t range) (range == HNDDMA_RANGE_ALL) ? "all" : ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : - "transfered"))); + "transferred"))); if (di->ntxd == 0) return NULL; diff --git a/drivers/staging/brcm80211/util/sbpcmcia.h b/drivers/staging/brcm80211/util/sbpcmcia.h index 6b9923f551a9..d4c156586e81 100644 --- a/drivers/staging/brcm80211/util/sbpcmcia.h +++ b/drivers/staging/brcm80211/util/sbpcmcia.h @@ -109,7 +109,7 @@ #define CISTPL_CFTABLE 0x1b /* Config table entry */ #define CISTPL_END 0xff /* End of the CIS tuple chain */ -/* Function identifier provides context for the function extentions tuple */ +/* Function identifier provides context for the function extensions tuple */ #define CISTPL_FID_SDIO 0x0c /* Extensions defined by SDIO spec */ /* Function extensions for LANs (assumed for extensions other than SDIO) */ diff --git a/drivers/staging/brcm80211/util/siutils.c b/drivers/staging/brcm80211/util/siutils.c index ed168ceba5f0..6ebd7f58af81 100644 --- a/drivers/staging/brcm80211/util/siutils.c +++ b/drivers/staging/brcm80211/util/siutils.c @@ -1319,7 +1319,7 @@ int si_clkctl_xtal(si_t *sih, uint what, bool on) } /* - * clock control policy function throught chipcommon + * clock control policy function through chipcommon * * set dynamic clk control mode (forceslow, forcefast, dynamic) * returns true if we are forcing fast clock diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index a4ceb29c358e..e7e72b8d8cde 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2064,7 +2064,7 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) COMEDI_CB_OVERFLOW)) { runflags_mask |= SRF_RUNNING; } - /* remember if an error event has occured, so an error + /* remember if an error event has occurred, so an error * can be returned the next time the user does a read() */ if (s->async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) { runflags_mask |= SRF_ERROR; diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c index 644bda44556e..482a412aa652 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c @@ -124,9 +124,9 @@ You should also find the complete GPL in the COPYING file accompanying this sour | -5: The selected PCI input clock is wrong | | -6: Timing unity selection is wrong | | -7: Base timing selection is wrong | -| -8: You can not used the 40MHz clock selection wich | +| -8: You can not used the 40MHz clock selection with | | this board | -| -9: You can not used the 40MHz clock selection wich | +| -9: You can not used the 40MHz clock selection with | | this CHRONOS version | +----------------------------------------------------------------------------+ */ @@ -721,10 +721,10 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_sub } } else { /**************************************************************/ - /* You can not used the 40MHz clock selection wich this board */ + /* You can not use the 40MHz clock selection with this board */ /**************************************************************/ - DPRINTK("You can not used the 40MHz clock selection wich this board\n"); + DPRINTK("You can not used the 40MHz clock selection with this board\n"); i_ReturnValue = -8; } diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c index 90e71e12784a..b973095146f9 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c @@ -59,7 +59,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour /*+----------------------------------------------------------------------------+*/ /*| Input Parameters : int i_NbOfWordsToRead : Nbr. of word to read |*/ /*| unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/ -/*| unsigned short w_EepromStartAddress : Eeprom strat address |*/ +/*| unsigned short w_EepromStartAddress : Eeprom start address |*/ /*+----------------------------------------------------------------------------+*/ /*| Output Parameters : unsigned short * pw_DataRead : Read data |*/ /*+----------------------------------------------------------------------------+*/ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c index 9dd857df93c8..002297dfe33f 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c @@ -498,7 +498,7 @@ void v_APCI2032_Interrupt(int irq, void *d) struct comedi_device *dev = d; unsigned int ui_DO; - ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; /* Check if VCC OR CC interrupt has occured. */ + ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; /* Check if VCC OR CC interrupt has occurred. */ if (ui_DO == 0) { printk("\nInterrupt from unKnown source\n"); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index a813fdbbd96e..fc61214151b7 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -148,7 +148,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd unsigned short us_ConvertTiming, us_TmpValue, i; unsigned char b_Tmp; - /* fix convertion time to 10 us */ + /* fix conversion time to 10 us */ if (!devpriv->ui_EocEosConversionTime) { printk("No timer0 Value using 10 us\n"); us_ConvertTiming = 10; @@ -251,7 +251,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd APCI3120_SELECT_TIMER_0_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - /* Set the convertion time */ + /* Set the conversion time */ outw(us_ConvertTiming, devpriv->iobase + APCI3120_TIMER_VALUE); @@ -311,7 +311,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd APCI3120_SELECT_TIMER_0_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - /* Set the convertion time */ + /* Set the conversion time */ outw(us_ConvertTiming, devpriv->iobase + APCI3120_TIMER_VALUE); @@ -354,9 +354,9 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd /* Start conversion */ outw(0, devpriv->iobase + APCI3120_START_CONVERSION); - /* Waiting of end of convertion if interrupt is not installed */ + /* Waiting of end of conversion if interrupt is not installed */ if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) { - /* Waiting the end of convertion */ + /* Waiting the end of conversion */ do { us_TmpValue = inw(devpriv->iobase + @@ -854,7 +854,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); - /* Set the convertion time */ + /* Set the conversion time */ outw(((unsigned short) ui_TimerValue0), dev->iobase + APCI3120_TIMER_VALUE); break; @@ -872,7 +872,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_1_WORD; outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); - /* Set the convertion time */ + /* Set the conversion time */ outw(((unsigned short) ui_TimerValue1), dev->iobase + APCI3120_TIMER_VALUE); @@ -889,7 +889,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev, APCI3120_SELECT_TIMER_0_WORD; outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); - /* Set the convertion time */ + /* Set the conversion time */ outw(((unsigned short) ui_TimerValue0), dev->iobase + APCI3120_TIMER_VALUE); break; @@ -1104,7 +1104,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev, /* * 4 - * amount of bytes to be transfered set transfer count used ADDON + * amount of bytes to be transferred set transfer count used ADDON * MWTC register commented testing * outl(devpriv->ui_DmaBufferUsesize[0], * devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h index b3c81979f14d..50eb0a0a0a05 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h @@ -169,7 +169,7 @@ struct str_AnalogReadInformation { unsigned char b_Type; /* EOC or EOS */ unsigned char b_InterruptFlag; /* Interrupt use or not */ - unsigned int ui_ConvertTiming; /* Selection of the convertion time */ + unsigned int ui_ConvertTiming; /* Selection of the conversion time */ unsigned char b_NbrOfChannel; /* Number of channel to read */ unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS]; /* Number of the channel to be read */ unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS]; /* Gain of each channel */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index a93e2349ad3a..c75a1a1fd775 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -103,7 +103,7 @@ struct str_BoardInfos s_BoardInfos[100]; /* 100 will be the max number of board /*+----------------------------------------------------------------------------+*/ /*| Input Parameters : int i_NbOfWordsToRead : Nbr. of word to read |*/ /*| unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/ -/*| unsigned short w_EepromStartAddress : Eeprom strat address |*/ +/*| unsigned short w_EepromStartAddress : Eeprom start address |*/ /*+----------------------------------------------------------------------------+*/ /*| Output Parameters : unsigned short * pw_DataRead : Read data |*/ /*+----------------------------------------------------------------------------+*/ @@ -849,7 +849,7 @@ int i_APCI3200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev | 0:Single Read | 1:Read more channel 2:Single scan - | 3:Continous Scan + | 3:Continuous Scan data[13] :Number of channels to read | data[14] :RTD connection type :0:RTD not used diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 766103c882ad..632d5d0721cd 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -23,7 +23,7 @@ For AI: - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46). - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44). - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46). -- It is not neccessary to have cmd.scan_end_arg=cmd.chanlist_len but +- It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but cmd.scan_end_arg modulo cmd.chanlist_len must by 0. - If return value of cmdtest is 5 then you've bad channel list (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar @@ -823,7 +823,7 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, move_block_from_dma(dev, s, devpriv->dmabuf_virt[devpriv->dma_actbuf], samplesinbuf); - m = m - sampls; /* m= how many samples was transfered */ + m = m - sampls; /* m= how many samples was transferred */ } /* DPRINTK("YYY\n"); */ @@ -1297,7 +1297,7 @@ static int Compute_and_setup_dma(struct comedi_device *dev) DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1); /* transfer without TRIG_WAKE_EOS */ if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) { - /* if it's possible then allign DMA buffers to length of scan */ + /* if it's possible then align DMA buffers to length of scan */ i = dmalen0; dmalen0 = (dmalen0 / (devpriv->ai_n_realscanlen << 1)) * diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 4b470000b69c..5361f318b010 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -65,7 +65,7 @@ If you do not specify any options, they will default to written by jeremy theler instituto balseiro - comision nacional de energia atomica + commission nacional de energia atomica universidad nacional de cuyo argentina @@ -342,7 +342,7 @@ static int adq12b_ai_rinsn(struct comedi_device *dev, /* convert n samples */ for (n = 0; n < insn->n; n++) { - /* wait for end of convertion */ + /* wait for end of conversion */ i = 0; do { /* udelay(1); */ diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 466e69f94ef2..da2b75b15d4e 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -98,7 +98,7 @@ Configuration options: #define Status_FE 0x0100 /* 1=FIFO is empty */ #define Status_FH 0x0200 /* 1=FIFO is half full */ #define Status_FF 0x0400 /* 1=FIFO is full, fatal error */ -#define Status_IRQ 0x0800 /* 1=IRQ occured */ +#define Status_IRQ 0x0800 /* 1=IRQ occurred */ /* bits from control register (PCI171x_CONTROL) */ #define Control_CNT0 0x0040 /* 1=CNT0 have external source, * 0=have internal 100kHz source */ @@ -1161,7 +1161,7 @@ static int check_channel_list(struct comedi_device *dev, } if (n_chan > 1) { - chansegment[0] = chanlist[0]; /* first channel is everytime ok */ + chansegment[0] = chanlist[0]; /* first channel is every time ok */ for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { /* build part of chanlist */ /* printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */ if (chanlist[0] == chanlist[i]) @@ -1176,9 +1176,9 @@ static int check_channel_list(struct comedi_device *dev, (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) nowmustbechan = (nowmustbechan + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */ + if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ printk - ("channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", + ("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", i, CR_CHAN(chanlist[i]), nowmustbechan, CR_CHAN(chanlist[0])); return 0; diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 0941643b3869..61968a505f24 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -115,7 +115,7 @@ analog triggering on 1602 series #define INT_MASK 0x3 /* mask of interrupt select bits */ #define INTE 0x4 /* interrupt enable */ #define DAHFIE 0x8 /* dac half full interrupt enable */ -#define EOAIE 0x10 /* end of aquisition interrupt enable */ +#define EOAIE 0x10 /* end of acquisition interrupt enable */ #define DAHFI 0x20 /* dac half full read status / write interrupt clear */ #define EOAI 0x40 /* read end of acq. interrupt status / write clear */ #define INT 0x80 /* read interrupt status / write clear */ @@ -440,7 +440,7 @@ struct cb_pcidas_private { unsigned int divisor1; unsigned int divisor2; volatile unsigned int count; /* number of analog input samples remaining */ - volatile unsigned int adc_fifo_bits; /* bits to write to interupt/adcfifo register */ + volatile unsigned int adc_fifo_bits; /* bits to write to interrupt/adcfifo register */ volatile unsigned int s5933_intcsr_bits; /* bits to write to amcc s5933 interrupt control/status register */ volatile unsigned int ao_control_bits; /* bits to write to ao control and status register */ short ai_buffer[AI_BUFFER_SIZE]; @@ -1653,7 +1653,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) spin_unlock_irqrestore(&dev->spinlock, flags); } else if (status & EOAI) { comedi_error(dev, - "bug! encountered end of aquisition interrupt?"); + "bug! encountered end of acquisition interrupt?"); /* clear EOA interrupt latch */ spin_lock_irqsave(&dev->spinlock, flags); outw(devpriv->adc_fifo_bits | EOAI, diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 2583e16cd02a..1e324198996c 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -104,7 +104,7 @@ TODO: #endif #define TIMER_BASE 25 /* 40MHz master clock */ -#define PRESCALED_TIMER_BASE 10000 /* 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday */ +#define PRESCALED_TIMER_BASE 10000 /* 100kHz 'prescaled' clock for slow acquisition, maybe I'll support this someday */ #define DMA_BUFFER_SIZE 0x1000 #define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307 @@ -136,7 +136,7 @@ enum write_only_registers { ADC_DELAY_INTERVAL_UPPER_REG = 0x1c, /* upper 8 bits of delay interval counter */ ADC_COUNT_LOWER_REG = 0x1e, /* lower 16 bits of hardware conversion/scan counter */ ADC_COUNT_UPPER_REG = 0x20, /* upper 8 bits of hardware conversion/scan counter */ - ADC_START_REG = 0x22, /* software trigger to start aquisition */ + ADC_START_REG = 0x22, /* software trigger to start acquisition */ ADC_CONVERT_REG = 0x24, /* initiates single conversion */ ADC_QUEUE_CLEAR_REG = 0x26, /* clears adc queue */ ADC_QUEUE_LOAD_REG = 0x28, /* loads adc queue */ @@ -199,7 +199,7 @@ enum intr_enable_contents { ADC_INTR_EOSCAN_BITS = 0x2, /* interrupt end of scan */ ADC_INTR_EOSEQ_BITS = 0x3, /* interrupt end of sequence (probably wont use this it's pretty fancy) */ EN_ADC_INTR_SRC_BIT = 0x4, /* enable adc interrupt source */ - EN_ADC_DONE_INTR_BIT = 0x8, /* enable adc aquisition done interrupt */ + EN_ADC_DONE_INTR_BIT = 0x8, /* enable adc acquisition done interrupt */ DAC_INTR_SRC_MASK = 0x30, DAC_INTR_QEMPTY_BITS = 0x0, DAC_INTR_HIGH_CHAN_BITS = 0x10, @@ -2867,7 +2867,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) spin_unlock_irqrestore(&dev->spinlock, flags); - /* start aquisition */ + /* start acquisition */ if (cmd->start_src == TRIG_NOW) { writew(0, priv(dev)->main_iobase + ADC_START_REG); DEBUG_PRINT("soft trig\n"); @@ -2942,7 +2942,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) /* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of pointers. * The pci-4020 hardware only supports * dma transfers (it only supports the use of pio for draining the last remaining - * points from the fifo when a data aquisition operation has completed). + * points from the fifo when a data acquisition operation has completed). */ static void pio_drain_ai_fifo_32(struct comedi_device *dev) { @@ -3046,7 +3046,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, comedi_error(dev, "fifo overrun"); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; } - /* spin lock makes sure noone else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); if (plx_status & ICS_DMA1_A) { /* dma chan 1 interrupt */ @@ -3170,7 +3170,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, async = s->async; cmd = &async->cmd; - /* spin lock makes sure noone else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); if (plx_status & ICS_DMA0_A) { /* dma chan 0 interrupt */ diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index b220b3055412..a804742b8022 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -81,7 +81,7 @@ static const struct waveform_board waveform_boards[] = { /* Data unique to this driver */ struct waveform_private { struct timer_list timer; - struct timeval last; /* time at which last timer interrupt occured */ + struct timeval last; /* time at which last timer interrupt occurred */ unsigned int uvolt_amplitude; /* waveform amplitude in microvolts */ unsigned long usec_period; /* waveform period in microseconds */ unsigned long usec_current; /* current time (modulo waveform period) */ diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 6ea93f9c0b48..60c2b12d6ffb 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1087,7 +1087,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev, return; } -/* flushes remaining data from board when external trigger has stopped aquisition +/* flushes remaining data from board when external trigger has stopped acquisition * and we are using dma transfers */ static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s) diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index aecaedc5027e..96d41ad76956 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -391,7 +391,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) spin_lock_irqsave(&dev->spinlock, irq_flags); outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select base address + 7 to be STATUS2 register */ status = inb(dev->iobase + DAS800_STATUS2) & STATUS2_HCEN; - /* don't release spinlock yet since we want to make sure noone else disables hardware conversions */ + /* don't release spinlock yet since we want to make sure no one else disables hardware conversions */ if (status == 0) { spin_unlock_irqrestore(&dev->spinlock, irq_flags); return IRQ_HANDLED; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 693728e14bdb..2b4e6e6eb825 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -532,7 +532,7 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, msb = dmm_inb(dev, DMM32AT_AIMSB); /* invert sign bit to make range unsigned, this is an - idiosyncracy of the diamond board, it return + idiosyncrasy of the diamond board, it return conversions as a signed value, i.e. -32768 to 32767, flipping the bit and interpreting it as signed gives you a range of 0 to 65535 which is diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index a1664caa1d96..0131d5225b52 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -560,7 +560,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig) switch (dev->i_admode) { case COMEDI_MDEMAND: dev->ntrig = adtrig->n - 1; - /* not neccessary */ + /* not necessary */ /*printk("dt2811: AD soft trigger\n"); */ /*outb(DT2811_CLRERROR|DT2811_INTENB, dev->iobase+DT2811_ADCSR); */ diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 06059850dae2..32d9c42e9659 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -773,7 +773,7 @@ static int dt9812_probe(struct usb_interface *interface, retval = dt9812_read_info(dev, 1, &fw, sizeof(fw)); if (retval == 0) { dev_info(&interface->dev, - "usb_reset_configuration succeded " + "usb_reset_configuration succeeded " "after %d iterations\n", i); break; } diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 1661b57ca2ad..bc020dea141b 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -1031,7 +1031,7 @@ static irqreturn_t handle_interrupt(int irq, void *d) writel(hpdi_intr_status, priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG); } - /* spin lock makes sure noone else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); if (plx_status & ICS_DMA0_A) { /* dma chan 0 interrupt */ @@ -1045,7 +1045,7 @@ static irqreturn_t handle_interrupt(int irq, void *d) } spin_unlock_irqrestore(&dev->spinlock, flags); - /* spin lock makes sure noone else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); if (plx_status & ICS_DMA1_A) { /* XXX *//* dma chan 1 interrupt */ diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 0bab39b3409b..126550f3c02b 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -715,7 +715,7 @@ Description: is built correctly Parameters: - struct comedi_device *dev Pointer to current sevice structure + struct comedi_device *dev Pointer to current service structure struct comedi_subdevice *s Pointer to current subdevice structure unsigned int *chanlist Pointer to packed channel list unsigned int n_chan Number of channels to scan @@ -772,7 +772,7 @@ Description: Status register. Parameters: - struct comedi_device *dev Pointer to current sevice structure + struct comedi_device *dev Pointer to current service structure struct comedi_subdevice *s Pointer to current subdevice structure unsigned int *chanlist Pointer to packed channel list unsigned int n_chan Number of channels to scan @@ -848,7 +848,7 @@ Description: This function resets the icp multi device to a 'safe' state Parameters: - struct comedi_device *dev Pointer to current sevice structure + struct comedi_device *dev Pointer to current service structure Returns:int 0 = success diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 75511bae0191..b692fea0d2b0 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1810,7 +1810,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_AI_HF) { ISR_PDEBUG - ("me4000_ai_isr(): Fifo half full interrupt occured\n"); + ("me4000_ai_isr(): Fifo half full interrupt occurred\n"); /* Read status register to find out what happened */ tmp = me4000_inl(dev, ai_context->ctrl_reg); @@ -1903,7 +1903,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) if (me4000_inl(dev, ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) { ISR_PDEBUG - ("me4000_ai_isr(): Sample counter interrupt occured\n"); + ("me4000_ai_isr(): Sample counter interrupt occurred\n"); s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA; diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index a89eebd23f65..dd09a6d46e5c 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -39,8 +39,8 @@ Status: working Configuration Options: [0] - I/O base address - [1] - convertion rate - Convertion rate RMS noise Effective Number Of Bits + [1] - conversion rate + Conversion rate RMS noise Effective Number Of Bits 0 3.52kHz 23uV 17 1 1.76kHz 3.5uV 20 2 880Hz 2uV 21.3 @@ -93,8 +93,8 @@ Configuration Options: #define MPC624_DMY_BIT (1<<30) #define MPC624_SGN_BIT (1<<29) -/* Convertion speeds */ -/* OSR4 OSR3 OSR2 OSR1 OSR0 Convertion rate RMS noise ENOB^ +/* Conversion speeds */ +/* OSR4 OSR3 OSR2 OSR1 OSR0 Conversion rate RMS noise ENOB^ * X 0 0 0 1 3.52kHz 23uV 17 * X 0 0 1 0 1.76kHz 3.5uV 20 * X 0 0 1 1 880Hz 2uV 21.3 @@ -227,7 +227,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) break; default: printk - (KERN_ERR "illegal convertion rate setting!" + (KERN_ERR "illegal conversion rate setting!" " Valid numbers are 0..9. Using 9 => 6.875 Hz, "); devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; } @@ -296,7 +296,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, } for (n = 0; n < insn->n; n++) { - /* Trigger the convertion */ + /* Trigger the conversion */ outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); udelay(1); outb(MPC624_ADCS | MPC624_ADSCK, dev->iobase + MPC624_ADC); @@ -304,7 +304,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, outb(0, dev->iobase + MPC624_ADC); udelay(1); - /* Wait for the convertion to end */ + /* Wait for the conversion to end */ for (i = 0; i < TIMEOUT; i++) { ucPort = inb(dev->iobase + MPC624_ADC); if (ucPort & MPC624_ADBUSY) diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 4d0053ea2465..c192b71ec04f 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -104,10 +104,10 @@ TRIG_WAKE_EOS #define STATUS_REG 0x12 /* read only */ #define FNE_BIT 0x1 /* fifo not empty */ #define OVFL_BIT 0x8 /* fifo overflow */ -#define EDAQ_BIT 0x10 /* end of aquisition interrupt */ +#define EDAQ_BIT 0x10 /* end of acquisition interrupt */ #define DCAL_BIT 0x20 /* offset calibration in progress */ -#define INTR_BIT 0x40 /* interrupt has occured */ -#define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occured */ +#define INTR_BIT 0x40 /* interrupt has occurred */ +#define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occurred */ #define ID_BITS(x) (((x) >> 8) & 0x3) #define IRQ_DMA_CNTRL_REG 0x12 /* write only */ #define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */ @@ -434,7 +434,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = a2150_cancel; /* need to do this for software counting of completed conversions, to - * prevent hardware count from stopping aquisition */ + * prevent hardware count from stopping acquisition */ outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG); /* set card's irq and dma levels */ @@ -729,7 +729,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* send trigger config bits */ outw(trigger_bits, dev->iobase + TRIGGER_REG); - /* start aquisition for soft trigger */ + /* start acquisition for soft trigger */ if (cmd->start_src == TRIG_NOW) { outw(0, dev->iobase + FIFO_START_REG); } @@ -768,7 +768,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, /* setup start triggering */ outw(0, dev->iobase + TRIGGER_REG); - /* start aquisition for soft trigger */ + /* start acquisition for soft trigger */ outw(0, dev->iobase + FIFO_START_REG); /* there is a 35.6 sample delay for data to get through the antialias filter */ diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 241fe525abf0..ab8f37022a3c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -183,11 +183,11 @@ NI manuals: #define OVERRUN_BIT 0x2 /* fifo overflow */ #define OVERFLOW_BIT 0x4 -/* timer interrupt has occured */ +/* timer interrupt has occurred */ #define TIMER_BIT 0x8 -/* dma terminal count has occured */ +/* dma terminal count has occurred */ #define DMATC_BIT 0x10 -/* external trigger has occured */ +/* external trigger has occurred */ #define EXT_TRIG_BIT 0x40 /* 1200 boards only */ #define STATUS2_REG 0x1d @@ -1149,7 +1149,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) range = CR_RANGE(cmd->chanlist[0]); aref = CR_AREF(cmd->chanlist[0]); - /* make sure board is disabled before setting up aquisition */ + /* make sure board is disabled before setting up acquisition */ spin_lock_irqsave(&dev->spinlock, flags); devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); @@ -1349,7 +1349,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT; devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); - /* startup aquisition */ + /* startup acquisition */ /* command2 reg */ /* use 2 cascaded counters for pacing */ @@ -1571,8 +1571,8 @@ static void handle_isa_dma(struct comedi_device *dev) devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG); } -/* makes sure all data acquired by board is transfered to comedi (used - * when aquisition is terminated by stop_src == TRIG_EXT). */ +/* makes sure all data acquired by board is transferred to comedi (used + * when acquisition is terminated by stop_src == TRIG_EXT). */ static void labpc_drain_dregs(struct comedi_device *dev) { if (devpriv->current_transfer == isa_dma_transfer) diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 005d2fe86ee4..8dd3a01d48dd 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -821,7 +821,7 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, cmd->scan_begin_arg = MAX_SPEED; err++; } - /* no minumum speed */ + /* no minimum speed */ } else { /* TRIG_EXT */ /* should be level/edge, hi/lo specification here */ diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index c6dce4a1425e..09ff4723b225 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -34,7 +34,7 @@ * and I cann't test all features.) * * This driver supports insn and cmd interfaces. Some boards support only insn - * becouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). + * because their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). * Data transfer over DMA is supported only when you measure only one * channel, this is too hardware limitation of these boards. * diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index ef3cc4f3be6e..8f3fc6ee088b 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -954,7 +954,7 @@ check_channel_list(struct comedi_device *dev, } if (chanlen > 1) { - /* first channel is everytime ok */ + /* first channel is every time ok */ chansegment[0] = chanlist[0]; for (i = 1, seglen = 1; i < chanlen; i++, seglen++) { /* build part of chanlist */ @@ -968,10 +968,10 @@ check_channel_list(struct comedi_device *dev, nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; if (nowmustbechan != CR_CHAN(chanlist[i])) { - /* channel list isn't continous :-( */ + /* channel list isn't continuous :-( */ printk(KERN_WARNING "comedi%d: pcl816: channel list must " - "be continous! chanlist[%i]=%d but " + "be continuous! chanlist[%i]=%d but " "must be %d or %d!\n", dev->minor, i, CR_CHAN(chanlist[i]), nowmustbechan, CR_CHAN(chanlist[0])); diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index f58d75be7295..e3eea09ae1fb 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1231,7 +1231,7 @@ static int check_channel_list(struct comedi_device *dev, } if (n_chan > 1) { - /* first channel is everytime ok */ + /* first channel is every time ok */ chansegment[0] = chanlist[0]; /* build part of chanlist */ for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { @@ -1245,9 +1245,9 @@ static int check_channel_list(struct comedi_device *dev, break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */ + if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ printk - ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", + ("comedi%d: pcl818: channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", dev->minor, i, CR_CHAN(chanlist[i]), nowmustbechan, CR_CHAN(chanlist[0])); return 0; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 5c832d7ed45d..f2e88e57d558 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -733,7 +733,7 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev, break; case INSN_CONFIG_DIO_QUERY: - /* retreive from shadow register */ + /* retrieve from shadow register */ data[1] = (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; @@ -1279,7 +1279,7 @@ static int wait_dac_ready(unsigned long iobase) "no busy waiting" policy. The fact is that the hardware is normally so fast that we usually only need one time through the loop anyway. The longer timeout is for rare occasions and for detecting - non-existant hardware. */ + non-existent hardware. */ while (retry--) { if (inb(iobase + 3) & 0x80) diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 7a9287433b2e..b2c2c8971a32 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -605,7 +605,7 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev, break; case INSN_CONFIG_DIO_QUERY: - /* retreive from shadow register */ + /* retrieve from shadow register */ data[1] = (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index ebba9bb47777..82942e5728a5 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -390,7 +390,7 @@ static int daqp_ai_insn_read(struct comedi_device *dev, outb(v, dev->iobase + DAQP_CONTROL); - /* Reset any pending interrupts (my card has a tendancy to require + /* Reset any pending interrupts (my card has a tendency to require * require multiple reads on the status register to achieve this) */ @@ -752,7 +752,7 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outb(v, dev->iobase + DAQP_CONTROL); - /* Reset any pending interrupts (my card has a tendancy to require + /* Reset any pending interrupts (my card has a tendency to require * require multiple reads on the status register to achieve this) */ counter = 100; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 357858d27441..7f09ed755fe6 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -75,7 +75,7 @@ Configuration options: das1800, since they have the best documented code. Driver cb_pcidas64.c uses the same DMA controller. - As far as I can tell, the About interrupt doesnt work if Sample is + As far as I can tell, the About interrupt doesn't work if Sample is also enabled. It turns out that About really isn't needed, since we always count down samples read. @@ -370,7 +370,7 @@ struct rtdPrivate { /* timer gate (when enabled) */ u8 utcGate[4]; /* 1 extra allows simple range check */ - /* shadow registers affect other registers, but cant be read back */ + /* shadow registers affect other registers, but can't be read back */ /* The macros below update these on writes */ u16 intMask; /* interrupt mask */ u16 intClearMask; /* interrupt clear mask */ @@ -485,7 +485,7 @@ struct rtdPrivate { #define RtdAdcFifoGet(dev) \ readw(devpriv->las1+LAS1_ADC_FIFO) -/* Read two ADC data values (DOESNT WORK) */ +/* Read two ADC data values (DOESN'T WORK) */ #define RtdAdcFifoGet2(dev) \ readl(devpriv->las1+LAS1_ADC_FIFO) @@ -857,7 +857,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) DPRINTK("rtd520: PCI latency = %d\n", pci_latency); } - /* Undocumented EPLD version (doesnt match RTD driver results) */ + /* Undocumented EPLD version (doesn't match RTD driver results) */ /*DPRINTK ("rtd520: Reading epld from %p\n", devpriv->las0+0); epld_version = readl (devpriv->las0+0); @@ -1291,7 +1291,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev) /* "instructions" read/write data in "one-shot" or "software-triggered" mode (simplest case). - This doesnt use interrupts. + This doesn't use interrupts. Note, we don't do any settling delays. Use a instruction list to select, delay, then read. @@ -2120,7 +2120,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* - Stop a running data aquisition. + Stop a running data acquisition. */ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index d5ba3ab357a3..23fc64b9988e 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -139,7 +139,7 @@ struct s626_private { int got_regions; short allocatedBuf; uint8_t ai_cmd_running; /* ai_cmd is running */ - uint8_t ai_continous; /* continous aquisition */ + uint8_t ai_continous; /* continous acquisition */ int ai_sample_count; /* number of samples to acquire */ unsigned int ai_sample_timer; /* time between samples in units of the timer */ @@ -1048,7 +1048,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d) uint8_t group; uint16_t irqbit; - DEBUG("s626_irq_handler: interrupt request recieved!!!\n"); + DEBUG("s626_irq_handler: interrupt request received!!!\n"); if (dev->attached == 0) return IRQ_NONE; @@ -1165,14 +1165,14 @@ static irqreturn_t s626_irq_handler(int irq, void *d) (16 * group))) == 1 && cmd->start_src == TRIG_EXT) { DEBUG - ("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", + ("s626_irq_handler: Edge capture interrupt received from channel %d\n", cmd->start_arg); /* Start executing the RPS program. */ MC_ENABLE(P_MC1, MC1_ERPS1); DEBUG - ("s626_irq_handler: aquisition start triggered!!!\n"); + ("s626_irq_handler: acquisition start triggered!!!\n"); if (cmd->scan_begin_src == TRIG_EXT) { @@ -1194,7 +1194,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d) && cmd->scan_begin_src == TRIG_EXT) { DEBUG - ("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", + ("s626_irq_handler: Edge capture interrupt received from channel %d\n", cmd->scan_begin_arg); /* Trigger ADC scan loop start by setting RPS Signal 0. */ @@ -1236,7 +1236,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d) == 1 && cmd->convert_src == TRIG_EXT) { DEBUG - ("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", + ("s626_irq_handler: Edge capture interrupt received from channel %d\n", cmd->convert_arg); /* Trigger ADC scan loop start by setting RPS Signal 0. */ @@ -1805,7 +1805,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) DEBUG("s626_ai_cmd: NULL command\n"); return -EINVAL; } else { - DEBUG("s626_ai_cmd: command recieved!!!\n"); + DEBUG("s626_ai_cmd: command received!!!\n"); } if (dev->irq == 0) { @@ -1880,7 +1880,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_continous = 0; break; case TRIG_NONE: - /* continous aquisition */ + /* continous acquisition */ devpriv->ai_continous = 1; devpriv->ai_sample_count = 0; break; @@ -2570,7 +2570,7 @@ static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val) while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ; - /* Return non-zero if I2C error occured. */ + /* Return non-zero if I2C error occurred. */ return RR7146(P_I2CCTRL) & I2C_ERR; } diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index be93c30e4b15..e543e6c2b1bb 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -285,7 +285,7 @@ struct usbduxsub { short int ao_cmd_running; /* pwm is running */ short int pwm_cmd_running; - /* continous aquisition */ + /* continous acquisition */ short int ai_continous; short int ao_continous; /* number of samples to acquire */ @@ -500,7 +500,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) /* test, if we transmit only a fixed number of samples */ if (!(this_usbduxsub->ai_continous)) { - /* not continous, fixed number of samples */ + /* not continuous, fixed number of samples */ this_usbduxsub->ai_sample_count--; /* all samples received? */ if (this_usbduxsub->ai_sample_count < 0) { @@ -653,7 +653,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) /* timer zero */ this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; - /* handle non continous aquisition */ + /* handle non continous acquisition */ if (!(this_usbduxsub->ao_continous)) { /* fixed number of samples */ this_usbduxsub->ao_sample_count--; @@ -957,7 +957,7 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++; - /* scanning is continous */ + /* scanning is continuous */ tmp = cmd->convert_src; cmd->convert_src &= TRIG_NOW; if (!cmd->convert_src || tmp != cmd->convert_src) @@ -1222,7 +1222,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) up(&this_usbduxsub->sem); return -EBUSY; } - /* set current channel of the running aquisition to zero */ + /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; this_usbduxsub->dux_commands[1] = cmd->chanlist_len; @@ -1284,7 +1284,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) this_usbduxsub->ai_sample_count = cmd->stop_arg; this_usbduxsub->ai_continous = 0; } else { - /* continous aquisition */ + /* continous acquisition */ this_usbduxsub->ai_continous = 1; this_usbduxsub->ai_sample_count = 0; } @@ -1515,7 +1515,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, /* just now we scan also in the high speed mode every frame */ /* this is due to ehci driver limitations */ if (0) { /* (this_usbduxsub->high_speed) */ - /* start immidiately a new scan */ + /* start immediately a new scan */ /* the sampling rate is set by the coversion rate */ cmd->scan_begin_src &= TRIG_FOLLOW; } else { @@ -1525,7 +1525,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++; - /* scanning is continous */ + /* scanning is continuous */ tmp = cmd->convert_src; /* we always output at 1kHz just now all channels at once */ if (0) { /* (this_usbduxsub->high_speed) */ @@ -1645,7 +1645,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n", dev->minor, __func__); - /* set current channel of the running aquisition to zero */ + /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; for (i = 0; i < cmd->chanlist_len; ++i) { chan = CR_CHAN(cmd->chanlist[i]); @@ -1694,7 +1694,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; if (cmd->stop_src == TRIG_COUNT) { - /* not continous */ + /* not continuous */ /* counter */ /* high speed also scans everything at once */ if (0) { /* (this_usbduxsub->high_speed) */ @@ -1708,7 +1708,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } this_usbduxsub->ao_continous = 0; } else { - /* continous aquisition */ + /* continous acquisition */ this_usbduxsub->ao_continous = 1; this_usbduxsub->ao_sample_count = 0; } diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 5b15e6df54e6..2a8e725b7859 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -180,7 +180,7 @@ struct usbduxfastsub_s { /* comedi device for the interrupt context */ struct comedi_device *comedidev; short int ai_cmd_running; /* asynchronous command is running */ - short int ai_continous; /* continous aquisition */ + short int ai_continous; /* continous acquisition */ long int ai_sample_count; /* number of samples to acquire */ uint8_t *dux_commands; /* commands */ int ignore; /* counter which ignores the first @@ -392,7 +392,7 @@ static void usbduxfastsub_ai_Irq(struct urb *urb) p = urb->transfer_buffer; if (!udfs->ignore) { if (!udfs->ai_continous) { - /* not continous, fixed number of samples */ + /* not continuous, fixed number of samples */ n = urb->actual_length / sizeof(uint16_t); if (unlikely(udfs->ai_sample_count < n)) { /* @@ -775,7 +775,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, up(&udfs->sem); return -EBUSY; } - /* set current channel of the running aquisition to zero */ + /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; /* @@ -1182,7 +1182,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, } udfs->ai_continous = 0; } else { - /* continous aquisition */ + /* continous acquisition */ udfs->ai_continous = 1; udfs->ai_sample_count = 0; } diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c index 76e4b782d2fb..0fe713e72e9d 100644 --- a/drivers/staging/cptm1217/clearpad_tm1217.c +++ b/drivers/staging/cptm1217/clearpad_tm1217.c @@ -52,7 +52,7 @@ #define TMA1217_DEV_STATUS 0x13 /* Device Status */ #define TMA1217_INT_STATUS 0x14 /* Interrupt Status */ -/* Controller can detect upto 2 possible finger touches. +/* Controller can detect up to 2 possible finger touches. * Each finger touch provides 12 bit X Y co-ordinates, the values are split * across 2 registers, and an 8 bit Z value */ #define TMA1217_FINGER_STATE 0x18 /* Finger State */ diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c index 1429608544d6..3735ed3da4c6 100644 --- a/drivers/staging/crystalhd/crystalhd_cmds.c +++ b/drivers/staging/crystalhd/crystalhd_cmds.c @@ -914,7 +914,7 @@ enum BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx, * Return: * status * - * Closer aplication handle and release app specific + * Closer application handle and release app specific * resources. */ enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc) diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c index 13a514dd0f79..5acf39e7cdef 100644 --- a/drivers/staging/crystalhd/crystalhd_hw.c +++ b/drivers/staging/crystalhd/crystalhd_hw.c @@ -302,7 +302,7 @@ static bool crystalhd_start_device(struct crystalhd_adp *adp) crystalhd_enable_interrupts(adp); /* Enable the option for getting the total no. of DWORDS - * that have been transfered by the RXDMA engine + * that have been transferred by the RXDMA engine */ dbg_options = crystalhd_reg_rd(adp, MISC1_DMA_DEBUG_OPTIONS_REG); dbg_options |= 0x10; @@ -1776,7 +1776,7 @@ enum BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, return sts; } - /*Get the Responce Address*/ + /*Get the Response Address*/ cmd_res_addr = bc_dec_reg_rd(hw->adp, Cpu2HstMbx1); /*Read the Response*/ @@ -2367,7 +2367,7 @@ enum BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *hw) BCMLOG(BCMLOG_INFO, "clock is moving to %d with n %d with vco_mg %d\n", hw->core_clock_mhz, n, vco_mg); - /* Change the DRAM refresh rate to accomodate the new frequency */ + /* Change the DRAM refresh rate to accommodate the new frequency */ /* refresh reg = ((refresh_rate * clock_rate)/16) - 1; rounding up*/ refresh_reg = (7 * hw->core_clock_mhz / 16); bc_dec_reg_wr(hw->adp, SDRAM_REF_PARAM, ((1 << 12) | refresh_reg)); diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c index f274c77fb3fc..5cc3423a6646 100644 --- a/drivers/staging/cxt1e1/musycc.c +++ b/drivers/staging/cxt1e1/musycc.c @@ -1455,7 +1455,7 @@ musycc_intr_bh_tasklet (ci_t * ci) /* * If the descriptor has not recovered, then leaving the EMPTY * entry set will not signal to the MUSYCC that this descriptor - * has been serviced. The Interrupt Queue can then start loosing + * has been serviced. The Interrupt Queue can then start losing * available descriptors and MUSYCC eventually encounters and * reports the INTFULL condition. Per manual, changing any bit * marks descriptor as available, thus the use of different diff --git a/drivers/staging/cxt1e1/musycc.h b/drivers/staging/cxt1e1/musycc.h index d2c91ef686d1..68f3660f4477 100644 --- a/drivers/staging/cxt1e1/musycc.h +++ b/drivers/staging/cxt1e1/musycc.h @@ -74,7 +74,7 @@ extern "C" #define INT_QUEUE_SIZE MUSYCC_NIQD -/* RAM image of MUSYCC registers layed out as a C structure */ +/* RAM image of MUSYCC registers laid out as a C structure */ struct musycc_groupr { VINT32 thp[32]; /* Transmit Head Pointer [5-29] */ @@ -96,7 +96,7 @@ extern "C" VINT32 pcd; /* Port Configuration Descriptor [5-19] */ }; -/* hardware MUSYCC registers layed out as a C structure */ +/* hardware MUSYCC registers laid out as a C structure */ struct musycc_globalr { VINT32 gbp; /* Group Base Pointer */ diff --git a/drivers/staging/cxt1e1/pmcc4_defs.h b/drivers/staging/cxt1e1/pmcc4_defs.h index 186347b8d565..a39505f45c29 100644 --- a/drivers/staging/cxt1e1/pmcc4_defs.h +++ b/drivers/staging/cxt1e1/pmcc4_defs.h @@ -54,8 +54,8 @@ #define MUSYCC_MTU 2048 /* default */ #define MUSYCC_TXDESC_MIN 10 /* HDLC mode default */ #define MUSYCC_RXDESC_MIN 18 /* HDLC mode default */ -#define MUSYCC_TXDESC_TRANS 4 /* Transparent mode minumum # of TX descriptors */ -#define MUSYCC_RXDESC_TRANS 12 /* Transparent mode minumum # of RX descriptors */ +#define MUSYCC_TXDESC_TRANS 4 /* Transparent mode minimum # of TX descriptors */ +#define MUSYCC_RXDESC_TRANS 12 /* Transparent mode minimum # of RX descriptors */ #define MAX_DEFAULT_IFQLEN 32 /* network qlen */ diff --git a/drivers/staging/cxt1e1/sbecrc.c b/drivers/staging/cxt1e1/sbecrc.c index 51232948091f..3f3cd60ac367 100644 --- a/drivers/staging/cxt1e1/sbecrc.c +++ b/drivers/staging/cxt1e1/sbecrc.c @@ -95,7 +95,7 @@ sbeCrc (u_int8_t *buffer, /* data buffer to crc */ /* * if table not yet created, do so. Don't care about "extra" time - * checking this everytime sbeCrc() is called, since CRC calculations are + * checking this every time sbeCrc() is called, since CRC calculations are * already time consuming */ if (!crcTableInit) diff --git a/drivers/staging/cxt1e1/sbeproc.c b/drivers/staging/cxt1e1/sbeproc.c index 70b9b33f3522..f42531c3d8da 100644 --- a/drivers/staging/cxt1e1/sbeproc.c +++ b/drivers/staging/cxt1e1/sbeproc.c @@ -239,7 +239,7 @@ sbecom_proc_get_sbe_info (char *buffer, char **start, off_t offset, */ #if 1 - /* #4 - intepretation of above = set EOF, return len */ + /* #4 - interpretation of above = set EOF, return len */ *eof = 1; #endif diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h index e6c8cb3828e9..425e9274f28a 100644 --- a/drivers/staging/et131x/et1310_address_map.h +++ b/drivers/staging/et131x/et1310_address_map.h @@ -856,7 +856,7 @@ typedef union _RXMAC_UNI_PF_ADDR3_t { */ /* - * structure for space availiable reg in rxmac address map. + * structure for space available reg in rxmac address map. * located at address 0x4094 * * 31-17: reserved @@ -1031,7 +1031,7 @@ typedef struct _RXMAC_t { /* Location: */ * 31: reset MII mgmt * 30-6: unused * 5: scan auto increment - * 4: preamble supress + * 4: preamble suppress * 3: undefined * 2-0: mgmt clock reset */ diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h index 78349adc7d8e..946c0c547404 100644 --- a/drivers/staging/et131x/et1310_phy.h +++ b/drivers/staging/et131x/et1310_phy.h @@ -468,7 +468,7 @@ typedef union _MI_ANAR_t { #define TRUEPHY_ANEG_COMPLETE 1 #define TRUEPHY_ANEG_DISABLED 2 -/* Define duplex advertisment flags */ +/* Define duplex advertisement flags */ #define TRUEPHY_ADV_DUPLEX_NONE 0x00 #define TRUEPHY_ADV_DUPLEX_FULL 0x01 #define TRUEPHY_ADV_DUPLEX_HALF 0x02 diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c index 339136f64be1..fc6bd438366d 100644 --- a/drivers/staging/et131x/et1310_rx.c +++ b/drivers/staging/et131x/et1310_rx.c @@ -122,7 +122,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * number of entries in FBR1. * * FBR1 holds "large" frames, FBR0 holds "small" frames. If FBR1 - * entries are huge in order to accomodate a "jumbo" frame, then it + * entries are huge in order to accommodate a "jumbo" frame, then it * will have less entries. Conversely, FBR1 will now be relied upon * to carry more "normal" frames, thus it's entry size also increases * and the number of entries goes up too (since it now carries diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c index ce4d93042679..f716e408712b 100644 --- a/drivers/staging/et131x/et131x_isr.c +++ b/drivers/staging/et131x/et131x_isr.c @@ -466,7 +466,7 @@ void et131x_isr_handler(struct work_struct *work) /* Handle SLV Timeout Interrupt */ if (status & ET_INTR_SLV_TIMEOUT) { /* - * This means a timeout has occured on a read or + * This means a timeout has occurred on a read or * write request to one of the JAGCore registers. The * Global Resources block has terminated the request * and on a read request, returned a "fake" value. diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c index 0c298cae90d9..b25bae29042e 100644 --- a/drivers/staging/et131x/et131x_netdev.c +++ b/drivers/staging/et131x/et131x_netdev.c @@ -415,7 +415,7 @@ void et131x_multicast(struct net_device *netdev) */ PacketFilter = adapter->PacketFilter; - /* Clear the 'multicast' flag locally; becuase we only have a single + /* Clear the 'multicast' flag locally; because we only have a single * flag to check multicast, and multiple multicast addresses can be * set, this is the easiest way to determine if more than one * multicast address is being set. diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h index 4a89bd1bbf74..0b63f051f27c 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------- // // Function: ft1000_read_reg -// Descripton: This function will read the value of a given ASIC register. +// Description: This function will read the value of a given ASIC register. // Input: // dev - device structure // offset - ASIC register offset @@ -49,7 +49,7 @@ static inline u16 ft1000_read_reg (struct net_device *dev, u16 offset) { //--------------------------------------------------------------------------- // // Function: ft1000_write_reg -// Descripton: This function will set the value for a given ASIC register. +// Description: This function will set the value for a given ASIC register. // Input: // dev - device structure // offset - ASIC register offset diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index ff691d9b984e..eeb7dd43f9a8 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -90,7 +90,7 @@ MODULE_SUPPORTED_DEVICE("FT1000"); //--------------------------------------------------------------------------- // // Function: ft1000_asic_read -// Descripton: This function will retrieve the value of a specific ASIC +// Description: This function will retrieve the value of a specific ASIC // register. // Input: // dev - network device structure @@ -107,7 +107,7 @@ inline u16 ft1000_asic_read(struct net_device *dev, u16 offset) //--------------------------------------------------------------------------- // // Function: ft1000_asic_write -// Descripton: This function will set the value of a specific ASIC +// Description: This function will set the value of a specific ASIC // register. // Input: // dev - network device structure @@ -124,7 +124,7 @@ inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value) //--------------------------------------------------------------------------- // // Function: ft1000_read_fifo_len -// Descripton: This function will read the ASIC Uplink FIFO status register +// Description: This function will read the ASIC Uplink FIFO status register // which will return the number of bytes remaining in the Uplink FIFO. // Sixteen bytes are subtracted to make sure that the ASIC does not // reach its threshold. @@ -148,7 +148,7 @@ static inline u16 ft1000_read_fifo_len(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_read_dpram -// Descripton: This function will read the specific area of dpram +// Description: This function will read the specific area of dpram // (Electrabuzz ASIC only) // Input: // dev - device structure @@ -175,7 +175,7 @@ u16 ft1000_read_dpram(struct net_device * dev, int offset) //--------------------------------------------------------------------------- // // Function: ft1000_write_dpram -// Descripton: This function will write to a specific area of dpram +// Description: This function will write to a specific area of dpram // (Electrabuzz ASIC only) // Input: // dev - device structure @@ -201,7 +201,7 @@ static inline void ft1000_write_dpram(struct net_device *dev, //--------------------------------------------------------------------------- // // Function: ft1000_read_dpram_mag_16 -// Descripton: This function will read the specific area of dpram +// Description: This function will read the specific area of dpram // (Magnemite ASIC only) // Input: // dev - device structure @@ -233,7 +233,7 @@ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index) //--------------------------------------------------------------------------- // // Function: ft1000_write_dpram_mag_16 -// Descripton: This function will write to a specific area of dpram +// Description: This function will write to a specific area of dpram // (Magnemite ASIC only) // Input: // dev - device structure @@ -263,7 +263,7 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev, //--------------------------------------------------------------------------- // // Function: ft1000_read_dpram_mag_32 -// Descripton: This function will read the specific area of dpram +// Description: This function will read the specific area of dpram // (Magnemite ASIC only) // Input: // dev - device structure @@ -290,7 +290,7 @@ u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset) //--------------------------------------------------------------------------- // // Function: ft1000_write_dpram_mag_32 -// Descripton: This function will write to a specific area of dpram +// Description: This function will write to a specific area of dpram // (Magnemite ASIC only) // Input: // dev - device structure @@ -315,7 +315,7 @@ void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value) //--------------------------------------------------------------------------- // // Function: ft1000_enable_interrupts -// Descripton: This function will enable interrupts base on the current interrupt mask. +// Description: This function will enable interrupts base on the current interrupt mask. // Input: // dev - device structure // Output: @@ -340,7 +340,7 @@ static void ft1000_enable_interrupts(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_disable_interrupts -// Descripton: This function will disable all interrupts. +// Description: This function will disable all interrupts. // Input: // dev - device structure // Output: @@ -364,7 +364,7 @@ static void ft1000_disable_interrupts(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_reset_asic -// Descripton: This function will call the Card Service function to reset the +// Description: This function will call the Card Service function to reset the // ASIC. // Input: // dev - device structure @@ -408,7 +408,7 @@ static void ft1000_reset_asic(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_reset_card -// Descripton: This function will reset the card +// Description: This function will reset the card // Input: // dev - device structure // Output: @@ -571,7 +571,7 @@ static int ft1000_reset_card(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_chkcard -// Descripton: This function will check if the device is presently available on +// Description: This function will check if the device is presently available on // the system. // Input: // dev - device structure @@ -607,7 +607,7 @@ static int ft1000_chkcard(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_hbchk -// Descripton: This function will perform the heart beat check of the DSP as +// Description: This function will perform the heart beat check of the DSP as // well as the ASIC. // Input: // dev - device structure @@ -828,7 +828,7 @@ static void ft1000_hbchk(u_long data) //--------------------------------------------------------------------------- // // Function: ft1000_send_cmd -// Descripton: +// Description: // Input: // Output: // @@ -908,7 +908,7 @@ void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qt //--------------------------------------------------------------------------- // // Function: ft1000_receive_cmd -// Descripton: This function will read a message from the dpram area. +// Description: This function will read a message from the dpram area. // Input: // dev - network device structure // pbuffer - caller supply address to buffer @@ -1003,7 +1003,7 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 //--------------------------------------------------------------------------- // // Function: ft1000_proc_drvmsg -// Descripton: This function will process the various driver messages. +// Description: This function will process the various driver messages. // Input: // dev - device structure // pnxtph - pointer to next pseudo header @@ -1285,7 +1285,7 @@ void ft1000_proc_drvmsg(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_parse_dpram_msg -// Descripton: This function will parse the message received from the DSP +// Description: This function will parse the message received from the DSP // via the DPRAM interface. // Input: // dev - device structure @@ -1442,7 +1442,7 @@ int ft1000_parse_dpram_msg(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_flush_fifo -// Descripton: This function will flush one packet from the downlink +// Description: This function will flush one packet from the downlink // FIFO. // Input: // dev - device structure @@ -1587,7 +1587,7 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) //--------------------------------------------------------------------------- // // Function: ft1000_copy_up_pkt -// Descripton: This function will pull Flarion packets out of the Downlink +// Description: This function will pull Flarion packets out of the Downlink // FIFO and convert it to an ethernet packet. The ethernet packet will // then be deliver to the TCP/IP stack. // Input: @@ -1773,7 +1773,7 @@ int ft1000_copy_up_pkt(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_copy_down_pkt -// Descripton: This function will take an ethernet packet and convert it to +// Description: This function will take an ethernet packet and convert it to // a Flarion packet prior to sending it to the ASIC Downlink // FIFO. // Input: diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index 8e622425aa13..1972b72450d4 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -488,7 +488,7 @@ static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset) // Parameters: struct ft1000_device - device structure // u16 **pUsFile - DSP image file pointer in u16 // u8 **pUcFile - DSP image file pointer in u8 -// long word_length - lenght of the buffer to be written +// long word_length - length of the buffer to be written // to DPRAM // // Returns: STATUS_SUCCESS - success @@ -628,7 +628,7 @@ static void usb_dnld_complete (struct urb *urb) // Parameters: struct ft1000_device - device structure // u16 **pUsFile - DSP image file pointer in u16 // u8 **pUcFile - DSP image file pointer in u8 -// long word_length - lenght of the buffer to be written +// long word_length - length of the buffer to be written // to DPRAM // // Returns: STATUS_SUCCESS - success @@ -817,7 +817,7 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, * Error, beyond boot code range. */ DEBUG - ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundry.\n", + ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", (int)word_length); status = STATUS_FAILURE; break; @@ -950,7 +950,7 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, * Error, beyond boot code range. */ DEBUG - ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundry.\n", + ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundary.\n", (int)word_length); status = STATUS_FAILURE; break; diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 78dcd49bb985..684e69eacb71 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -585,7 +585,7 @@ int dsp_reload(struct ft1000_device *ft1000dev) //--------------------------------------------------------------------------- // // Function: ft1000_reset_asic -// Descripton: This function will call the Card Service function to reset the +// Description: This function will call the Card Service function to reset the // ASIC. // Input: // dev - device structure @@ -626,7 +626,7 @@ static void ft1000_reset_asic(struct net_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_reset_card -// Descripton: This function will reset the card +// Description: This function will reset the card // Input: // dev - device structure // Output: @@ -917,7 +917,7 @@ static void ft1000_usb_transmit_complete(struct urb *urb) //--------------------------------------------------------------------------- // // Function: ft1000_copy_down_pkt -// Descripton: This function will take an ethernet packet and convert it to +// Description: This function will take an ethernet packet and convert it to // a Flarion packet prior to sending it to the ASIC Downlink // FIFO. // Input: @@ -1075,10 +1075,10 @@ err: //--------------------------------------------------------------------------- // // Function: ft1000_copy_up_pkt -// Descripton: This function will take a packet from the FIFO up link and +// Description: This function will take a packet from the FIFO up link and // convert it into an ethernet packet and deliver it to the IP stack // Input: -// urb - the receving usb urb +// urb - the receiving usb urb // // Output: // status - FAILURE @@ -1182,7 +1182,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) //--------------------------------------------------------------------------- // // Function: ft1000_submit_rx_urb -// Descripton: the receiving function of the network driver +// Description: the receiving function of the network driver // // Input: // info - a private structure contains the device information @@ -1316,7 +1316,7 @@ Jim //--------------------------------------------------------------------------- // // Function: ft1000_chkcard -// Descripton: This function will check if the device is presently available on +// Description: This function will check if the device is presently available on // the system. // Input: // dev - device structure @@ -1363,7 +1363,7 @@ static int ft1000_chkcard(struct ft1000_device *dev) //--------------------------------------------------------------------------- // // Function: ft1000_receive_cmd -// Descripton: This function will read a message from the dpram area. +// Description: This function will read a message from the dpram area. // Input: // dev - network device structure // pbuffer - caller supply address to buffer diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h index 3f72d5bb3f92..6a8a1969f9e1 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h @@ -55,7 +55,7 @@ struct pseudo_hdr { unsigned char seq_num; //sequence number unsigned char rsvd2; //reserved unsigned short qos_class; //Quality of Service class (Not applicable on Mobile) - unsigned short checksum; //Psuedo header checksum + unsigned short checksum; //Pseudo header checksum } __attribute__ ((packed)); typedef struct _IOCTL_GET_VER diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h index e047c03fbf3a..f2ecb3eae9cd 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h @@ -364,7 +364,7 @@ struct prov_record { #define ISR_EMPTY (u8)0x00 // no bits set in ISR -#define ISR_DOORBELL_ACK (u8)0x01 // the doorbell i sent has been recieved. +#define ISR_DOORBELL_ACK (u8)0x01 // the doorbell i sent has been received. #define ISR_DOORBELL_PEND (u8)0x02 // doorbell for me diff --git a/drivers/staging/generic_serial/generic_serial.c b/drivers/staging/generic_serial/generic_serial.c index 466988dbc37d..f29dda4e9f20 100644 --- a/drivers/staging/generic_serial/generic_serial.c +++ b/drivers/staging/generic_serial/generic_serial.c @@ -113,7 +113,7 @@ int gs_write(struct tty_struct * tty, c = count; - /* This is safe because we "OWN" the "head". Noone else can + /* This is safe because we "OWN" the "head". No one else can change the "head": we own the port_write_mutex. */ /* Don't overrun the end of the buffer */ t = SERIAL_XMIT_SIZE - port->xmit_head; diff --git a/drivers/staging/generic_serial/rio/map.h b/drivers/staging/generic_serial/rio/map.h index 8366978578c1..28a66129293e 100644 --- a/drivers/staging/generic_serial/rio/map.h +++ b/drivers/staging/generic_serial/rio/map.h @@ -87,7 +87,7 @@ struct Map { ** The Topology array contains the ID of the unit connected to each of the ** four links on this unit. The entry will be 0xFFFF if NOTHING is connected ** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link. -** The Name field is a null-terminated string, upto 31 characters, containing +** The Name field is a null-terminated string, up to 31 characters, containing ** the 'cute' name that the sysadmin/users know the RTA by. It is permissible ** for this string to contain any character in the range \040 to \176 inclusive. ** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The diff --git a/drivers/staging/generic_serial/rio/rioboot.c b/drivers/staging/generic_serial/rio/rioboot.c index d956dd316005..ffa01c590216 100644 --- a/drivers/staging/generic_serial/rio/rioboot.c +++ b/drivers/staging/generic_serial/rio/rioboot.c @@ -109,7 +109,7 @@ int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp) rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP); /* - ** Check that we have set asside enough memory for this + ** Check that we have set aside enough memory for this */ if (rbp->Count > SIXTY_FOUR_K) { rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); @@ -293,7 +293,7 @@ int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) /* ** S T O P ! ** - ** Upto this point the code has been fairly rational, and possibly + ** Up to this point the code has been fairly rational, and possibly ** even straight forward. What follows is a pile of crud that will ** magically turn into six bytes of transputer assembler. Normally ** you would expect an array or something, but, being me, I have @@ -419,7 +419,7 @@ int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n"); /* - ** Now, wait for upto five seconds for the Tp to setup the parmmap + ** Now, wait for up to five seconds for the Tp to setup the parmmap ** pointer: */ for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) { @@ -475,7 +475,7 @@ int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) /* ** now wait for the card to set all the parmmap->XXX stuff - ** this is a wait of upto two seconds.... + ** this is a wait of up to two seconds.... */ rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime); HostP->timeout_id = 0; diff --git a/drivers/staging/generic_serial/rio/riocmd.c b/drivers/staging/generic_serial/rio/riocmd.c index f121357e5af0..61efd538e850 100644 --- a/drivers/staging/generic_serial/rio/riocmd.c +++ b/drivers/staging/generic_serial/rio/riocmd.c @@ -863,7 +863,7 @@ int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) ** being transferred from the write queue into the transmit packets ** (add_transmit) and no furthur transmit interrupt will be sent for that ** data. The next interrupt will occur up to 500ms later (RIOIntr is called - ** twice a second as a saftey measure). This was the case when kermit was + ** twice a second as a safety measure). This was the case when kermit was ** used to send data into a RIO port. After each packet was sent, TCFLSH ** was called to flush the read queue preemptively. PortP->InUse was ** incremented, thereby blocking the 6 byte acknowledgement packet diff --git a/drivers/staging/generic_serial/rio/rioroute.c b/drivers/staging/generic_serial/rio/rioroute.c index f9b936ac3394..8757378e8320 100644 --- a/drivers/staging/generic_serial/rio/rioroute.c +++ b/drivers/staging/generic_serial/rio/rioroute.c @@ -450,7 +450,7 @@ int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct ** we reset the unit, because we didn't boot it. ** However, if the table is full, it could be that we did boot ** this unit, and so we won't reboot it, because it isn't really - ** all that disasterous to keep the old bins in most cases. This + ** all that disastrous to keep the old bins in most cases. This ** is a rather tacky feature, but we are on the edge of reallity ** here, because the implication is that someone has connected ** 16+MAX_EXTRA_UNITS onto one host. @@ -678,7 +678,7 @@ static int RIOCheck(struct Host *HostP, unsigned int UnitId) HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; - /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */ + /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESN'T KNOW THE HOST!\n", UnitId)); */ return 0; } diff --git a/drivers/staging/generic_serial/rio/riotty.c b/drivers/staging/generic_serial/rio/riotty.c index 8a90393faf3c..e7e9911d7a72 100644 --- a/drivers/staging/generic_serial/rio/riotty.c +++ b/drivers/staging/generic_serial/rio/riotty.c @@ -124,7 +124,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) } /* - ** Grab pointer to the port stucture + ** Grab pointer to the port structure */ PortP = p->RIOPortp[SysPort]; /* Get control struc */ rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP); @@ -161,7 +161,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) } /* - ** If the RTA has not booted yet and the user has choosen to block + ** If the RTA has not booted yet and the user has chosen to block ** until the RTA is present then we must spin here waiting for ** the RTA to boot. */ diff --git a/drivers/staging/generic_serial/sx.c b/drivers/staging/generic_serial/sx.c index 1291462bcddb..4f94aaffbe83 100644 --- a/drivers/staging/generic_serial/sx.c +++ b/drivers/staging/generic_serial/sx.c @@ -158,13 +158,13 @@ * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). * * Revision 0.12 1999/03/28 09:20:10 wolff - * Fixed problem in 0.11, continueing cleanup. + * Fixed problem in 0.11, continuing cleanup. * * Revision 0.11 1999/03/28 08:46:44 wolff * cleanup. Not good. * * Revision 0.10 1999/03/28 08:09:43 wolff - * Fixed loosing characters on close. + * Fixed losing characters on close. * * Revision 0.9 1999/03/21 22:52:01 wolff * Ported back to 2.2.... (minor things) @@ -1588,7 +1588,7 @@ static void sx_close(void *ptr) #define R0 if (read_sx_byte(board, i) != 0x55) return 1 #define R1 if (read_sx_byte(board, i) != 0xaa) return 1 -/* This memtest takes a human-noticable time. You normally only do it +/* This memtest takes a human-noticeable time. You normally only do it once a boot, so I guess that it is worth it. */ static int do_memtest(struct sx_board *board, int min, int max) { @@ -1645,7 +1645,7 @@ static int do_memtest(struct sx_board *board, int min, int max) #define R1 if (read_sx_word(board, i) != 0xaa55) return 1 #if 0 -/* This memtest takes a human-noticable time. You normally only do it +/* This memtest takes a human-noticeable time. You normally only do it once a boot, so I guess that it is worth it. */ static int do_memtest_w(struct sx_board *board, int min, int max) { diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h index fb9b4245bada..a339406052ef 100644 --- a/drivers/staging/gma500/psb_drm.h +++ b/drivers/staging/gma500/psb_drm.h @@ -131,7 +131,7 @@ struct drm_psb_reloc { u32 pre_add; /* Destination format: */ u32 background; /* Destination add */ u32 dst_buffer; /* Destination buffer. Index into buffer_list */ - u32 arg0; /* Reloc-op dependant */ + u32 arg0; /* Reloc-op dependent */ u32 arg1; }; diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c index 44cd095d2862..d01d45e7a14d 100644 --- a/drivers/staging/gma500/psb_drv.c +++ b/drivers/staging/gma500/psb_drv.c @@ -561,7 +561,7 @@ static int psb_driver_unload(struct drm_device *dev) kfree(dev_priv); dev->dev_private = NULL; - /*destory VBT data*/ + /*destroy VBT data*/ psb_intel_destroy_bios(dev); } diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c index f5bcd119b87d..48ac8ba7f40b 100644 --- a/drivers/staging/gma500/psb_intel_bios.c +++ b/drivers/staging/gma500/psb_intel_bios.c @@ -271,7 +271,7 @@ bool psb_intel_init_bios(struct drm_device *dev) } /** - * Destory and free VBT data + * Destroy and free VBT data */ void psb_intel_destroy_bios(struct drm_device *dev) { diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c index 731a5a2261d3..1d2bb021c0a5 100644 --- a/drivers/staging/gma500/psb_intel_sdvo.c +++ b/drivers/staging/gma500/psb_intel_sdvo.c @@ -573,7 +573,7 @@ static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output, /* Make all fields of the args/ret to zero */ memset(byArgs, 0, sizeof(byArgs)); - /* Fill up the arguement values; */ + /* Fill up the argument values; */ byArgs[0] = (u8) (in0outputmask & 0xFF); byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF); byArgs[2] = (u8) (in1outputmask & 0xFF); diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h index a1d1475a9315..c7107a37e33d 100644 --- a/drivers/staging/gma500/psb_intel_sdvo_regs.h +++ b/drivers/staging/gma500/psb_intel_sdvo_regs.h @@ -217,7 +217,7 @@ struct psb_intel_sdvo_set_target_input_args { } __attribute__ ((packed)); /** - * Takes a struct psb_intel_sdvo_output_flags of which outputs are targetted by + * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by * future output commands. * * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], diff --git a/drivers/staging/gma500/psb_ttm_fence_user.h b/drivers/staging/gma500/psb_ttm_fence_user.h index fc13f89c6e12..762a05728632 100644 --- a/drivers/staging/gma500/psb_ttm_fence_user.h +++ b/drivers/staging/gma500/psb_ttm_fence_user.h @@ -130,7 +130,7 @@ struct ttm_fence_unref_arg { }; /* - * Ioctl offsets frome extenstion start. + * Ioctl offsets from extenstion start. */ #define TTM_FENCE_SIGNALED 0x01 diff --git a/drivers/staging/go7007/go7007.txt b/drivers/staging/go7007/go7007.txt index 06a76da32128..9db1f3952fd2 100644 --- a/drivers/staging/go7007/go7007.txt +++ b/drivers/staging/go7007/go7007.txt @@ -2,7 +2,7 @@ This is a driver for the WIS GO7007SB multi-format video encoder. Pete Eberlein -The driver was orignally released under the GPL and is currently hosted at: +The driver was originally released under the GPL and is currently hosted at: http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver The go7007 firmware can be acquired from the package on the site above. diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index af789937be4e..68ad17d67098 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -894,7 +894,7 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req, /* * We break the request into 1 or more blkvsc_requests and submit - * them. If we cant submit them all, we put them on the + * them. If we can't submit them all, we put them on the * pending_list. The blkvsc_request() will work on the pending_list. */ static int blkvsc_do_request(struct block_device_context *blkdev, diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index bc0393a41d29..06b573227e8d 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -166,7 +166,7 @@ EXPORT_SYMBOL(prep_negotiate_resp); * from Hyper-V. This stub responds to the default negotiate messages * that come in for every non IDE/SCSI/Network request. * This behavior is normally overwritten in the hv_utils driver. That - * driver handles requests like gracefull shutdown, heartbeats etc. + * driver handles requests like graceful shutdown, heartbeats etc. * * Mainly used by Hyper-V drivers. */ diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c index 2d492adb95bb..0b06f4fe5838 100644 --- a/drivers/staging/hv/hv.c +++ b/drivers/staging/hv/hv.c @@ -37,7 +37,7 @@ struct hv_context hv_context = { /* * query_hypervisor_presence - * - Query the cpuid for presense of windows hypervisor + * - Query the cpuid for presence of windows hypervisor */ static int query_hypervisor_presence(void) { diff --git a/drivers/staging/hv/hv_api.h b/drivers/staging/hv/hv_api.h index 7114fceab21e..43a722888dc4 100644 --- a/drivers/staging/hv/hv_api.h +++ b/drivers/staging/hv/hv_api.h @@ -53,14 +53,14 @@ struct hv_guid { /* * HV_STATUS_INVALID_ALIGNMENT - * The hypervisor could not perform the operation beacuse a parameter has an + * The hypervisor could not perform the operation because a parameter has an * invalid alignment. */ #define HV_STATUS_INVALID_ALIGNMENT ((u16)0x0004) /* * HV_STATUS_INVALID_PARAMETER - * The hypervisor could not perform the operation beacuse an invalid parameter + * The hypervisor could not perform the operation because an invalid parameter * was specified. */ #define HV_STATUS_INVALID_PARAMETER ((u16)0x0005) diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/staging/hv/hv_kvp.h index e069f59b5135..8c402f357d37 100644 --- a/drivers/staging/hv/hv_kvp.h +++ b/drivers/staging/hv/hv_kvp.h @@ -36,7 +36,7 @@ * registry. * * Note: This value is used in defining the KVP exchange message - this value - * cannot be modified without affecting the message size and compatability. + * cannot be modified without affecting the message size and compatibility. */ /* diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index 4792f2c402b2..2df15683f8fa 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -80,7 +80,7 @@ static void shutdown_onchannelcallback(void *context) execute_shutdown = true; DPRINT_INFO(VMBUS, "Shutdown request received -" - " gracefull shutdown initiated"); + " graceful shutdown initiated"); break; default: icmsghdrp->status = HV_E_FAIL; diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c index e7189cd324ca..048376b2b676 100644 --- a/drivers/staging/hv/rndis_filter.c +++ b/drivers/staging/hv/rndis_filter.c @@ -585,7 +585,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev, ret = -1; DPRINT_ERR(NETVSC, "timeout before we got a set response..."); /* - * We cant deallocate the request since we may still receive a + * We can't deallocate the request since we may still receive a * send completion for it. */ goto Exit; diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c index f5a2dd694611..aa77a971aace 100644 --- a/drivers/staging/hv/tools/hv_kvp_daemon.c +++ b/drivers/staging/hv/tools/hv_kvp_daemon.c @@ -202,7 +202,7 @@ kvp_get_ip_address(int family, char *buffer, int length) /* * We only support AF_INET and AF_INET6 - * and the list of addresses is seperated by a ";". + * and the list of addresses is separated by a ";". */ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) curp->ifa_addr; diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index 8095727b3966..fd78e4ff99ae 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -556,7 +556,7 @@ int _write_sysfs_string(char *filename, char *basedir, char *val, int verify) if (strcmp(temp, val) != 0) { printf("Possible failure in string write of %s " "Should be %s " - "writen to %s\%s\n", + "written to %s\%s\n", temp, val, basedir, diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index c9bf22c13428..23fe54d09d12 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -70,7 +70,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16201_state { diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index b39323eac9e3..b88688128d61 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -65,7 +65,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16203_state { diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h index e9ed7cb048cf..e61844684f99 100644 --- a/drivers/staging/iio/accel/adis16204.h +++ b/drivers/staging/iio/accel/adis16204.h @@ -73,7 +73,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16204_state { diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h index 4e97596620ef..8b0da1349555 100644 --- a/drivers/staging/iio/accel/adis16209.h +++ b/drivers/staging/iio/accel/adis16209.h @@ -109,7 +109,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16209_state { diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h index 7013314a9d77..4d5758c2c047 100644 --- a/drivers/staging/iio/accel/adis16220.h +++ b/drivers/staging/iio/accel/adis16220.h @@ -132,7 +132,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16220_state { diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h index 51a807dde27c..76a45797b9dd 100644 --- a/drivers/staging/iio/accel/adis16240.h +++ b/drivers/staging/iio/accel/adis16240.h @@ -132,7 +132,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16240_state { diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index 579b3a26e5d7..11402187f9ae 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -57,7 +57,7 @@ /* Reboot memory content */ #define LIS3L02DQ_REG_CTRL_2_REBOOT_MEMORY 0x10 -/* Interupt Enable - applies data ready to the RDY pad */ +/* Interrupt Enable - applies data ready to the RDY pad */ #define LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT 0x08 /* Enable Data Ready Generation - relationship with previous unclear in docs */ @@ -70,34 +70,34 @@ * - option for 16 bit left justified */ #define LIS3L02DQ_REG_CTRL_2_DATA_ALIGNMENT_16_BIT_LEFT_JUSTIFIED 0x01 -/* Interupt related stuff */ +/* Interrupt related stuff */ #define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23 /* Switch from or combination fo conditions to and */ #define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80 -/* Latch interupt request, +/* Latch interrupt request, * if on ack must be given by reading the ack register */ #define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40 -/* Z Interupt on High (above threshold)*/ +/* Z Interrupt on High (above threshold)*/ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20 -/* Z Interupt on Low */ +/* Z Interrupt on Low */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10 -/* Y Interupt on High */ +/* Y Interrupt on High */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH 0x08 -/* Y Interupt on Low */ +/* Y Interrupt on Low */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW 0x04 -/* X Interupt on High */ +/* X Interrupt on High */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH 0x02 -/* X Interupt on Low */ +/* X Interrupt on Low */ #define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW 0x01 -/* Register that gives description of what caused interupt +/* Register that gives description of what caused interrupt * - latched if set in CFG_ADDRES */ #define LIS3L02DQ_REG_WAKE_UP_SRC_ADDR 0x24 /* top bit ignored */ -/* Interupt Active */ +/* Interrupt Active */ #define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_ACTIVATED 0x40 /* Interupts that have been triggered */ #define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH 0x20 @@ -123,7 +123,7 @@ #define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01 /* The accelerometer readings - low and high bytes. -Form of high byte dependant on justification set in ctrl reg */ +Form of high byte dependent on justification set in ctrl reg */ #define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28 #define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29 #define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A @@ -155,7 +155,7 @@ Form of high byte dependant on justification set in ctrl reg */ * @inter: used to check if new interrupt has been triggered * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct lis3l02dq_state { diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index c4b4ab7e6423..3067f9662d20 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -77,7 +77,7 @@ int lis3l02dq_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) /** * lis3l02dq_spi_write_reg_8() - write single byte to a register * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @reg_address: the address of the register to be writen + * @reg_address: the address of the register to be written * @val: the value to write **/ int lis3l02dq_spi_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 2c461a31f129..529a3cc6d0c7 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -217,7 +217,7 @@ static const u8 read_all_tx_array[] = { /** * lis3l02dq_read_all() Reads all channels currently selected * @st: device specific state - * @rx_array: (dma capable) recieve array, must be at least + * @rx_array: (dma capable) receive array, must be at least * 4*number of channels **/ static int lis3l02dq_read_all(struct lis3l02dq_state *st, u8 *rx_array) @@ -409,7 +409,7 @@ static const struct attribute_group lis3l02dq_trigger_attr_group = { * * As the trigger may occur on any data element being updated it is * really rather likely to occur during the read from the previous - * trigger event. The only way to discover if this has occured on + * trigger event. The only way to discover if this has occurred on * boards not supporting level interrupts is to take a look at the line. * If it is indicating another interrupt and we don't seem to have a * handler looking at it, then we need to notify the core that we need diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index 23892848f5ae..db710334b99b 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -185,7 +185,7 @@ struct sca3000_state { }; /** - * struct sca3000_chip_info - model dependant parameters + * struct sca3000_chip_info - model dependent parameters * @name: model identification * @scale: string containing floating point scale factor * @temp_output: some devices have temperature sensors. @@ -213,7 +213,7 @@ struct sca3000_chip_info { * sca3000_read_data() read a series of values from the device * @dev: device * @reg_address_high: start address (decremented read) - * @rx: pointer where recieved data is placed. Callee + * @rx: pointer where received data is placed. Callee * responsible for freeing this. * @len: number of bytes to read * diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index c872fddfb2bf..a730a7638de1 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -43,7 +43,7 @@ * leading byte used in bus comms. * * Currently does not provide timestamps. As the hardware doesn't add them they - * can only be inferred aproximately from ring buffer events such as 50% full + * can only be inferred approximately from ring buffer events such as 50% full * and knowledge of when buffer was last emptied. This is left to userspace. **/ static int sca3000_rip_hw_rb(struct iio_ring_buffer *r, diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index 19d1aced1e6c..9068d7f54d15 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -157,7 +157,7 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev) /** * ad7298_poll_func_th() th of trigger launched polling to ring buffer * - * As sampling only occurs on spi comms occuring, leave timestamping until + * As sampling only occurs on spi comms occurring, leave timestamping until * then. Some triggers will generate their own time stamp. Currently * there is no way of notifying them when no one cares. **/ diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index 1d654c86099d..92d93787d5b8 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -112,7 +112,7 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev) /** * ad7476_poll_func_th() th of trigger launched polling to ring buffer * - * As sampling only occurs on i2c comms occuring, leave timestamping until + * As sampling only occurs on i2c comms occurring, leave timestamping until * then. Some triggers will generate their own time stamp. Currently * there is no way of notifying them when no one cares. **/ diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index 2d7fe65049dd..da77f266c16b 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -165,7 +165,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev) /** * ad7887_poll_func_th() th of trigger launched polling to ring buffer * - * As sampling only occurs on spi comms occuring, leave timestamping until + * As sampling only occurs on spi comms occurring, leave timestamping until * then. Some triggers will generate their own time stamp. Currently * there is no way of notifying them when no one cares. **/ diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index e50841b3ac69..f04e642e7272 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -184,7 +184,7 @@ static ssize_t ad799x_read_single_channel(struct device *dev, mutex_lock(&dev_info->mlock); mask = 1 << this_attr->address; - /* If ring buffer capture is occuring, query the buffer */ + /* If ring buffer capture is occurring, query the buffer */ if (iio_ring_enabled(dev_info)) { data = ret = ad799x_single_channel_from_ring(st, mask); if (ret < 0) diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 56abc395f177..0875a7ef67a5 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -101,7 +101,7 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev) /** * ad799x_poll_func_th() th of trigger launched polling to ring buffer * - * As sampling only occurs on i2c comms occuring, leave timestamping until + * As sampling only occurs on i2c comms occurring, leave timestamping until * then. Some triggers will generate their own time stamp. Currently * there is no way of notifying them when no one cares. **/ diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index dde097afb430..de83c3b37a2d 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -255,7 +255,7 @@ static ssize_t max1363_read_single_channel(struct device *dev, goto error_ret; } - /* If ring buffer capture is occuring, query the buffer */ + /* If ring buffer capture is occurring, query the buffer */ if (iio_ring_enabled(dev_info)) { mask = max1363_mode_table[this_attr->address].modemask; data = max1363_single_channel_from_ring(mask, st); @@ -1425,7 +1425,7 @@ error_ret: } /* - * To keep this managable we always use one of 3 scan modes. + * To keep this manageable we always use one of 3 scan modes. * Scan 0...3, 0-1,2-3 and 1-0,3-2 */ static inline int __max1363_check_event_mask(int thismask, int checkmask) diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index 5532f3e466bc..d36fcc62e976 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -108,7 +108,7 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev) /** * max1363_poll_func_th() - th of trigger launched polling to ring buffer * - * As sampling only occurs on i2c comms occuring, leave timestamping until + * As sampling only occurs on i2c comms occurring, leave timestamping until * then. Some triggers will generate their own time stamp. Currently * there is no way of notifying them when no one cares. **/ diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h index 98d1a2c12df2..4fcb99c816f9 100644 --- a/drivers/staging/iio/chrdev.h +++ b/drivers/staging/iio/chrdev.h @@ -33,7 +33,7 @@ struct iio_handler { /** * struct iio_event_data - The actual event being pushed to userspace * @id: event identifier - * @timestamp: best estimate of time of event occurance (often from + * @timestamp: best estimate of time of event occurrence (often from * the interrupt handler) */ struct iio_event_data { @@ -42,7 +42,7 @@ struct iio_event_data { }; /** - * struct iio_detected_event_list - list element for events that have occured + * struct iio_detected_event_list - list element for events that have occurred * @list: linked list header * @ev: the event itself * @shared_pointer: used when the event is shared - i.e. can be escallated @@ -98,7 +98,7 @@ struct iio_event_interface { * @list: list header * @refcount: as the handler may be shared between multiple device * side events, reference counting ensures clean removal - * @exist_lock: prevents race conditions related to refcount useage. + * @exist_lock: prevents race conditions related to refcount usage. * @handler: event handler function - called on event if this * event_handler is enabled. * diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index 700eb3980f9e..ae53e71d1c2f 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -30,7 +30,7 @@ * @us_w: actual spi_device to write config * @us_r: actual spi_device to read back data * @indio_dev: industrial I/O device structure - * @buf: transmit or recieve buffer + * @buf: transmit or receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16060_state { diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index fb4336c7d2a6..ef9e304a226d 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -35,7 +35,7 @@ * struct adis16080_state - device instance specific data * @us: actual spi_device to write data * @indio_dev: industrial I/O device structure - * @buf: transmit or recieve buffer + * @buf: transmit or receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16080_state { diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h index c1fd4364287f..1369501b4096 100644 --- a/drivers/staging/iio/gyro/adis16260.h +++ b/drivers/staging/iio/gyro/adis16260.h @@ -91,7 +91,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx * @negate: negate the scale parameter **/ diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 248bdd2846fd..7127f26f8d26 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -92,7 +92,7 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el, * changes * @available_scan_masks: [DRIVER] optional array of allowed bitmasks * @trig: [INTERN] current device trigger (ring buffer modes) - * @pollfunc: [DRIVER] function run on trigger being recieved + * @pollfunc: [DRIVER] function run on trigger being received **/ struct iio_dev { int id; diff --git a/drivers/staging/iio/imu/adis16300.h b/drivers/staging/iio/imu/adis16300.h index 1f25d68064a0..c0957591aed7 100644 --- a/drivers/staging/iio/imu/adis16300.h +++ b/drivers/staging/iio/imu/adis16300.h @@ -99,7 +99,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16300_state { diff --git a/drivers/staging/iio/imu/adis16350.h b/drivers/staging/iio/imu/adis16350.h index b00001e3edd0..b1ad48662a2c 100644 --- a/drivers/staging/iio/imu/adis16350.h +++ b/drivers/staging/iio/imu/adis16350.h @@ -105,7 +105,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16350_state { diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index 6ff33e1ad8c1..7a127029e099 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -131,7 +131,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct adis16400_state { diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index f3bf111f354f..1795ee1e8207 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -258,7 +258,7 @@ static ssize_t iio_event_chrdev_read(struct file *filep, ->det_events.list)); if (ret) goto error_ret; - /* Single access device so noone else can get the data */ + /* Single access device so no one else can get the data */ mutex_lock(&ev_int->event_list_lock); } diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h index 70dabae6efe9..3b9c7f6a50e7 100644 --- a/drivers/staging/iio/meter/ade7753.h +++ b/drivers/staging/iio/meter/ade7753.h @@ -62,7 +62,7 @@ * @us: actual spi_device * @indio_dev: industrial I/O device structure * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct ade7753_state { diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h index 8faa9b3b48b6..0aa0522a33a3 100644 --- a/drivers/staging/iio/meter/ade7754.h +++ b/drivers/staging/iio/meter/ade7754.h @@ -80,7 +80,7 @@ * @us: actual spi_device * @indio_dev: industrial I/O device structure * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct ade7754_state { diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index df5bb7ba5a0f..c6fd94f3b3ee 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -98,7 +98,7 @@ * @indio_dev: industrial I/O device structure * @trig: data ready trigger registered with iio * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct ade7758_state { diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h index e9d1c43336fe..cc76c2c4c039 100644 --- a/drivers/staging/iio/meter/ade7759.h +++ b/drivers/staging/iio/meter/ade7759.h @@ -43,7 +43,7 @@ * @us: actual spi_device * @indio_dev: industrial I/O device structure * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct ade7759_state { diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h index 4ad84a3bb462..79a21109f4e2 100644 --- a/drivers/staging/iio/meter/ade7854.h +++ b/drivers/staging/iio/meter/ade7854.h @@ -149,7 +149,7 @@ * @spi: actual spi_device * @indio_dev: industrial I/O device structure * @tx: transmit buffer - * @rx: recieve buffer + * @rx: receive buffer * @buf_lock: mutex to protect tx and rx **/ struct ade7854_state { diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h index f21ac09373cf..32948e55dc81 100644 --- a/drivers/staging/iio/ring_generic.h +++ b/drivers/staging/iio/ring_generic.h @@ -30,7 +30,7 @@ int iio_push_ring_event(struct iio_ring_buffer *ring_buf, * @event_code: event indentification code * @timestamp: time of event * - * Typical usecase is to escalate a 50% ring full to 75% full if noone has yet + * Typical usecase is to escalate a 50% ring full to 75% full if no one has yet * read the first event. Clearly the 50% full is no longer of interest in * typical use case. **/ diff --git a/drivers/staging/intel_sst/TODO b/drivers/staging/intel_sst/TODO index a24e5ed5689c..c733d7011091 100644 --- a/drivers/staging/intel_sst/TODO +++ b/drivers/staging/intel_sst/TODO @@ -1,7 +1,7 @@ TODO ---- -Get the memrar driver cleaned up and upstream (dependancy blocking SST) +Get the memrar driver cleaned up and upstream (dependency blocking SST) Replace long/short press with two virtual buttons Review the printks and kill off any left over ST_ERR: messages Review the misc device ioctls for 32/64bit safety and sanity diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c index ce4a9f79ccd2..81c24d19eb9e 100644 --- a/drivers/staging/intel_sst/intel_sst.c +++ b/drivers/staging/intel_sst/intel_sst.c @@ -263,7 +263,7 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, /* Init the device */ ret = pci_enable_device(pci); if (ret) { - pr_err("device cant be enabled\n"); + pr_err("device can't be enabled\n"); goto do_free_mem; } sst_drv_ctx->pci = pci_dev_get(pci); @@ -453,7 +453,7 @@ int intel_sst_resume(struct pci_dev *pci) pci_restore_state(pci); ret = pci_enable_device(pci); if (ret) - pr_err("device cant be enabled\n"); + pr_err("device can't be enabled\n"); mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_UN_INIT; diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c index a367991d5600..1d0621260ea8 100644 --- a/drivers/staging/intel_sst/intel_sst_app_interface.c +++ b/drivers/staging/intel_sst/intel_sst_app_interface.c @@ -236,7 +236,7 @@ int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma) if (!sst_drv_ctx->mmap_mem) return -EIO; - /* round it up to the page bondary */ + /* round it up to the page boundary */ /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem) + PAGE_SIZE - 1) & PAGE_MASK);*/ mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem); @@ -871,7 +871,7 @@ int sst_send_algo_ipc(struct ipc_post **msg) } /** - * intel_sst_ioctl_dsp - recieves the device ioctl's + * intel_sst_ioctl_dsp - receives the device ioctl's * * @cmd:Ioctl cmd * @arg:data @@ -1067,7 +1067,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - pr_debug("SET_VOLUME recieved for %d!\n", + pr_debug("SET_VOLUME received for %d!\n", set_vol.stream_id); if (minor == STREAM_MODULE && set_vol.stream_id == 0) { pr_debug("invalid operation!\n"); @@ -1085,7 +1085,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - pr_debug("IOCTL_GET_VOLUME recieved for stream = %d!\n", + pr_debug("IOCTL_GET_VOLUME received for stream = %d!\n", get_vol.stream_id); if (minor == STREAM_MODULE && get_vol.stream_id == 0) { pr_debug("invalid operation!\n"); @@ -1117,7 +1117,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - pr_debug("SNDRV_SST_SET_VOLUME recieved for %d!\n", + pr_debug("SNDRV_SST_SET_VOLUME received for %d!\n", set_mute.stream_id); if (minor == STREAM_MODULE && set_mute.stream_id == 0) { retval = -EPERM; @@ -1153,7 +1153,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): { struct snd_sst_mmap_buffs mmap_buf; - pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n"); + pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE received!\n"); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -1239,7 +1239,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): { struct snd_sst_target_device target_device; - pr_debug("SET_TARGET_DEVICE recieved!\n"); + pr_debug("SET_TARGET_DEVICE received!\n"); if (copy_from_user(&target_device, (void __user *)arg, sizeof(target_device))) { retval = -EFAULT; @@ -1256,7 +1256,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_DRIVER_INFO): { struct snd_sst_driver_info info; - pr_debug("SNDRV_SST_DRIVER_INFO recived\n"); + pr_debug("SNDRV_SST_DRIVER_INFO received\n"); info.version = SST_VERSION_NUM; /* hard coding, shud get sumhow later */ info.active_pcm_streams = sst_drv_ctx->stream_cnt - diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c index ea8e251b5099..e9c182108243 100644 --- a/drivers/staging/intel_sst/intel_sst_drv_interface.c +++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c @@ -315,7 +315,7 @@ int sst_open_pcm_stream(struct snd_sst_params *str_param) pm_runtime_get_sync(&sst_drv_ctx->pci->dev); if (sst_drv_ctx->sst_state == SST_SUSPENDED) { - /* LPE is suspended, resume it before proceding*/ + /* LPE is suspended, resume it before proceeding*/ pr_debug("Resuming from Suspended state\n"); retval = intel_sst_resume(sst_drv_ctx->pci); if (retval) { diff --git a/drivers/staging/intel_sst/intel_sst_dsp.c b/drivers/staging/intel_sst/intel_sst_dsp.c index 6e5c9152da9f..bffe4c6e2928 100644 --- a/drivers/staging/intel_sst/intel_sst_dsp.c +++ b/drivers/staging/intel_sst/intel_sst_dsp.c @@ -350,7 +350,7 @@ static int sst_download_library(const struct firmware *fw_lib, } -/* This function is called befoer downloading the codec/postprocessing +/* This function is called before downloading the codec/postprocessing library is set for download to SST DSP*/ static int sst_validate_library(const struct firmware *fw_lib, struct lib_slot_info *slot, @@ -405,7 +405,7 @@ exit: } -/* This function is called when FW requests for a particular libary download +/* This function is called when FW requests for a particular library download This function prepares the library to download*/ int sst_load_library(struct snd_sst_lib_download *lib, u8 ops) { diff --git a/drivers/staging/intel_sst/intel_sst_fw_ipc.h b/drivers/staging/intel_sst/intel_sst_fw_ipc.h index 8df313d10d2a..0f0c5bbc5f4b 100644 --- a/drivers/staging/intel_sst/intel_sst_fw_ipc.h +++ b/drivers/staging/intel_sst/intel_sst_fw_ipc.h @@ -111,7 +111,7 @@ #define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */ #define IPC_IA_TARGET_DEV_CHNGD 0x98 /* error in processing a stream */ -#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occured */ +#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */ /* L2S messages */ #define IPC_SC_DDR_LINK_UP 0xC0 #define IPC_SC_DDR_LINK_DOWN 0xC1 diff --git a/drivers/staging/intel_sst/intel_sst_stream.c b/drivers/staging/intel_sst/intel_sst_stream.c index 795e42ab7360..dd58be5b1975 100644 --- a/drivers/staging/intel_sst/intel_sst_stream.c +++ b/drivers/staging/intel_sst/intel_sst_stream.c @@ -98,7 +98,7 @@ static unsigned int get_mrst_stream_id(void) if (sst_drv_ctx->streams[i].status == STREAM_UN_INIT) return i; } - pr_debug("Didnt find empty stream for mrst\n"); + pr_debug("Didn't find empty stream for mrst\n"); return -EBUSY; } diff --git a/drivers/staging/intel_sst/intel_sst_stream_encoded.c b/drivers/staging/intel_sst/intel_sst_stream_encoded.c index 29753c7519a7..d5f07b878828 100644 --- a/drivers/staging/intel_sst/intel_sst_stream_encoded.c +++ b/drivers/staging/intel_sst/intel_sst_stream_encoded.c @@ -914,7 +914,7 @@ static int sst_prepare_input_buffers_rar(struct stream_info *str_info, (void *) ((unsigned long) rar_buffers.bus_address); pr_debug("RAR buf addr in DnR (input buffer function)0x%lu", (unsigned long) str_info->decode_ibuf); - pr_debug("rar in DnR decode funtion/output b_add rar =0x%lu", + pr_debug("rar in DnR decode function/output b_add rar =0x%lu", (unsigned long) rar_buffers.bus_address); *input_index = i + 1; str_info->decode_isize = dbufs->ibufs->buff_entry[i].size; diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c index fb2292186703..d207636a7b6d 100644 --- a/drivers/staging/intel_sst/intelmid.c +++ b/drivers/staging/intel_sst/intelmid.c @@ -773,7 +773,7 @@ static int __devinit snd_intelmad_sst_register( if (ret_val) return ret_val; sst_card_vendor_id = (vendor_addr.value & (MASK2|MASK1|MASK0)); - pr_debug("orginal n extrated vendor id = 0x%x %d\n", + pr_debug("original n extrated vendor id = 0x%x %d\n", vendor_addr.value, sst_card_vendor_id); if (sst_card_vendor_id < 0 || sst_card_vendor_id > 2) { pr_err("vendor card not supported!!\n"); diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h index ca881b790cb2..e77da87e1df0 100644 --- a/drivers/staging/intel_sst/intelmid.h +++ b/drivers/staging/intel_sst/intelmid.h @@ -90,7 +90,7 @@ struct mad_jack_msg_wq { * @card_index: sound card index * @card_id: sound card id detected * @sstdrv_ops: ptr to sst driver ops - * @pdev: ptr to platfrom device + * @pdev: ptr to platform device * @irq: interrupt number detected * @pmic_status: Device status of sound card * @int_base: ptr to MMIO interrupt region diff --git a/drivers/staging/keucr/init.c b/drivers/staging/keucr/init.c index 5c01f28f0734..8af7c84daee2 100644 --- a/drivers/staging/keucr/init.c +++ b/drivers/staging/keucr/init.c @@ -90,7 +90,7 @@ int ENE_MSInit(struct us_data *us) result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0); if (result != USB_STOR_XFER_GOOD) { - printk(KERN_ERR "Exection MS Init Code Fail !!\n"); + printk(KERN_ERR "Execution MS Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -145,7 +145,7 @@ int ENE_SMInit(struct us_data *us) result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0); if (result != USB_STOR_XFER_GOOD) { printk(KERN_ERR - "Exection SM Init Code Fail !! result = %x\n", result); + "Execution SM Init Code Fail !! result = %x\n", result); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c index 2cbe9f897eef..95c688a5c95a 100644 --- a/drivers/staging/keucr/smilmain.c +++ b/drivers/staging/keucr/smilmain.c @@ -64,7 +64,7 @@ extern struct SSFDCTYPE Ssfdc; extern struct ADDRESS Media; extern struct CIS_AREA CisArea; -//BIT Controll Macro +//BIT Control Macro BYTE BitData[] = { 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 } ; #define Set_D_Bit(a,b) (a[(BYTE)((b)/8)]|= BitData[(b)%8]) #define Clr_D_Bit(a,b) (a[(BYTE)((b)/8)]&=~BitData[(b)%8]) @@ -76,7 +76,7 @@ extern BYTE IsXDCompliance; // -////Power Controll & Media Exist Check Function +////Power Control & Media Exist Check Function ////----- Init_D_SmartMedia() -------------------------------------------- //int Init_D_SmartMedia(void) //{ @@ -575,7 +575,7 @@ int Media_D_OneSectWriteFlush(PFDO_DEVICE_EXTENSION fdoExt) // return(SUCCESS); //} // -////Power Controll & Media Exist Check Subroutine +////Power Control & Media Exist Check Subroutine ////----- Initialize_D_Media() ------------------------------------------- //void Initialize_D_Media(void) //{ @@ -738,7 +738,7 @@ int Check_D_MediaFmt(struct us_data *us) // return(SUCCESS); //} */ -//SmartMedia Physical Address Controll Subroutine +//SmartMedia Physical Address Control Subroutine //----- Conv_D_MediaAddr() --------------------------------------------- int Conv_D_MediaAddr(struct us_data *us, DWORD addr) { diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c index 80da61c37bff..4fe47422eb79 100644 --- a/drivers/staging/keucr/smilsub.c +++ b/drivers/staging/keucr/smilsub.c @@ -57,7 +57,7 @@ extern WORD WriteBlock; #define ODD 1 // Odd Page for 256byte/page -//SmartMedia Redundant buffer data Controll Subroutine +//SmartMedia Redundant buffer data Control Subroutine //----- Check_D_DataBlank() -------------------------------------------- int Check_D_DataBlank(BYTE *redundant) { @@ -1367,7 +1367,7 @@ BYTE _Check_D_DevCode(BYTE dcode) } } /* -////SmartMedia Power Controll Subroutine +////SmartMedia Power Control Subroutine ////----- Cnt_D_Reset() ---------------------------------------------- //void Cnt_D_Reset(void) //{ @@ -1478,7 +1478,7 @@ BYTE _Check_D_DevCode(BYTE dcode) //} // */ -//SmartMedia ECC Controll Subroutine +//SmartMedia ECC Control Subroutine //----- Check_D_ReadError() ---------------------------------------------- int Check_D_ReadError(BYTE *redundant) { diff --git a/drivers/staging/lirc/lirc_ene0100.h b/drivers/staging/lirc/lirc_ene0100.h index 776b693bb307..06bebd6acc46 100644 --- a/drivers/staging/lirc/lirc_ene0100.h +++ b/drivers/staging/lirc/lirc_ene0100.h @@ -81,7 +81,7 @@ /* CIR block settings */ #define ENE_CIR_CONF1 0xFEC0 -#define ENE_CIR_CONF1_ADC_ON 0x7 /* reciever on gpio40 enabled */ +#define ENE_CIR_CONF1_ADC_ON 0x7 /* receiver on gpio40 enabled */ #define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */ #define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */ #define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */ @@ -96,7 +96,7 @@ /* transmitter - not implemented yet */ /* KB3926C and higher */ -/* transmission is very similiar to recieving, a byte is written to */ +/* transmission is very similar to receiving, a byte is written to */ /* ENE_TX_INPUT, in same manner as it is read from sample buffer */ /* sample period is fixed*/ diff --git a/drivers/staging/memrar/memrar_handler.c b/drivers/staging/memrar/memrar_handler.c index cfcaa8e5b8e6..1d9399d6f10f 100644 --- a/drivers/staging/memrar/memrar_handler.c +++ b/drivers/staging/memrar/memrar_handler.c @@ -690,7 +690,7 @@ static int memrar_mmap(struct file *filp, struct vm_area_struct *vma) * @inode: inode to open * @filp: file handle * - * As we support multiple arbitary opens there is no work to be done + * As we support multiple arbitrary opens there is no work to be done * really. */ diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c index de284c28faa1..b9acf5299297 100644 --- a/drivers/staging/msm/mdp4_overlay.c +++ b/drivers/staging/msm/mdp4_overlay.c @@ -696,7 +696,7 @@ void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe) stage = pipe->mixer_stage; mixer = pipe->mixer_num; - if (pipe != ctrl->stage[mixer][stage]) /* not runing */ + if (pipe != ctrl->stage[mixer][stage]) /* not running */ return; /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c index 3dc1c0cc61f9..3a687c7a5695 100644 --- a/drivers/staging/msm/mdp_ppp_dq.c +++ b/drivers/staging/msm/mdp_ppp_dq.c @@ -200,7 +200,7 @@ static void mdp_ppp_flush_dirty_djobs(void *cond) msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1); /* Schedule jobs for cleanup - * A seperate worker thread does this */ + * A separate worker thread does this */ queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner, mdp_timer_duration); } diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c index a2f29d464051..e7ef836eb8de 100644 --- a/drivers/staging/msm/msm_fb.c +++ b/drivers/staging/msm/msm_fb.c @@ -859,7 +859,7 @@ static int msm_fb_register(struct msm_fb_data_type *mfd) break; default: - MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n", + MSM_FB_ERR("msm_fb_init: fb %d unknown image type!\n", mfd->index); return ret; } @@ -1793,9 +1793,9 @@ static int msmfb_async_blit(struct fb_info *info, void __user *p) /* * NOTE: The userspace issues blit operations in a sequence, the sequence * start with a operation marked START and ends in an operation marked - * END. It is guranteed by the userspace that all the blit operations + * END. It is guaranteed by the userspace that all the blit operations * between START and END are only within the regions of areas designated - * by the START and END operations and that the userspace doesnt modify + * by the START and END operations and that the userspace doesn't modify * those areas. Hence it would be enough to perform barrier/cache operations * only on the START and END operations. */ diff --git a/drivers/staging/octeon/cvmx-cmd-queue.h b/drivers/staging/octeon/cvmx-cmd-queue.h index 59d221422293..614653b686a0 100644 --- a/drivers/staging/octeon/cvmx-cmd-queue.h +++ b/drivers/staging/octeon/cvmx-cmd-queue.h @@ -214,7 +214,7 @@ static inline int __cvmx_cmd_queue_get_index(cvmx_cmd_queue_id_t queue_id) /* * Warning: This code currently only works with devices that * have 256 queues or less. Devices with more than 16 queues - * are layed out in memory to allow cores quick access to + * are laid out in memory to allow cores quick access to * every 16th queue. This reduces cache thrashing when you are * running 16 queues per port to support lockless operation. */ diff --git a/drivers/staging/octeon/cvmx-fpa.h b/drivers/staging/octeon/cvmx-fpa.h index 50a8c91778fa..1f04f9658736 100644 --- a/drivers/staging/octeon/cvmx-fpa.h +++ b/drivers/staging/octeon/cvmx-fpa.h @@ -195,7 +195,7 @@ static inline void cvmx_fpa_async_alloc(uint64_t scr_addr, uint64_t pool) cvmx_fpa_iobdma_data_t data; /* - * Hardware only uses 64 bit alligned locations, so convert + * Hardware only uses 64 bit aligned locations, so convert * from byte address to 64-bit index */ data.s.scraddr = scr_addr >> 3; diff --git a/drivers/staging/octeon/cvmx-helper-board.h b/drivers/staging/octeon/cvmx-helper-board.h index 611a8e03c216..b465bec43553 100644 --- a/drivers/staging/octeon/cvmx-helper-board.h +++ b/drivers/staging/octeon/cvmx-helper-board.h @@ -81,7 +81,7 @@ extern int cvmx_helper_board_get_mii_address(int ipd_port); * @phy_addr: The address of the PHY to program * @link_flags: * Flags to control autonegotiation. Bit 0 is autonegotiation - * enable/disable to maintain backware compatability. + * enable/disable to maintain backware compatibility. * @link_info: Link speed to program. If the speed is zero and autonegotiation * is enabled, all possible negotiation speeds are advertised. * diff --git a/drivers/staging/octeon/cvmx-helper-util.c b/drivers/staging/octeon/cvmx-helper-util.c index 41ef8a40bb03..131182bf5abb 100644 --- a/drivers/staging/octeon/cvmx-helper-util.c +++ b/drivers/staging/octeon/cvmx-helper-util.c @@ -362,7 +362,7 @@ int __cvmx_helper_setup_gmx(int interface, int num_ports) } /** - * Returns the IPD/PKO port number for a port on teh given + * Returns the IPD/PKO port number for a port on the given * interface. * * @interface: Interface to use diff --git a/drivers/staging/octeon/cvmx-helper.c b/drivers/staging/octeon/cvmx-helper.c index 591506643d02..e9c5c836ceff 100644 --- a/drivers/staging/octeon/cvmx-helper.c +++ b/drivers/staging/octeon/cvmx-helper.c @@ -691,7 +691,7 @@ int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) if (!retry_cnt) cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " - "get_work() timeout occured.\n"); + "get_work() timeout occurred.\n"); /* Free packet */ if (work) diff --git a/drivers/staging/octeon/cvmx-mdio.h b/drivers/staging/octeon/cvmx-mdio.h index f45dc49512f2..d88ab8d8e37d 100644 --- a/drivers/staging/octeon/cvmx-mdio.h +++ b/drivers/staging/octeon/cvmx-mdio.h @@ -254,7 +254,7 @@ typedef union { #define MDIO_CLAUSE_45_READ_INC 2 #define MDIO_CLAUSE_45_READ 3 -/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */ +/* MMD identifiers, mostly for accessing devices within XENPAK modules. */ #define CVMX_MMD_DEVICE_PMA_PMD 1 #define CVMX_MMD_DEVICE_WIS 2 #define CVMX_MMD_DEVICE_PCS 3 diff --git a/drivers/staging/octeon/cvmx-pko.h b/drivers/staging/octeon/cvmx-pko.h index f068c1982497..de3412aada5d 100644 --- a/drivers/staging/octeon/cvmx-pko.h +++ b/drivers/staging/octeon/cvmx-pko.h @@ -98,7 +98,7 @@ typedef enum { /* * PKO doesn't do any locking. It is the responsibility of the * application to make sure that no other core is accessing - * the same queue at the smae time + * the same queue at the same time */ CVMX_PKO_LOCK_NONE = 0, /* @@ -324,7 +324,7 @@ static inline void cvmx_pko_doorbell(uint64_t port, uint64_t queue, * - CVMX_PKO_LOCK_NONE * - PKO doesn't do any locking. It is the responsibility * of the application to make sure that no other core - * is accessing the same queue at the smae time. + * is accessing the same queue at the same time. * - CVMX_PKO_LOCK_ATOMIC_TAG * - PKO performs an atomic tagswitch to insure exclusive * access to the output queue. This will maintain diff --git a/drivers/staging/octeon/cvmx-pow.h b/drivers/staging/octeon/cvmx-pow.h index bf9e069a898c..999aefe3274c 100644 --- a/drivers/staging/octeon/cvmx-pow.h +++ b/drivers/staging/octeon/cvmx-pow.h @@ -1492,8 +1492,8 @@ static inline void cvmx_pow_tag_sw_full(cvmx_wqe_t *wqp, uint32_t tag, /** * Switch to a NULL tag, which ends any ordering or * synchronization provided by the POW for the current - * work queue entry. This operation completes immediatly, - * so completetion should not be waited for. + * work queue entry. This operation completes immediately, + * so completion should not be waited for. * This function does NOT wait for previous tag switches to complete, * so the caller must ensure that any previous tag switches have completed. */ @@ -1532,8 +1532,8 @@ static inline void cvmx_pow_tag_sw_null_nocheck(void) /** * Switch to a NULL tag, which ends any ordering or * synchronization provided by the POW for the current - * work queue entry. This operation completes immediatly, - * so completetion should not be waited for. + * work queue entry. This operation completes immediately, + * so completion should not be waited for. * This function waits for any pending tag switches to complete * before requesting the switch to NULL. */ @@ -1672,7 +1672,7 @@ static inline void cvmx_pow_set_priority(uint64_t core_num, /** * Performs a tag switch and then an immediate deschedule. This completes - * immediatly, so completion must not be waited for. This function does NOT + * immediately, so completion must not be waited for. This function does NOT * update the wqe in DRAM to match arguments. * * This function does NOT wait for any prior tag switches to complete, so the @@ -1758,7 +1758,7 @@ static inline void cvmx_pow_tag_sw_desched_nocheck( /** * Performs a tag switch and then an immediate deschedule. This completes - * immediatly, so completion must not be waited for. This function does NOT + * immediately, so completion must not be waited for. This function does NOT * update the wqe in DRAM to match arguments. * * This function waits for any prior tag switches to complete, so the diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h index 23467563fe57..c745a72a0594 100644 --- a/drivers/staging/octeon/ethernet-util.h +++ b/drivers/staging/octeon/ethernet-util.h @@ -55,7 +55,7 @@ static inline int INTERFACE(int ipd_port) return 2; else if (ipd_port < 40) /* Interface 3 for loopback */ return 3; - else if (ipd_port == 40) /* Non existant interface for POW0 */ + else if (ipd_port == 40) /* Non existent interface for POW0 */ return 4; else panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port); diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c index b154be7a2fe6..b5d21f6497f9 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c @@ -80,7 +80,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon) lob &= ~(1 << DCON_IRQ); outb(lob, 0x4d0); - /* Register the interupt handler */ + /* Register the interrupt handler */ if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) { printk(KERN_ERR "olpc-dcon: failed to request DCON's irq\n"); goto err_req_irq; diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c index 6540864216c8..5cca24fcf6ca 100644 --- a/drivers/staging/pohmelfs/crypto.c +++ b/drivers/staging/pohmelfs/crypto.c @@ -745,7 +745,7 @@ static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb) /* * At this point NETFS_CAPABILITIES response command - * should setup superblock in a way, which is acceptible + * should setup superblock in a way, which is acceptable * for both client and server, so if server refuses connection, * it will send error in transaction response. */ diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c index c45b09ed0d35..ca098cabc2bc 100644 --- a/drivers/staging/quatech_usb2/quatech_usb2.c +++ b/drivers/staging/quatech_usb2/quatech_usb2.c @@ -148,7 +148,7 @@ static struct usb_driver quausb2_usb_driver = { * value of the line status flags from the port * @shadowMSR: Last received state of the modem status register, holds * the value of the modem status received from the port - * @rcv_flush: Flag indicating that a receive flush has occured on + * @rcv_flush: Flag indicating that a receive flush has occurred on * the hardware. * @xmit_flush: Flag indicating that a transmit flush has been processed by * the hardware. @@ -156,7 +156,7 @@ static struct usb_driver quausb2_usb_driver = { * includes the size (excluding header) of URBs that have been submitted but * have not yet been sent to to the device, and bytes that have been sent out * of the port but not yet reported sent by the "xmit_empty" messages (which - * indicate the number of bytes sent each time they are recieved, despite the + * indicate the number of bytes sent each time they are received, despite the * misleading name). * - Starts at zero when port is initialised. * - is incremented by the size of the data to be written (no headers) @@ -649,7 +649,7 @@ static void qt2_close(struct usb_serial_port *port) /* although the USB side is now empty, the UART itself may * still be pushing characters out over the line, so we have to * wait testing the actual line status until the lines change - * indicating that the data is done transfering. */ + * indicating that the data is done transferring. */ /* FIXME: slow this polling down so it doesn't run the USB bus flat out * if it actually has to spend any time in this loop (which it normally * doesn't because the buffer is nearly empty) */ @@ -726,7 +726,7 @@ static int qt2_write(struct tty_struct *tty, struct usb_serial_port *port, return 0; } else if (port_extra->tx_pending_bytes >= QT2_FIFO_DEPTH) { /* buffer is full (==). > should not occur, but would indicate - * that an overflow had occured */ + * that an overflow had occurred */ dbg("%s(): port transmit buffer is full!", __func__); /* schedule_work(&port->work); commented in vendor driver */ return 0; @@ -823,7 +823,7 @@ static int qt2_write_room(struct tty_struct *tty) * reduce the free space count by the size of the dispatched write. * When a "transmit empty" message comes back up the USB read stream, * we decrement the count by the number of bytes reported sent, thus - * keeping track of the difference between sent and recieved bytes. + * keeping track of the difference between sent and received bytes. */ room = (QT2_FIFO_DEPTH - port_extra->tx_pending_bytes); @@ -1795,7 +1795,7 @@ static void qt2_process_rx_char(struct usb_serial_port *port, } } -/** @brief Retreive the value of a register from the device +/** @brief Retrieve the value of a register from the device * * Issues a GET_REGISTER vendor-spcific request over the USB control * pipe to obtain a value back from a specific register on a specific diff --git a/drivers/staging/rt2860/chip/rtmp_phy.h b/drivers/staging/rt2860/chip/rtmp_phy.h index 98454df30a22..a52221f1294e 100644 --- a/drivers/staging/rt2860/chip/rtmp_phy.h +++ b/drivers/staging/rt2860/chip/rtmp_phy.h @@ -467,7 +467,7 @@ DBGPRINT_ERR("BBP write R%d=0x%x fail. BusyCnt= %d.bPCIclkOff = %d. \n", _I, BbpCsr.word, BusyCnt, (_A)->bPCIclkOff); \ } \ } else { \ - DBGPRINT_ERR("****** BBP_Write_Latch Buffer exceeds max boundry ****** \n"); \ + DBGPRINT_ERR("****** BBP_Write_Latch Buffer exceeds max boundary ****** \n"); \ } \ } #endif /* RTMP_MAC_PCI // */ diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c index 62f6f6be4acb..133bc1b87d2c 100644 --- a/drivers/staging/rt2860/common/ba_action.c +++ b/drivers/staging/rt2860/common/ba_action.c @@ -28,7 +28,7 @@ #include "../rt_config.h" #include -#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // inital sequence number of BA session */ +#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // initial sequence number of BA session */ #define ORI_SESSION_MAX_RETRY 8 #define ORI_BA_SESSION_TIMEOUT (2000) /* ms */ @@ -1487,7 +1487,7 @@ static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd, /* * flush all pending reordering mpdus - * and receving mpdu to upper layer + * and receiving mpdu to upper layer * make tcp/ip to take care reordering mechanism */ /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ diff --git a/drivers/staging/rt2860/common/cmm_aes.c b/drivers/staging/rt2860/common/cmm_aes.c index a99879bada42..d70d229a6e53 100644 --- a/drivers/staging/rt2860/common/cmm_aes.c +++ b/drivers/staging/rt2860/common/cmm_aes.c @@ -858,7 +858,7 @@ static uint32 KT1[256]; static uint32 KT2[256]; static uint32 KT3[256]; -/* platform-independant 32-bit integer manipulation macros */ +/* platform-independent 32-bit integer manipulation macros */ #define GET_UINT32(n,b,i) \ { \ diff --git a/drivers/staging/rt2860/common/cmm_cfg.c b/drivers/staging/rt2860/common/cmm_cfg.c index 24f439378439..727f79929258 100644 --- a/drivers/staging/rt2860/common/cmm_cfg.c +++ b/drivers/staging/rt2860/common/cmm_cfg.c @@ -223,7 +223,7 @@ int RT_CfgSetWepKey(struct rt_rtmp_adapter *pAd, pAdapter Pointer to our adapter keyString WPA pre-shared key string pHashStr String used for password hash function - hashStrLen Lenght of the hash string + hashStrLen Length of the hash string pPMKBuf Output buffer of WPAPSK key Return: diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c index f6c193cb84ee..33799e1449ae 100644 --- a/drivers/staging/rt2860/common/cmm_data.c +++ b/drivers/staging/rt2860/common/cmm_data.c @@ -337,7 +337,7 @@ int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd, /* */ /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ - /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ + /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ /* if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) */ { if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || @@ -1933,7 +1933,7 @@ BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket) if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */ /* - DestMAC(6) + SrcMAC(6) + Lenght(2) + + DestMAC(6) + SrcMAC(6) + Length(2) + DSAP(1) + SSAP(1) + Control(1) + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. => + SNAP (5, OriginationID(3) + etherType(2)) diff --git a/drivers/staging/rt2860/common/cmm_data_pci.c b/drivers/staging/rt2860/common/cmm_data_pci.c index 7af59ff9e220..bef0bbd8cef7 100644 --- a/drivers/staging/rt2860/common/cmm_data_pci.c +++ b/drivers/staging/rt2860/common/cmm_data_pci.c @@ -438,13 +438,13 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, /* Add Rx size to channel load counter, we should ignore error counts */ pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14); - /* Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics */ + /* Drop ToDs promiscuous frame, it is opened due to CCX 2 channel load statistics */ if (pHeader != NULL) { if (pHeader->FC.ToDs) { return (NDIS_STATUS_FAILURE); } } - /* Drop not U2M frames, cant's drop here because we will drop beacon in this case */ + /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */ /* I am kind of doubting the U2M bit operation */ /* if (pRxD->U2M == 0) */ /* return(NDIS_STATUS_FAILURE); */ @@ -939,7 +939,7 @@ int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd, /* */ /* */ /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ - /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ + /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ if (pHeader_802_11->FC.Type != BTYPE_DATA) { if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable diff --git a/drivers/staging/rt2860/common/cmm_data_usb.c b/drivers/staging/rt2860/common/cmm_data_usb.c index 7c56c2f51987..5637857ae9eb 100644 --- a/drivers/staging/rt2860/common/cmm_data_usb.c +++ b/drivers/staging/rt2860/common/cmm_data_usb.c @@ -702,7 +702,7 @@ Arguments: *pRxPending pending received packet flag Return Value: - the recieved packet + the received packet Note: ======================================================================== @@ -850,7 +850,7 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, /* Add Rx size to channel load counter, we should ignore error counts */ pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount + 14); - /* Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics */ + /* Drop ToDs promiscuous frame, it is opened due to CCX 2 channel load statistics */ if (pHeader->FC.ToDs) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n")); return NDIS_STATUS_FAILURE; @@ -860,7 +860,7 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n")); return NDIS_STATUS_FAILURE; } - /* Drop not U2M frames, cant's drop here because we will drop beacon in this case */ + /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */ /* I am kind of doubting the U2M bit operation */ /* if (pRxD->U2M == 0) */ /* return(NDIS_STATUS_FAILURE); */ diff --git a/drivers/staging/rt2860/common/cmm_mac_pci.c b/drivers/staging/rt2860/common/cmm_mac_pci.c index 21eed2507e1c..d06f0a6dc379 100644 --- a/drivers/staging/rt2860/common/cmm_mac_pci.c +++ b/drivers/staging/rt2860/common/cmm_mac_pci.c @@ -1446,7 +1446,7 @@ BOOLEAN RT28xxPciAsicRadioOff(struct rt_rtmp_adapter *pAd, pAd->CheckDmaBusyCount = 0; } */ -/*KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it. */ +/*KH Debug:My original codes have the following codes, but currecnt codes do not have it. */ /* Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment. */ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280); /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ); */ diff --git a/drivers/staging/rt2860/common/cmm_sanity.c b/drivers/staging/rt2860/common/cmm_sanity.c index 6b003c903444..3bfb4ad00c1a 100644 --- a/drivers/staging/rt2860/common/cmm_sanity.c +++ b/drivers/staging/rt2860/common/cmm_sanity.c @@ -67,7 +67,7 @@ BOOLEAN MlmeAddBAReqSanity(struct rt_rtmp_adapter *pAd, if ((MsgLen != sizeof(struct rt_mlme_addba_req))) { DBGPRINT(RT_DEBUG_TRACE, - ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); + ("MlmeAddBAReqSanity fail - message length not correct.\n")); return FALSE; } @@ -104,7 +104,7 @@ BOOLEAN MlmeDelBAReqSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned lon if ((MsgLen != sizeof(struct rt_mlme_delba_req))) { DBGPRINT(RT_DEBUG_ERROR, - ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + ("MlmeDelBAReqSanity fail - message length not correct.\n")); return FALSE; } diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c index f84194da47bc..aefe1b774650 100644 --- a/drivers/staging/rt2860/common/cmm_sync.c +++ b/drivers/staging/rt2860/common/cmm_sync.c @@ -694,7 +694,7 @@ void ScanNextChannel(struct rt_rtmp_adapter *pAd) MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } - /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse */ + /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe response */ pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; } diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c index 0040f45b629b..616ebec50c61 100644 --- a/drivers/staging/rt2860/common/cmm_wpa.c +++ b/drivers/staging/rt2860/common/cmm_wpa.c @@ -1222,7 +1222,7 @@ void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd, Note: All these constants are defined in wpa.h - For supplicant, there is only EAPOL Key message avaliable + For supplicant, there is only EAPOL Key message available ======================================================================== */ @@ -1267,7 +1267,7 @@ BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType) int prefix_len - the length of the label u8 *data - a specific data with variable length int data_len - the length of a specific data - int len - the output lenght + int len - the output length Return Value: u8 *output - the calculated result diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c index d9c3fd5c2166..e48eac0f3a29 100644 --- a/drivers/staging/rt2860/common/mlme.c +++ b/drivers/staging/rt2860/common/mlme.c @@ -632,7 +632,7 @@ void MlmeHalt(struct rt_rtmp_adapter *pAd) pChipOps->AsicHaltAction(pAd); } - RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled */ + RTMPusecDelay(5000); /* 5 msec to guarantee Ant Diversity timer canceled */ MlmeQueueDestroy(&pAd->Mlme.Queue); NdisFreeSpinLock(&pAd->Mlme.TaskLock); @@ -1107,14 +1107,14 @@ void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd, *pInitTxRateIdx = RateSwitchTable11N1S[1]; DBGPRINT_RAW(RT_DEBUG_ERROR, - ("DRS: unkown mode,default use 11N 1S AP \n")); + ("DRS: unknown mode,default use 11N 1S AP \n")); } else { *ppTable = RateSwitchTable11N2S; *pTableSize = RateSwitchTable11N2S[0]; *pInitTxRateIdx = RateSwitchTable11N2S[1]; DBGPRINT_RAW(RT_DEBUG_ERROR, - ("DRS: unkown mode,default use 11N 2S AP \n")); + ("DRS: unknown mode,default use 11N 2S AP \n")); } } else { if (pAd->CommonCfg.TxStream == 1) { @@ -1123,7 +1123,7 @@ void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd, *pInitTxRateIdx = RateSwitchTable11N1S[1]; DBGPRINT_RAW(RT_DEBUG_ERROR, - ("DRS: unkown mode,default use 11N 1S AP \n")); + ("DRS: unknown mode,default use 11N 1S AP \n")); } else { *ppTable = RateSwitchTable11N2SForABand; *pTableSize = @@ -1131,11 +1131,11 @@ void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd, *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; DBGPRINT_RAW(RT_DEBUG_ERROR, - ("DRS: unkown mode,default use 11N 2S AP \n")); + ("DRS: unknown mode,default use 11N 2S AP \n")); } } DBGPRINT_RAW(RT_DEBUG_ERROR, - ("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", + ("DRS: unknown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], @@ -1368,7 +1368,7 @@ void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd) if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) { DBGPRINT(RT_DEBUG_TRACE, - ("MMCHK - Roaming, No eligable entry, try new scan!\n")); + ("MMCHK - Roaming, No eligible entry, try new scan!\n")); pAd->StaCfg.ScanCnt = 2; pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; @@ -2828,7 +2828,7 @@ void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter) /* IRQL = PASSIVE_LEVEL */ /* IRQL = DISPATCH_LEVEL */ -/* bLinkUp is to identify the inital link speed. */ +/* bLinkUp is to identify the initial link speed. */ /* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */ void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx) { diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c index d359a14f5d4d..5fa193eac0d3 100644 --- a/drivers/staging/rt2860/common/rtmp_init.c +++ b/drivers/staging/rt2860/common/rtmp_init.c @@ -2037,7 +2037,7 @@ void NICUpdateFifoStaCounters(struct rt_rtmp_adapter *pAd) pEntry->FIFOCount = 0; pEntry->OneSecTxNoRetryOkCount++; - /* update NoDataIdleCount when sucessful send packet to STA. */ + /* update NoDataIdleCount when successful send packet to STA. */ pEntry->NoDataIdleCount = 0; pEntry->ContinueTxFailCnt = 0; } @@ -2516,7 +2516,7 @@ void UserCfgInit(struct rt_rtmp_adapter *pAd) /*pAd->TurnAggrBulkInCount = 0; */ pAd->bUsbTxBulkAggre = 0; - /* init as unsed value to ensure driver will set to MCU once. */ + /* init as unused value to ensure driver will set to MCU once. */ pAd->LedIndicatorStrength = 0xFF; pAd->CommonCfg.MaxPktOneTxBulk = 2; @@ -3076,11 +3076,11 @@ void RTMPSetLED(struct rt_rtmp_adapter *pAd, u8 Status) ======================================================================== Routine Description: - Set LED Signal Stregth + Set LED Signal Strength Arguments: pAd Pointer to our adapter - Dbm Signal Stregth + Dbm Signal Strength Return Value: None @@ -3090,7 +3090,7 @@ void RTMPSetLED(struct rt_rtmp_adapter *pAd, u8 Status) Note: Can be run on any IRQL level. - According to Microsoft Zero Config Wireless Signal Stregth definition as belows. + According to Microsoft Zero Config Wireless Signal Strength definition as belows. <= -90 No Signal <= -81 Very Low <= -71 Low @@ -3118,7 +3118,7 @@ void RTMPSetSignalLED(struct rt_rtmp_adapter *pAd, IN NDIS_802_11_RSSI Dbm) nLed = 31; /* */ - /* Update Signal Stregth to firmware if changed. */ + /* Update Signal Strength to firmware if changed. */ /* */ if (pAd->LedIndicatorStrength != nLed) { AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, @@ -3166,7 +3166,7 @@ void RTMPEnableRxTx(struct rt_rtmp_adapter *pAd) if (pAd->CommonCfg.PSPXlink) rx_filter_flag = PSPXLINK; else - rx_filter_flag = STANORMAL; /* Staion not drop control frame will fail WiFi Certification. */ + rx_filter_flag = STANORMAL; /* Station not drop control frame will fail WiFi Certification. */ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); } diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c index c0d2f428069c..ceb622df12d7 100644 --- a/drivers/staging/rt2860/common/spectrum.c +++ b/drivers/staging/rt2860/common/spectrum.c @@ -1058,8 +1058,8 @@ static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd, 3. Measure Token. 4. Measure Request Mode. 5. Measure Request Type. - 6. Length of Report Infomation - 7. Pointer of Report Infomation Buffer. + 6. Length of Report Information + 7. Pointer of Report Information Buffer. Return : None. ========================================================================== @@ -1400,7 +1400,7 @@ static void StartDFSProcedure(struct rt_rtmp_adapter *pAd, Parametrs: 1. MLME message containing the received frame 2. message length. - 3. Channel switch announcement infomation buffer. + 3. Channel switch announcement information buffer. Return : None. ========================================================================== @@ -1465,7 +1465,7 @@ static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd, Parametrs: 1. MLME message containing the received frame 2. message length. - 3. Measurement request infomation buffer. + 3. Measurement request information buffer. Return : None. ========================================================================== @@ -1538,8 +1538,8 @@ static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd, Parametrs: 1. MLME message containing the received frame 2. message length. - 3. Measurement report infomation buffer. - 4. basic report infomation buffer. + 3. Measurement report information buffer. + 4. basic report information buffer. Return : None. ========================================================================== diff --git a/drivers/staging/rt2860/mlme.h b/drivers/staging/rt2860/mlme.h index cd1ee3d7a91d..a285851692ee 100644 --- a/drivers/staging/rt2860/mlme.h +++ b/drivers/staging/rt2860/mlme.h @@ -374,7 +374,7 @@ struct PACKED rt_sec_cha_offset_ie { struct rt_ht_phy_info { BOOLEAN bHtEnable; /* If we should use ht rate. */ BOOLEAN bPreNHt; /* If we should use ht rate. */ - /*Substract from HT Capability IE */ + /*Subtract from HT Capability IE */ u8 MCSSet[16]; }; @@ -392,7 +392,7 @@ struct rt_ht_capability { u16 AmsduSize:1; /* Max receiving A-MSDU size */ u16 rsv:5; - /*Substract from Addiont HT INFO IE */ + /*Subtract from Addiont HT INFO IE */ u8 MaxRAmpduFactor:2; u8 MpduDensity:3; u8 ExtChanOffset:2; /* Please note the difference with following u8 NewExtChannelOffset; from 802.11n */ @@ -410,7 +410,7 @@ struct rt_ht_capability { u8 BSSCoexist2040; }; -/* field in Addtional HT Information IE . */ +/* field in Additional HT Information IE . */ struct PACKED rt_add_htinfo { u8 ExtChanOffset:2; u8 RecomWidth:1; @@ -857,7 +857,7 @@ struct rt_state_machine { }; /* MLME AUX data structure that holds temporarliy settings during a connection attempt. */ -/* Once this attemp succeeds, all settings will be copy to pAd->StaActive. */ +/* Once this attempt succeeds, all settings will be copy to pAd->StaActive. */ /* A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of */ /* several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely */ /* separate this under-trial settings away from pAd->StaActive so that once */ diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c index e5b042712430..1583347fcd52 100644 --- a/drivers/staging/rt2860/rt_linux.c +++ b/drivers/staging/rt2860/rt_linux.c @@ -283,7 +283,7 @@ BOOLEAN OS_Need_Clone_Packet(void) Arguments: pAd Pointer to our adapter pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU. - *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet. + *pSrcTotalLen return total packet length. This length is calculated with 802.3 format packet. Return Value: NDIS_STATUS_SUCCESS diff --git a/drivers/staging/rt2860/rt_pci_rbus.c b/drivers/staging/rt2860/rt_pci_rbus.c index e5fb67cd9a68..f80ab4e6a0ac 100644 --- a/drivers/staging/rt2860/rt_pci_rbus.c +++ b/drivers/staging/rt2860/rt_pci_rbus.c @@ -619,7 +619,7 @@ IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance) Or kernel will panic after ifconfig ra0 down sometimes */ /* */ - /* Inital the Interrupt source. */ + /* Initial the Interrupt source. */ /* */ IntSource.word = 0x00000000L; /* McuIntSource.word = 0x00000000L; */ diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h index d16b06a6e2ac..3c31340c946a 100644 --- a/drivers/staging/rt2860/rtmp.h +++ b/drivers/staging/rt2860/rtmp.h @@ -756,7 +756,7 @@ struct rt_tkip_key_info { /* */ struct rt_private { u32 SystemResetCnt; /* System reset counter */ - u32 TxRingFullCnt; /* Tx ring full occurrance number */ + u32 TxRingFullCnt; /* Tx ring full occurrence number */ u32 PhyRxErrCnt; /* PHY Rx error count, for debug purpose, might move to global counter */ /* Variables for WEP encryption / decryption in rtmp_wep.c */ u32 FCSCRC32; @@ -925,7 +925,7 @@ struct rt_mlme { **************************************************************************/ struct reordering_mpdu { struct reordering_mpdu *next; - void *pPacket; /* coverted to 802.3 frame */ + void *pPacket; /* converted to 802.3 frame */ int Sequence; /* sequence number of MPDU */ BOOLEAN bAMSDU; }; diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c index 5717e12a9544..49b1013e7a03 100644 --- a/drivers/staging/rt2860/sta_ioctl.c +++ b/drivers/staging/rt2860/sta_ioctl.c @@ -2460,7 +2460,7 @@ int rt28xx_sta_ioctl(IN struct net_device *net_dev, } } - { /* determine this ioctl command is comming from which interface. */ + { /* determine this ioctl command is coming from which interface. */ pObj->ioctl_if_type = INT_MAIN; pObj->ioctl_if = MAIN_MBSSID; } diff --git a/drivers/staging/rt2870/common/rtusb_bulk.c b/drivers/staging/rt2870/common/rtusb_bulk.c index d2746f8732e6..679b802d2169 100644 --- a/drivers/staging/rt2870/common/rtusb_bulk.c +++ b/drivers/staging/rt2870/common/rtusb_bulk.c @@ -298,7 +298,7 @@ void RTUSBBulkOutDataPacket(struct rt_rtmp_adapter *pAd, /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */ ) { /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */ - /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ + /* For performance in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; @@ -311,7 +311,7 @@ void RTUSBBulkOutDataPacket(struct rt_rtmp_adapter *pAd, TmpBulkEndPos; break; } else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize & 0xfffff800) != 0)) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) */) { /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */ - /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ + /* For performance in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. */ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; @@ -1016,7 +1016,7 @@ void RTUSBKickBulkOut(struct rt_rtmp_adapter *pAd) RTUSBBulkOutNullFrame(pAd); } } - /* 8. No data avaliable */ + /* 8. No data available */ else ; } diff --git a/drivers/staging/rt2870/common/rtusb_data.c b/drivers/staging/rt2870/common/rtusb_data.c index 69368862217c..5b72bcdaa78f 100644 --- a/drivers/staging/rt2870/common/rtusb_data.c +++ b/drivers/staging/rt2870/common/rtusb_data.c @@ -71,7 +71,7 @@ void REPORT_AMSDU_FRAMES_TO_LLC(struct rt_rtmp_adapter *pAd, Routine Description: This subroutine will scan through releative ring descriptor to find - out avaliable free ring descriptor and compare with request size. + out available free ring descriptor and compare with request size. Arguments: pAd Pointer to our adapter diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h index dc608c70deb1..16aa6a8952fd 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -1099,7 +1099,7 @@ struct ieee80211_device { * not set. As some cards may have different HW queues that * one might want to use for data and management frames * the option to have two callbacks might be useful. - * This fucntion can't sleep. + * This function can't sleep. */ int (*softmac_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev); @@ -1138,9 +1138,9 @@ struct ieee80211_device { * it is called in a work_queue when swithcing to ad-hoc mode * or in behalf of iwlist scan when the card is associated * and root user ask for a scan. - * the fucntion stop_scan should stop both the syncro and + * the function stop_scan should stop both the syncro and * background scanning and can sleep. - * The fucntion start_scan should initiate the background + * The function start_scan should initiate the background * scanning and can't sleep. */ void (*scan_syncro)(struct net_device *dev); diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 771e0196842e..736a1404f287 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -1954,7 +1954,7 @@ associate_complete: -/* following are for a simplier TX queue management. +/* following are for a simpler TX queue management. * Instead of using netif_[stop/wake]_queue the driver * will uses these two function (plus a reset one), that * will internally uses the kernel netif_* and takes diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 70ab0084e5f5..2155a771c339 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -1591,7 +1591,7 @@ void rtl8180_rx(struct net_device *dev) priv->RSSI = RSSI; /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */ if (quality >= 127) - quality = 1; /*0; */ /* 0 will cause epc to show signal zero , walk aroud now; */ + quality = 1; /*0; */ /* 0 will cause epc to show signal zero , walk around now; */ else if (quality < 27) quality = 100; else @@ -3883,7 +3883,7 @@ void rtl8180_tx_isr(struct net_device *dev, int pri, short error) * If the packet previous of the nic pointer has been * processed this doesn't matter: it will be checked * here at the next round. Anyway if no more packet are - * TXed no memory leak occour at all. + * TXed no memory leak occur at all. */ switch (pri) { diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c index fc4907839c58..261085d4b74a 100644 --- a/drivers/staging/rtl8187se/r8180_dm.c +++ b/drivers/staging/rtl8187se/r8180_dm.c @@ -123,7 +123,7 @@ DoTxHighPower( // // Description: // Callback function of UpdateTxPowerWorkItem. -// Because of some event happend, e.g. CCX TPC, High Power Mechanism, +// Because of some event happened, e.g. CCX TPC, High Power Mechanism, // We update Tx power of current channel again. // void rtl8180_tx_pw_wq (struct work_struct *work) @@ -984,7 +984,7 @@ StaRateAdaptive87SE( { priv->TryupingCount = 0; // - // When transfering from CCK to OFDM, DIG is an important issue. + // When transferring from CCK to OFDM, DIG is an important issue. // if(priv->CurrentOperaRate == 22) bUpdateInitialGain = true; diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c index 2a2afd51cf42..3f09f76080af 100644 --- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c +++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c @@ -378,7 +378,7 @@ static u32 read_rtl8225(struct net_device *dev, u8 adr) mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1)); /* - * We must set data pin to HW controled, otherwise RF can't driver it + * We must set data pin to HW controlled, otherwise RF can't driver it * and value RF register won't be able to read back properly. */ write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01))); diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c index 3bdf9b31cc4e..4b0b830f9ab6 100644 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ b/drivers/staging/rtl8187se/r8185b_init.c @@ -1273,7 +1273,7 @@ MgntDisconnectIBSS( /* Stop Beacon. - Vista add a Adhoc profile, HW radio off untill OID_DOT11_RESET_REQUEST + Vista add a Adhoc profile, HW radio off until OID_DOT11_RESET_REQUEST Driver would set MSR=NO_LINK, then HW Radio ON, MgntQueue Stuck. Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send. diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h index 3ca388152616..dbe21ab0dbf7 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h @@ -1967,7 +1967,7 @@ struct ieee80211_device { u16 prev_seq_ctl; /* used to drop duplicate frames */ /* map of allowed channels. 0 is dummy */ - // FIXME: remeber to default to a basic channel plan depending of the PHY type + // FIXME: remember to default to a basic channel plan depending of the PHY type #ifdef ENABLE_DOT11D void* pDot11dInfo; bool bGlobalDomain; @@ -2121,7 +2121,7 @@ struct ieee80211_device { * not set. As some cards may have different HW queues that * one might want to use for data and management frames * the option to have two callbacks might be useful. - * This fucntion can't sleep. + * This function can't sleep. */ int (*softmac_hard_start_xmit)(struct sk_buff *skb, struct ieee80211_device *ieee80211); @@ -2160,9 +2160,9 @@ struct ieee80211_device { * it is called in a work_queue when swithcing to ad-hoc mode * or in behalf of iwlist scan when the card is associated * and root user ask for a scan. - * the fucntion stop_scan should stop both the syncro and + * the function stop_scan should stop both the syncro and * background scanning and can sleep. - * The fucntion start_scan should initiate the background + * The function start_scan should initiate the background * scanning and can't sleep. */ void (*scan_syncro)(struct ieee80211_device *ieee80211); diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c index add015ebba1c..ed5a38023094 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c @@ -1426,7 +1426,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; /* -* Make ther structure we read from the beacon packet has +* Make the structure we read from the beacon packet to have * the right values */ static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c index f6922d40a88a..7d4cba3a7c12 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c @@ -2023,7 +2023,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, return 1; } else - { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network. + { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network. memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen); memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen); } @@ -2163,7 +2163,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, return 0; } -/* following are for a simplier TX queue management. +/* following are for a simpler TX queue management. * Instead of using netif_[stop/wake]_queue the driver * will uses these two function (plus a reset one), that * will internally uses the kernel netif_* and takes diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h index f968817d073c..56a120cf6291 100644 --- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h @@ -64,7 +64,7 @@ typedef enum _HT_CHANNEL_WIDTH{ }HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; // -// Represent Extention Channel Offset in HT Capabilities +// Represent Extension Channel Offset in HT Capabilities // This is available only in 40Mhz mode. // typedef enum _HT_EXTCHNL_OFFSET{ diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c index a2a4fe9dd9da..f7a9da3ec829 100644 --- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c @@ -459,7 +459,7 @@ u8 HTIOTActIsForcedCTS2Self(struct ieee80211_device *ieee, struct ieee80211_netw /** * Function: HTIOTActIsDisableMCS15 * -* Overview: Check whether driver should declare capability of receving MCS15 +* Overview: Check whether driver should declare capability of receiving MCS15 * * Input: * PADAPTER Adapter, @@ -496,7 +496,7 @@ bool HTIOTActIsDisableMCS15(struct ieee80211_device* ieee) /** * Function: HTIOTActIsDisableMCSTwoSpatialStream * -* Overview: Check whether driver should declare capability of receving All 2 ss packets +* Overview: Check whether driver should declare capability of receiving All 2 ss packets * * Input: * PADAPTER Adapter, @@ -1681,7 +1681,7 @@ void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidt //if in half N mode, set to 20M bandwidth please 09.08.2008 WB. if (Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee))) { - // Handle Illegal extention channel offset!! + // Handle Illegal extension channel offset!! if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER) Offset = HT_EXTCHNL_OFFSET_NO_EXT; if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) { @@ -1698,7 +1698,7 @@ void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidt pHTInfo->bSwBwInProgress = true; - // TODO: 2007.7.13 by Emily Wait 2000ms in order to garantee that switching + // TODO: 2007.7.13 by Emily Wait 2000ms in order to guarantee that switching // bandwidth is executed after scan is finished. It is a temporal solution // because software should ganrantee the last operation of switching bandwidth // is executed properlly. diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h index baaac2149de1..e7e26fd96395 100644 --- a/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h +++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h @@ -44,7 +44,7 @@ typedef struct _RX_TS_RECORD { u16 RxTimeoutIndicateSeq; struct list_head RxPendingPktList; struct timer_list RxPktPendingTimer; - BA_RECORD RxAdmittedBARecord; // For BA Recepient + BA_RECORD RxAdmittedBARecord; // For BA Recipient u16 RxLastSeqNum; u8 RxLastFragNum; u8 num; diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c index 29eecf0ab769..ad6872dcf1c2 100644 --- a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c @@ -135,7 +135,7 @@ void ResetRxTsEntry(PRX_TS_RECORD pTS) ResetTsCommonInfo(&pTS->TsCommonInfo); pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!! pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!! - ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recepient + ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recipient } void TSInitialize(struct ieee80211_device *ieee) diff --git a/drivers/staging/rtl8192e/r819xE_phy.c b/drivers/staging/rtl8192e/r819xE_phy.c index dfa4e112ef46..9e7828ef1cbe 100644 --- a/drivers/staging/rtl8192e/r819xE_phy.c +++ b/drivers/staging/rtl8192e/r819xE_phy.c @@ -2032,13 +2032,13 @@ void rtl8192_SetBWModeWorkItem(struct r8192_priv *priv) { case HT_CHANNEL_WIDTH_20: regBwOpMode |= BW_OPMODE_20MHZ; - // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + // 2007/02/07 Mark by Emily because we have not verify whether this register works write_nic_byte(priv, BW_OPMODE, regBwOpMode); break; case HT_CHANNEL_WIDTH_20_40: regBwOpMode &= ~BW_OPMODE_20MHZ; - // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + // 2007/02/07 Mark by Emily because we have not verify whether this register works write_nic_byte(priv, BW_OPMODE, regBwOpMode); break; @@ -2116,7 +2116,7 @@ void rtl8192_SetBWModeWorkItem(struct r8192_priv *priv) } /****************************************************************************** - *function: This function schedules bandwith switch work. + *function: This function schedules bandwidth switch work. * input: struct net_device *dev * HT_CHANNEL_WIDTH Bandwidth //20M or 40M * HT_EXTCHNL_OFFSET Offset //Upper, Lower, or Don't care diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index c0b844d75c0d..e716f7b1144f 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -1965,7 +1965,7 @@ struct ieee80211_device { u16 prev_seq_ctl; /* used to drop duplicate frames */ /* map of allowed channels. 0 is dummy */ - // FIXME: remeber to default to a basic channel plan depending of the PHY type + // FIXME: remember to default to a basic channel plan depending of the PHY type void* pDot11dInfo; bool bGlobalDomain; int rate; /* current rate */ @@ -2119,7 +2119,7 @@ struct ieee80211_device { * not set. As some cards may have different HW queues that * one might want to use for data and management frames * the option to have two callbacks might be useful. - * This fucntion can't sleep. + * This function can't sleep. */ int (*softmac_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev); @@ -2158,9 +2158,9 @@ struct ieee80211_device { * it is called in a work_queue when swithcing to ad-hoc mode * or in behalf of iwlist scan when the card is associated * and root user ask for a scan. - * the fucntion stop_scan should stop both the syncro and + * the function stop_scan should stop both the syncro and * background scanning and can sleep. - * The fucntion start_scan should initiate the background + * The function start_scan should initiate the background * scanning and can't sleep. */ void (*scan_syncro)(struct net_device *dev); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 498b520efcf4..a414303aef54 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1399,7 +1399,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; /* -* Make ther structure we read from the beacon packet has +* Make the structure we read from the beacon packet to have * the right values */ static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 4992d630f984..4ec0a6520ddc 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -1973,7 +1973,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, return 1; } else - { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network. + { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network. memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen); memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen); } @@ -2113,7 +2113,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, return 0; } -/* following are for a simplier TX queue management. +/* following are for a simpler TX queue management. * Instead of using netif_[stop/wake]_queue the driver * will uses these two function (plus a reset one), that * will internally uses the kernel netif_* and takes diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index cde603f67f43..0b1a1fc09391 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -64,7 +64,7 @@ typedef enum _HT_CHANNEL_WIDTH{ }HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; // -// Represent Extention Channel Offset in HT Capabilities +// Represent Extension Channel Offset in HT Capabilities // This is available only in 40Mhz mode. // typedef enum _HT_EXTCHNL_OFFSET{ diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c index 50f4f5943e75..e88a839b2a91 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -423,7 +423,7 @@ u8 HTIOTActIsDisableMCS14(struct ieee80211_device* ieee, u8* PeerMacAddr) /** * Function: HTIOTActIsDisableMCS15 * -* Overview: Check whether driver should declare capability of receving MCS15 +* Overview: Check whether driver should declare capability of receiving MCS15 * * Input: * PADAPTER Adapter, @@ -460,7 +460,7 @@ bool HTIOTActIsDisableMCS15(struct ieee80211_device* ieee) /** * Function: HTIOTActIsDisableMCSTwoSpatialStream * -* Overview: Check whether driver should declare capability of receving All 2 ss packets +* Overview: Check whether driver should declare capability of receiving All 2 ss packets * * Input: * PADAPTER Adapter, @@ -1409,7 +1409,7 @@ void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidt //if in half N mode, set to 20M bandwidth please 09.08.2008 WB. if(Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))) { - // Handle Illegal extention channel offset!! + // Handle Illegal extension channel offset!! if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER) Offset = HT_EXTCHNL_OFFSET_NO_EXT; if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) { @@ -1426,7 +1426,7 @@ void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidt pHTInfo->bSwBwInProgress = true; - // TODO: 2007.7.13 by Emily Wait 2000ms in order to garantee that switching + // TODO: 2007.7.13 by Emily Wait 2000ms in order to guarantee that switching // bandwidth is executed after scan is finished. It is a temporal solution // because software should ganrantee the last operation of switching bandwidth // is executed properlly. diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h index baaac2149de1..e7e26fd96395 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TS.h @@ -44,7 +44,7 @@ typedef struct _RX_TS_RECORD { u16 RxTimeoutIndicateSeq; struct list_head RxPendingPktList; struct timer_list RxPktPendingTimer; - BA_RECORD RxAdmittedBARecord; // For BA Recepient + BA_RECORD RxAdmittedBARecord; // For BA Recipient u16 RxLastSeqNum; u8 RxLastFragNum; u8 num; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index c3fcaae0750d..957ce4ef48b5 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -135,7 +135,7 @@ void ResetRxTsEntry(PRX_TS_RECORD pTS) ResetTsCommonInfo(&pTS->TsCommonInfo); pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!! pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!! - ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recepient + ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recipient } void TSInitialize(struct ieee80211_device *ieee) diff --git a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c index 49f401fbce88..3543a6145046 100644 --- a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c +++ b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c @@ -71,7 +71,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out, unsigned int more) { /* walk->data may be pointing the first byte of the next page; - however, we know we transfered at least one byte. So, + however, we know we transferred at least one byte. So, walk->data - 1 will be a virtual address in the mapped page. */ if (out) diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index da612e6d994e..e81b8ab6aa9d 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -460,7 +460,7 @@ u32 read_nic_dword(struct net_device *dev, int indx) /* u8 read_phy_cck(struct net_device *dev, u8 adr); */ /* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */ /* this might still called in what was the PHY rtl8185/rtl8192 common code - * plans are to possibilty turn it again in one common code... + * plans are to possibility turn it again in one common code... */ inline void force_pci_posting(struct net_device *dev) { @@ -1378,7 +1378,7 @@ struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv //tx_agg_desc->LINIP = 0; //tx_agg_desc->CmdInit = 1; tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8; - /* already raw data, need not to substract header length */ + /* already raw data, need not to subtract header length */ tx_agg_desc->PktSize = skb->len & 0xffff; /*DWORD 1*/ @@ -2888,7 +2888,7 @@ static void rtl8192_get_eeprom_size(struct net_device* dev) RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype); } -//used to swap endian. as ntohl & htonl are not neccessary to swap endian, so use this instead. +//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead. static inline u16 endian_swap(u16* data) { u16 tmp = *data; diff --git a/drivers/staging/rtl8192u/r819xU_HTType.h b/drivers/staging/rtl8192u/r819xU_HTType.h index 01f58b902028..2ac421626e7c 100644 --- a/drivers/staging/rtl8192u/r819xU_HTType.h +++ b/drivers/staging/rtl8192u/r819xU_HTType.h @@ -65,7 +65,7 @@ typedef enum _HT_CHANNEL_WIDTH{ }HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; // -// Represent Extention Channel Offset in HT Capabilities +// Represent Extension Channel Offset in HT Capabilities // This is available only in 40Mhz mode. // typedef enum _HT_EXTCHNL_OFFSET{ diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index 41684e8fcf4c..c4586b0817d1 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -1531,13 +1531,13 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev) { case HT_CHANNEL_WIDTH_20: regBwOpMode |= BW_OPMODE_20MHZ; - // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + // 2007/02/07 Mark by Emily because we have not verify whether this register works write_nic_byte(dev, BW_OPMODE, regBwOpMode); break; case HT_CHANNEL_WIDTH_20_40: regBwOpMode &= ~BW_OPMODE_20MHZ; - // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + // 2007/02/07 Mark by Emily because we have not verify whether this register works write_nic_byte(dev, BW_OPMODE, regBwOpMode); break; @@ -1647,7 +1647,7 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev) } /****************************************************************************** - *function: This function schedules bandwith switch work. + *function: This function schedules bandwidth switch work. * input: struct net_device *dev * HT_CHANNEL_WIDTH Bandwidth //20M or 40M * HT_EXTCHNL_OFFSET Offset //Upper, Lower, or Don't care diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index 3a945b5f0e01..2dc78476b7d3 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -656,7 +656,7 @@ struct PT_param { /* * Result: * 0x00: success - * 0x01: sucess, and check Response. + * 0x01: success, and check Response. * 0x02: cmd ignored due to duplicated sequcne number * 0x03: cmd dropped due to invalid cmd code * 0x04: reserved. diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h index 994ef82141ab..8085e5eb82b1 100644 --- a/drivers/staging/rtl8712/rtl871x_led.h +++ b/drivers/staging/rtl8712/rtl871x_led.h @@ -78,14 +78,14 @@ struct LED_871x { }; struct led_priv { - /* add for led controll */ + /* add for led control */ struct LED_871x SwLed0; struct LED_871x SwLed1; enum LED_STRATEGY_871x LedStrategy; u8 bRegUseLed; void (*LedControlHandler)(struct _adapter *padapter, enum LED_CTL_MODE LedAction); - /* add for led controll */ + /* add for led control */ }; /*=========================================================================== diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 98ba7602e250..866554d48d86 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1663,7 +1663,7 @@ void r8712_update_registrypriv_dev_network(struct _adapter *adapter) (struct ndis_wlan_bssid_ex *)pdev_network); } -/*the fucntion is at passive_level*/ +/*the function is at passive_level*/ void r8712_joinbss_reset(struct _adapter *padapter) { int i; @@ -1726,7 +1726,7 @@ unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie, return phtpriv->ht_option; } -/* the fucntion is > passive_level (in critical_section) */ +/* the function is > passive_level (in critical_section) */ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len) { u8 *p, max_ampdu_sz; @@ -1803,7 +1803,7 @@ void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority) } } -/*the fucntion is >= passive_level*/ +/*the function is >= passive_level*/ unsigned int r8712_add_ht_addt_info(struct _adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len) diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index 2b35b740ab89..2794804d0822 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -29,7 +29,7 @@ * single-tone*/ #define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in cont, tx * background due to out of skb*/ -#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continous tx*/ +#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx*/ #define WIFI_MP_CTX_CCK_CS 0x00200000 /* in cont, tx with carrier * suppression*/ #define WIFI_MP_LPBK_STATE 0x00400000 diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h index e386fb0aac3e..23532a793859 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h +++ b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h @@ -38,7 +38,7 @@ * 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 * 3. RF register 0x00-2E * 4. Bit Mask for BB/RF register - * 5. Other defintion for BB/RF R/W + * 5. Other definition for BB/RF R/W * * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF * 1. Page1(0x100) diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c index 0e9483bbabe1..46287c17a417 100644 --- a/drivers/staging/rtl8712/usb_halinit.c +++ b/drivers/staging/rtl8712/usb_halinit.c @@ -112,7 +112,7 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter) /* Initialization for power on sequence, */ r8712_write8(padapter, SPS0_CTRL + 1, 0x53); r8712_write8(padapter, SPS0_CTRL, 0x57); - /* Enable AFE Macro Block's Bandgap adn Enable AFE Macro + /* Enable AFE Macro Block's Bandgap and Enable AFE Macro * Block's Mbias */ val8 = r8712_read8(padapter, AFE_MISC); diff --git a/drivers/staging/rts_pstor/rtsx_chip.h b/drivers/staging/rts_pstor/rtsx_chip.h index 713c5eaadacd..9f7cd82a1541 100644 --- a/drivers/staging/rts_pstor/rtsx_chip.h +++ b/drivers/staging/rts_pstor/rtsx_chip.h @@ -180,8 +180,8 @@ #define CUR_ERR 0x70 /* current error */ #define DEF_ERR 0x71 /* specific command error */ -/*---- sense key Infomation ----*/ -#define SNSKEYINFO_LEN 3 /* length of sense key infomation */ +/*---- sense key Information ----*/ +#define SNSKEYINFO_LEN 3 /* length of sense key information */ #define SKSV 0x80 #define CDB_ILLEGAL 0x40 @@ -235,13 +235,13 @@ struct sense_data_t { unsigned char seg_no; /* segment No. */ unsigned char sense_key; /* byte5 : ILI */ /* bit3-0 : sense key */ - unsigned char info[4]; /* infomation */ + unsigned char info[4]; /* information */ unsigned char ad_sense_len; /* additional sense data length */ - unsigned char cmd_info[4]; /* command specific infomation */ + unsigned char cmd_info[4]; /* command specific information */ unsigned char asc; /* ASC */ unsigned char ascq; /* ASCQ */ unsigned char rfu; /* FRU */ - unsigned char sns_key_info[3]; /* sense key specific infomation */ + unsigned char sns_key_info[3]; /* sense key specific information */ }; /* PCI Operation Register Address */ diff --git a/drivers/staging/rts_pstor/rtsx_scsi.h b/drivers/staging/rts_pstor/rtsx_scsi.h index fac122c1eabd..64b84992fdb3 100644 --- a/drivers/staging/rts_pstor/rtsx_scsi.h +++ b/drivers/staging/rts_pstor/rtsx_scsi.h @@ -85,7 +85,7 @@ #define CHIP_NORMALMODE 0x00 #define CHIP_DEBUGMODE 0x01 -/* SD Pass Through Command Extention */ +/* SD Pass Through Command Extension */ #define SD_PASS_THRU_MODE 0xD0 #define SD_EXECUTE_NO_DATA 0xD1 #define SD_EXECUTE_READ 0xD2 diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c index 21bfa5755bec..8d066bd428c4 100644 --- a/drivers/staging/rts_pstor/sd.c +++ b/drivers/staging/rts_pstor/sd.c @@ -1719,7 +1719,7 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_d } Search_Finish: - RTSX_DEBUGP("Final choosen phase: %d\n", final_phase); + RTSX_DEBUGP("Final chosen phase: %d\n", final_phase); return final_phase; } diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c index 71a5fbc041e4..c2f2664b61ae 100644 --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -586,7 +586,7 @@ static unsigned int sep_poll(struct file *filp, poll_table *wait) dev_dbg(&sep->pdev->dev, "poll: send_ct is %lx reply ct is %lx\n", sep->send_ct, sep->reply_ct); - /* Check if error occured during poll */ + /* Check if error occurred during poll */ retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); if (retval2 != 0x0) { dev_warn(&sep->pdev->dev, "poll; poll error %x\n", retval2); @@ -1106,7 +1106,7 @@ static int sep_lock_user_pages(struct sep_device *sep, lli_array[count].block_size); } - /* Set output params acording to the in_out flag */ + /* Set output params according to the in_out flag */ if (in_out_flag == SEP_DRIVER_IN_FLAG) { *lli_array_ptr = lli_array; sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages = num_pages; @@ -1577,7 +1577,7 @@ static int sep_prepare_input_dma_table(struct sep_device *sep, /* * If this is not the last table - - * then allign it to the block size + * then align it to the block size */ if (!last_table_flag) table_data_size = @@ -1974,7 +1974,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep, dev_dbg(&sep->pdev->dev, "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - /* Call the fucntion that creates table from the lli arrays */ + /* Call the function that creates table from the lli arrays */ error = sep_construct_dma_tables_from_lli(sep, lli_in_array, sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages, lli_out_array, @@ -2416,7 +2416,7 @@ end_function: * @cmd: command * @arg: pointer to argument structure * - * Implement the ioctl methods availble on the SEP device. + * Implement the ioctl methods available on the SEP device. */ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h index d3b9220f3963..1033425c9c30 100644 --- a/drivers/staging/sep/sep_driver_config.h +++ b/drivers/staging/sep/sep_driver_config.h @@ -65,11 +65,11 @@ #define SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE 16 /* flag that signifies tah the lock is -currently held by the proccess (struct file) */ +currently held by the process (struct file) */ #define SEP_DRIVER_OWN_LOCK_FLAG 1 /* flag that signifies tah the lock is currently NOT -held by the proccess (struct file) */ +held by the process (struct file) */ #define SEP_DRIVER_DISOWN_LOCK_FLAG 0 /* indicates whether driver has mapped/unmapped shared area */ diff --git a/drivers/staging/slicoss/README b/drivers/staging/slicoss/README index 70f49099c065..b83bba19b7f0 100644 --- a/drivers/staging/slicoss/README +++ b/drivers/staging/slicoss/README @@ -33,7 +33,7 @@ TODO: - NAPI? - wasted overhead of extra stats - state variables for things that are - easily availble and shouldn't be kept in card structure, cardnum, ... + easily available and shouldn't be kept in card structure, cardnum, ... slotnumber, events, ... - get rid of slic_spinlock wrapper - volatile == bad design => bad code diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c index d007e4a12c14..78a16a768509 100644 --- a/drivers/staging/sm7xx/smtcfb.c +++ b/drivers/staging/sm7xx/smtcfb.c @@ -965,7 +965,7 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, goto failed; smtcfb_setmode(sfb); - /* Primary display starting from 0 postion */ + /* Primary display starting from 0 position */ hw.BaseAddressInVRAM = 0; sfb->fb.par = &hw; @@ -1055,7 +1055,7 @@ static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg) pdev->dev.power.power_state = msg; - /* additionaly turn off all function blocks including internal PLLs */ + /* additionally turn off all function blocks including internal PLLs */ smtc_seqw(0x21, 0xff); return 0; diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c index 23cf7f44f450..170f38815ffd 100644 --- a/drivers/staging/speakup/keyhelp.c +++ b/drivers/staging/speakup/keyhelp.c @@ -69,7 +69,7 @@ static void build_key_data(void) memset(key_offsets, 0, sizeof(key_offsets)); kp = state_tbl + nstates + 1; while (*kp++) { - /* count occurrances of each function */ + /* count occurrences of each function */ for (i = 0; i < nstates; i++, kp++) { if (!*kp) continue; diff --git a/drivers/staging/speakup/spkguide.txt b/drivers/staging/speakup/spkguide.txt index 24362eb7b8f1..f3210571e396 100644 --- a/drivers/staging/speakup/spkguide.txt +++ b/drivers/staging/speakup/spkguide.txt @@ -1091,7 +1091,7 @@ screen that is constantly changing, such as a clock or status line. There is no way to save these window settings, and you can only have one window defined for each virtual console. There is also no way to have -windows automaticly defined for specific applications. +windows automatically defined for specific applications. In order to define a window, use the review keys to move your reading cursor to the beginning of the area you want to define. Then press diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c index 007b24b54e25..20dae73d3b78 100644 --- a/drivers/staging/spectra/ffsport.c +++ b/drivers/staging/spectra/ffsport.c @@ -38,7 +38,7 @@ * Outputs: Number of Used Bits * 0, if the argument is 0 * Description: Calculate the number of bits used by a given power of 2 number -* Number can be upto 32 bit +* Number can be up to 32 bit *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ int GLOB_Calc_Used_Bits(u32 n) { @@ -653,7 +653,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which) } dev->queue->queuedata = dev; - /* As Linux block layer doens't support >4KB hardware sector, */ + /* As Linux block layer does't support >4KB hardware sector, */ /* Here we force report 512 byte hardware sector size to Kernel */ blk_queue_logical_block_size(dev->queue, 512); diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c index a2f820025ae4..aead358e5c2a 100644 --- a/drivers/staging/spectra/flash.c +++ b/drivers/staging/spectra/flash.c @@ -965,7 +965,7 @@ static void process_cmd_fail_abort(int *first_failed_cmd, if (0 == *first_failed_cmd) *first_failed_cmd = PendingCMD[idx].SBDCmdIndex; - nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occured " + nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occurred " "while executing %u Command %u accesing Block %u\n", (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt, PendingCMD[idx].CMD, @@ -1879,7 +1879,7 @@ static int write_back_to_l2_cache(u8 *buf, u64 logical_addr) } /* - * Seach in the Level2 Cache table to find the cache item. + * Search in the Level2 Cache table to find the cache item. * If find, read the data from the NAND page of L2 Cache, * Otherwise, return FAIL. */ @@ -3989,7 +3989,7 @@ int GLOB_FTL_Block_Erase(u64 blk_addr) * Inputs: index to block that was just incremented and is at the max * Outputs: PASS=0 / FAIL=1 * Description: If any erase counts at MAX, adjusts erase count of every -* block by substracting least worn +* block by subtracting least worn * counter from counter value of every entry in wear table *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX) diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c index d55a8e40318b..3e68d58fdffd 100644 --- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c +++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c @@ -71,7 +71,7 @@ #define SYNAPTICS_RMI4_DEVICE_CONTROL_FUNC_NUM (0x01) /** - * struct synaptics_rmi4_fn_desc - contains the funtion descriptor information + * struct synaptics_rmi4_fn_desc - contains the function descriptor information * @query_base_addr: base address for query * @cmd_base_addr: base address for command * @ctrl_base_addr: base address for control @@ -92,7 +92,7 @@ struct synaptics_rmi4_fn_desc { }; /** - * struct synaptics_rmi4_fn - contains the funtion information + * struct synaptics_rmi4_fn - contains the function information * @fn_number: function number * @num_of_data_sources: number of data sources * @num_of_data_points: number of fingers touched @@ -151,7 +151,7 @@ struct synaptics_rmi4_device_info { * @input_dev: pointer for input device * @i2c_client: pointer for i2c client * @board: constant pointer for touch platform data - * @fn_list_mutex: mutex for funtion list + * @fn_list_mutex: mutex for function list * @rmi4_page_mutex: mutex for rmi4 page * @current_page: variable for integer * @number_of_interrupt_register: interrupt registers count @@ -278,7 +278,7 @@ static int synaptics_rmi4_i2c_byte_write(struct synaptics_rmi4_data *pdata, txbuf[0] = address & MASK_8BIT; txbuf[1] = data; retval = i2c_master_send(pdata->i2c_client, txbuf, 2); - /* Add in retry on writes only in certian error return values */ + /* Add in retry on writes only in certain error return values */ if (retval != 2) { dev_err(&i2c->dev, "%s:failed:%d\n", __func__, retval); retval = -EIO; @@ -561,7 +561,7 @@ static int synpatics_rmi4_touchpad_detect(struct synaptics_rmi4_data *pdata, } /* * 2D data sources have only 3 bits for the number of fingers - * supported - so the encoding is a bit wierd. + * supported - so the encoding is a bit weird. */ if ((queries[1] & MASK_3BIT) <= 4) /* add 1 since zero based */ @@ -1027,7 +1027,7 @@ err_input: * synaptics_rmi4_remove() - Removes the i2c-client touchscreen driver * @client: i2c client structure pointer * - * This funtion uses to remove the i2c-client + * This function uses to remove the i2c-client * touchscreen driver and returns integer. */ static int __devexit synaptics_rmi4_remove(struct i2c_client *client) @@ -1053,7 +1053,7 @@ static int __devexit synaptics_rmi4_remove(struct i2c_client *client) * synaptics_rmi4_suspend() - suspend the touch screen controller * @dev: pointer to device structure * - * This funtion is used to suspend the + * This function is used to suspend the * touch panel controller and returns integer */ static int synaptics_rmi4_suspend(struct device *dev) @@ -1089,7 +1089,7 @@ static int synaptics_rmi4_suspend(struct device *dev) * synaptics_rmi4_resume() - resume the touch screen controller * @dev: pointer to device structure * - * This funtion is used to resume the touch panel + * This function is used to resume the touch panel * controller and returns integer. */ static int synaptics_rmi4_resume(struct device *dev) @@ -1148,7 +1148,7 @@ static struct i2c_driver synaptics_rmi4_driver = { /** * synaptics_rmi4_init() - Initialize the touchscreen driver * - * This funtion uses to initializes the synaptics + * This function uses to initializes the synaptics * touchscreen driver and returns integer. */ static int __init synaptics_rmi4_init(void) @@ -1158,7 +1158,7 @@ static int __init synaptics_rmi4_init(void) /** * synaptics_rmi4_exit() - De-initialize the touchscreen driver * - * This funtion uses to de-initialize the synaptics + * This function uses to de-initialize the synaptics * touchscreen driver and returns none. */ static void __exit synaptics_rmi4_exit(void) diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h index 1e0273e50d2b..7cb587103975 100644 --- a/drivers/staging/tidspbridge/core/_tiomap.h +++ b/drivers/staging/tidspbridge/core/_tiomap.h @@ -366,7 +366,7 @@ extern s32 dsp_debug; * ======== sm_interrupt_dsp ======== * Purpose: * Set interrupt value & send an interrupt to the DSP processor(s). - * This is typicaly used when mailbox interrupt mechanisms allow data + * This is typically used when mailbox interrupt mechanisms allow data * to be associated with interrupt such as for OMAP's CMD/DATA regs. * Parameters: * dev_context: Handle to Bridge driver defined device info. diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c index 8381130e1460..6d66e7d0fba8 100644 --- a/drivers/staging/tidspbridge/core/chnl_sm.c +++ b/drivers/staging/tidspbridge/core/chnl_sm.c @@ -578,7 +578,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout, } else if (stat_sync == -EPERM) { /* This can occur when the user mode thread is * aborted (^C), or when _VWIN32_WaitSingleObject() - * fails due to unkown causes. */ + * fails due to unknown causes. */ /* Even though Wait failed, there may be something in * the Q: */ if (list_empty(&pchnl->io_completions)) { diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c index 390040984e03..5cecd237e3f6 100644 --- a/drivers/staging/tidspbridge/dynload/cload.c +++ b/drivers/staging/tidspbridge/dynload/cload.c @@ -718,7 +718,7 @@ static void dload_symbols(struct dload_state *dlthis) * as a temporary for .dllview record construction. * Allocate storage for the whole table. Add 1 to the section count * in case a trampoline section is auto-generated as well as the - * size of the trampoline section name so DLLView doens't get lost. + * size of the trampoline section name so DLLView does't get lost. */ siz = sym_count * sizeof(struct local_symbol); diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.c b/drivers/staging/tidspbridge/hw/hw_mmu.c index 014f5d5293ae..c214df9b205e 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.c +++ b/drivers/staging/tidspbridge/hw/hw_mmu.c @@ -59,7 +59,7 @@ enum hw_mmu_page_size_t { * RETURNS: * * Type : hw_status - * Description : 0 -- No errors occured + * Description : 0 -- No errors occurred * RET_BAD_NULL_PARAM -- A Pointer * Paramater was set to NULL * @@ -102,7 +102,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address); * RETURNS: * * Type : hw_status - * Description : 0 -- No errors occured + * Description : 0 -- No errors occurred * RET_BAD_NULL_PARAM -- A Pointer Paramater * was set to NULL * RET_PARAM_OUT_OF_RANGE -- Input Parameter out @@ -147,7 +147,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, * RETURNS: * * Type : hw_status - * Description : 0 -- No errors occured + * Description : 0 -- No errors occurred * RET_BAD_NULL_PARAM -- A Pointer Paramater * was set to NULL * RET_PARAM_OUT_OF_RANGE -- Input Parameter diff --git a/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h b/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h index d60e25258020..6e7ab4fd8c39 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h +++ b/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h @@ -144,7 +144,7 @@ struct chnl_object { s8 chnl_mode; /* Chnl mode and attributes */ /* Chnl I/O completion event (user mode) */ void *user_event; - /* Abstract syncronization object */ + /* Abstract synchronization object */ struct sync_object *sync_event; u32 process; /* Process which created this channel */ u32 cb_arg; /* Argument to use with callback */ @@ -156,7 +156,7 @@ struct chnl_object { struct list_head io_completions; struct list_head free_packets_list; /* List of free Irps */ struct ntfy_object *ntfy_obj; - u32 bytes_moved; /* Total number of bytes transfered */ + u32 bytes_moved; /* Total number of bytes transferred */ /* For DSP-DMA */ diff --git a/drivers/staging/tidspbridge/include/dspbridge/clk.h b/drivers/staging/tidspbridge/include/dspbridge/clk.h index b23950323421..685341c50693 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/clk.h +++ b/drivers/staging/tidspbridge/include/dspbridge/clk.h @@ -55,7 +55,7 @@ extern void dsp_clk_exit(void); * Initializes private state of CLK module. * Parameters: * Returns: - * TRUE if initialized; FALSE if error occured. + * TRUE if initialized; FALSE if error occurred. * Requires: * Ensures: * CLK initialized. @@ -71,7 +71,7 @@ void dsp_gpt_wait_overflow(short int clk_id, unsigned int load); * Parameters: * Returns: * 0: Success. - * -EPERM: Error occured while enabling the clock. + * -EPERM: Error occurred while enabling the clock. * Requires: * Ensures: */ @@ -86,7 +86,7 @@ u32 dsp_clock_enable_all(u32 dsp_per_clocks); * Parameters: * Returns: * 0: Success. - * -EPERM: Error occured while disabling the clock. + * -EPERM: Error occurred while disabling the clock. * Requires: * Ensures: */ diff --git a/drivers/staging/tidspbridge/include/dspbridge/cmm.h b/drivers/staging/tidspbridge/include/dspbridge/cmm.h index 27a21b5f3ff0..aff22051cf57 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/cmm.h +++ b/drivers/staging/tidspbridge/include/dspbridge/cmm.h @@ -190,7 +190,7 @@ extern int cmm_get_info(struct cmm_object *hcmm_mgr, * Initializes private state of CMM module. * Parameters: * Returns: - * TRUE if initialized; FALSE if error occured. + * TRUE if initialized; FALSE if error occurred. * Requires: * Ensures: * CMM initialized. diff --git a/drivers/staging/tidspbridge/include/dspbridge/cod.h b/drivers/staging/tidspbridge/include/dspbridge/cod.h index 53bd4bb8b0bb..cb684c11b302 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/cod.h +++ b/drivers/staging/tidspbridge/include/dspbridge/cod.h @@ -249,7 +249,7 @@ extern int cod_get_sym_value(struct cod_manager *cod_mgr_obj, * Parameters: * None. * Returns: - * TRUE if initialized; FALSE if error occured. + * TRUE if initialized; FALSE if error occurred. * Requires: * Ensures: * A requirement for each of the other public COD functions. diff --git a/drivers/staging/tidspbridge/include/dspbridge/dev.h b/drivers/staging/tidspbridge/include/dspbridge/dev.h index f41e4783157f..f92b4be0b413 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/dev.h +++ b/drivers/staging/tidspbridge/include/dspbridge/dev.h @@ -497,7 +497,7 @@ extern void dev_exit(void); * Initialize DEV's private state, keeping a reference count on each call. * Parameters: * Returns: - * TRUE if initialized; FALSE if error occured. + * TRUE if initialized; FALSE if error occurred. * Requires: * Ensures: * TRUE: A requirement for the other public DEV functions. diff --git a/drivers/staging/tidspbridge/include/dspbridge/drv.h b/drivers/staging/tidspbridge/include/dspbridge/drv.h index 25ef1a2c58eb..9cdbd955dce9 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/drv.h +++ b/drivers/staging/tidspbridge/include/dspbridge/drv.h @@ -154,7 +154,7 @@ struct process_context { * Parameters: * drv_obj: Location to store created DRV Object handle. * Returns: - * 0: Sucess + * 0: Success * -ENOMEM: Failed in Memory allocation * -EPERM: General Failure * Requires: @@ -170,7 +170,7 @@ struct process_context { * There is one Driver Object for the Driver representing * the driver itself. It contains the list of device * Objects and the list of Device Extensions in the system. - * Also it can hold other neccessary + * Also it can hold other necessary * information in its storage area. */ extern int drv_create(struct drv_object **drv_obj); @@ -180,7 +180,7 @@ extern int drv_create(struct drv_object **drv_obj); * Purpose: * destroys the Dev Object list, DrvExt list * and destroy the DRV object - * Called upon driver unLoading.or unsuccesful loading of the driver. + * Called upon driver unLoading.or unsuccessful loading of the driver. * Parameters: * driver_obj: Handle to Driver object . * Returns: diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h b/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h index c2ba26c09308..ed32bf383132 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h +++ b/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h @@ -52,7 +52,7 @@ struct bridge_dev_context; * dev_ctxt: Handle to Bridge driver defined device context. * Returns: * 0: Success. - * -ETIMEDOUT: Timeout occured waiting for a response from hardware. + * -ETIMEDOUT: Timeout occurred waiting for a response from hardware. * -EPERM: Other, unspecified error. * Requires: * dev_ctxt != NULL @@ -91,7 +91,7 @@ typedef int(*fxn_brd_setstate) (struct bridge_dev_context * dsp_addr: DSP address at which to start execution. * Returns: * 0: Success. - * -ETIMEDOUT: Timeout occured waiting for a response from hardware. + * -ETIMEDOUT: Timeout occurred waiting for a response from hardware. * -EPERM: Other, unspecified error. * Requires: * dev_ctxt != NULL @@ -142,7 +142,7 @@ typedef int(*fxn_brd_memcopy) (struct bridge_dev_context * mem_type: Memory space on DSP to which to transfer. * Returns: * 0: Success. - * -ETIMEDOUT: Timeout occured waiting for a response from hardware. + * -ETIMEDOUT: Timeout occurred waiting for a response from hardware. * -EPERM: Other, unspecified error. * Requires: * dev_ctxt != NULL; @@ -205,7 +205,7 @@ typedef int(*fxn_brd_memunmap) (struct bridge_dev_context * dev_ctxt: Handle to Bridge driver defined device context. * Returns: * 0: Success. - * -ETIMEDOUT: Timeout occured waiting for a response from hardware. + * -ETIMEDOUT: Timeout occurred waiting for a response from hardware. * -EPERM: Other, unspecified error. * Requires: * dev_ctxt != NULL @@ -248,7 +248,7 @@ typedef int(*fxn_brd_status) (struct bridge_dev_context *dev_ctxt, * mem_type: Memory space on DSP from which to transfer. * Returns: * 0: Success. - * -ETIMEDOUT: Timeout occured waiting for a response from hardware. + * -ETIMEDOUT: Timeout occurred waiting for a response from hardware. * -EPERM: Other, unspecified error. * Requires: * dev_ctxt != NULL; @@ -274,7 +274,7 @@ typedef int(*fxn_brd_read) (struct bridge_dev_context *dev_ctxt, * mem_type: Memory space on DSP to which to transfer. * Returns: * 0: Success. - * -ETIMEDOUT: Timeout occured waiting for a response from hardware. + * -ETIMEDOUT: Timeout occurred waiting for a response from hardware. * -EPERM: Other, unspecified error. * Requires: * dev_ctxt != NULL; @@ -601,7 +601,7 @@ typedef int(*fxn_chnl_getmgrinfo) (struct chnl_mgr * Returns: * 0: Success; * -EFAULT: Invalid chnl_obj. - * -ETIMEDOUT: Timeout occured before channel could be idled. + * -ETIMEDOUT: Timeout occurred before channel could be idled. * Requires: * Ensures: */ diff --git a/drivers/staging/tidspbridge/include/dspbridge/mgr.h b/drivers/staging/tidspbridge/include/dspbridge/mgr.h index e506c4d49472..47b0318430e1 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/mgr.h +++ b/drivers/staging/tidspbridge/include/dspbridge/mgr.h @@ -176,7 +176,7 @@ extern void mgr_exit(void); * mgr_handle: Handle to the Manager Object * dcd_handle: Ptr to receive the DCD Handle. * Returns: - * 0: Sucess + * 0: Success * -EPERM: Failure to get the Handle * Requires: * MGR is initialized. @@ -195,7 +195,7 @@ extern int mgr_get_dcd_handle(struct mgr_object * call. Initializes the DCD. * Parameters: * Returns: - * TRUE if initialized; FALSE if error occured. + * TRUE if initialized; FALSE if error occurred. * Requires: * Ensures: * TRUE: A requirement for the other public MGR functions. diff --git a/drivers/staging/tidspbridge/include/dspbridge/node.h b/drivers/staging/tidspbridge/include/dspbridge/node.h index 53da0ef483c8..16371d818e3d 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/node.h +++ b/drivers/staging/tidspbridge/include/dspbridge/node.h @@ -44,7 +44,7 @@ * -ESPIPE: iAlg functions not found for a DAIS node. * -EDOM: attr_in != NULL and attr_in->prio out of * range. - * -EPERM: A failure occured, unable to allocate node. + * -EPERM: A failure occurred, unable to allocate node. * -EBADR: Proccessor is not in the running state. * Requires: * node_init(void) called. diff --git a/drivers/staging/tidspbridge/include/dspbridge/proc.h b/drivers/staging/tidspbridge/include/dspbridge/proc.h index 5e09fd165d9d..f00dffd51989 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/proc.h +++ b/drivers/staging/tidspbridge/include/dspbridge/proc.h @@ -89,7 +89,7 @@ extern int proc_auto_start(struct cfg_devnode *dev_node_obj, * Returns: * 0 : SUCCESS * -EFAULT : Invalid processor handle. - * -ETIME: A Timeout Occured before the Control information + * -ETIME: A Timeout Occurred before the Control information * could be sent. * -EPERM : General Failure. * Requires: @@ -169,7 +169,7 @@ extern int proc_enum_nodes(void *hprocessor, * 0 : Success. * -EFAULT : Invalid processor handle. * -EBADR: The processor is not in the PROC_RUNNING state. - * -ETIME: A timeout occured before the DSP responded to the + * -ETIME: A timeout occurred before the DSP responded to the * querry. * -EPERM : Unable to get Resource Information * Requires: @@ -229,7 +229,7 @@ extern int proc_get_dev_object(void *hprocessor, * call. * Parameters: * Returns: - * TRUE if initialized; FALSE if error occured. + * TRUE if initialized; FALSE if error occurred. * Requires: * Ensures: * TRUE: A requirement for the other public PROC functions. diff --git a/drivers/staging/tidspbridge/include/dspbridge/pwr.h b/drivers/staging/tidspbridge/include/dspbridge/pwr.h index 5e3ab2123aaa..0fb066488da9 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/pwr.h +++ b/drivers/staging/tidspbridge/include/dspbridge/pwr.h @@ -46,7 +46,7 @@ * 0: Success. * 0: Success, but the DSP was already asleep. * -EINVAL: The specified sleep_code is not supported. - * -ETIME: A timeout occured while waiting for DSP sleep + * -ETIME: A timeout occurred while waiting for DSP sleep * confirmation. * -EPERM: General failure, unable to send sleep command to * the DSP. @@ -67,7 +67,7 @@ extern int pwr_sleep_dsp(const u32 sleep_code, const u32 timeout); * Returns: * 0: Success. * 0: Success, but the DSP was already awake. - * -ETIME: A timeout occured while waiting for wake + * -ETIME: A timeout occurred while waiting for wake * confirmation. * -EPERM: General failure, unable to send wake command to * the DSP. @@ -85,7 +85,7 @@ extern int pwr_wake_dsp(const u32 timeout); * Returns: * 0: Success. * 0: Success, but the DSP was already awake. - * -ETIME: A timeout occured while waiting for wake + * -ETIME: A timeout occurred while waiting for wake * confirmation. * -EPERM: General failure, unable to send wake command to * the DSP. @@ -103,7 +103,7 @@ extern int pwr_pm_pre_scale(u16 voltage_domain, u32 level); * Returns: * 0: Success. * 0: Success, but the DSP was already awake. - * -ETIME: A timeout occured while waiting for wake + * -ETIME: A timeout occurred while waiting for wake * confirmation. * -EPERM: General failure, unable to send wake command to * the DSP. diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c index 9a38d86a84a0..522810bc7427 100644 --- a/drivers/staging/tidspbridge/pmgr/dev.c +++ b/drivers/staging/tidspbridge/pmgr/dev.c @@ -787,7 +787,7 @@ int dev_notify_clients(struct dev_object *dev_obj, u32 ret) /* * FIXME: this code needs struct proc_object to have a list_head - * at the begining. If not, this can go horribly wrong. + * at the beginning. If not, this can go horribly wrong. */ list_for_each(curr, &dev_obj->proc_list) proc_notify_clients((void *)curr, ret); @@ -810,7 +810,7 @@ int dev_remove_device(struct cfg_devnode *dev_node_obj) if (!dev_node_obj) status = -EFAULT; - /* Retrieve the device object handle originaly stored with + /* Retrieve the device object handle originally stored with * the dev_node: */ if (!status) { /* check the device string and then store dev object */ @@ -986,7 +986,7 @@ int dev_insert_proc_object(struct dev_object *hdev_obj, /* Add DevObject to tail. */ /* * FIXME: this code needs struct proc_object to have a list_head - * at the begining. If not, this can go horribly wrong. + * at the beginning. If not, this can go horribly wrong. */ list_add_tail((struct list_head *)proc_obj, &dev_obj->proc_list); diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index 8c88583364eb..db8215f540d8 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -609,7 +609,7 @@ int drv_request_resources(u32 dw_context, u32 *dev_node_strg) DBC_REQUIRE(dev_node_strg != NULL); /* - * Allocate memory to hold the string. This will live untill + * Allocate memory to hold the string. This will live until * it is freed in the Release resources. Update the driver object * list. */ diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c index fb5c2ba01d47..0e70cba15ebc 100644 --- a/drivers/staging/tidspbridge/rmgr/nldr.c +++ b/drivers/staging/tidspbridge/rmgr/nldr.c @@ -57,9 +57,9 @@ * uuuuuuuu|fueeeeee|fudddddd|fucccccc| * where * u = unused - * cccccc = prefered/required dynamic mem segid for create phase data/code - * dddddd = prefered/required dynamic mem segid for delete phase data/code - * eeeeee = prefered/req. dynamic mem segid for execute phase data/code + * cccccc = preferred/required dynamic mem segid for create phase data/code + * dddddd = preferred/required dynamic mem segid for delete phase data/code + * eeeeee = preferred/req. dynamic mem segid for execute phase data/code * f = flag indicating if memory is preferred or required: * f = 1 if required, f = 0 if preferred. * diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c index c4e5c4e0d71c..242dd1399996 100644 --- a/drivers/staging/tidspbridge/rmgr/proc.c +++ b/drivers/staging/tidspbridge/rmgr/proc.c @@ -1670,7 +1670,7 @@ int proc_stop(void *hprocessor) if (!status) { dev_dbg(bridge, "%s: processor in standby mode\n", __func__); p_proc_object->proc_state = PROC_STOPPED; - /* Destory the Node Manager, msg_ctrl Manager */ + /* Destroy the Node Manager, msg_ctrl Manager */ if (!(dev_destroy2(p_proc_object->dev_obj))) { /* Destroy the msg_ctrl by calling msg_delete */ dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr); @@ -1827,7 +1827,7 @@ static int proc_monitor(struct proc_object *proc_obj) /* This is needed only when Device is loaded when it is * already 'ACTIVE' */ - /* Destory the Node Manager, msg_ctrl Manager */ + /* Destroy the Node Manager, msg_ctrl Manager */ if (!dev_destroy2(proc_obj->dev_obj)) { /* Destroy the msg_ctrl by calling msg_delete */ dev_get_msg_mgr(proc_obj->dev_obj, &hmsg_mgr); diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index c80a316d9d8f..17db6684abbe 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c @@ -182,7 +182,7 @@ static inline void get_next_buf(struct tm6000_dmaqueue *dma_q, if (!buf) return; - /* Cleans up buffer - Usefull for testing for frame/URB loss */ + /* Cleans up buffer - Useful for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); return; diff --git a/drivers/staging/tty/cd1865.h b/drivers/staging/tty/cd1865.h index 9940966e7a1d..8c2ad654b79d 100644 --- a/drivers/staging/tty/cd1865.h +++ b/drivers/staging/tty/cd1865.h @@ -9,7 +9,7 @@ * Please DO contact io8-linux@specialix.co.uk if you require * support. * - * This driver was developped in the BitWizard linux device + * This driver was developed in the BitWizard linux device * driver service. If you require a linux device driver for your * product, please contact devices@BitWizard.nl for a quote. * diff --git a/drivers/staging/tty/epca.c b/drivers/staging/tty/epca.c index 7ad3638967ae..7f1369e5b418 100644 --- a/drivers/staging/tty/epca.c +++ b/drivers/staging/tty/epca.c @@ -7,7 +7,7 @@ ** This driver is no longer supported by Digi ** Much of this design and code came from epca.c which was - copyright (C) 1994, 1995 Troy De Jongh, and subsquently + copyright (C) 1994, 1995 Troy De Jongh, and subsequently modified by David Nugent, Christoph Lameter, Mike McLagan. This program is free software; you can redistribute it and/or modify @@ -471,7 +471,7 @@ static void shutdown(struct channel *ch, struct tty_struct *tty) memoff(ch); /* - * The channel has officialy been closed. The next time it is opened it + * The channel has officially been closed. The next time it is opened it * will have to reinitialized. Set a flag to indicate this. */ /* Prevent future Digi programmed interrupts from coming active */ @@ -975,7 +975,7 @@ static int __init pc_init(void) /* * Note : If lilo was used to configure the driver and the ignore - * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards + * epcaconfig option was chosen (digiepca=2) then nbdevs and num_cards * will equal 0 at this point. This is okay; PCI cards will still be * picked up if detected. */ @@ -1230,14 +1230,14 @@ static void post_fep_init(unsigned int crd) memaddr = bd->re_map_membase; /* - * The below assignment will set bc to point at the BEGINING of the + * The below assignment will set bc to point at the BEGINNING of the * cards channel structures. For 1 card there will be between 8 and 64 * of these structures. */ bc = memaddr + CHANSTRUCT; /* - * The below assignment will set gd to point at the BEGINING of global + * The below assignment will set gd to point at the BEGINNING of global * memory address 0xc00. The first data in that global memory actually * starts at address 0xc1a. The command in pointer begins at 0xd10. */ @@ -1492,7 +1492,7 @@ static void doevent(int crd) /* * The two assignments below get the current modem status * (mstat) and the previous modem status (lstat). These are - * useful becuase an event could signal a change in modem + * useful because an event could signal a change in modem * signals itself. */ mstat = readb(eventbuf + 2); @@ -1897,7 +1897,7 @@ static void receive_data(struct channel *ch, struct tty_struct *tty) /* * Even if head has wrapped around only report the amount of * data to be equal to the size - tail. Remember memcpy can't - * automaticly wrap around the receive buffer. + * automatically wrap around the receive buffer. */ dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; @@ -2543,7 +2543,7 @@ static void __init epca_setup(char *str, int *ints) break; /* * If the index incremented above refers to a - * legitamate board type set it here. + * legitimate board type set it here. */ if (index < EPCA_NUM_TYPES) board.type = loop; diff --git a/drivers/staging/tty/ip2/i2hw.h b/drivers/staging/tty/ip2/i2hw.h index c0ba6c05f0cd..8df2f487217a 100644 --- a/drivers/staging/tty/ip2/i2hw.h +++ b/drivers/staging/tty/ip2/i2hw.h @@ -335,7 +335,7 @@ be off by a factor of five. The important point is that the first command reset in fact generates a reset pulse on the board. This pulse is guaranteed to last less than 10 milliseconds. The additional delay ensures the 1400 has had the chance to respond sufficiently to the first reset. Why not a longer delay? Much -more than 50 milliseconds gets to be noticable, but the board would still work. +more than 50 milliseconds gets to be noticeable, but the board would still work. Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap firmware is ready to receive loadware. @@ -399,7 +399,7 @@ typedef union _porStr // "por" stands for Power On Reset // expandable products must report a MAP of available channels. Since // each UART supports four ports, we represent each UART found by a // single bit. Using two bytes to supply the mapping information we - // report the presense or absense of up to 16 UARTS, or 64 ports in + // report the presence or absence of up to 16 UARTS, or 64 ports in // steps of 4 ports. For -IIEX products, the ports are numbered // starting at the box closest to the controller in the "chain". diff --git a/drivers/staging/tty/ip2/i2lib.c b/drivers/staging/tty/ip2/i2lib.c index 0d10b89218ed..13a3caba85f2 100644 --- a/drivers/staging/tty/ip2/i2lib.c +++ b/drivers/staging/tty/ip2/i2lib.c @@ -821,7 +821,7 @@ i2GetStatus(i2ChanStrPtr pCh, int resetBits) // // Description: // Strips data from the input buffer and writes it to pDest. If there is a -// collosal blunder, (invalid structure pointers or the like), returns -1. +// colossal blunder, (invalid structure pointers or the like), returns -1. // Otherwise, returns the number of bytes read. //****************************************************************************** static int @@ -909,7 +909,7 @@ i2Input_exit: // Returns: Number of bytes stripped, or -1 for error // // Description: -// Strips any data from the input buffer. If there is a collosal blunder, +// Strips any data from the input buffer. If there is a colossal blunder, // (invalid structure pointers or the like), returns -1. Otherwise, returns the // number of bytes stripped. //****************************************************************************** @@ -963,7 +963,7 @@ i2InputFlush(i2ChanStrPtr pCh) // Returns: Number of bytes available, or -1 for error // // Description: -// If there is a collosal blunder, (invalid structure pointers or the like), +// If there is a colossal blunder, (invalid structure pointers or the like), // returns -1. Otherwise, returns the number of bytes stripped. Otherwise, // returns the number of bytes available in the buffer. //****************************************************************************** @@ -1001,7 +1001,7 @@ i2InputAvailable(i2ChanStrPtr pCh) // // Description: // Queues the data at pSource to be sent as data packets to the board. If there -// is a collosal blunder, (invalid structure pointers or the like), returns -1. +// is a colossal blunder, (invalid structure pointers or the like), returns -1. // Otherwise, returns the number of bytes written. What if there is not enough // room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then // we transfer as many characters as we can now, then return. If this bit is diff --git a/drivers/staging/tty/ip2/ip2main.c b/drivers/staging/tty/ip2/ip2main.c index ea7a8fb08283..ba074fbb4ce2 100644 --- a/drivers/staging/tty/ip2/ip2main.c +++ b/drivers/staging/tty/ip2/ip2main.c @@ -1824,7 +1824,7 @@ ip2_flush_chars( PTTY tty ) // ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); // - // We may need to restart i2Output if it does not fullfill this request + // We may need to restart i2Output if it does not fulfill this request // strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff); if ( strip != pCh->Pbuf_stuff ) { diff --git a/drivers/staging/tty/specialix.c b/drivers/staging/tty/specialix.c index 17a1be536a46..cb24c6d999db 100644 --- a/drivers/staging/tty/specialix.c +++ b/drivers/staging/tty/specialix.c @@ -9,7 +9,7 @@ * support. But please read the documentation (specialix.txt) * first. * - * This driver was developped in the BitWizard linux device + * This driver was developed in the BitWizard linux device * driver service. If you require a linux device driver for your * product, please contact devices@BitWizard.nl for a quote. * @@ -978,7 +978,7 @@ static void sx_change_speed(struct specialix_board *bp, spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); - /* The Specialix board doens't implement the RTS lines. + /* The Specialix board does't implement the RTS lines. They are used to set the IRQ level. Don't touch them. */ if (sx_crtscts(tty)) port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); diff --git a/drivers/staging/tty/specialix_io8.h b/drivers/staging/tty/specialix_io8.h index c63005274d9b..1215d7e2cb37 100644 --- a/drivers/staging/tty/specialix_io8.h +++ b/drivers/staging/tty/specialix_io8.h @@ -10,7 +10,7 @@ * Please DO contact io8-linux@specialix.co.uk if you require * support. * - * This driver was developped in the BitWizard linux device + * This driver was developed in the BitWizard linux device * driver service. If you require a linux device driver for your * product, please contact devices@BitWizard.nl for a quote. * @@ -79,7 +79,7 @@ more than a few PCI versions of the card. */ #define SPECIALIX_MAGIC 0x0907 -#define SX_CCR_TIMEOUT 10000 /* CCR timeout. You may need to wait upto +#define SX_CCR_TIMEOUT 10000 /* CCR timeout. You may need to wait up to 10 milliseconds before the internal processor is available again after you give it a command */ diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index e23484998598..0f02a4b12ae4 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -194,7 +194,7 @@ void rh_port_disconnect(int rhport) * * So, the maximum number of ports is 31 ( port 0 to port 30) ? * - * The return value is the actual transfered length in byte. If nothing has + * The return value is the actual transferred length in byte. If nothing has * been changed, return 0. In the case that the number of ports is less than or * equal to 6 (VHCI_NPORTS==7), return 1. * diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index d4a48c4e59c2..a4007287ef47 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -621,7 +621,7 @@ static int ca91cx42_master_set(struct vme_master_resource *image, int enabled, /* * Let's allocate the resource here rather than further up the stack as - * it avoids pushing loads of bus dependant stuff up the stack + * it avoids pushing loads of bus dependent stuff up the stack */ retval = ca91cx42_alloc_resource(image, size); if (retval) { @@ -1052,7 +1052,7 @@ static int ca91cx42_dma_list_add(struct vme_dma_list *list, pci_attr = dest->private; } - /* Check we can do fullfill required attributes */ + /* Check we can do fulfill required attributes */ if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | VME_USER2)) != 0) { @@ -1069,7 +1069,7 @@ static int ca91cx42_dma_list_add(struct vme_dma_list *list, goto err_cycle; } - /* Check to see if we can fullfill source and destination */ + /* Check to see if we can fulfill source and destination */ if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c index b00a53e793e7..106aa9daff48 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ b/drivers/staging/vme/bridges/vme_tsi148.c @@ -928,7 +928,7 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, spin_lock(&image->lock); /* Let's allocate the resource here rather than further up the stack as - * it avoids pushing loads of bus dependant stuff up the stack. If size + * it avoids pushing loads of bus dependent stuff up the stack. If size * is zero, any existing resource will be freed. */ retval = tsi148_alloc_resource(image, size); @@ -1320,7 +1320,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, /* * Writes are posted. We need to do a read on the VME bus to flush out - * all of the writes before we check for errors. We can't guarentee + * all of the writes before we check for errors. We can't guarantee * that reading the data we have just written is safe. It is believed * that there isn't any read, write re-ordering, so we can read any * location in VME space, so lets read the Device ID from the tsi148's diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/staging/vme/bridges/vme_tsi148.h index 9f97fa8084e8..a3ac2fe98816 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.h +++ b/drivers/staging/vme/bridges/vme_tsi148.h @@ -212,7 +212,7 @@ static const int TSI148_LCSR_OT[8] = { TSI148_LCSR_OT0, TSI148_LCSR_OT1, #define TSI148_LCSR_OFFSET_OTAT 0x1C /* - * VMEbus interupt ack + * VMEbus interrupt ack * offset 200 */ #define TSI148_LCSR_VIACK1 0x204 @@ -613,7 +613,7 @@ static const int TSI148_GCSR_MBOX[4] = { TSI148_GCSR_MBOX0, /* * PCI-X Status Register (CRG +$054) */ -#define TSI148_PCFS_PCIXSTAT_RSCEM (1<<29) /* Recieved Split Comp Error */ +#define TSI148_PCFS_PCIXSTAT_RSCEM (1<<29) /* Received Split Comp Error */ #define TSI148_PCFS_PCIXSTAT_DMCRS_M (7<<26) /* max Cumulative Read Size */ #define TSI148_PCFS_PCIXSTAT_DMOST_M (7<<23) /* max outstanding Split Trans */ @@ -982,8 +982,8 @@ static const int TSI148_GCSR_MBOX[4] = { TSI148_GCSR_MBOX0, #define TSI148_LCSR_VICR_CNTS_IRQ1 (2<<22) /* IRQ1 to Cntr */ #define TSI148_LCSR_VICR_CNTS_IRQ2 (3<<22) /* IRQ2 to Cntr */ -#define TSI148_LCSR_VICR_EDGIS_M (3<<20) /* Edge interupt MASK */ -#define TSI148_LCSR_VICR_EDGIS_DIS (1<<20) /* Edge interupt Disable */ +#define TSI148_LCSR_VICR_EDGIS_M (3<<20) /* Edge interrupt MASK */ +#define TSI148_LCSR_VICR_EDGIS_DIS (1<<20) /* Edge interrupt Disable */ #define TSI148_LCSR_VICR_EDGIS_IRQ1 (2<<20) /* IRQ1 to Edge */ #define TSI148_LCSR_VICR_EDGIS_IRQ2 (3<<20) /* IRQ2 to Edge */ diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt index a910a0c4388b..4910e92c52af 100644 --- a/drivers/staging/vme/vme_api.txt +++ b/drivers/staging/vme/vme_api.txt @@ -6,7 +6,7 @@ Driver registration As with other subsystems within the Linux kernel, VME device drivers register with the VME subsystem, typically called from the devices init routine. This is -achieved via a call to the follwoing function: +achieved via a call to the following function: int vme_register_driver (struct vme_driver *driver); @@ -108,7 +108,7 @@ Master windows ============== Master windows provide access from the local processor[s] out onto the VME bus. -The number of windows available and the available access modes is dependant on +The number of windows available and the available access modes is dependent on the underlying chipset. A window must be configured before it can be used. @@ -163,7 +163,7 @@ Slave windows Slave windows provide devices on the VME bus access into mapped portions of the local memory. The number of windows available and the access modes that can be -used is dependant on the underlying chipset. A window must be configured before +used is dependent on the underlying chipset. A window must be configured before it can be used. diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 951a3a8ddcb2..2721e0798496 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -1186,7 +1186,7 @@ CARDbStartMeasure ( wDuration += 1; // 1 TU for channel switching if ((LODWORD(qwStartTSF) == 0) && (HIDWORD(qwStartTSF) == 0)) { - // start imediately by setting start TSF == current TSF + 2 TU + // start immediately by setting start TSF == current TSF + 2 TU LODWORD(qwStartTSF) = LODWORD(qwCurrTSF) + 2048; HIDWORD(qwStartTSF) = HIDWORD(qwCurrTSF); if (LODWORD(qwCurrTSF) > LODWORD(qwStartTSF)) { diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index efaf19bc07b7..ad39c8727e9b 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -137,7 +137,7 @@ DEVICE_PARAM(TxDescriptors1,"Number of transmit descriptors1"); /* IP_byte_align[] is used for IP header unsigned long byte aligned 0: indicate the IP header won't be unsigned long byte aligned.(Default) . 1: indicate the IP header will be unsigned long byte aligned. - In some enviroment, the IP header should be unsigned long byte aligned, + In some environment, the IP header should be unsigned long byte aligned, or the packet will be droped when we receive it. (eg: IPVS) */ DEVICE_PARAM(IP_byte_align,"Enable IP header dword aligned"); diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index abd6745bc3fe..c30170a2bc44 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -587,7 +587,7 @@ printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySS if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { // Call mgr to begin the deauthentication - // reason = (3) beacuse sta has left ESS + // reason = (3) because sta has left ESS if (pMgmt->eCurrState>= WMAC_STATE_AUTH) { vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status); } diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h index 141e80b843af..e3ae562f521a 100644 --- a/drivers/staging/vt6655/wmgr.h +++ b/drivers/staging/vt6655/wmgr.h @@ -220,7 +220,7 @@ typedef enum tagWMAC_POWER_MODE { */ -// Tx Managment Packet descriptor +// Tx Management Packet descriptor typedef struct tagSTxMgmtPacket { PUWLAN_80211HDR p80211Header; @@ -230,7 +230,7 @@ typedef struct tagSTxMgmtPacket { } STxMgmtPacket, *PSTxMgmtPacket; -// Rx Managment Packet descriptor +// Rx Management Packet descriptor typedef struct tagSRxMgmtPacket { PUWLAN_80211HDR p80211Header; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 8f18578a5903..5185d61564d7 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1938,7 +1938,7 @@ s_vGenerateMACHeader ( * Out: * none * - * Return Value: CMD_STATUS_PENDING if MAC Tx resource avaliable; otherwise FALSE + * Return Value: CMD_STATUS_PENDING if MAC Tx resource available; otherwise FALSE * -*/ diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index b83b660b1f0f..019fb52de366 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -421,7 +421,7 @@ void vRunCommand(void *hDeviceContext) pMgmt->eScanState = WMAC_IS_SCANNING; pDevice->byScanBBType = pDevice->byBBType; //lucas pDevice->bStopDataPkt = TRUE; - // Turn off RCR_BSSID filter everytime + // Turn off RCR_BSSID filter every time MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_BSSID); pDevice->byRxMode &= ~RCR_BSSID; @@ -604,7 +604,7 @@ void vRunCommand(void *hDeviceContext) // if Infra mode if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { // Call mgr to begin the deauthentication - // reason = (3) beacuse sta has left ESS + // reason = (3) because sta has left ESS if (pMgmt->eCurrState >= WMAC_STATE_AUTH) { vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h index 594f3a89d8a7..13dfb3bf8328 100644 --- a/drivers/staging/vt6656/wmgr.h +++ b/drivers/staging/vt6656/wmgr.h @@ -218,7 +218,7 @@ typedef enum tagWMAC_POWER_MODE { -// Tx Managment Packet descriptor +// Tx Management Packet descriptor typedef struct tagSTxMgmtPacket { PUWLAN_80211HDR p80211Header; @@ -228,7 +228,7 @@ typedef struct tagSTxMgmtPacket { } STxMgmtPacket, *PSTxMgmtPacket; -// Rx Managment Packet descriptor +// Rx Management Packet descriptor typedef struct tagSRxMgmtPacket { PUWLAN_80211HDR p80211Header; diff --git a/drivers/staging/westbridge/astoria/api/src/cyasdma.c b/drivers/staging/westbridge/astoria/api/src/cyasdma.c index 16b8ec124510..c461d4f60bfb 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyasdma.c +++ b/drivers/staging/westbridge/astoria/api/src/cyasdma.c @@ -1082,7 +1082,7 @@ cy_as_dma_received_data(cy_as_device *dev_p, /* * if the data received exceeds the size of the DMA buffer, * clip the data to the size of the buffer. this can lead - * to loosing some data, but is not different than doing + * to losing some data, but is not different than doing * non-packet reads on the other endpoints. */ if (dsize > dma_p->size - dma_p->offset) diff --git a/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c b/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c index 60b6f3525332..76821e51b817 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c +++ b/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c @@ -126,7 +126,7 @@ find_endpoint_directions(cy_as_device *dev_p, cy_as_physical_endpoint_state desired; /* - * note, there is no error checking here becuase + * note, there is no error checking here because * ISO error checking happens when the API is called. */ for (i = 0; i < 10; i++) { diff --git a/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c b/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c index d43dd858de58..96a86d088305 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c +++ b/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c @@ -432,7 +432,7 @@ cy_as_mail_box_queued_data_handler(cy_as_device *dev_p) * is received. When a complete request is received, the callback * associated with requests on that context is called. When a complete * response is recevied, the callback associated with the request that -* generated the reponse is called. +* generated the response is called. */ void cy_as_mail_box_interrupt_handler(cy_as_device *dev_p) diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c index 7852410b0a4c..4564fc11df22 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c +++ b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c @@ -428,7 +428,7 @@ my_misc_callback(cy_as_device *dev_p, uint8_t context, if (v & CY_AS_MEM_P0_VM_SET_CFGMODE) cy_as_hal_print_message( "initialization message " - "recieved, but config bit " + "received, but config bit " "still set\n"); v = cy_as_hal_read_register(dev_p->tag, @@ -436,7 +436,7 @@ my_misc_callback(cy_as_device *dev_p, uint8_t context, if ((v & CY_AS_MEM_RST_RSTCMPT) == 0) cy_as_hal_print_message( "initialization message " - "recieved, but reset complete " + "received, but reset complete " "bit still not set\n"); } break; @@ -2381,7 +2381,7 @@ try_wakeup_again: /* * release the west bridge micro-_controller from reset, * so that firmware initialization can complete. the attempt - * to release antioch reset is made upto 8 times. + * to release antioch reset is made up to 8 times. */ v = 0x03; count = 0x08; diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c index 368984633874..8598364f7ab7 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c +++ b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c @@ -346,7 +346,7 @@ cy_as_mtp_start(cy_as_device_handle handle, dev_p->mtp_event_cb = event_c_b; /* - * we register here becuase the start request may cause + * we register here because the start request may cause * events to occur before the response to the start request. */ cy_as_ll_register_request_callback(dev_p, @@ -424,7 +424,7 @@ my_handle_response_mtp_stop(cy_as_device *dev_p, goto destroy; /* - * we sucessfully shutdown the stack, so decrement + * we successfully shutdown the stack, so decrement * to make the count zero. */ dev_p->mtp_count--; diff --git a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c index 2451404b88d4..7abd6a35e828 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c +++ b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c @@ -1773,7 +1773,7 @@ cy_as_storage_async_oper(cy_as_device *dev_p, cy_as_end_point_number_t ep, if (unit > 255) return CY_AS_ERROR_NO_SUCH_UNIT; - /* We are supposed to return sucess if the number of + /* We are supposed to return success if the number of * blocks is zero */ if (num_blocks == 0) { @@ -1969,7 +1969,7 @@ cy_as_storage_sync_oper(cy_as_device *dev_p, if (cy_as_device_is_usb_async_pending(dev_p, 6)) return CY_AS_ERROR_ASYNC_PENDING; - /* We are supposed to return sucess if the number of + /* We are supposed to return success if the number of * blocks is zero */ if (num_blocks == 0) @@ -3285,7 +3285,7 @@ cy_as_sdio_extended_i_o_async( if (callback == 0) return CY_AS_ERROR_NULL_CALLBACK; - /* We are supposed to return sucess if the number of + /* We are supposed to return success if the number of * blocks is zero */ if (((misc_buf&CY_SDIO_BLOCKMODE) != 0) && (argument == 0)) { diff --git a/drivers/staging/westbridge/astoria/api/src/cyasusb.c b/drivers/staging/westbridge/astoria/api/src/cyasusb.c index 92ea42503bf3..1b55e611191e 100644 --- a/drivers/staging/westbridge/astoria/api/src/cyasusb.c +++ b/drivers/staging/westbridge/astoria/api/src/cyasusb.c @@ -739,7 +739,7 @@ cy_as_usb_start(cy_as_device_handle handle, cy_as_usb_reset_e_p0_state(dev_p); /* - * we register here becuase the start request may cause + * we register here because the start request may cause * events to occur before the response to the start request. */ cy_as_ll_register_request_callback(dev_p, @@ -867,7 +867,7 @@ my_handle_response_usb_stop(cy_as_device *dev_p, goto destroy; /* - * we sucessfully shutdown the stack, so + * we successfully shutdown the stack, so * decrement to make the count zero. */ cy_as_usb_cleanup(dev_p); diff --git a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c index 21cdb0637beb..3bcedce13f4a 100644 --- a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c +++ b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c @@ -87,7 +87,7 @@ /* - * For performance reasons, we handle storage endpoint transfers upto 4 KB + * For performance reasons, we handle storage endpoint transfers up to 4 KB * within the HAL itself. */ #define CYASSTORAGE_WRITE_EP_NUM (4) @@ -108,12 +108,12 @@ ((ep) == 6) || ((ep) == 8)) /* - * persistant, stores current GPMC interface cfg mode + * persistent, stores current GPMC interface cfg mode */ static uint8_t pnand_16bit; /* - * keep processing new WB DRQ in ISR untill all handled (performance feature) + * keep processing new WB DRQ in ISR until all handled (performance feature) */ #define PROCESS_MULTIPLE_DRQ_IN_ISR (1) @@ -157,7 +157,7 @@ typedef struct cy_as_hal_endpoint_dma { * dma_xfer_sz - size of the next dma xfer on P port * seg_xfer_cnt - counts xfered bytes for in current sg_list * memory segment - * req_xfer_cnt - total number of bytes transfered so far in + * req_xfer_cnt - total number of bytes transferred so far in * current request * req_length - total request length */ @@ -2160,7 +2160,7 @@ void cy_as_hal_mem_set(void *ptr, uint8_t value, uint32_t cnt) /* * This function is expected to create a sleep channel. * The data structure that represents the sleep channel object - * sleep channel (which is Linux "wait_queue_head_t wq" for this paticular HAL) + * sleep channel (which is Linux "wait_queue_head_t wq" for this particular HAL) * passed as a pointer, and allpocated by the caller * (typically as a local var on the stack) "Create" word should read as * "SleepOn", this func doesn't actually create anything @@ -2364,7 +2364,7 @@ int start_o_m_a_p_kernel(const char *pgm, */ cy_as_hal_gpmc_enable_16bit_bus(cy_true); #else - /* Astoria and GPMC are already in 8 bit mode, jsut initialize PNAND_CFG */ + /* Astoria and GPMC are already in 8 bit mode, just initialize PNAND_CFG */ ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0000); #endif diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h index 80dd530bc4fd..6426ea61f3d4 100644 --- a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h +++ b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h @@ -20,7 +20,7 @@ */ /* - * This file contains the defintion of the hardware abstraction + * This file contains the definition of the hardware abstraction * layer on OMAP3430 talking to the West Bridge Astoria device */ diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h index 3eee192ffe89..46f06ee29357 100644 --- a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h +++ b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h @@ -51,7 +51,7 @@ * GPMC_ADDR * [A8:A1]->upD[7:0] * INT# -GPMC_nWP_GPIO_62 - * DACK -N/C not conected + * DACK -N/C not connected * WAKEUP-GPIO_167 * RESET-GPIO_126 * R/B -GPMC_WAIT2_GPIO_64 @@ -108,7 +108,7 @@ * will be monitored * PF_EN_ENGINE - 1- ENABLES ENGINE, but it needs to be started after * that C ctrl reg bit 0 - * PF_FIFO_THRESHOLD - FIFO threshhold in number of BUS(8 or 16) words + * PF_FIFO_THRESHOLD - FIFO threshold in number of BUS(8 or 16) words * PF_WEIGHTED_PRIO - NUM of cycles granted to PFE if RND_ROBIN * prioritization is enabled * PF_ROUND_ROBIN - if enabled, gives priority to other CS, but diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c index 0bbb8a3e191d..d1996a27515e 100644 --- a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c +++ b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c @@ -222,7 +222,7 @@ static int cyasblkdev_queue_thread(void *d) continue; } - /* new req recieved, issue it to the driver */ + /* new req received, issue it to the driver */ set_current_state(TASK_RUNNING); #ifndef WESTBRIDGE_NDEBUG diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h index 0c0726b678ad..6452a9070091 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h @@ -119,7 +119,7 @@ #define CY_AS_REQUEST_LIST_STATE_QUEUED (0x00) /* The request is sent, waiting for response */ #define CY_AS_REQUEST_LIST_STATE_WAITING (0x01) -/* The response has been received, processing reponse */ +/* The response has been received, processing response */ #define CY_AS_REQUEST_LIST_STATE_RECEIVED (0x02) /* The request/response is being canceled */ #define CY_AS_REQUEST_LIST_STATE_CANCELING (0x03) @@ -517,7 +517,7 @@ typedef struct cy_as_context { cy_as_ll_request_list_node *request_queue_p; /* The list node in the request queue */ cy_as_ll_request_list_node *last_node_p; - /* Index upto which data is stored. */ + /* Index up to which data is stored. */ uint16_t queue_index; /* Index to the next request in the queue. */ uint16_t rqt_index; @@ -768,7 +768,7 @@ struct cy_as_device { uint32_t mtp_count; /* The MTP event callback supplied by the client */ cy_as_mtp_event_callback mtp_event_cb; - /* The current block table to be transfered */ + /* The current block table to be transferred */ cy_as_mtp_block_table *tp_blk_tbl; cy_as_c_b_queue *func_cbs_mtp; diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h index 8dab5e900149..16dc9f96018c 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h @@ -108,7 +108,7 @@ typedef enum cy_as_dma_direction { completes a requested DMA operation. Returns - CY_AS_ERROR_SUCCESS - the module initialized sucessfully + CY_AS_ERROR_SUCCESS - the module initialized successfully CY_AS_ERROR_OUT_OF_MEMORY - memory allocation failed during initialization CY_AS_ERROR_ALREADY_RUNNING - the DMA module was already running @@ -131,7 +131,7 @@ cy_as_dma_start( then freeing the resources associated with each DMA endpoint. Returns - CY_AS_ERROR_SUCCESS - the module shutdown sucessfully + CY_AS_ERROR_SUCCESS - the module shutdown successfully CY_AS_ERROR_NOT_RUNNING - the DMA module was not running See Also @@ -161,7 +161,7 @@ cy_as_dma_stop( Returns CY_AS_ERROR_SUCCESS - the traffic on the endpoint is canceled - sucessfully + successfully See Also */ @@ -266,7 +266,7 @@ cy_as_dma_queue_request( will have to maintain a list of sleep channels to wake. Returns - * CY_AS_ERROR_SUCCESS - the queue has drained sucessfully + * CY_AS_ERROR_SUCCESS - the queue has drained successfully * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given is not valid * CY_AS_ERROR_NESTED_SLEEP - CyAsDmaQueueRequest() was requested * on an endpoint where CyAsDmaQueueRequest was already called @@ -295,7 +295,7 @@ cy_as_dma_drain_queue( CyAsHalDmaSetupRead() functoins. Returns - * CY_AS_ERROR_SUCCESS - the value was set sucessfully + * CY_AS_ERROR_SUCCESS - the value was set successfully * CY_AS_ERROR_INVALID_SIZE - the size value was not valid */ extern cy_as_return_status_t diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h index f78d60270d45..2cd0af1ed781 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h @@ -29,7 +29,7 @@ */ /* Summary - The function completed sucessfully + The function completed successfully */ #define CY_AS_ERROR_SUCCESS (0) @@ -796,7 +796,7 @@ Description This error is returned when an operation is attempted that cannot be completed while the USB stack is connected to a USB host. In order - to sucessfully complete the desired operation, CyAsUsbDisconnect() + to successfully complete the desired operation, CyAsUsbDisconnect() must be called to disconnect from the host. */ #define CY_AS_ERROR_USB_CONNECTED (53) diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h index 28136ad75115..5bcbe9bf2f5d 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h @@ -597,7 +597,7 @@ cy_as_mem_set( CyAsHalSleepChannel. Returns - CyTrue is the initialization was sucessful, and CyFalse otherwise + CyTrue is the initialization was successful, and CyFalse otherwise See Also * CyAsHalSleepChannel diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h index 3d7063ea3093..60a6fffb5d53 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h @@ -69,7 +69,7 @@ cy_as_intr_start( Returns * CY_AS_ERROR_SUCCESS - the interrupt module was stopped - * sucessfully + * successfully * CY_AS_ERROR_NOT_RUNNING - the interrupt module was not * running diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h index 2f0701850561..df7c2b66cf27 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h @@ -620,7 +620,7 @@ cy_as_misc_in_standby( * Nestable: YES Returns - * CY_AS_ERROR_SUCCESS - the firmware was sucessfully downloaded + * CY_AS_ERROR_SUCCESS - the firmware was successfully downloaded * CY_AS_ERROR_INVALID_HANDLE * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device * was not configured @@ -836,7 +836,7 @@ cy_as_misc_reset( ownership. Returns - * CY_AS_ERROR_SUCCESS - the p port sucessfully acquired the + * CY_AS_ERROR_SUCCESS - the p port successfully acquired the * resource of interest * CY_AS_ERROR_INVALID_HANDLE * CY_AS_ERROR_NOT_CONFIGURED @@ -879,7 +879,7 @@ cy_as_misc_acquire_resource( * Valid In Asynchronous Callback: NO Returns - * CY_AS_ERROR_SUCCESS - the p port sucessfully released + * CY_AS_ERROR_SUCCESS - the p port successfully released * the resource of interest * CY_AS_ERROR_INVALID_HANDLE * CY_AS_ERROR_NOT_CONFIGURED @@ -929,7 +929,7 @@ cy_as_misc_release_resource( Returns * CY_AS_ERROR_SUCCESS - the trace configuration has been - * sucessfully changed + * successfully changed * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device * pair does not exist diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h index 317805fc4ff4..773b645ea7eb 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h @@ -756,7 +756,7 @@ * 1 : Debug mode Description - This reponse is sent to return the firmware version + This response is sent to return the firmware version number to the requestor. */ #define CY_RESP_FIRMWARE_VERSION (16) @@ -3655,7 +3655,7 @@ This request is sent to the West Bridge when the P port needs to send data to the Host in a Turbo Endpoint. Upon receiving this event, Firmware will make the end point - avilable for the P port. If the length is zero, then + available for the P port. If the length is zero, then firmware will send a zero length packet. Direction diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h index 64f078cf202c..52b93c3e4813 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h @@ -832,7 +832,7 @@ typedef struct cy_as_sdio_func { * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been * loaded into West Bridge * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in - * CY_AS_ERROR_SUCCESS - the module started sucessfully + * CY_AS_ERROR_SUCCESS - the module started successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating * with the West Bridge device * CY_AS_ERROR_OUT_OF_MEMORY @@ -882,7 +882,7 @@ cy_as_storage_start( * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was * passed in * CY_AS_ERROR_SUCCESS - this module was shut - * down sucessfully + * down successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred * communicating with the West Bridge device * CY_AS_ERROR_NOT_RUNNING @@ -934,7 +934,7 @@ cy_as_storage_stop( * CY_AS_ERROR_INVALID_HANDLE - an invalid handle * was passed in * CY_AS_ERROR_SUCCESS - the function was registered - * sucessfully + * successfully * CY_AS_ERROR_NOT_RUNNING - the stack is not running See Also @@ -981,7 +981,7 @@ cy_as_storage_register_callback( * been started * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was * passed in - * CY_AS_ERROR_SUCCESS - this request was sucessfully + * CY_AS_ERROR_SUCCESS - this request was successfully * transmitted to the West Bridge device * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating * with the West Bridge device @@ -1034,7 +1034,7 @@ cy_as_storage_claim( * been started * CY_AS_ERROR_INVALID_HANDLE - an invalid handle * was passed in - * CY_AS_ERROR_SUCCESS - the media was sucessfully + * CY_AS_ERROR_SUCCESS - the media was successfully * released * CY_AS_ERROR_MEDIA_NOT_CLAIMED - the media was not * claimed by the P port @@ -1905,7 +1905,7 @@ cy_as_storage_get_transfer_amount( differ between SD cards. A large erase can take a while to complete depending on the SD - card. In such a case it is reccomended that an async call is made. + card. In such a case it is recommended that an async call is made. Returns * CY_AS_ERROR_SUCCESS - API call completed successfully @@ -1926,7 +1926,7 @@ cy_as_storage_get_transfer_amount( * required before erase is allowed * CY_AS_ERROR_NO_SUCH_BUS * CY_AS_ERROR_NO_SUCH_DEVICE - * CY_AS_ERROR_NOT_SUPPORTED - Erase is currenly only supported + * CY_AS_ERROR_NOT_SUPPORTED - Erase is currently only supported * on SD and using SD only firmware * CY_AS_ERROR_OUT_OF_MEMORY @@ -1985,7 +1985,7 @@ cy_as_storage_erase( * type was made * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in * reading from the media * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to @@ -2047,7 +2047,7 @@ cy_as_sdio_get_c_i_s_info( * pair does not exist * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware */ cy_as_return_status_t @@ -2095,7 +2095,7 @@ cy_as_sdio_query_card( * pair does not exist * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware */ cy_as_return_status_t cy_as_sdio_reset_card( @@ -2139,7 +2139,7 @@ cy_as_sdio_reset_card( * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair * does not exist * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available - * CY_AS_ERROR_INVALID_RESPONSE - an error message was recieved + * CY_AS_ERROR_INVALID_RESPONSE - an error message was received * from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in reading * from the media @@ -2198,7 +2198,7 @@ cy_as_sdio_direct_read( * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device * pair does not exist * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available - * CY_AS_ERROR_INVALID_RESPONSE - an error message was recieved + * CY_AS_ERROR_INVALID_RESPONSE - an error message was received * from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in * reading from the media @@ -2262,7 +2262,7 @@ cy_as_sdio_direct_write( * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory * available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in * reading from the media * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made @@ -2319,7 +2319,7 @@ cy_as_sdio_set_blocksize( * pair does not exist * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available - * CY_AS_ERROR_INVALID_RESPONSE - an error message was recieved + * CY_AS_ERROR_INVALID_RESPONSE - an error message was received * from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in * reading from the media @@ -2396,7 +2396,7 @@ cy_as_sdio_extended_read( * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in * reading from the media * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made @@ -2471,7 +2471,7 @@ cy_as_sdio_extended_write( * pair does not exist * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in * reading from the media * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made @@ -2714,7 +2714,7 @@ cy_as_sdio_suspend( * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory * available * CY_AS_ERROR_INVALID_RESPONSE - an error message was - * recieved from the firmware + * received from the firmware * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error * in reading from the media * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h index 4a549e146812..e3ba9ca4c75f 100644 --- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h @@ -464,7 +464,7 @@ typedef struct cy_as_usb_end_point_config { be selected on a partitioned storage device. Description - West Bridge firmware supports creating upto two + West Bridge firmware supports creating up to two partitions on mass storage devices connected to West Bridge. When there are two partitions on a device, the user can choose which of these partitions should be @@ -698,7 +698,7 @@ cy_as_usb_start( * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded * into West Bridge - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with * the West Bridge device @@ -752,7 +752,7 @@ cy_as_usb_register_callback( * Nestable: YES Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -791,7 +791,7 @@ cy_as_usb_connect( * Nestable: YES Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -825,7 +825,7 @@ cy_as_usb_disconnect( * Valid In Asynchronous Callback: Yes (if cb supplied) Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -855,13 +855,13 @@ cy_as_usb_set_enum_config( the USB stack Description - This function sends a request to West Bridge to retreive + This function sends a request to West Bridge to retrieve the current configuration * Valid In Asynchronous Callback: Yes (if cb supplied) Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -906,7 +906,7 @@ cy_as_usb_get_enum_config( Chapter 9. Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -993,7 +993,7 @@ cy_as_usb_clear_descriptors( Description This data structure the buffer to hold the descriptor data, and an in/out parameter ti indicate the - lenght of the buffer and descriptor data in bytes. + length of the buffer and descriptor data in bytes. See Also * CyAsUsbGetDescriptor @@ -1027,7 +1027,7 @@ typedef struct cy_as_get_descriptor_data { Chapter 9. Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -1106,7 +1106,7 @@ cy_as_usb_get_descriptor( * Valid In Asynchronous Callback: NO Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -1140,7 +1140,7 @@ cy_as_usb_set_physical_configuration( Add documentation about endpoint configuration limitations Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -1181,7 +1181,7 @@ cy_as_usb_set_end_point_config( * Valid In Asynchronous Callback: NO Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not * been configured * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded @@ -1219,7 +1219,7 @@ cy_as_usb_get_end_point_config( functions store away the configuration information and this CyAsUsbCommitConfig() actually finds the best hardware configuration based on the requested endpoint - configuration and sends thsi optimal + configuration and sends this optimal confiuration down to the West Bridge device. * Valid In Asynchronous Callback: YES (if cb supplied) @@ -1268,7 +1268,7 @@ cy_as_usb_commit_config( * Valid In Asynchronous Callback: NO Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with * the West Bridge device * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running @@ -1311,7 +1311,7 @@ cy_as_usb_read_data( * Valid In Asynchronous Callback: YES Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with * the West Bridge device * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running @@ -1355,7 +1355,7 @@ cy_as_usb_read_data_async( a zero length packet transmitted to the USB host. Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with * the West Bridge device * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running @@ -1395,7 +1395,7 @@ cy_as_usb_write_data( in a zero length packet transmitted to the USB host. Returns - * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_SUCCESS - this module was shut down successfully * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with * the West Bridge device * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running @@ -1435,7 +1435,7 @@ cy_as_usb_write_data_async( Returns * CY_AS_ERROR_SUCCESS - this module was shut down - * sucessfully + * successfully * CY_AS_ERROR_NOT_RUNNING - the USB stack is not * running * CY_AS_ERROR_ASYNC_NOT_PENDING - no asynchronous USB @@ -1791,7 +1791,7 @@ cy_as_usb_set_m_s_report_threshold( device should be made visible to USB. Description - West Bridge firmware supports the creation of upto two + West Bridge firmware supports the creation of up to two partitions on mass storage devices connected to the West Bridge device. When there are two partitions on a device, the user can choose which of these partitions should be made visible to the diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c index 9cfea94bcea5..c9f0e8f856a0 100644 --- a/drivers/staging/winbond/mds.c +++ b/drivers/staging/winbond/mds.c @@ -492,7 +492,7 @@ Mds_Tx(struct wbsoft_priv *adapter) TxDesIndex = pMds->TxDesIndex; /* Get the current ID */ pTxDes->Descriptor_ID = TxDesIndex; - pMds->TxDesFrom[TxDesIndex] = 2; /* Storing the information of source comming from */ + pMds->TxDesFrom[TxDesIndex] = 2; /* Storing the information of source coming from */ pMds->TxDesIndex++; pMds->TxDesIndex %= MAX_USB_TX_DESCRIPTOR; diff --git a/drivers/staging/wlags49_h2/README.ubuntu b/drivers/staging/wlags49_h2/README.ubuntu index 47beaec86e4a..edee8b9385be 100644 --- a/drivers/staging/wlags49_h2/README.ubuntu +++ b/drivers/staging/wlags49_h2/README.ubuntu @@ -116,7 +116,7 @@ LICENSE The Agere Systems license applies. This is why I include the original README.wlags49. The instructions in that file are bogus now. I also -include the man page. Eventhough setting parameters on the module +include the man page. Even though setting parameters on the module does not work anymore but it provides some information about all the settings. diff --git a/drivers/staging/wlags49_h2/TODO b/drivers/staging/wlags49_h2/TODO index 14aa415b1a82..94032b6ac2b5 100644 --- a/drivers/staging/wlags49_h2/TODO +++ b/drivers/staging/wlags49_h2/TODO @@ -1,7 +1,7 @@ First of all, the best thing would be that this driver becomes obsolte by adding support for Hermes II and Hermes II.5 cards to the existing orinoco driver. The orinoco driver currently only supports Hermes I based cards. -Since this will not happen by magic and has not happend until now this +Since this will not happen by magic and has not happened until now this driver provides a stop-gap solution for these type of cards. Having said that, the following wishlist comes to mind to make the driver @@ -18,7 +18,7 @@ TODO: - the driver is split into a Hermes II and a Hermes II.5 part, it would be nice to handle both with one module instead of two - review by the wireless developer community - - verify the code against the coding standards for a propper linux + - verify the code against the coding standards for a proper linux driver - resolve license issues (?) diff --git a/drivers/staging/wlags49_h2/hcf.c b/drivers/staging/wlags49_h2/hcf.c index d4bdd3ee8be1..a73317ef9350 100644 --- a/drivers/staging/wlags49_h2/hcf.c +++ b/drivers/staging/wlags49_h2/hcf.c @@ -540,7 +540,7 @@ HCF_STATIC hcf_16* BASED xxxx[ ] = { * *.CONDITIONS * Except for hcf_action with HCF_ACT_INT_FORCE_ON or HCF_ACT_INT_OFF as parameter or hcf_connect with an I/O -* address (i.e. not HCF_DISCONNECT), all hcf-function calls MUST be preceeded by a call of hcf_action with +* address (i.e. not HCF_DISCONNECT), all hcf-function calls MUST be preceded by a call of hcf_action with * HCF_ACT_INT_OFF as parameter. * Note that hcf_connect defaults to NIC interrupt disabled mode, i.e. as if hcf_action( HCF_ACT_INT_OFF ) * was called. @@ -843,7 +843,7 @@ hcf_16 i; *.MODULE int hcf_cntl( IFBP ifbp, hcf_16 cmd ) *.PURPOSE Connect or disconnect a specific port to a specific network. *!! ;???????????????? continue needs more explanation -* recovers by means of "continue" when the connect proces in CCX mode fails +* recovers by means of "continue" when the connect process in CCX mode fails * Enables or disables data transmission and reception for the NIC. * Activates static NIC configuration for a specific port at connect. * Activates static configuration for all ports at enable. @@ -1170,12 +1170,12 @@ LTV_STRCT x; io_addr = io_base; } -#if 0 //;? if a subsequent hcf_connect is preceeded by an hcf_disconnect the wakeup is not needed !! +#if 0 //;? if a subsequent hcf_connect is preceded by an hcf_disconnect the wakeup is not needed !! #if HCF_SLEEP OUT_PORT_WORD( .....+HREG_IO, HREG_IO_WAKEUP_ASYNC ); //OPW not yet useable MSF_WAIT(800); // MSF-defined function to wait n microseconds. note that MSF_WAIT uses not yet defined!!!! IFB_IOBase and IFB_TickIni (via PROT_CNT_INI) - so be carefull if this code is restored + so be careful if this code is restored #endif // HCF_SLEEP #endif // 0 @@ -1563,7 +1563,7 @@ DESC_STRCT *p = descp->next_desc_addr; //pointer to 2nd descriptor of frame * This function is called by the MSF to supply the HCF with new/more buffers for receive purposes. * The HCF can be used in 2 fashions: with and without encapsulation for data transfer. * This is controlled at compile time by the HCF_ENC bit of the HCF_ENCAP system constant. -* As a consequence, some additional constaints apply to the number of descriptor and the buffers associated +* As a consequence, some additional constraints apply to the number of descriptor and the buffers associated * with the first 2 descriptors. Independent of the encapsulation feature, the COUNT fields are ignored. * A special case is the supplying of the DELWA descriptor, which must be supplied as the first descriptor. * @@ -1735,7 +1735,7 @@ DESC_STRCT *descp; // pointer to start of FrameList * - in case encapsulation by the HCF is selected: * - The FrameList does not consists of at least 2 Descriptors. * - The first databuffer does not contain exactly the (space for) the 802.11 header (== 28 words) -* - The first databuffer does not have a size to additionally accomodate the 802.3 header and the +* - The first databuffer does not have a size to additionally accommodate the 802.3 header and the * SNAP header of the frame after encapsulation (== 39 words). * - The second databuffer does not contain at least DA, SA and 'type/length' (==14 bytes or 7 words) *!! The 2nd part of the list of asserts should be kept in sync with put_frame_lst, in order to get @@ -1762,14 +1762,14 @@ DESC_STRCT *descp; // pointer to start of FrameList * - Copy DA/SA fields from the 2nd buffer * - Calculate total length of the message (snap-header + type-field + the length of all buffer fragments * associated with the 802.3 frame (i.e all descriptors except the first), but not the DestinationAddress, -* SourceAddress and lenght-field) +* SourceAddress and length-field) * Assert the message length * Write length. Note that the message is in BE format, hence on LE platforms the length must be converted * ;? THIS IS NOT WHAT CURRENTLY IS IMPLEMENTED * - Write snap header. Note that the last byte of the snap header is NOT copied, that byte is already in * place as result of the call to hcf_encap. * Note that there are many ways to skin a cat. To express the offsets in the 1st buffer while writing -* the snap header, HFS_TYPE is choosen as a reference point to make it easier to grasp that the snap header +* the snap header, HFS_TYPE is chosen as a reference point to make it easier to grasp that the snap header * and encapsualtion type are at least relative in the right. *8: modify 1st descriptor to reflect moved part of the 802.3 header + Snap-header * modify 2nd descriptor to skip the moved part of the 802.3 header (DA/SA @@ -1933,7 +1933,7 @@ hcf_16 t = (hcf_16)(*type<<8) + *(type+1); /* 2 */ * HCF_SUCCESS Success *!! via cmd_exe ( type >= CFG_RID_FW_MIN ) * HCF_ERR_NO_NIC NIC removed during retrieval -* HCF_ERR_TIME_OUT Expected Hermes event did not occure in expected time +* HCF_ERR_TIME_OUT Expected Hermes event did not occur in expected time *!! via cmd_exe and setup_bap (type >= CFG_RID_FW_MIN ) * HCF_ERR_DEFUNCT_... HCF is in defunct mode (bits 0x7F reflect cause) * @@ -2958,7 +2958,7 @@ or * hcf_service_nic is also skipped in those cases. * To prevent that hcf_service_nic reports bogus information to the MSF with all - possibly difficult to * debug - undesirable side effects, it is paramount to check the NIC presence. In former days the presence -* test was based on the Hermes register HREG_SW_0. Since in HCF_ACT_INT_OFF is choosen for strategy based on +* test was based on the Hermes register HREG_SW_0. Since in HCF_ACT_INT_OFF is chosen for strategy based on * HREG_EV_STAT, this is now also used in hcf_service_nic. The motivation to change strategy is partly * due to inconsistent F/W implementations with respect to HREG_SW_0 manipulation around reset and download. * Note that in polled environments Card Removal is not detected by INT_OFF which makes the check in @@ -4048,7 +4048,7 @@ hcf_32 FAR *p4; //prevent side effects from macro HCFASSERT( word_len == 0 || word_len == 2 || word_len == 4, word_len ) HCFASSERT( word_len == 0 || ((hcf_32)bufp & 1 ) == 0, (hcf_32)bufp ) HCFASSERT( word_len <= len, MERGE2( word_len, len ) ) - //see put_frag for an alternative implementation, but be carefull about what are int's and what are + //see put_frag for an alternative implementation, but be careful about what are int's and what are //hcf_16's if ( word_len ) { //. if there is anything to convert hcf_8 c; @@ -4712,7 +4712,7 @@ int rc = HCF_SUCCESS; * Note that len is unsigned, so even MSF I/F violation works out O.K. * The '2' in the expression "len+2" is used because 1 word is needed for L itself and 1 word is needed * for the zero-sentinel -*8: update MailBox Info length report to MSF with "oldest" MB Info Block size. Be carefull here, if you get +*8: update MailBox Info length report to MSF with "oldest" MB Info Block size. Be careful here, if you get * here before the MailBox is registered, you can't read from the buffer addressed by IFB_MBp (it is the * Null buffer) so don't move this code till the end of this routine but keep it where there is garuanteed * a buffer. diff --git a/drivers/staging/wlags49_h2/hcfdef.h b/drivers/staging/wlags49_h2/hcfdef.h index 4e20171b7829..cb1966d8473f 100644 --- a/drivers/staging/wlags49_h2/hcfdef.h +++ b/drivers/staging/wlags49_h2/hcfdef.h @@ -315,7 +315,7 @@ err: these values should match; #if HCF_DMA //************************* DMA (bus mastering) - // Be carefull to use these registers only at a genuine 32 bits NIC + // Be careful to use these registers only at a genuine 32 bits NIC // On 16 bits NICs, these addresses are mapped into the range 0x00 through 0x3F with all consequences // thereof, e.g. HREG_DMA_CTRL register maps to HREG_CMD. #define HREG_DMA_CTRL 0x0040 diff --git a/drivers/staging/wlags49_h2/wl_wext.c b/drivers/staging/wlags49_h2/wl_wext.c index 9e5da0815371..522a31090c58 100644 --- a/drivers/staging/wlags49_h2/wl_wext.c +++ b/drivers/staging/wlags49_h2/wl_wext.c @@ -2575,7 +2575,7 @@ static int wireless_set_scan(struct net_device *dev, struct iw_request_info *inf * This looks like a nice place to test if the HCF is still * communicating with the card. It seems that sometimes BAP_1 * gets corrupted. By looking at the comments in HCF the - * cause is still a mistery. Okay, the communication to the + * cause is still a mystery. Okay, the communication to the * card is dead, reset the card to revive. */ if((lp->hcfCtx.IFB_CardStat & CARD_STAT_DEFUNCT) != 0) @@ -3924,7 +3924,7 @@ void wl_wext_event_mic_failed( struct net_device *dev ) memset( msg, 0, sizeof( msg )); - /* Becuase MIC failures are not part of the Wireless Extensions yet, they + /* Because MIC failures are not part of the Wireless Extensions yet, they must be passed as a string using an IWEVCUSTOM event. In order for the event to be effective, the string format must be known by both the driver and the supplicant. The following is the string format used by the @@ -3999,7 +3999,7 @@ void wl_wext_event_assoc_ie( struct net_device *dev ) memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 ); wpa_ie = wl_parse_wpa_ie( &data, &length ); - /* Becuase this event (Association WPA-IE) is not part of the Wireless + /* Because this event (Association WPA-IE) is not part of the Wireless Extensions yet, it must be passed as a string using an IWEVCUSTOM event. In order for the event to be effective, the string format must be known by both the driver and the supplicant. The following is the string format diff --git a/drivers/staging/wlags49_h25/TODO b/drivers/staging/wlags49_h25/TODO index 14aa415b1a82..94032b6ac2b5 100644 --- a/drivers/staging/wlags49_h25/TODO +++ b/drivers/staging/wlags49_h25/TODO @@ -1,7 +1,7 @@ First of all, the best thing would be that this driver becomes obsolte by adding support for Hermes II and Hermes II.5 cards to the existing orinoco driver. The orinoco driver currently only supports Hermes I based cards. -Since this will not happen by magic and has not happend until now this +Since this will not happen by magic and has not happened until now this driver provides a stop-gap solution for these type of cards. Having said that, the following wishlist comes to mind to make the driver @@ -18,7 +18,7 @@ TODO: - the driver is split into a Hermes II and a Hermes II.5 part, it would be nice to handle both with one module instead of two - review by the wireless developer community - - verify the code against the coding standards for a propper linux + - verify the code against the coding standards for a proper linux driver - resolve license issues (?) diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index ed751f418db9..21f25a21c291 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1976,7 +1976,7 @@ static wlandevice_t *create_wlan(void) wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | P80211_NSDCAP_AUTOJOIN; - /* Initialize the device private data stucture. */ + /* Initialize the device private data structure. */ hw->dot11_desired_bss_type = 1; return wlandev; diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 8762a5327693..9669c22cc82c 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -7834,7 +7834,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, == 600)) { index++; } - /* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */ + /* Alan 10/19/2007; do the similar adjustment like XGISearchCRT1Rate() */ if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1024) && (pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 768)) { diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h index 4b87951f4322..d613e84aab62 100644 --- a/drivers/staging/xgifb/vgatypes.h +++ b/drivers/staging/xgifb/vgatypes.h @@ -85,7 +85,7 @@ struct xgi_hw_device_info unsigned long *); }; -/* Addtional IOCTL for communication xgifb <> X driver */ +/* Additional IOCTL for communication xgifb <> X driver */ /* If changing this, xgifb.h must also be changed (for xgifb) */ diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 2c5fcfed5934..30cbb743d9ba 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -496,8 +496,8 @@ static int core_alua_state_check( nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); /* - * Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a seperate conditional - * statement so the complier knows explictly to check this case first. + * Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a separate conditional + * statement so the compiler knows explicitly to check this case first. * For the Optimized ALUA access state case, we want to process the * incoming fabric cmd ASAP.. */ @@ -1157,7 +1157,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) spin_unlock(&lu_gp->lu_gp_lock); /* * - * lu_gp_mem is assoicated with a single + * lu_gp_mem is associated with a single * struct se_device->dev_alua_lu_gp_mem, and is released when * struct se_device is released via core_alua_free_lu_gp_mem(). * @@ -1429,7 +1429,7 @@ void core_alua_free_tg_pt_gp( } spin_unlock(&tg_pt_gp->tg_pt_gp_lock); /* - * tg_pt_gp_mem is assoicated with a single + * tg_pt_gp_mem is associated with a single * se_port->sep_alua_tg_pt_gp_mem, and is released via * core_alua_free_tg_pt_gp_mem(). * @@ -1963,7 +1963,7 @@ int core_setup_alua(struct se_device *dev, int force_pt) printk(KERN_INFO "%s: Enabling ALUA Emulation for SPC-3" " device\n", TRANSPORT(dev)->name); /* - * Assoicate this struct se_device with the default ALUA + * Associate this struct se_device with the default ALUA * LUN Group. */ lu_gp_mem = core_alua_allocate_lu_gp_mem(dev); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 3fb8e32506ed..d25e20829012 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -371,7 +371,7 @@ int core_update_device_list_for_node( if (!(enable)) { /* * deve->se_lun_acl will be NULL for demo-mode created LUNs - * that have not been explictly concerted to MappedLUNs -> + * that have not been explicitly concerted to MappedLUNs -> * struct se_lun_acl, but we remove deve->alua_port_list from * port->sep_alua_list. This also means that active UAs and * NodeACL context specific PR metadata for demo-mode diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c index d57ad672677f..1e193f324895 100644 --- a/drivers/target/target_core_fabric_lib.c +++ b/drivers/target/target_core_fabric_lib.c @@ -433,7 +433,7 @@ char *iscsi_parse_pr_out_transport_id( /* * Go ahead and do the lower case conversion of the received * 12 ASCII characters representing the ISID in the TransportID - * for comparision against the running iSCSI session's ISID from + * for comparison against the running iSCSI session's ISID from * iscsi_target.c:lio_sess_get_initiator_sid() */ for (i = 0; i < 12; i++) { diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 02f553aef43d..150c4305f385 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -159,7 +159,7 @@ static struct se_device *fd_create_virtdevice( #endif /* flags |= O_DIRECT; */ /* - * If fd_buffered_io=1 has not been set explictly (the default), + * If fd_buffered_io=1 has not been set explicitly (the default), * use O_SYNC to force FILEIO writes to disk. */ if (!(fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO)) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 2521f75362c3..a79f518ca6e2 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -478,7 +478,7 @@ static int core_scsi3_pr_seq_non_holder( break; } /* - * Case where the CDB is explictly allowed in the above switch + * Case where the CDB is explicitly allowed in the above switch * statement. */ if (!(ret) && !(other_cdb)) { @@ -3735,7 +3735,7 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb) return PYX_TRANSPORT_LU_COMM_FAILURE; if (cmd->data_length < 24) { - printk(KERN_WARNING "SPC-PR: Recieved PR OUT parameter list" + printk(KERN_WARNING "SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); return PYX_TRANSPORT_INVALID_PARAMETER_LIST; } @@ -3778,7 +3778,7 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb) */ if (!(spec_i_pt) && ((cdb[1] & 0x1f) != PRO_REGISTER_AND_MOVE) && (cmd->data_length != 24)) { - printk(KERN_WARNING "SPC-PR: Recieved PR OUT illegal parameter" + printk(KERN_WARNING "SPC-PR: Received PR OUT illegal parameter" " list length: %u\n", cmd->data_length); return PYX_TRANSPORT_INVALID_PARAMETER_LIST; } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index bf6aa8a9f1d8..9583b23c9c84 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -719,7 +719,7 @@ static int transport_cmd_check_stop( cmd->se_lun = NULL; /* * Some fabric modules like tcm_loop can release - * their internally allocated I/O refrence now and + * their internally allocated I/O reference now and * struct se_cmd now. */ if (CMD_TFO(cmd)->check_stop_free != NULL) { @@ -2029,7 +2029,7 @@ int transport_generic_handle_data( * If the received CDB has aleady been ABORTED by the generic * target engine, we now call transport_check_aborted_status() * to queue any delated TASK_ABORTED status for the received CDB to the - * fabric module as we are expecting no futher incoming DATA OUT + * fabric module as we are expecting no further incoming DATA OUT * sequences at this point. */ if (transport_check_aborted_status(cmd, 1) != 0) @@ -2501,7 +2501,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) return 1; /* - * Check for the existance of HEAD_OF_QUEUE, and if true return 1 + * Check for the existence of HEAD_OF_QUEUE, and if true return 1 * to allow the passed struct se_cmd list of tasks to the front of the list. */ if (cmd->sam_task_attr == TASK_ATTR_HOQ) { @@ -2547,7 +2547,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) if (atomic_read(&SE_DEV(cmd)->dev_ordered_sync) != 0) { /* * Otherwise, add cmd w/ tasks to delayed cmd queue that - * will be drained upon competion of HEAD_OF_QUEUE task. + * will be drained upon completion of HEAD_OF_QUEUE task. */ spin_lock(&SE_DEV(cmd)->delayed_cmd_lock); cmd->se_cmd_flags |= SCF_DELAYED_CMD_FROM_SAM_ATTR; @@ -2589,7 +2589,7 @@ static int transport_execute_tasks(struct se_cmd *cmd) } /* * Call transport_cmd_check_stop() to see if a fabric exception - * has occured that prevents execution. + * has occurred that prevents execution. */ if (!(transport_cmd_check_stop(cmd, 0, TRANSPORT_PROCESSING))) { /* @@ -3109,7 +3109,7 @@ static int transport_generic_cmd_sequencer( if (ret != 0) { cmd->transport_wait_for_tasks = &transport_nop_wait_for_tasks; /* - * Set SCSI additional sense code (ASC) to 'LUN Not Accessable'; + * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; * The ALUA additional sense code qualifier (ASCQ) is determined * by the ALUA primary or secondary access state.. */ @@ -3867,7 +3867,7 @@ static void transport_generic_complete_ok(struct se_cmd *cmd) } } /* - * Check for a callback, used by amoungst other things + * Check for a callback, used by amongst other things * XDWRITE_READ_10 emulation. */ if (cmd->transport_complete_callback) diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index a2ef346087e8..df355176a377 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -247,7 +247,7 @@ void core_scsi3_ua_for_check_condition( } /* * Otherwise for the default 00b, release the UNIT ATTENTION - * condition. Return the ASC/ASCQ of the higest priority UA + * condition. Return the ASC/ASCQ of the highest priority UA * (head of the list) in the outgoing CHECK_CONDITION + sense. */ if (head) { @@ -304,7 +304,7 @@ int core_scsi3_ua_clear_for_request_sense( * matching struct se_lun. * * Once the returning ASC/ASCQ values are set, we go ahead and - * release all of the Unit Attention conditions for the assoicated + * release all of the Unit Attention conditions for the associated * struct se_lun. */ spin_lock(&deve->ua_lock); diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index b00101972f20..d5f923bcdffe 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -169,7 +169,7 @@ * Added support for Linux 2.4.x kernels. * * Revision 3.77 2001/01/09 04:00:52 eokerson - * Linetest will now test the line, even if it has previously succeded. + * Linetest will now test the line, even if it has previously succeeded. * * Revision 3.76 2001/01/08 19:27:00 eokerson * Fixed problem with standard cable on Internet PhoneCARD. @@ -352,7 +352,7 @@ static void ixj_fsk_alloc(IXJ *j) } else { j->fsksize = 8000; if(ixjdebug & 0x0200) { - printk("IXJ phone%d - allocate succeded\n", j->board); + printk("IXJ phone%d - allocate succeeded\n", j->board); } } } @@ -487,7 +487,7 @@ DSPbase + 8-9 Hardware Status Register Read Only A-B Hardware Control Register Read Write C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only -E-F Host Recieve (Read) Data Buffer Access Port (buffer input) Read Only +E-F Host Receive (Read) Data Buffer Access Port (buffer input) Read Only ************************************************************************/ static inline void ixj_read_HSR(IXJ *j) @@ -4195,7 +4195,7 @@ static void ixj_aec_start(IXJ *j, int level) ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ /* Now we can set the AGC initial parameters and turn it on */ - ixj_WriteDSPCommand(0xCF90, j); /* Set AGC Minumum gain */ + ixj_WriteDSPCommand(0xCF90, j); /* Set AGC Minimum gain */ ixj_WriteDSPCommand(0x0020, j); /* to 0.125 (-18dB) */ ixj_WriteDSPCommand(0xCF91, j); /* Set AGC Maximum gain */ diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index 4c32a43b7914..2c841134f61c 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -1149,7 +1149,7 @@ typedef struct { unsigned int firstring:1; /* First ring cadence is complete */ unsigned int pstncheck:1; /* Currently checking the PSTN Line */ unsigned int pstn_rmr:1; - unsigned int x:3; /* unsed bits */ + unsigned int x:3; /* unused bits */ } IXJ_FLAGS; diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index c3425bb3a1f6..b6f7d52f7c35 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -255,7 +255,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, default: written = -EIO; } - /* remove buffer if an error has occured or received data + /* remove buffer if an error has occurred or received data * is not correct */ if (rc || (rb->mbuf->version != MSG_VERSION) || (rb->msg.length != MSG_SIZE(rb->mbuf->datalen))) @@ -620,7 +620,7 @@ static void hvc_iucv_hangup(struct hvc_iucv_private *priv) * the index of an struct hvc_iucv_private instance. * * This routine notifies the HVC back-end that a tty hangup (carrier loss, - * virtual or otherwise) has occured. + * virtual or otherwise) has occurred. * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup()) * to keep an existing IUCV communication path established. * (Background: vhangup() is called from user space (by getty or login) to diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index 5e2f52b33327..e6eea1485244 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -1,7 +1,7 @@ /* * vio driver interface to hvc_console.c * - * This code was moved here to allow the remaing code to be reused as a + * This code was moved here to allow the remaining code to be reused as a * generic polling mode with semi-reliable transport driver core to the * console and tty subsystems. * diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index bef238f9ffd7..4c8b66546930 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -118,7 +118,7 @@ * arch/powerepc/include/asm/hvcserver.h * * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to - * prevent possible lockup with realtime scheduling as similarily pointed out by + * prevent possible lockup with realtime scheduling as similarly pointed out by * akpm in hvc_console. Changed resulted in the removal of hvcs_final_close() * to reorder cleanup operations and prevent discarding of pending data during * an hvcs_close(). Removed spinlock protection of hvcs_struct data members in @@ -581,7 +581,7 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd) /* * We are still obligated to deliver the data to the * hypervisor even if the tty has been closed because - * we commited to delivering it. But don't try to wake + * we committed to delivering it. But don't try to wake * a non-existent tty. */ if (tty) { @@ -1349,7 +1349,7 @@ static int hvcs_write(struct tty_struct *tty, spin_lock_irqsave(&hvcsd->lock, flags); /* - * Somehow an open succedded but the device was removed or the + * Somehow an open succeeded but the device was removed or the * connection terminated between the vty-server and partner vty during * the middle of a write operation? This is a crummy place to do this * but we want to keep it all in the spinlock. @@ -1420,7 +1420,7 @@ static int hvcs_write(struct tty_struct *tty, } /* - * This is really asking how much can we guarentee that we can send or that we + * This is really asking how much can we guarantee that we can send or that we * absolutely WILL BUFFER if we can't send it. This driver MUST honor the * return value, hence the reason for hvcs_struct buffering. */ diff --git a/drivers/tty/mxser.h b/drivers/tty/mxser.h index 41878a69203d..0bf794313ffd 100644 --- a/drivers/tty/mxser.h +++ b/drivers/tty/mxser.h @@ -113,7 +113,7 @@ #define MOXA_MUST_IIR_RTO 0x0C #define MOXA_MUST_IIR_LSR 0x06 -/* recieved Xon/Xoff or specical interrupt pending */ +/* received Xon/Xoff or specical interrupt pending */ #define MOXA_MUST_IIR_XSC 0x10 /* RTS/CTS change state interrupt pending */ diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 176f63256b37..47f8cdb207f1 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -74,7 +74,7 @@ module_param(debug, int, 0600); #endif /* - * Semi-arbitary buffer size limits. 0710 is normally run with 32-64 byte + * Semi-arbitrary buffer size limits. 0710 is normally run with 32-64 byte * limits so this is plenty */ #define MAX_MRU 512 @@ -82,7 +82,7 @@ module_param(debug, int, 0600); /* * Each block of data we have queued to go out is in the form of - * a gsm_msg which holds everything we need in a link layer independant + * a gsm_msg which holds everything we need in a link layer independent * format */ @@ -1193,8 +1193,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, break; /* Optional unsupported commands */ case CMD_PN: /* Parameter negotiation */ - case CMD_RPN: /* Remote port negotation */ - case CMD_SNC: /* Service negotation command */ + case CMD_RPN: /* Remote port negotiation */ + case CMD_SNC: /* Service negotiation command */ default: /* Reply to bad commands with an NSC */ buf[0] = command; @@ -2026,7 +2026,7 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux); * @mux: mux to free * * Dispose of allocated resources for a dead mux. No refcounting - * at present so the mux must be truely dead. + * at present so the mux must be truly dead. */ void gsm_free_mux(struct gsm_mux *gsm) { diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index f4f11164efe5..fd0a98524d51 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -1673,7 +1673,7 @@ static void ntty_hangup(struct tty_struct *tty) /* * called when the userspace process writes to the tty (/dev/noz*). - * Data is inserted into a fifo, which is then read and transfered to the modem. + * Data is inserted into a fifo, which is then read and transferred to the modem. */ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, int count) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 3780da8ad12d..036feeb5e3f6 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -2060,7 +2060,7 @@ static __init int register_PCI(int i, struct pci_dev *dev) sClockPrescale = 0x19; rp_baud_base[i] = 230400; } else { - /* mod 4 (devide by 5) prescale */ + /* mod 4 (divide by 5) prescale */ sClockPrescale = 0x14; rp_baud_base[i] = 460800; } @@ -2183,7 +2183,7 @@ static int __init init_ISA(int i) sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */ rp_baud_base[i] = 230400; } else { - sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */ + sClockPrescale = 0x14; /* mod 4 (divide by 5) prescale */ rp_baud_base[i] = 460800; } diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index b3b881bc4712..6611535f4440 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -1629,7 +1629,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) up->port.iotype == UPIO_DWAPB32) && (iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* The DesignWare APB UART has an Busy Detect (0x07) - * interrupt meaning an LCR write attempt occured while the + * interrupt meaning an LCR write attempt occurred while the * UART was busy. The interrupt must be cleared by reading * the UART status register (USR) and the LCR re-written. */ unsigned int status; diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 8b8930f700b5..738cec9807d3 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -433,7 +433,7 @@ static void __devexit sbs_exit(struct pci_dev *dev) /* * SIIG serial cards have an PCI interface chip which also controls * the UART clocking frequency. Each UART can be clocked independently - * (except cards equiped with 4 UARTs) and initial clocking settings + * (except cards equipped with 4 UARTs) and initial clocking settings * are stored in the EEPROM chip. It can cause problems because this * version of serial driver doesn't support differently clocked UART's * on single PCI card. To prevent this, initialization functions set diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 57731e870085..6deee4e546be 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -520,7 +520,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap) /* * We don't have a TX buffer queued, so try to queue one. - * If we succesfully queued a buffer, mask the TX IRQ. + * If we successfully queued a buffer, mask the TX IRQ. */ if (pl011_dma_tx_refill(uap) > 0) { uap->im &= ~UART011_TXIM; diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index 53a468227056..8a869e58f6d7 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -1248,7 +1248,7 @@ static void icom_set_termios(struct uart_port *port, } } - /* Enable Transmitter and Reciever */ + /* Enable Transmitter and Receiver */ offset = (unsigned long) &ICOM_PORT->statStg->rcv[0] - (unsigned long) ICOM_PORT->statStg; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index dfcf4b1878aa..cb36b0d4ef3c 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -78,7 +78,7 @@ #define URXD_FRMERR (1<<12) #define URXD_BRK (1<<11) #define URXD_PRERR (1<<10) -#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADEN (1<<15) /* Auto detect interrupt */ #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ #define UCR1_IDEN (1<<12) /* Idle condition interrupt */ diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index ebff4a1d4bcc..7b1cda59ebb5 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -375,7 +375,7 @@ static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, * be nice to transmit console writes just like we normally would for * a TTY line. (ie. buffered and TX interrupt driven). That is not * easy because console writes cannot sleep. One solution might be - * to poll on enough port->xmit space becomming free. -DaveM + * to poll on enough port->xmit space becoming free. -DaveM */ if (!(status & Tx_BUF_EMP)) return; diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h index 38a509c684cd..b704c8ce0d71 100644 --- a/drivers/tty/serial/jsm/jsm.h +++ b/drivers/tty/serial/jsm/jsm.h @@ -273,7 +273,7 @@ struct neo_uart_struct { u8 fctr; /* WR FCTR - Feature Control Reg */ u8 efr; /* WR EFR - Enhanced Function Reg */ u8 tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */ - u8 rfifo; /* WR RXCNT/RXTRG - Recieve FIFO Reg */ + u8 rfifo; /* WR RXCNT/RXTRG - Receive FIFO Reg */ u8 xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */ u8 xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */ u8 xonchar1; /* WR XON 1 - Xon Character 1 Reg */ diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c index 7960d9633c15..4538c3e3646e 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c @@ -381,7 +381,7 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch) /* Copy data from uart to the queue */ memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n); /* - * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed + * Since RX_FIFO_DATA_ERROR was 0, we are guaranteed * that all the data currently in the FIFO is free of * breaks and parity/frame/orun errors. */ @@ -1210,7 +1210,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * Why would I check EVERY possibility of type of * interrupt, when we know its TXRDY??? * Becuz for some reason, even tho we got triggered for TXRDY, - * it seems to be occassionally wrong. Instead of TX, which + * it seems to be occasionally wrong. Instead of TX, which * it should be, I was getting things like RXDY too. Weird. */ neo_parse_isr(brd, port); diff --git a/drivers/tty/serial/max3107.h b/drivers/tty/serial/max3107.h index 7ab632392502..8415fc723b96 100644 --- a/drivers/tty/serial/max3107.h +++ b/drivers/tty/serial/max3107.h @@ -369,7 +369,7 @@ struct max3107_port { struct spi_device *spi; #if defined(CONFIG_GPIOLIB) - /* GPIO chip stucture */ + /* GPIO chip structure */ struct gpio_chip chip; #endif diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 37e13c3d91d9..2f548af4e98a 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -23,7 +23,7 @@ * 1 word. If SPI master controller doesn't support sclk frequency change, * then the char need be sent out one by one with some delay * - * 2. Currently only RX availabe interrrupt is used, no need for waiting TXE + * 2. Currently only RX available interrrupt is used, no need for waiting TXE * interrupt for a low speed UART device */ diff --git a/drivers/tty/serial/mrst_max3110.h b/drivers/tty/serial/mrst_max3110.h index d1ef43af397c..c37ea48c825a 100644 --- a/drivers/tty/serial/mrst_max3110.h +++ b/drivers/tty/serial/mrst_max3110.h @@ -21,7 +21,7 @@ #define WC_IRQ_MASK (0xF << 8) #define WC_TXE_IRQ_ENABLE (1 << 11) /* TX empty irq */ -#define WC_RXA_IRQ_ENABLE (1 << 10) /* RX availabe irq */ +#define WC_RXA_IRQ_ENABLE (1 << 10) /* RX available irq */ #define WC_PAR_HIGH_IRQ_ENABLE (1 << 9) #define WC_REC_ACT_IRQ_ENABLE (1 << 8) diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index b906f11f7c1a..624701f8138a 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -495,7 +495,7 @@ static void msm_hs_pm(struct uart_port *uport, unsigned int state, * * Interrupts should be disabled before we are called, as * we modify Set Baud rate - * Set receive stale interrupt level, dependant on Bit Rate + * Set receive stale interrupt level, dependent on Bit Rate * Goal is to have around 8 ms before indicate stale. * roundup (((Bit Rate * .008) / 10) + 1 */ @@ -1350,7 +1350,7 @@ static irqreturn_t msm_hs_rx_wakeup_isr(int irq, void *dev) spin_lock_irqsave(&uport->lock, flags); if (msm_uport->clk_state == MSM_HS_CLK_OFF) { - /* ignore the first irq - it is a pending irq that occured + /* ignore the first irq - it is a pending irq that occurred * before enable_irq() */ if (msm_uport->rx_wakeup.ignore) msm_uport->rx_wakeup.ignore = 0; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 763537943a53..47cadf474149 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -13,7 +13,7 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * Note: This driver is made seperate from 8250 driver as we cannot + * Note: This driver is made separate from 8250 driver as we cannot * over load 8250 driver with omap platform specific configuration for * features like DMA, it makes easier to implement features like DMA and * hardware flow control and software flow control configuration with diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 5b9cde79e4ea..e1c8d4f1ce58 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -330,7 +330,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) * When that happens, I disable the receive side of the driver. * Note that what I've been experiencing is a real irq loop where * I'm getting flooded regardless of the actual port speed. - * Something stange is going on with the HW + * Something strange is going on with the HW */ if ((++loops) > 1000) goto flood; @@ -396,7 +396,7 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap) * be nice to transmit console writes just like we normally would for * a TTY line. (ie. buffered and TX interrupt driven). That is not * easy because console writes cannot sleep. One solution might be - * to poll on enough port->xmit space becomming free. -DaveM + * to poll on enough port->xmit space becoming free. -DaveM */ if (!(status & Tx_BUF_EMP)) return; @@ -809,7 +809,7 @@ static int pmz_set_scc_power(struct uart_pmac_port *uap, int state) #endif /* !CONFIG_PPC_PMAC */ /* - * FixZeroBug....Works around a bug in the SCC receving channel. + * FixZeroBug....Works around a bug in the SCC receiving channel. * Inspired from Darwin code, 15 Sept. 2000 -DanM * * The following sequence prevents a problem that is seen with O'Hare ASICs diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 2335edafe903..9e2fa8d784e2 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -64,7 +64,7 @@ #define tx_enabled(port) ((port)->unused[0]) #define rx_enabled(port) ((port)->unused[1]) -/* flag to ignore all characters comming in */ +/* flag to ignore all characters coming in */ #define RXSTAT_DUMMY_READ (0x10000000) static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) @@ -291,7 +291,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) goto out; } - /* if there isnt anything more to transmit, or the uart is now + /* if there isn't anything more to transmit, or the uart is now * stopped, disable the uart and exit */ diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index eb7958c675a8..a7b083f4ea78 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -812,7 +812,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) } /* - * Here we define a transistion notifier so that we can update all of our + * Here we define a transition notifier so that we can update all of our * ports' baud rate when the peripheral clock changes. */ static int sci_notifier(struct notifier_block *self, diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c index cff9a306660f..377ae74e7154 100644 --- a/drivers/tty/serial/sn_console.c +++ b/drivers/tty/serial/sn_console.c @@ -146,7 +146,7 @@ static struct sn_sal_ops intr_ops = { }; /* the console does output in two distinctly different ways: - * synchronous (raw) and asynchronous (buffered). initally, early_printk + * synchronous (raw) and asynchronous (buffered). initially, early_printk * does synchronous output. any data written goes directly to the SAL * to be output (incidentally, it is internally buffered by the SAL) * after interrupts and timers are initialized and available for use, @@ -481,7 +481,7 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) while (port->sc_ops->sal_input_pending()) { ch = port->sc_ops->sal_getc(); if (ch < 0) { - printk(KERN_ERR "sn_console: An error occured while " + printk(KERN_ERR "sn_console: An error occurred while " "obtaining data from the console (0x%0x)\n", ch); break; } diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 99ff9abf57ce..8e916e76b7b5 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -474,7 +474,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, * be nice to transmit console writes just like we normally would for * a TTY line. (ie. buffered and TX interrupt driven). That is not * easy because console writes cannot sleep. One solution might be - * to poll on enough port->xmit space becomming free. -DaveM + * to poll on enough port->xmit space becoming free. -DaveM */ if (!(status & Tx_BUF_EMP)) return; diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 18888d005a0a..27da23d98e3f 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -4072,7 +4072,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags, info->device_name, info ) < 0 ) { - printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n", + printk( "%s(%d):Can't request interrupt on device %s IRQ=%d\n", __FILE__,__LINE__,info->device_name, info->irq_level ); goto errout; } @@ -4095,7 +4095,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) info->memory_base = ioremap_nocache(info->phys_memory_base, 0x40000); if (!info->memory_base) { - printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n", + printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); goto errout; } @@ -4109,7 +4109,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE); if (!info->lcr_base) { - printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n", + printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); goto errout; } @@ -4119,7 +4119,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) /* claim DMA channel */ if (request_dma(info->dma_level,info->device_name) < 0){ - printk( "%s(%d):Cant request DMA channel on device %s DMA=%d\n", + printk( "%s(%d):Can't request DMA channel on device %s DMA=%d\n", __FILE__,__LINE__,info->device_name, info->dma_level ); mgsl_release_resources( info ); return -ENODEV; @@ -4132,7 +4132,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) } if ( mgsl_allocate_dma_buffers(info) < 0 ) { - printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n", + printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n", __FILE__,__LINE__,info->device_name, info->dma_level ); goto errout; } diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index a35dd549a008..18b48cd3b41d 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -3491,7 +3491,7 @@ static int claim_resources(struct slgt_info *info) info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE); if (!info->reg_addr) { - DBGERR(("%s cant map device registers, addr=%08X\n", + DBGERR(("%s can't map device registers, addr=%08X\n", info->device_name, info->phys_reg_addr)); info->init_error = DiagStatus_CantAssignPciResources; goto errout; diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index 327343694473..c77831c7675a 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -3595,7 +3595,7 @@ static int claim_resources(SLMP_INFO *info) info->memory_base = ioremap_nocache(info->phys_memory_base, SCA_MEM_SIZE); if (!info->memory_base) { - printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n", + printk( "%s(%d):%s Can't map shared memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); info->init_error = DiagStatus_CantAssignPciResources; goto errout; @@ -3603,7 +3603,7 @@ static int claim_resources(SLMP_INFO *info) info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE); if (!info->lcr_base) { - printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n", + printk( "%s(%d):%s Can't map LCR memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); info->init_error = DiagStatus_CantAssignPciResources; goto errout; @@ -3612,7 +3612,7 @@ static int claim_resources(SLMP_INFO *info) info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE); if (!info->sca_base) { - printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n", + printk( "%s(%d):%s Can't map SCA memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_sca_base ); info->init_error = DiagStatus_CantAssignPciResources; goto errout; @@ -3622,7 +3622,7 @@ static int claim_resources(SLMP_INFO *info) info->statctrl_base = ioremap_nocache(info->phys_statctrl_base, PAGE_SIZE); if (!info->statctrl_base) { - printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n", + printk( "%s(%d):%s Can't map SCA Status/Control memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_statctrl_base ); info->init_error = DiagStatus_CantAssignPciResources; goto errout; @@ -3869,7 +3869,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev) port_array[0]->irq_flags, port_array[0]->device_name, port_array[0]) < 0 ) { - printk( "%s(%d):%s Cant request interrupt, IRQ=%d\n", + printk( "%s(%d):%s Can't request interrupt, IRQ=%d\n", __FILE__,__LINE__, port_array[0]->device_name, port_array[0]->irq_level ); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 936a4ead6c21..d7d50b48287e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2134,7 +2134,7 @@ done: * actually has driver level meaning and triggers a VC resize. * * Locking: - * Driver dependant. The default do_resize method takes the + * Driver dependent. The default do_resize method takes the * tty termios mutex and ctrl_lock. The console takes its own lock * then calls into the default method. */ @@ -2155,7 +2155,7 @@ static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) * tioccons - allow admin to move logical console * @file: the file to become console * - * Allow the adminstrator to move the redirected console device + * Allow the administrator to move the redirected console device * * Locking: uses redirect_lock to guard the redirect information */ @@ -2290,7 +2290,7 @@ EXPORT_SYMBOL_GPL(tty_get_pgrp); /** * tiocgpgrp - get process group * @tty: tty passed by user - * @real_tty: tty side of the tty pased by the user if a pty else the tty + * @real_tty: tty side of the tty passed by the user if a pty else the tty * @p: returned pid * * Obtain the process group of the tty. If there is no process group @@ -2367,7 +2367,7 @@ out_unlock: /** * tiocgsid - get session id * @tty: tty passed by user - * @real_tty: tty side of the tty pased by the user if a pty else the tty + * @real_tty: tty side of the tty passed by the user if a pty else the tty * @p: pointer to returned session id * * Obtain the session id of the tty. If there is no session diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 1a1135d580a2..21574cb32343 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -247,7 +247,7 @@ speed_t tty_termios_baud_rate(struct ktermios *termios) cbaud = termios->c_cflag & CBAUD; #ifdef BOTHER - /* Magic token for arbitary speed via c_ispeed/c_ospeed */ + /* Magic token for arbitrary speed via c_ispeed/c_ospeed */ if (cbaud == BOTHER) return termios->c_ospeed; #endif @@ -283,7 +283,7 @@ speed_t tty_termios_input_baud_rate(struct ktermios *termios) if (cbaud == B0) return tty_termios_baud_rate(termios); - /* Magic token for arbitary speed via c_ispeed*/ + /* Magic token for arbitrary speed via c_ispeed*/ if (cbaud == BOTHER) return termios->c_ispeed; @@ -449,7 +449,7 @@ EXPORT_SYMBOL(tty_get_baud_rate); * @new: New termios * @old: Old termios * - * Propogate the hardware specific terminal setting bits from + * Propagate the hardware specific terminal setting bits from * the old termios structure to the new one. This is used in cases * where the hardware does not support reconfiguration or as a helper * in some cases where only minimal reconfiguration is supported diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index c83cdfb56fcc..4bea1efaec98 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3963,7 +3963,7 @@ void reset_palette(struct vc_data *vc) * of 32 pixels. Userspace fontdata is stored with 32 bytes (shorts/ints, * depending on width) reserved for each character which is kinda wasty, but * this is done in order to maintain compatibility with the EGA/VGA fonts. It - * is upto the actual low-level console-driver convert data into its favorite + * is up to the actual low-level console-driver convert data into its favorite * format (maybe we should add a `fontoffset' field to the `display' * structure so we won't have to convert the fontdata all the time. * /Jes diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c index daf6e77de2b1..e67b566e7aa3 100644 --- a/drivers/uio/uio_pruss.c +++ b/drivers/uio/uio_pruss.c @@ -39,7 +39,7 @@ module_param(extram_pool_sz, int, 0); MODULE_PARM_DESC(extram_pool_sz, "external ram pool size to allocate"); /* - * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt + * Host event IRQ numbers from PRUSS - PRUSS can generate up to 8 interrupt * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS * firmware and user space application, async notification from PRU firmware * to user space application diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index b268e9fccb47..e71521ce3010 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1283,7 +1283,7 @@ static void uea_set_bulk_timeout(struct uea_softc *sc, u32 dsrate) /* in bulk mode the modem have problem with high rate * changing internal timing could improve things, but the - * value is misterious. + * value is mysterious. * ADI930 don't support it (-EPIPE error). */ @@ -1743,7 +1743,7 @@ static int uea_send_cmvs_e1(struct uea_softc *sc) goto out; } } else { - /* This realy should not happen */ + /* This really should not happen */ uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); goto out; } @@ -1798,7 +1798,7 @@ static int uea_send_cmvs_e4(struct uea_softc *sc) goto out; } } else { - /* This realy should not happen */ + /* This really should not happen */ uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); goto out; } @@ -1829,7 +1829,7 @@ static int uea_start_reset(struct uea_softc *sc) /* mask interrupt */ sc->booting = 1; - /* We need to set this here because, a ack timeout could have occured, + /* We need to set this here because, a ack timeout could have occurred, * but before we start the reboot, the ack occurs and set this to 1. * So we will failed to wait Ready CMV. */ diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c index b6d49234e521..62050f7a4f97 100644 --- a/drivers/usb/c67x00/c67x00-drv.c +++ b/drivers/usb/c67x00/c67x00-drv.c @@ -27,7 +27,7 @@ * the link between the common hardware parts and the subdrivers (e.g. * interrupt handling). * - * The c67x00 has 2 SIE's (serial interface engine) wich can be configured + * The c67x00 has 2 SIE's (serial interface engine) which can be configured * to be host, device or OTG (with some limitations, E.G. only SIE1 can be OTG). * * Depending on the platform configuration, the SIE's are created and diff --git a/drivers/usb/c67x00/c67x00-hcd.h b/drivers/usb/c67x00/c67x00-hcd.h index 74e44621e313..e3d493d4d61a 100644 --- a/drivers/usb/c67x00/c67x00-hcd.h +++ b/drivers/usb/c67x00/c67x00-hcd.h @@ -34,7 +34,7 @@ /* * The following parameters depend on the CPU speed, bus speed, ... * These can be tuned for specific use cases, e.g. if isochronous transfers - * are very important, bandwith can be sacrificed to guarantee that the + * are very important, bandwidth can be sacrificed to guarantee that the * 1ms deadline will be met. * If bulk transfers are important, the MAX_FRAME_BW can be increased, * but some (or many) isochronous deadlines might not be met. diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index f6b3c253f3fa..a03fbc15fa9c 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c @@ -907,7 +907,7 @@ static inline int c67x00_end_of_data(struct c67x00_td *td) /* Remove all td's from the list which come * after last_td and are meant for the same pipe. - * This is used when a short packet has occured */ + * This is used when a short packet has occurred */ static inline void c67x00_clear_pipe(struct c67x00_hcd *c67x00, struct c67x00_td *last_td) { diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 5eeb570b9a61..b4ea54dbf323 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -52,7 +52,7 @@ */ /* - * The only reason to have several buffers is to accomodate assumptions + * The only reason to have several buffers is to accommodate assumptions * in line disciplines. They ask for empty space amount, receive our URB size, * and proceed to issue several 1-character writes, assuming they will fit. * The very first write takes a complete URB. Fortunately, this only happens diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 6a54634ab823..385acb895ab3 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -483,7 +483,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, } done += n_characters; - /* Terminate if end-of-message bit recieved from device */ + /* Terminate if end-of-message bit received from device */ if ((buffer[8] & 0x01) && (actual >= n_characters + 12)) remaining = 0; else diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 02b4dbfa488a..8eed05d23838 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -700,7 +700,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) /* The USB 2.0 spec says 256 ms. This is close enough and won't * exceed that limit if HZ is 100. The math is more clunky than * maybe expected, this is to make sure that all timers for USB devices - * fire at the same time to give the CPU a break inbetween */ + * fire at the same time to give the CPU a break in between */ if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) : (length == 0 && hcd->status_urb != NULL)) mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 564eaa5525d7..8fb754916c67 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1649,7 +1649,7 @@ void usb_disconnect(struct usb_device **pdev) /* mark the device as inactive, so any further urb submissions for * this device (and any of its children) will fail immediately. - * this quiesces everyting except pending urbs. + * this quiesces everything except pending urbs. */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); dev_info(&udev->dev, "USB disconnect, device number %d\n", diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 0bc06e2bcfcb..a6a350f5827b 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -648,7 +648,7 @@ static int ehci_reset_port(int port) if (!(portsc & PORT_CONNECT)) return -ENOTCONN; - /* bomb out completely if something weird happend */ + /* bomb out completely if something weird happened */ if ((portsc & PORT_CSC)) return -EINVAL; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index f8dd7269d79c..6e42aab75806 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -278,7 +278,7 @@ static int udc_enable_dev_setup_interrupts(struct udc *dev) return 0; } -/* Calculates fifo start of endpoint based on preceeding endpoints */ +/* Calculates fifo start of endpoint based on preceding endpoints */ static int udc_set_txfifo_addr(struct udc_ep *ep) { struct udc *dev; @@ -2137,7 +2137,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix) if (use_dma) { /* BNA event ? */ if (tmp & AMD_BIT(UDC_EPSTS_BNA)) { - DBG(dev, "BNA ep%dout occured - DESPTR = %x \n", + DBG(dev, "BNA ep%dout occurred - DESPTR = %x \n", ep->num, readl(&ep->regs->desptr)); /* clear BNA */ writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts); @@ -2151,7 +2151,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix) } /* HE event ? */ if (tmp & AMD_BIT(UDC_EPSTS_HE)) { - dev_err(&dev->pdev->dev, "HE ep%dout occured\n", ep->num); + dev_err(&dev->pdev->dev, "HE ep%dout occurred\n", ep->num); /* clear HE */ writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); @@ -2354,7 +2354,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) /* BNA ? */ if (epsts & AMD_BIT(UDC_EPSTS_BNA)) { dev_err(&dev->pdev->dev, - "BNA ep%din occured - DESPTR = %08lx \n", + "BNA ep%din occurred - DESPTR = %08lx \n", ep->num, (unsigned long) readl(&ep->regs->desptr)); @@ -2367,7 +2367,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) /* HE event ? */ if (epsts & AMD_BIT(UDC_EPSTS_HE)) { dev_err(&dev->pdev->dev, - "HE ep%dn occured - DESPTR = %08lx \n", + "HE ep%dn occurred - DESPTR = %08lx \n", ep->num, (unsigned long) readl(&ep->regs->desptr)); /* clear HE */ @@ -2384,7 +2384,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) req = list_entry(ep->queue.next, struct udc_request, queue); /* - * length bytes transfered + * length bytes transferred * check dma done of last desc. in PPBDU mode */ if (use_dma_ppb_du) { @@ -2784,7 +2784,7 @@ static irqreturn_t udc_control_in_isr(struct udc *dev) /* write fifo */ udc_txfifo_write(ep, &req->req); - /* lengh bytes transfered */ + /* lengh bytes transferred */ len = req->req.length - req->req.actual; if (len > ep->ep.maxpacket) len = ep->ep.maxpacket; diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h index 4bbabbbfc93f..1d1c7543468e 100644 --- a/drivers/usb/gadget/amd5536udc.h +++ b/drivers/usb/gadget/amd5536udc.h @@ -584,7 +584,7 @@ union udc_setup_data { * SET and GET bitfields in u32 values * via constants for mask/offset: * is the text between - * UDC_ and _MASK|_OFS of appropiate + * UDC_ and _MASK|_OFS of appropriate * constant * * set bitfield value in u32 u32Val diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index bb8ddf0469f9..9b7cdb16f26b 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -826,7 +826,7 @@ done: return status; } -/* reinit == restore inital software state */ +/* reinit == restore initial software state */ static void udc_reinit(struct at91_udc *udc) { u32 i; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index c2251c40a205..82314ed22506 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -42,7 +42,7 @@ static struct usb_composite_driver *composite; static int (*composite_gadget_bind)(struct usb_composite_dev *cdev); -/* Some systems will need runtime overrides for the product identifers +/* Some systems will need runtime overrides for the product identifiers * published in the device descriptor, either numbers or strings or both. * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ @@ -205,14 +205,14 @@ int usb_function_activate(struct usb_function *function) * usb_interface_id() is called from usb_function.bind() callbacks to * allocate new interface IDs. The function driver will then store that * ID in interface, association, CDC union, and other descriptors. It - * will also handle any control requests targetted at that interface, + * will also handle any control requests targeted at that interface, * particularly changing its altsetting via set_alt(). There may * also be class-specific or vendor-specific requests to handle. * * All interface identifier should be allocated using this routine, to * ensure that for example different functions don't wrongly assign * different meanings to the same identifier. Note that since interface - * identifers are configuration-specific, functions used in more than + * identifiers are configuration-specific, functions used in more than * one configuration (or more than once in a given configuration) need * multiple versions of the relevant descriptors. * diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index 00975ed903d1..9abecfddb27d 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -742,7 +742,7 @@ int __init control_selector_init(struct f_audio *audio) } /** - * audio_bind_config - add USB audio fucntion to a configuration + * audio_bind_config - add USB audio function to a configuration * @c: the configuration to supcard the USB audio function * Context: single threaded during gadget setup * diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index 130eee678c8b..86902a60bcdb 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -111,7 +111,7 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g) #define NTB_OUT_SIZE 16384 /* - * skbs of size less than that will not be alligned + * skbs of size less than that will not be aligned * to NCM's dwNtbInMaxSize to save bus bandwidth */ diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index bea5b827bebe..e35e24fd64bb 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -208,14 +208,14 @@ struct qe_frame{ /* Frame status field */ /* Receive side */ #define FRAME_OK 0x00000000 /* Frame tranmitted or received OK */ -#define FRAME_ERROR 0x80000000 /* Error occured on frame */ +#define FRAME_ERROR 0x80000000 /* Error occurred on frame */ #define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */ #define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */ #define RX_ER_NONOCT 0x10000000 /* Rx Non Octet Aligned Packet */ #define RX_ER_BITSTUFF 0x08000000 /* Frame Aborted --Received packet with bit stuff error */ #define RX_ER_CRC 0x04000000 /* Received packet with CRC error */ -#define RX_ER_OVERUN 0x02000000 /* Over-run occured on reception */ +#define RX_ER_OVERUN 0x02000000 /* Over-run occurred on reception */ #define RX_ER_PID 0x01000000 /* Wrong PID received */ /* Tranmit side */ #define TX_ER_NAK 0x00800000 /* Received NAK handshake */ @@ -379,7 +379,7 @@ struct qe_udc { #define T_LSP 0x01000000 /* Low-speed transaction */ #define T_PID 0x00c00000 /* packet id */ #define T_NAK 0x00100000 /* No ack. */ -#define T_STAL 0x00080000 /* Stall recieved */ +#define T_STAL 0x00080000 /* Stall received */ #define T_TO 0x00040000 /* time out */ #define T_UN 0x00020000 /* underrun */ diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 912cb8e63fe3..07499c1cdcc4 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -464,7 +464,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, max = le16_to_cpu(desc->wMaxPacketSize); - /* Disable automatic zlp generation. Driver is reponsible to indicate + /* Disable automatic zlp generation. Driver is responsible to indicate * explicitly through req->req.zero. This is needed to enable multi-td * request. */ zlt = 1; @@ -648,7 +648,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) | EP_QUEUE_HEAD_STATUS_HALT)); dQH->size_ioc_int_sts &= temp; - /* Ensure that updates to the QH will occure before priming. */ + /* Ensure that updates to the QH will occur before priming. */ wmb(); /* Prime endpoint by writing 1 to ENDPTPRIME */ @@ -1459,7 +1459,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe, status = -EILSEQ; break; } else - ERR("Unknown error has occured (0x%x)!\n", + ERR("Unknown error has occurred (0x%x)!\n", errors); } else if (le32_to_cpu(curr_td->size_ioc_sts) diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 20aeceed48c7..e88cce5c2c0d 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -15,7 +15,7 @@ struct usb_dr_device { u8 res1[256]; u16 caplength; /* Capability Register Length */ u16 hciversion; /* Host Controller Interface Version */ - u32 hcsparams; /* Host Controller Structual Parameters */ + u32 hcsparams; /* Host Controller Structural Parameters */ u32 hccparams; /* Host Controller Capability Parameters */ u8 res2[20]; u32 dciversion; /* Device Controller Interface Version */ @@ -52,7 +52,7 @@ struct usb_dr_host { u8 res1[256]; u16 caplength; /* Capability Register Length */ u16 hciversion; /* Host Controller Interface Version */ - u32 hcsparams; /* Host Controller Structual Parameters */ + u32 hcsparams; /* Host Controller Structural Parameters */ u32 hccparams; /* Host Controller Capability Parameters */ u8 res2[20]; u32 dciversion; /* Device Controller Interface Version */ diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 0ab7e141d494..47b86b99d449 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -67,7 +67,7 @@ MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter."); module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter."); -/* Some systems will want different product identifers published in the +/* Some systems will want different product identifiers published in the * device descriptor, either numbers or strings or both. These string * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 1eca8b47ce3c..9cee88a43a73 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -642,7 +642,7 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req) dqh->dtd_status &= dtd_status; dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status); - /* ensure that updates to the dQH will occure before priming */ + /* ensure that updates to the dQH will occur before priming */ wmb(); /* write 1 to endptprime register to PRIME endpoint */ diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index d5468a7f38e0..b62b2640deb0 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -325,7 +325,7 @@ static int queue_dtd(struct mv_ep *ep, struct mv_req *req) /* * Ensure that updates to the QH will - * occure before priming. + * occur before priming. */ wmb(); @@ -338,7 +338,7 @@ static int queue_dtd(struct mv_ep *ep, struct mv_req *req) & EP_QUEUE_HEAD_NEXT_POINTER_MASK;; dqh->size_ioc_int_sts = 0; - /* Ensure that updates to the QH will occure before priming. */ + /* Ensure that updates to the QH will occur before priming. */ wmb(); /* Prime the Endpoint */ @@ -1845,7 +1845,7 @@ static irqreturn_t mv_udc_irq(int irq, void *dev) return IRQ_NONE; } - /* Clear all the interrupts occured */ + /* Clear all the interrupts occurred */ writel(status, &udc->op_regs->usbsts); if (status & USBSTS_ERR) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index d09155b25d73..24696f7fa6a9 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -117,7 +117,7 @@ module_param (fifo_mode, ushort, 0644); /* enable_suspend -- When enabled, the driver will respond to * USB suspend requests by powering down the NET2280. Otherwise, - * USB suspend requests will be ignored. This is acceptible for + * USB suspend requests will be ignored. This is acceptable for * self-powered devices */ static int enable_suspend = 0; diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index b5364f9d7cd2..55ca63ad3506 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -203,7 +203,7 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) goto err_usb; } - /* finaly register the configuration */ + /* finally register the configuration */ status = usb_add_config(cdev, &nokia_config_500ma_driver, nokia_bind_config); if (status < 0) diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 12ff6cffedc9..c3f2bd42bd5a 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -126,7 +126,7 @@ static struct printer_dev usb_printer_gadget; #define PRINTER_VENDOR_NUM 0x0525 /* NetChip */ #define PRINTER_PRODUCT_NUM 0xa4a8 /* Linux-USB Printer Gadget */ -/* Some systems will want different product identifers published in the +/* Some systems will want different product identifiers published in the * device descriptor, either numbers or strings or both. These string * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 2efd6732d130..78a39a41547d 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -602,7 +602,7 @@ static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in) /** * inc_ep_stats_bytes - Update ep stats counts * @ep: physical endpoint - * @count: bytes transfered on endpoint + * @count: bytes transferred on endpoint * @is_in: ep direction (USB_DIR_IN or 0) */ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in) @@ -877,7 +877,7 @@ static void nuke(struct pxa_ep *ep, int status) * If there is less space in request than bytes received in OUT endpoint, * bytes are left in the OUT endpoint. * - * Returns how many bytes were actually transfered + * Returns how many bytes were actually transferred */ static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -914,7 +914,7 @@ static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req) * endpoint. If there are no bytes to transfer, doesn't write anything * to physical endpoint. * - * Returns how many bytes were actually transfered. + * Returns how many bytes were actually transferred. */ static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req, unsigned int max) @@ -991,7 +991,7 @@ static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req) * caller guarantees at least one packet buffer is ready (or a zlp). * Doesn't complete the request, that's the caller's job * - * Returns 1 if request fully transfered, 0 if partial transfer + * Returns 1 if request fully transferred, 0 if partial transfer */ static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -1094,7 +1094,7 @@ static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req) * Sends a request (or a part of the request) to the control endpoint (ep0 in). * If the request doesn't fit, the remaining part will be sent from irq. * The request is considered fully written only if either : - * - last write transfered all remaining bytes, but fifo was not fully filled + * - last write transferred all remaining bytes, but fifo was not fully filled * - last write was a 0 length write * * Returns 1 if request fully written, 0 if request only partially sent @@ -1548,7 +1548,7 @@ static int pxa_udc_get_frame(struct usb_gadget *_gadget) * pxa_udc_wakeup - Force udc device out of suspend * @_gadget: usb gadget * - * Returns 0 if successfull, error code otherwise + * Returns 0 if successful, error code otherwise */ static int pxa_udc_wakeup(struct usb_gadget *_gadget) { diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index ef825c3baed9..0912679de99a 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -41,8 +41,8 @@ /* EP0_MPS_LIMIT * * Unfortunately there seems to be a limit of the amount of data that can - * be transfered by IN transactions on EP0. This is either 127 bytes or 3 - * packets (which practially means 1 packet and 63 bytes of data) when the + * be transferred by IN transactions on EP0. This is either 127 bytes or 3 + * packets (which practically means 1 packet and 63 bytes of data) when the * MPS is set to 64. * * This means if we are wanting to move >127 bytes of data, we need to @@ -783,7 +783,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, hsotg->regs + S3C_DIEPINT(index)); /* Note, trying to clear the NAK here causes problems with transmit - * on the S3C6400 ending up with the TXFIFO becomming full. */ + * on the S3C6400 ending up with the TXFIFO becoming full. */ /* check ep is enabled */ if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna)) @@ -1176,10 +1176,10 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, writel(ctrl, hsotg->regs + reg); dev_dbg(hsotg->dev, - "writen DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", + "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", ctrl, reg, readl(hsotg->regs + reg)); - /* don't belive we need to anything more to get the EP + /* don't believe we need to anything more to get the EP * to reply with a STALL packet */ } } @@ -1416,7 +1416,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) * transaction. * * Note, since we don't write any data to the TxFIFO, then it is - * currently belived that we do not need to wait for any space in + * currently believed that we do not need to wait for any space in * the TxFIFO. */ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, @@ -1540,7 +1540,7 @@ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) * that requires processing, so find out what is in there and do the * appropriate read. * - * The RXFIFO is a true FIFO, the packets comming out are still in packet + * The RXFIFO is a true FIFO, the packets coming out are still in packet * chunks, so if you have x packets received on an endpoint you'll get x * FIFO events delivered, each with a packet's worth of data in it. * @@ -2188,7 +2188,7 @@ irq_retry: /* these next two seem to crop-up occasionally causing the core * to shutdown the USB transfer, so try clearing them and logging - * the occurence. */ + * the occurrence. */ if (gintsts & S3C_GINTSTS_GOUTNakEff) { dev_info(hsotg->dev, "GOUTNakEff triggered\n"); @@ -2469,7 +2469,7 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = { .queue = s3c_hsotg_ep_queue, .dequeue = s3c_hsotg_ep_dequeue, .set_halt = s3c_hsotg_ep_sethalt, - /* note, don't belive we have any call for the fifo routines */ + /* note, don't believe we have any call for the fifo routines */ }; /** diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 9483acdf2e9e..e0e0787b724b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -402,7 +402,7 @@ config FHCI_DEBUG depends on USB_FHCI_HCD && DEBUG_FS help Say "y" to see some FHCI debug information and statistics - throught debugfs. + through debugfs. config USB_U132_HCD tristate "Elan U132 Adapter Host Controller" diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index f86d3fa20214..333ddc156919 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -644,7 +644,7 @@ static inline void ehci_writel(const struct ehci_hcd *ehci, /* * On certain ppc-44x SoC there is a HW issue, that could only worked around with * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch. - * Other common bits are dependant on has_amcc_usb23 quirk flag. + * Other common bits are dependent on has_amcc_usb23 quirk flag. */ #ifdef CONFIG_44x static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index b84ff7e51896..19223c7449e1 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -401,7 +401,7 @@ static int fhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, /* 1 td fro setup,1 for ack */ size = 2; case PIPE_BULK: - /* one td for every 4096 bytes(can be upto 8k) */ + /* one td for every 4096 bytes(can be up to 8k) */ size += urb->transfer_buffer_length / 4096; /* ...add for any remaining bytes... */ if ((urb->transfer_buffer_length % 4096) != 0) diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index 38fe058fbe61..0ea577bfca2a 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c @@ -40,7 +40,7 @@ #define TD_RXER 0x0020 /* Rx error or not */ #define TD_NAK 0x0010 /* No ack. */ -#define TD_STAL 0x0008 /* Stall recieved */ +#define TD_STAL 0x0008 /* Stall received */ #define TD_TO 0x0004 /* time out */ #define TD_UN 0x0002 /* underrun */ #define TD_NO 0x0010 /* Rx Non Octet Aligned Packet */ @@ -274,7 +274,7 @@ void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep, * It is also preparing the TDs for new frames. If the Tx interrupts * are disabled, the application should call that routine to get * confirmation about the submitted frames. Otherwise, the routine is - * called frome the interrupt service routine during the Tx interrupt. + * called from the interrupt service routine during the Tx interrupt. * In that case the application is informed by calling the application * specific 'fhci_transaction_confirm' routine */ @@ -337,7 +337,7 @@ static void fhci_td_transaction_confirm(struct fhci_usb *usb) pkt->status = USB_TD_RX_ER_NONOCT; else fhci_err(usb->fhci, "illegal error " - "occured\n"); + "occurred\n"); } else if (td_status & TD_NAK) pkt->status = USB_TD_TX_ER_NAK; else if (td_status & TD_TO) @@ -347,7 +347,7 @@ static void fhci_td_transaction_confirm(struct fhci_usb *usb) else if (td_status & TD_STAL) pkt->status = USB_TD_TX_ER_STALL; else - fhci_err(usb->fhci, "illegal error occured\n"); + fhci_err(usb->fhci, "illegal error occurred\n"); } else if ((extra_data & TD_TOK_IN) && pkt->len > td_length - CRC_SIZE) { pkt->status = USB_TD_RX_DATA_UNDERUN; diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index 71c3caaea4c1..dc6939a44a1a 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h @@ -82,7 +82,7 @@ #define USB_TD_RX_ER_NONOCT 0x40000000 /* Tx Non Octet Aligned Packet */ #define USB_TD_RX_ER_BITSTUFF 0x20000000 /* Frame Aborted-Received pkt */ #define USB_TD_RX_ER_CRC 0x10000000 /* CRC error */ -#define USB_TD_RX_ER_OVERUN 0x08000000 /* Over - run occured */ +#define USB_TD_RX_ER_OVERUN 0x08000000 /* Over - run occurred */ #define USB_TD_RX_ER_PID 0x04000000 /* wrong PID received */ #define USB_TD_RX_DATA_UNDERUN 0x02000000 /* shorter than expected */ #define USB_TD_RX_DATA_OVERUN 0x01000000 /* longer than expected */ @@ -363,7 +363,7 @@ struct ed { struct td { void *data; /* a pointer to the data buffer */ unsigned int len; /* length of the data to be submitted */ - unsigned int actual_len; /* actual bytes transfered on this td */ + unsigned int actual_len; /* actual bytes transferred on this td */ enum fhci_ta_type type; /* transaction type */ u8 toggle; /* toggle for next trans. within this TD */ u16 iso_index; /* ISO transaction index */ diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 2562e92e3178..af05718bdc73 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1323,7 +1323,7 @@ static void process_etds(struct usb_hcd *hcd, struct imx21 *imx21, int sof) * (and hence no interrupt occurs). * This causes the transfer in question to hang. * The kludge below checks for this condition at each SOF and processes any - * blocked ETDs (after an arbitary 10 frame wait) + * blocked ETDs (after an arbitrary 10 frame wait) * * With a single active transfer the usbtest test suite will run for days * without the kludge. diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index 12db961acdfb..9a2c400e6090 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h @@ -13,7 +13,7 @@ /* Full speed: max # of bytes to transfer for a single urb at a time must be < 1024 && must be multiple of 64. - 832 allows transfering 4kiB within 5 frames. */ + 832 allows transferring 4kiB within 5 frames. */ #define MAX_TRANSFER_SIZE_FULLSPEED 832 /* Low speed: there is no reason to schedule in very big diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 662cd002adfc..f97570a847ca 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -546,7 +546,7 @@ static void postproc_ep(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep) if (usb_pipecontrol(urb->pipe)) { ep->nextpid = USB_PID_ACK; /* save the data underrun error code for later and - * procede with the status stage + * proceed with the status stage */ urb->actual_length += PTD_GET_COUNT(ptd); BUG_ON(urb->actual_length > urb->transfer_buffer_length); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index e7288639edb0..d55723514860 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -162,7 +162,7 @@ static int ohci_urb_enqueue ( // case PIPE_INTERRUPT: // case PIPE_BULK: default: - /* one TD for every 4096 Bytes (can be upto 8K) */ + /* one TD for every 4096 Bytes (can be up to 8K) */ size += urb->transfer_buffer_length / 4096; /* ... and for any remaining bytes ... */ if ((urb->transfer_buffer_length % 4096) != 0) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 44e4deb362e1..4a771f6cc822 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -2879,7 +2879,7 @@ static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, /* Ok, we have more job to do! :) */ for (i = 0; i < num - 1; i++) { - /* Get free micro URB poll till a free urb is recieved */ + /* Get free micro URB poll till a free urb is received */ do { murb = (struct urb *) oxu_murb_alloc(oxu); @@ -2911,7 +2911,7 @@ static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, /* Last urb requires special handling */ - /* Get free micro URB poll till a free urb is recieved */ + /* Get free micro URB poll till a free urb is received */ do { murb = (struct urb *) oxu_murb_alloc(oxu); if (!murb) diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index dc0ab8382f5d..d6e175428618 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -739,7 +739,7 @@ static int get_urb_status_from_qtd(struct urb *urb, u32 status) * process_inactive_qtd - process an inactive (but not halted) qTD. * * Update the urb with the transfer bytes from the qTD, if the urb is - * completely transfered or (in the case of an IN only) the LPF is + * completely transferred or (in the case of an IN only) the LPF is * set, then the transfer is complete and the urb should be returned * to the system. */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9a3645fd759b..196e0181b2ed 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -741,7 +741,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) int retval; /* Wait a bit if either of the roothubs need to settle from the - * transistion into bus suspend. + * transition into bus suspend. */ if (time_before(jiffies, xhci->bus_state[0].next_statechange) || time_before(jiffies, @@ -2072,7 +2072,7 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, return -EINVAL; } vdev = xhci->devs[udev->slot_id]; - /* Mark each endpoint as being in transistion, so + /* Mark each endpoint as being in transition, so * xhci_urb_enqueue() will reject all URBs. */ for (i = 0; i < num_eps; i++) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 711de253bc0f..07e263063e37 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -873,7 +873,7 @@ struct xhci_transfer_event { #define COMP_CMD_ABORT 25 /* Stopped - transfer was terminated by a stop endpoint command */ #define COMP_STOP 26 -/* Same as COMP_EP_STOPPED, but the transfered length in the event is invalid */ +/* Same as COMP_EP_STOPPED, but the transferred length in the event is invalid */ #define COMP_STOP_INVAL 27 /* Control Abort Error - Debug Capability - control pipe aborted */ #define COMP_DBG_ABORT 28 diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index c90c89dc0003..a0037961e5bd 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -69,7 +69,7 @@ * 20000513 added IDs for all products supported by Windows driver (john) * 20000514 Rewrote mts_scsi_queuecommand to use URBs (john) * 20000514 Version 0.0.8j - * 20000514 Fix reporting of non-existant devices to SCSI layer (john) + * 20000514 Fix reporting of non-existent devices to SCSI layer (john) * 20000514 Added MTS_DEBUG_INT (john) * 20000514 Changed "usb-microtek" to "microtek" for consistency (john) * 20000514 Stupid bug fixes (john) @@ -557,14 +557,14 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc) if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len ) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image); - MTS_DEBUG( "transfering from desc->ep_image == %d\n", + MTS_DEBUG( "transferring from desc->ep_image == %d\n", (int)desc->ep_image ); } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response); - MTS_DEBUG( "transfering from desc->ep_response == %d\n", + MTS_DEBUG( "transferring from desc->ep_response == %d\n", (int)desc->ep_response); } else { - MTS_DEBUG("transfering to desc->ep_out == %d\n", + MTS_DEBUG("transferring to desc->ep_out == %d\n", (int)desc->ep_out); pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out); } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index e573e4704015..a2190b983f52 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -40,7 +40,7 @@ #ifdef CONFIG_USB_DYNAMIC_MINORS #define IOWARRIOR_MINOR_BASE 0 #else -#define IOWARRIOR_MINOR_BASE 208 // SKELETON_MINOR_BASE 192 + 16, not offical yet +#define IOWARRIOR_MINOR_BASE 208 // SKELETON_MINOR_BASE 192 + 16, not official yet #endif /* interrupt input queue size */ diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 8c6fdef61d1c..e25700f44b6f 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -1531,7 +1531,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) i2c_set_clientdata(i2c, isp); isp->client = i2c; - /* verify the chip (shouldn't be necesary) */ + /* verify the chip (shouldn't be necessary) */ status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); if (status != I2C_VENDOR_ID_PHILIPS) { dev_dbg(&i2c->dev, "not philips id: %d\n", status); diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c index 7f9b8cd4514b..e973ff19c55a 100644 --- a/drivers/usb/otg/langwell_otg.c +++ b/drivers/usb/otg/langwell_otg.c @@ -580,7 +580,7 @@ static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) time = TB_BUS_SUSPEND; break; default: - dev_dbg(lnw->dev, "unkown timer, cannot enable it\n"); + dev_dbg(lnw->dev, "unknown timer, cannot enable it\n"); return; } @@ -1381,7 +1381,7 @@ static void langwell_otg_work(struct work_struct *work) } else if (!iotg->hsm.a_bus_req && iotg->otg.host && iotg->otg.host->b_hnp_enable) { /* It is not safe enough to do a fast - * transistion from A_WAIT_BCON to + * transition from A_WAIT_BCON to * A_SUSPEND */ msleep(10000); if (iotg->hsm.a_bus_req) diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 0db6ace16f7b..aba201cb872c 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -16,7 +16,7 @@ * When reading the process is almost equal except that the header starts with * 0x00 0x20. * - * The device simply need some stuff to understand data comming from the usb + * The device simply need some stuff to understand data coming from the usb * buffer: The First and Second byte is used for a Header, the Third and Fourth * tells the device the amount of information the package holds. * Packages are 60 bytes long Header Stuff. @@ -30,7 +30,7 @@ * one. * * The driver registers himself with the USB-serial core and the USB Core. I had - * to implement a probe function agains USB-serial, because other way, the + * to implement a probe function against USB-serial, because other way, the * driver was attaching himself to both interfaces. I have tryed with different * configurations of usb_serial_driver with out exit, only the probe function * could handle this correctly. diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 4df3e0cecbae..0f11afdda134 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -101,7 +101,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */ { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ - { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ + { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 987e9bf7bd02..d9906eb9d16a 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -35,7 +35,7 @@ * * Lonnie Mendez * 04-10-2004 - * Driver modified to support dynamic line settings. Various improvments + * Driver modified to support dynamic line settings. Various improvements * and features. * * Neil Whelchel diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 65967b36365f..a973c7a29d6e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -17,7 +17,7 @@ * See Documentation/usb/usb-serial.txt for more information on using this * driver * - * See http://ftdi-usb-sio.sourceforge.net for upto date testing info + * See http://ftdi-usb-sio.sourceforge.net for up to date testing info * and extra documentation * * Change entries from 2004 and earlier can be found in versions of this diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index f1aedfa7c420..abf095be5753 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1981,7 +1981,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, if (code == IOSP_STATUS_OPEN_RSP) { edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3); edge_port->maxTxCredits = edge_port->txCredits; - dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits); + dbg("%s - Port %u Open Response Initial MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits); handle_new_msr(edge_port, byte2); /* send the current line settings to the port so we are diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h index dced7ec65470..ad9c1d47a619 100644 --- a/drivers/usb/serial/io_edgeport.h +++ b/drivers/usb/serial/io_edgeport.h @@ -68,7 +68,7 @@ struct comMapper { #define PROC_SET_COM_ENTRY 2 -/* The following sturcture is passed to the write */ +/* The following structure is passed to the write */ struct procWrite { int Command; union { diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index d8434910fa7b..0aac00afb5c8 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -433,7 +433,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, /* We can only send a maximum of 1 aligned byte page at a time */ - /* calulate the number of bytes left in the first page */ + /* calculate the number of bytes left in the first page */ write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1)); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 201f6096844b..a6f63cc8c130 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -116,7 +116,7 @@ static void opticon_read_bulk_callback(struct urb *urb) } else { if ((data[0] == 0x00) && (data[1] == 0x01)) { spin_lock_irqsave(&priv->lock, flags); - /* CTS status infomation package */ + /* CTS status information package */ if (data[2] == 0x00) priv->cts = false; else diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 08e03745e251..0e5aafda4537 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -562,7 +562,7 @@ static int ene_sd_init(struct us_data *us) result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); if (result != USB_STOR_XFER_GOOD) { - US_DEBUGP("Exection SD Init Code Fail !!\n"); + US_DEBUGP("Execution SD Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -581,7 +581,7 @@ static int ene_sd_init(struct us_data *us) result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); if (result != USB_STOR_XFER_GOOD) { - US_DEBUGP("Exection SD Init Code Fail !!\n"); + US_DEBUGP("Execution SD Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 6b9982cd5423..09e52ba47ddf 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1510,7 +1510,7 @@ static int isd200_Initialization(struct us_data *us) * Protocol and Transport for the ISD200 ASIC * * This protocol and transport are for ATA devices connected to an ISD200 - * ASIC. An ATAPI device that is conected as a slave device will be + * ASIC. An ATAPI device that is connected as a slave device will be * detected in the driver initialization function and the protocol will * be changed to an ATAPI protocol (Transparent SCSI). * diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 689ee1fb702a..13b8bcdf3dba 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -123,7 +123,7 @@ static int slave_configure(struct scsi_device *sdev) { struct us_data *us = host_to_us(sdev->host); - /* Many devices have trouble transfering more than 32KB at a time, + /* Many devices have trouble transferring more than 32KB at a time, * while others have trouble with more than 64K. At this time we * are limiting both to 32K (64 sectores). */ diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index bd3f415893d8..0b00091d2ae9 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -340,7 +340,7 @@ static int usbat_check_status(struct us_data *us) } /* - * Stores critical information in internal registers in prepartion for the execution + * Stores critical information in internal registers in preparation for the execution * of a conditional usbat_read_blocks or usbat_write_blocks call. */ static int usbat_set_shuttle_features(struct us_data *us, diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c index 827c87f10cc5..7e4bf95f8f7b 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/usb/wusbcore/crypto.c @@ -180,7 +180,7 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2, * using the 14 bytes of @a to fill up * b1.{mac_header,e0,security_reserved,padding}. * - * NOTE: The definiton of l(a) in WUSB1.0[6.5] vs the definition of + * NOTE: The definition of l(a) in WUSB1.0[6.5] vs the definition of * l(m) is orthogonal, they bear no relationship, so it is not * in conflict with the parameter's relation that * WUSB1.0[6.4.2]) defines. @@ -272,7 +272,7 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] * The procedure is to AES crypt the A0 block and XOR the MIC - * Tag agains it; we only do the first 8 bytes and place it + * Tag against it; we only do the first 8 bytes and place it * directly in the destination buffer. * * POS Crypto API: size is assumed to be AES's block size. diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/usb/wusbcore/reservation.c index 4ed97360c046..6f4fafdc2401 100644 --- a/drivers/usb/wusbcore/reservation.c +++ b/drivers/usb/wusbcore/reservation.c @@ -71,7 +71,7 @@ static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv) /** * wusbhc_rsv_establish - establish a reservation for the cluster - * @wusbhc: the WUSB HC requesting a bandwith reservation + * @wusbhc: the WUSB HC requesting a bandwidth reservation */ int wusbhc_rsv_establish(struct wusbhc *wusbhc) { diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index c175b7300c73..39de3900ad20 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c @@ -133,7 +133,7 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) * big of a problem [and we can't make it an spinlock * because other parts need to take it and sleep] . * - * @usb_hcd is refcounted, so it won't dissapear under us + * @usb_hcd is refcounted, so it won't disappear under us * and before killing a host, the polling of the root hub * would be stopped anyway. */ diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index 8cb9d80207fa..ca80171f42c6 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c @@ -24,7 +24,7 @@ * * RPIPE * - * Targetted at different downstream endpoints + * Targeted at different downstream endpoints * * Descriptor: use to config the remote pipe. * diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 84b744c428a4..6ccd93a9b909 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -61,7 +61,7 @@ * * Two methods it could be done: * - * (a) set up a timer everytime an rpipe's use count drops to 1 + * (a) set up a timer every time an rpipe's use count drops to 1 * (which means unused) or when a transfer ends. Reset the * timer when a xfer is queued. If the timer expires, release * the rpipe [see rpipe_ep_disable()]. @@ -140,7 +140,7 @@ struct wa_xfer { struct wahc *wa; /* Wire adapter we are plugged to */ struct usb_host_endpoint *ep; - struct urb *urb; /* URB we are transfering for */ + struct urb *urb; /* URB we are transferring for */ struct wa_seg **seg; /* transfer segments */ u8 segs, segs_submitted, segs_done; unsigned is_inbound:1; @@ -161,7 +161,7 @@ static inline void wa_xfer_init(struct wa_xfer *xfer) } /* - * Destory a transfer structure + * Destroy a transfer structure * * Note that the xfer->seg[index] thingies follow the URB life cycle, * so we need to put them, not free them. @@ -494,7 +494,7 @@ static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, * function does almost the same thing and they work closely * together. * - * If the seg request has failed but this DTO phase has suceeded, + * If the seg request has failed but this DTO phase has succeeded, * wa_seg_cb() has already failed the segment and moved the * status to WA_SEG_ERROR, so this will go through 'case 0' and * effectively do nothing. diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 6bd426b7ec07..3a2d09162e70 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -231,7 +231,7 @@ struct wusb_port { * * Most of the times when you need to use it, it will be non-NULL, * so there is no real need to check for it (wusb_dev will - * dissapear before usb_dev). + * disappear before usb_dev). * * - The following fields need to be filled out before calling * wusbhc_create(): ports_max, mmcies_max, mmcie_{add,rm}. diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index 08bd6dbfd4a6..3e5454aba5d4 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c @@ -61,7 +61,7 @@ /** - * If a beacon dissapears for longer than this, then we consider the + * If a beacon disappears for longer than this, then we consider the * device who was represented by that beacon to be gone. * * ECMA-368[17.2.3, last para] establishes that a device must not diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index a8d83e25e3b6..3fbcf789dfaa 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c @@ -27,7 +27,7 @@ /* DRP Conflict Actions ([ECMA-368 2nd Edition] 17.4.6) */ enum uwb_drp_conflict_action { - /* Reservation is mantained, no action needed */ + /* Reservation is maintained, no action needed */ UWB_DRP_CONFLICT_MANTAIN = 0, /* the device shall not transmit frames in conflicting MASs in @@ -741,12 +741,12 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, * DRP notifications can occur for three different reasons: * * - UWB_DRP_NOTIF_DRP_IE_RECVD: one or more DRP IEs with the RC as - * the target or source have been recieved. + * the target or source have been received. * * These DRP IEs could be new or for an existing reservation. * * If the DRP IE for an existing reservation ceases to be to - * recieved for at least mMaxLostBeacons, the reservation should be + * received for at least mMaxLostBeacons, the reservation should be * considered to be terminated. Note that the TERMINATE reason (see * below) may not always be signalled (e.g., the remote device has * two or more reservations established with the RC). diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c index b0091c771b9a..b4395f41a007 100644 --- a/drivers/uwb/lc-rc.c +++ b/drivers/uwb/lc-rc.c @@ -168,7 +168,7 @@ int uwb_rc_mac_addr_setup(struct uwb_rc *rc) } if (uwb_mac_addr_unset(&addr) || uwb_mac_addr_bcast(&addr)) { - addr.data[0] = 0x02; /* locally adminstered and unicast */ + addr.data[0] = 0x02; /* locally administered and unicast */ get_random_bytes(&addr.data[1], sizeof(addr.data)-1); result = uwb_rc_mac_addr_set(rc, &addr); diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c index 27849292b552..3de630b0f691 100644 --- a/drivers/uwb/reset.c +++ b/drivers/uwb/reset.c @@ -52,7 +52,7 @@ const char *__strerror[] = { "cancelled", "invalid state", "invalid size", - "ack not recieved", + "ack not received", "no more asie notification", }; diff --git a/drivers/uwb/umc-dev.c b/drivers/uwb/umc-dev.c index ccd2184e05d2..b2948ec57878 100644 --- a/drivers/uwb/umc-dev.c +++ b/drivers/uwb/umc-dev.c @@ -78,7 +78,7 @@ EXPORT_SYMBOL_GPL(umc_device_register); * First we unregister the device, make sure the driver can do it's * resource release thing and then we try to release any left over * resources. We take a ref to the device, to make sure it doesn't - * dissapear under our feet. + * disappear under our feet. */ void umc_device_unregister(struct umc_dev *umc) { diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index ccecf9974587..4484c721f0f9 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -637,7 +637,7 @@ static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitf * magnitude which needs to be scaled in this function for the hardware. * Things to take into consideration are how many color registers, if * any, are supported with the current color visual. With truecolor mode - * no color palettes are supported. Here a psuedo palette is created + * no color palettes are supported. Here a pseudo palette is created * which we store the value in pseudo_palette in struct fb_info. For * pseudocolor mode we have a limited color palette. To deal with this * we can program what color is displayed for a particular pixel value. diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index d437b3daf1f5..ebb893c49e90 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -3124,12 +3124,12 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, M = pll_regs[2]; /* - * PLL Feedback Divider N (Dependant on CLOCK_CNTL): + * PLL Feedback Divider N (Dependent on CLOCK_CNTL): */ N = pll_regs[7 + (clock_cntl & 3)]; /* - * PLL Post Divider P (Dependant on CLOCK_CNTL): + * PLL Post Divider P (Dependent on CLOCK_CNTL): */ P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1)); diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index 2ba8b3c421a1..46f72ed53510 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c @@ -51,7 +51,7 @@ * to a larger number and saturate CUR_HORZ_POSN to zero. * * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number, - * CUR_OFFSET must be adjusted to a point to the appropraite line in the cursor + * CUR_OFFSET must be adjusted to a point to the appropriate line in the cursor * definitation and CUR_VERT_POSN must be saturated to zero. */ diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 4ea187d93768..5dff32ac8044 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1572,7 +1572,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) /* Copy monitor specs from panel data */ /* fixme: we're setting up LCD controller windows, so these dont give a damn as to what the monitor specs are (the panel itself does, but that - isnt done here...so maybe need a generic catchall monitor setting??? */ + isn't done here...so maybe need a generic catchall monitor setting??? */ memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); /* We first try the user mode passed in argument. If that failed, diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index af6098396fe6..c6533bad26f8 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -109,7 +109,7 @@ static unsigned long corgibl_flags; #define CORGIBL_BATTLOW 0x02 /* - * This is only a psuedo I2C interface. We can't use the standard kernel + * This is only a pseudo I2C interface. We can't use the standard kernel * routines as the interface is write only. We just assume the data is acked... */ static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data) diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index bbca3127071e..be20b5cbe26c 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -6,7 +6,7 @@ * GPL v2 * * This driver assumes single CPU. That's okay, because collie is - * slightly old hardware, and noone is going to retrofit second CPU to + * slightly old hardware, and no one is going to retrofit second CPU to * old PDA. */ diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/bfin_adv7393fb.h index 8c7f9e4fc6eb..cd591b5152a5 100644 --- a/drivers/video/bfin_adv7393fb.h +++ b/drivers/video/bfin_adv7393fb.h @@ -87,12 +87,12 @@ static const u8 init_NTSC_TESTPATTERN[] = { static const u8 init_NTSC[] = { 0x00, 0x1E, /* Power up all DACs and PLL */ - 0xC3, 0x26, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xC5, 0x12, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xC2, 0x4A, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xC6, 0x5E, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xBD, 0x19, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xBF, 0x42, /* Program RGB->YCrCb Color Space convertion matrix */ + 0xC3, 0x26, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xC5, 0x12, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xC2, 0x4A, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xC6, 0x5E, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xBD, 0x19, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xBF, 0x42, /* Program RGB->YCrCb Color Space conversion matrix */ 0x8C, 0x1F, /* NTSC Subcarrier Frequency */ 0x8D, 0x7C, /* NTSC Subcarrier Frequency */ 0x8E, 0xF0, /* NTSC Subcarrier Frequency */ @@ -109,12 +109,12 @@ static const u8 init_NTSC[] = { static const u8 init_PAL[] = { 0x00, 0x1E, /* Power up all DACs and PLL */ - 0xC3, 0x26, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xC5, 0x12, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xC2, 0x4A, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xC6, 0x5E, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xBD, 0x19, /* Program RGB->YCrCb Color Space convertion matrix */ - 0xBF, 0x42, /* Program RGB->YCrCb Color Space convertion matrix */ + 0xC3, 0x26, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xC5, 0x12, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xC2, 0x4A, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xC6, 0x5E, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xBD, 0x19, /* Program RGB->YCrCb Color Space conversion matrix */ + 0xBF, 0x42, /* Program RGB->YCrCb Color Space conversion matrix */ 0x8C, 0xCB, /* PAL Subcarrier Frequency */ 0x8D, 0x8A, /* PAL Subcarrier Frequency */ 0x8E, 0x09, /* PAL Subcarrier Frequency */ diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c index a19a7f33133e..fa6e698e63c4 100644 --- a/drivers/video/console/font_mini_4x6.c +++ b/drivers/video/console/font_mini_4x6.c @@ -1,5 +1,5 @@ -/* Hand composed "Miniscule" 4x6 font, with binary data generated using +/* Hand composed "Minuscule" 4x6 font, with binary data generated using * Perl stub. * * Use 'perl -x mini_4x6.c < mini_4x6.c > new_version.c' to regenerate diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8d61ef96eedd..8b7d47386f39 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -763,7 +763,7 @@ static int fb_wait_for_vsync(struct fb_info *info) /* * Set flag to 0 and wait for isr to set to 1. It would seem there is a - * race condition here where the ISR could have occured just before or + * race condition here where the ISR could have occurred just before or * just after this set. But since we are just coarsely waiting for * a frame to complete then that's OK. i.e. if the frame completed * just before this code executed then we have to wait another full diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c index f6a09ab0dac6..0c647d7af0ee 100644 --- a/drivers/video/display/display-sysfs.c +++ b/drivers/video/display/display-sysfs.c @@ -182,7 +182,7 @@ void display_device_unregister(struct display_device *ddev) mutex_lock(&ddev->lock); device_unregister(ddev->dev); mutex_unlock(&ddev->lock); - // Mark device index as avaliable + // Mark device index as available mutex_lock(&allocated_dsp_lock); idr_remove(&allocated_dsp, ddev->idx); mutex_unlock(&allocated_dsp_lock); diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index b358d045f130..cbdb1bd77c21 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c @@ -456,7 +456,7 @@ static int __init ep93xxfb_alloc_videomem(struct fb_info *info) * There is a bug in the ep93xx framebuffer which causes problems * if bit 27 of the physical address is set. * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2 - * There does not seem to be any offical errata for this, but I + * There does not seem to be any official errata for this, but I * have confirmed the problem exists on my hardware (ep9315) at * least. */ diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index f4a32779168b..04251ce89184 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -33,7 +33,7 @@ * for driver private data (info->par). info->par (if any) will be * aligned to sizeof(long). * - * Returns the new structure, or NULL if an error occured. + * Returns the new structure, or NULL if an error occurred. * */ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 1b0feb8e7244..d0533b7aad79 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -45,7 +45,7 @@ * buffer needs an amount of memory of 1.769.472 bytes which * is near to 2 MByte (the allocated address space of Zorro2). * The memory is channel interleaved. That means every channel - * owns four VRAMs. Unfortunatly most FrameMasters II are + * owns four VRAMs. Unfortunately most FrameMasters II are * not assembled with memory for the alpha channel. In this * case it could be possible to add the frame buffer into the * normal memory pool. diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 9048f87fa8c1..bedf5be27f05 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -882,7 +882,7 @@ static inline __u32 CNVT_TOHW(__u32 val, __u32 width) * which needs to be scaled in this function for the hardware. Things to take * into consideration are how many color registers, if any, are supported with * the current color visual. With truecolor mode no color palettes are - * supported. Here a psuedo palette is created which we store the value in + * supported. Here a pseudo palette is created which we store the value in * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited * color palette. */ diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 933899dca33a..7e7b7a9ba274 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -721,7 +721,7 @@ static int gbefb_set_par(struct fb_info *info) Tiles have the advantage that they can be allocated individually in memory. However, this mapping is not linear at all, which is not - really convienient. In order to support linear addressing, the GBE + really convenient. In order to support linear addressing, the GBE DMA hardware is fooled into thinking the screen is only one tile large and but has a greater height, so that the DMA transfer covers the same region. diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h index be8ccb47ebe0..cfcd8090f313 100644 --- a/drivers/video/geode/lxfb.h +++ b/drivers/video/geode/lxfb.h @@ -117,7 +117,7 @@ enum gp_registers { }; #define GP_BLT_STATUS_CE (1 << 4) /* cmd buf empty */ -#define GP_BLT_STATUS_PB (1 << 0) /* primative busy */ +#define GP_BLT_STATUS_PB (1 << 0) /* primitive busy */ /* Display Controller registers (table 6-47 from the data book) */ diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c index f5bedee4310a..7672d2ea9b35 100644 --- a/drivers/video/i810/i810_accel.c +++ b/drivers/video/i810/i810_accel.c @@ -112,7 +112,7 @@ static inline int wait_for_engine_idle(struct fb_info *info) * @par: pointer to i810fb_par structure * * DESCRIPTION: - * Checks/waits for sufficent space in ringbuffer of size + * Checks/waits for sufficient space in ringbuffer of size * space. Returns the tail of the buffer */ static inline u32 begin_iring(struct fb_info *info, u32 space) diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c index a8c9713413e6..0aeeaa10708b 100644 --- a/drivers/video/kyro/STG4000OverlayDevice.c +++ b/drivers/video/kyro/STG4000OverlayDevice.c @@ -417,7 +417,7 @@ int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg, /***************** Horizontal decimation/scaling ***************************/ /* - * Now we handle the horizontal case, this is a simplified verison of + * Now we handle the horizontal case, this is a simplified version of * the vertical case in that we decimate by factors of 2. as we are * working in words we should always be able to decimate by these * factors. as we always have to have a buffer which is aligned to a diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/kyro/STG4000Reg.h index 244549e61368..5d6269882589 100644 --- a/drivers/video/kyro/STG4000Reg.h +++ b/drivers/video/kyro/STG4000Reg.h @@ -16,7 +16,7 @@ /* * Macros that access memory mapped card registers in PCI space - * Add an appropraite section for your OS or processor architecture. + * Add an appropriate section for your OS or processor architecture. */ #if defined(__KERNEL__) #include diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h index c6ed7801efe2..1e6e45b57b78 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.h +++ b/drivers/video/matrox/matroxfb_DAC1064.h @@ -46,7 +46,7 @@ void DAC1064_global_restore(struct matrox_fb_info *minfo); #define M1064_XDVICLKCTRL_DVILOOPCTL 0x30 /* CRTC2 pixel clock allowed to(0)/blocked from(1) driving CRTC2 */ #define M1064_XDVICLKCTRL_C2DVICLKEN 0x40 - /* P1PLL loop filter bandwith selection */ + /* P1PLL loop filter bandwidth selection */ #define M1064_XDVICLKCTRL_P1LOOPBWDTCTL 0x80 #define M1064_XCURCOL0RED 0x08 #define M1064_XCURCOL0GREEN 0x09 diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 835aaaae6b96..9a44cec394b5 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -387,7 +387,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m) hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW; break; case 16: - /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */ + /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */ hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565); hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT; hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2; @@ -399,7 +399,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m) hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4; break; case 32: - /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used everytime) */ + /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */ hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT; break; default: diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 5ce6fa6e59f0..44bf8d4a216b 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -621,7 +621,7 @@ static int matroxfb_decode_var(const struct matrox_fb_info *minfo, var->yoffset = var->yres_virtual - var->yres; if (bpp == 16 && var->green.length == 5) { - bpp--; /* an artifical value - 15 */ + bpp--; /* an artificial value - 15 */ } for (rgbt = table; rgbt->bpp < bpp; rgbt++); diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index f96a471cb1a8..11ed57bb704e 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -12,7 +12,7 @@ #undef MATROXFB_DEBUG /* heavy debugging: */ -/* -- logs putc[s], so everytime a char is displayed, it's logged */ +/* -- logs putc[s], so every time a char is displayed, it's logged */ #undef MATROXFB_DEBUG_HEAVY /* This one _could_ cause infinite loops */ diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h index 6c23aa3d3b89..bc7c9300f276 100644 --- a/drivers/video/nuc900fb.h +++ b/drivers/video/nuc900fb.h @@ -8,7 +8,7 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * Auther: + * Author: * Wang Qiang(rurality.linux@gmail.com) 2009/12/16 */ diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 15e7f1912af9..196fa2e7f438 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -64,7 +64,7 @@ config FB_OMAP_MANUAL_UPDATE depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL help Say Y here, if your user-space applications are capable of - notifying the frame buffer driver when a change has occured in + notifying the frame buffer driver when a change has occurred in the frame buffer content and thus a reload of the image data to the external frame buffer is required. If unsure, say N. diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 0d44f070ef36..a981def8099a 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -587,7 +587,7 @@ static void get_edid_timing_data(u8 *edid) struct hdmi_cm cm; struct omap_video_timings edid_timings; - /* seach block 0, there are 4 DTDs arranged in priority order */ + /* search block 0, there are 4 DTDs arranged in priority order */ for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { current_descriptor_addrs = EDID_DESCRIPTOR_BLOCK0_ADDRESS + diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index cf4beb9dc9bb..0283c7021090 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c @@ -25,7 +25,7 @@ /* * WARNING: This controller is attached to System Bus 2 of the PXA which - * needs its arbiter to be enabled explictly (CKENB & 1<<9). + * needs its arbiter to be enabled explicitly (CKENB & 1<<9). * There is currently no way to do this from Linux, so you need to teach * your bootloader for now. */ diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index e4c3f214eb8e..4e9490c19d7d 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h @@ -153,7 +153,7 @@ struct savage_reg { unsigned char CRTC[25]; /* Crtc Controller */ unsigned char Sequencer[5]; /* Video Sequencer */ unsigned char Graphics[9]; /* Video Graphics */ - unsigned char Attribute[21]; /* Video Atribute */ + unsigned char Attribute[21]; /* Video Attribute */ unsigned int mode, refresh; unsigned char SR08, SR0E, SR0F; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 487911e2926c..a2dc1a7ec758 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -385,7 +385,7 @@ SavageSetup2DEngine(struct savagefb_par *par) BCI_SEND(GlobalBitmapDescriptor); /* - * I don't know why, sending this twice fixes the intial black screen, + * I don't know why, sending this twice fixes the initial black screen, * prevents X from crashing at least in Toshiba laptops with SavageIX. * --Tony */ @@ -2211,7 +2211,7 @@ static int __devinit savagefb_probe(struct pci_dev* dev, goto failed_mmio; video_len = savage_init_hw(par); - /* FIXME: cant be negative */ + /* FIXME: can't be negative */ if (video_len < 0) { err = video_len; goto failed_mmio; diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 46d1a64fe80d..56ef6b3a9851 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -265,7 +265,7 @@ static unsigned long sm501fb_ps_to_hz(unsigned long psvalue) return (unsigned long)numerator; } -/* sm501fb_hz_to_ps is identical to the oposite transform */ +/* sm501fb_hz_to_ps is identical to the opposite transform */ #define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x) @@ -1719,7 +1719,7 @@ static int sm501fb_init_fb(struct fb_info *fb, (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl, sizeof(struct fb_ops)); - /* update ops dependant on what we've been passed */ + /* update ops dependent on what we've been passed */ if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0) par->ops.fb_cursor = NULL; diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 2ab704118c44..2301c275d63a 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -221,7 +221,7 @@ static int __sst_wait_idle(u8 __iomem *vbase) while(1) { if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) { f_dddprintk("status: busy\n"); -/* FIXME basicaly, this is a busy wait. maybe not that good. oh well; +/* FIXME basically, this is a busy wait. maybe not that good. oh well; * this is a small loop after all. * Or maybe we should use mdelay() or udelay() here instead ? */ count = 0; @@ -501,7 +501,7 @@ static int sstfb_set_par(struct fb_info *info) } if (IS_VOODOO2(par)) { - /* voodoo2 has 32 pixel wide tiles , BUT stange things + /* voodoo2 has 32 pixel wide tiles , BUT strange things happen with odd number of tiles */ par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2; } else { @@ -920,11 +920,11 @@ static int __devinit sst_detect_ti(struct fb_info *info) * we get the 1st byte (M value) of preset f1,f7 and fB * why those 3 ? mmmh... for now, i'll do it the glide way... * and ask questions later. anyway, it seems that all the freq registers are - * realy at their default state (cf specs) so i ask again, why those 3 regs ? + * really at their default state (cf specs) so i ask again, why those 3 regs ? * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be * touched... - * is it realy safe ? how can i reset this ramdac ? geee... + * is it really safe ? how can i reset this ramdac ? geee... */ static int __devinit sst_detect_ics(struct fb_info *info) { diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index 7fe5be4bc70e..addf7b615ef8 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h @@ -79,7 +79,7 @@ struct sti_glob_cfg_ext { u8 curr_mon; /* current monitor configured */ u8 friendly_boot; /* in friendly boot mode */ s16 power; /* power calculation (in Watts) */ - s32 freq_ref; /* frequency refrence */ + s32 freq_ref; /* frequency reference */ u32 sti_mem_addr; /* pointer to global sti memory (size=sti_mem_request) */ u32 future_ptr; /* pointer to future data */ }; diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 3ee5e63cfa4f..a99b994c9b6b 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -877,12 +877,12 @@ static void tdfxfb_fillrect(struct fb_info *info, else tdfx_rop = TDFX_ROP_XOR; - /* asume always rect->height < 4096 */ + /* assume always rect->height < 4096 */ if (dy + rect->height > 4095) { dstbase = stride * dy; dy = 0; } - /* asume always rect->width < 4096 */ + /* assume always rect->width < 4096 */ if (dx + rect->width > 4095) { dstbase += dx * bpp >> 3; dx = 0; @@ -915,22 +915,22 @@ static void tdfxfb_copyarea(struct fb_info *info, u32 dstbase = 0; u32 srcbase = 0; - /* asume always area->height < 4096 */ + /* assume always area->height < 4096 */ if (sy + area->height > 4095) { srcbase = stride * sy; sy = 0; } - /* asume always area->width < 4096 */ + /* assume always area->width < 4096 */ if (sx + area->width > 4095) { srcbase += sx * bpp >> 3; sx = 0; } - /* asume always area->height < 4096 */ + /* assume always area->height < 4096 */ if (dy + area->height > 4095) { dstbase = stride * dy; dy = 0; } - /* asume always area->width < 4096 */ + /* assume always area->width < 4096 */ if (dx + area->width > 4095) { dstbase += dx * bpp >> 3; dx = 0; @@ -1003,12 +1003,12 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) #else srcfmt = 0x400000; #endif - /* asume always image->height < 4096 */ + /* assume always image->height < 4096 */ if (dy + image->height > 4095) { dstbase = stride * dy; dy = 0; } - /* asume always image->width < 4096 */ + /* assume always image->width < 4096 */ if (dx + image->width > 4095) { dstbase += dx * bpp >> 3; dx = 0; @@ -1124,7 +1124,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) * lower half (least significant 64 bits) of a 128 bit word * and pattern 1 the upper half. If you examine the data of * the cursor image the graphics card uses then from the - * begining you see line one of pattern 0, line one of + * beginning you see line one of pattern 0, line one of * pattern 1, line two of pattern 0, line two of pattern 1, * etc etc. The linear stride for the cursor is always 16 bytes * (128 bits) which is the maximum cursor width times two for diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 9710bf8caeae..0c341d739604 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -359,7 +359,7 @@ tmiofb_acc_wait(struct fb_info *info, unsigned int ccs) { struct tmiofb_par *par = info->par; /* - * This code can be called whith interrupts disabled. + * This code can be called with interrupts disabled. * So instead of relaying on irq to trigger the event, * poll the state till the necessary command is executed. */ diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 2c8364e9b632..68041d9dc260 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -769,7 +769,7 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, /* * If we have a damage-aware client, turn fb_defio "off" - * To avoid perf imact of unecessary page fault handling. + * To avoid perf imact of unnecessary page fault handling. * Done by resetting the delay for this fb_info to a very * long period. Pages will become writable and stay that way. * Reset to normal value when all clients have closed this fb. diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 28ccab44a391..53b2c5aae067 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -152,7 +152,7 @@ static inline int setop(int op) } /* Set the Enable Set/Reset Register and return its old value. - The code here always uses value 0xf for thsi register. */ + The code here always uses value 0xf for this register. */ static inline int setsr(int sr) { int oldsr; diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index d05ccb62b55f..35458a5eadc8 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c @@ -174,7 +174,7 @@ void viafb_set_gamma_table(int bpp, unsigned int *gamma_table) } /* If adjust Gamma value in SAMM, fill IGA1, - IGA2 Gamma table simultanous. */ + IGA2 Gamma table simultaneous. */ /* Switch to IGA2 Gamma Table */ if ((active_device_amount > 1) && !((viaparinfo->chip_info->gfx_chip_name == diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h index 1670ba82143f..f23be1708c14 100644 --- a/drivers/video/via/via_utility.h +++ b/drivers/video/via/via_utility.h @@ -21,7 +21,7 @@ #ifndef __VIAUTILITY_H__ #define __VIAUTILITY_H__ -/* These functions are used to get infomation about device's state */ +/* These functions are used to get information about device's state */ void viafb_get_device_support_state(u32 *support_state); void viafb_get_device_connect_state(u32 *connect_state); bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index f555b891cc72..b64818953aa7 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2019,7 +2019,7 @@ int __init viafb_init(void) return -EINVAL; printk(KERN_INFO - "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", + "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n", VERSION_MAJOR, VERSION_MINOR); return 0; } diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index d8b12c32e3ef..c8be8af0cc6d 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -1306,7 +1306,7 @@ static void w100_init_lcd(struct w100fb_par *par) union graphic_v_disp_u graphic_v_disp; union crtc_total_u crtc_total; - /* w3200 doesnt like undefined bits being set so zero register values first */ + /* w3200 doesn't like undefined bits being set so zero register values first */ active_h_disp.val = 0; active_h_disp.f.active_h_start=mode->left_margin; diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 38e96ab90945..5ef385bfed18 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -545,7 +545,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) return; } - /* Second write, data transfered. Release the module */ + /* Second write, data transferred. Release the module */ if (hdq_data->init_trans > 1) { omap_hdq_put(hdq_data); ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b69d71482554..1b0f98bc51b5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -933,7 +933,7 @@ config PNX833X_WDT depends on SOC_PNX8335 help Hardware driver for the PNX833x's watchdog. This is a - watchdog timer that will reboot the machine after a programable + watchdog timer that will reboot the machine after a programmable timer has expired and no process has written to /dev/watchdog during that time. diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index d520bf9c3355..3f8608b922a7 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -4,7 +4,7 @@ # Only one watchdog can succeed. We probe the ISA/PCI/USB based # watchdog-cards first, then the architecture specific watchdog -# drivers and then the architecture independant "softdog" driver. +# drivers and then the architecture independent "softdog" driver. # This means that if your ISA/PCI/USB card isn't detected that # you can fall back to an architecture specific driver and if # that also fails then you can fall back to the software watchdog @@ -153,7 +153,7 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o # Xen obj-$(CONFIG_XEN_WDT) += xen_wdt.o -# Architecture Independant +# Architecture Independent obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 2ffce4d75443..b6a2b58cbe64 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -26,7 +26,7 @@ * Theory of Operation: * The Watch-Dog Timer is provided to ensure that standalone * Systems can always recover from catastrophic conditions that - * caused the CPU to crash. This condition may have occured by + * caused the CPU to crash. This condition may have occurred by * external EMI or a software bug. When the CPU stops working * correctly, hardware on the board will either perform a hardware * reset (cold boot) or a non-maskable interrupt (NMI) to bring the diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 139d773300c6..b7c139051575 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -49,7 +49,7 @@ #define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) #define SWC_LDN 0x04 #define SIOCFG2 0x22 /* Serial IO register */ -#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ +#define WDCTL 0x10 /* Watchdog-Timer-Control-Register */ #define WDTO 0x11 /* Watchdog timeout register */ #define WDCFG 0x12 /* Watchdog config register */ diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c index 67ddeb1c830a..ff11504c376e 100644 --- a/drivers/watchdog/sbc7240_wdt.c +++ b/drivers/watchdog/sbc7240_wdt.c @@ -273,7 +273,7 @@ static int __init sbc7240_wdt_init(void) /* The IO port 0x043 used to disable the watchdog * is already claimed by the system timer, so we - * cant request_region() it ...*/ + * can't request_region() it ...*/ if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) { timeout = SBC7240_TIMEOUT; diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index b61ab1c54293..c7cf4b01f58d 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -201,7 +201,7 @@ static void sch311x_wdt_get_status(int *status) spin_lock(&sch311x_wdt_data.io_lock); /* -- Watchdog timer control -- - * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured + * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occurred * Bit 1 Reserved * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) * Bit 3 P20 Force Timeout enabled: diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 4e3e7eb5919c..db84f2322d1a 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -50,7 +50,7 @@ * necssary. * * As a result of this timing problem, the only modes that are particularly - * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms + * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms * overflow periods respectively. * * Also, since we can't really expect userspace to be responsive enough diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index df88cfa05f35..e97b0499bd0d 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -191,7 +191,7 @@ static inline void wdt_timer_conf(unsigned char conf) static inline void wdt_timer_ctrl(unsigned char reg) { /* -- Watchdog timer control -- - * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured + * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occurred * Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) * Bit 3 P20 Force Timeout enabled: diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 0a0efe713bc8..0d80e08b6439 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -90,7 +90,7 @@ static void wdt_setload(unsigned int timeout) /* * sp805 runs counter with given value twice, after the end of first * counter it gives an interrupt and then starts counter again. If - * interrupt already occured then it resets the system. This is why + * interrupt already occurred then it resets the system. This is why * load is half of what should be required. */ load = div_u64(rate, 2) * timeout - 1; diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 036343ba204e..42d6c930cc87 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -5,7 +5,7 @@ * domain gets 1024 event channels, but NR_IRQ is not that large, we * must dynamically map irqs<->event channels. The event channels * interface with the rest of the kernel by defining a xen interrupt - * chip. When an event is recieved, it is mapped to an irq and sent + * chip. When an event is received, it is mapped to an irq and sent * through the normal interrupt processing path. * * There are four kinds of events which can be mapped to an event @@ -416,7 +416,7 @@ static int __must_check xen_allocate_irq_dynamic(void) #ifdef CONFIG_X86_IO_APIC /* * For an HVM guest or domain 0 which see "real" (emulated or - * actual repectively) GSIs we allocate dynamic IRQs + * actual respectively) GSIs we allocate dynamic IRQs * e.g. those corresponding to event channels or MSIs * etc. from the range above those "real" GSIs to avoid * collisions. diff --git a/fs/adfs/map.c b/fs/adfs/map.c index d1a5932bb0f1..6935f05202ac 100644 --- a/fs/adfs/map.c +++ b/fs/adfs/map.c @@ -51,7 +51,7 @@ static DEFINE_RWLOCK(adfs_map_lock); /* * This is fun. We need to load up to 19 bits from the map at an - * arbitary bit alignment. (We're limited to 19 bits by F+ version 2). + * arbitrary bit alignment. (We're limited to 19 bits by F+ version 2). */ #define GET_FRAG_ID(_map,_start,_idmask) \ ({ \ diff --git a/fs/afs/cache.c b/fs/afs/cache.c index 0fb315dd4d2a..577763c3d88b 100644 --- a/fs/afs/cache.c +++ b/fs/afs/cache.c @@ -98,7 +98,7 @@ static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data, } /* - * provide new auxilliary cache data + * provide new auxiliary cache data */ static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, void *buffer, uint16_t bufmax) @@ -117,7 +117,7 @@ static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, } /* - * check that the auxilliary data indicates that the entry is still valid + * check that the auxiliary data indicates that the entry is still valid */ static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data, const void *buffer, @@ -150,7 +150,7 @@ static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data, } /* - * provide new auxilliary cache data + * provide new auxiliary cache data */ static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, void *buffer, uint16_t bufmax) @@ -172,7 +172,7 @@ static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, } /* - * check that the auxilliary data indicates that the entry is still valid + * check that the auxiliary data indicates that the entry is still valid */ static enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data, @@ -283,7 +283,7 @@ static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, } /* - * provide new auxilliary cache data + * provide new auxiliary cache data */ static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, void *buffer, uint16_t bufmax) @@ -309,7 +309,7 @@ static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, } /* - * check that the auxilliary data indicates that the entry is still valid + * check that the auxiliary data indicates that the entry is still valid */ static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, const void *buffer, diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 0d5eeadf6121..3c090b7555ea 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -293,7 +293,7 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz, if (!cell) { /* this should not happen unless user tries to mount * when root cell is not set. Return an impossibly - * bizzare errno to alert the user. Things like + * bizarre errno to alert the user. Things like * ENOENT might be "more appropriate" but they happen * for other reasons. */ diff --git a/fs/attr.c b/fs/attr.c index 1007ed616314..91dbe2a107f2 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL(inode_newsize_ok); * setattr_copy must be called with i_mutex held. * * setattr_copy updates the inode's metadata with that specified - * in attr. Noticably missing is inode size update, which is more complex + * in attr. Noticeably missing is inode size update, which is more complex * as it requires pagecache updates. * * The inode is not marked as dirty after this operation. The rationale is diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 96804a17bbd0..f55ae23b137e 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -612,7 +612,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) * set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves * of the directory tree. There is no need to clear the automount flag * following a mount or restore it after an expire because these mounts - * are always covered. However, it is neccessary to ensure that these + * are always covered. However, it is necessary to ensure that these * flags are clear on non-empty directories to avoid unnecessary calls * during path walks. */ diff --git a/fs/befs/ChangeLog b/fs/befs/ChangeLog index ce8c787916be..75a461cfaca6 100644 --- a/fs/befs/ChangeLog +++ b/fs/befs/ChangeLog @@ -24,7 +24,7 @@ Version 0.9 (2002-03-14) Version 0.64 (2002-02-07) ========== -* Did the string comparision really right this time (btree.c) [WD] +* Did the string comparison really right this time (btree.c) [WD] * Fixed up some places where I assumed that a long int could hold a pointer value. (btree.c) [WD] @@ -114,7 +114,7 @@ Version 0.6 (2001-12-15) More flexible. Will soon be controllable at mount time (see TODO). [WD] -* Rewrote datastream positon lookups. +* Rewrote datastream position lookups. (datastream.c) [WD] * Moved the TODO list to its own file. @@ -150,7 +150,7 @@ Version 0.50 (2001-11-13) * Anton also told me that the blocksize is not allowed to be larger than the page size in linux, which is 4k i386. Oops. Added a test for (blocksize > PAGE_SIZE), and refuse to mount in that case. What this - practicaly means is that 8k blocksize volumes won't work without a major + practically means is that 8k blocksize volumes won't work without a major restructuring of the driver (or an alpha or other 64bit hardware). [WD] * Cleaned up the befs_count_blocks() function. Much smarter now. @@ -183,7 +183,7 @@ Version 0.45 (2001-10-29) structures into the generic pointer fields of the public structures with kmalloc(). put_super and put_inode free them. This allows us not to have to touch the definitions of the public structures in - include/linux/fs.h. Also, befs_inode_info is huge (becuase of the + include/linux/fs.h. Also, befs_inode_info is huge (because of the symlink string). (super.c, inode.c, befs_fs.h) [WD] * Fixed a thinko that was corrupting file reads after the first block_run @@ -404,7 +404,7 @@ Version 0.4 (2001-10-28) * Fixed compile errors on 2.4.1 kernel (WD) Resolve rejected patches - Accomodate changed NLS interface (util.h) + Accommodate changed NLS interface (util.h) Needed to include in most files Makefile changes fs/Config.in changes diff --git a/fs/befs/befs_fs_types.h b/fs/befs/befs_fs_types.h index 7893eaa1e58c..eb557d9dc8be 100644 --- a/fs/befs/befs_fs_types.h +++ b/fs/befs/befs_fs_types.h @@ -234,7 +234,7 @@ typedef struct { } PACKED befs_btree_super; /* - * Header stucture of each btree node + * Header structure of each btree node */ typedef struct { fs64 left; diff --git a/fs/befs/btree.c b/fs/befs/btree.c index 4202db7496cb..a66c9b1136e0 100644 --- a/fs/befs/btree.c +++ b/fs/befs/btree.c @@ -5,7 +5,7 @@ * * Licensed under the GNU GPL. See the file COPYING for details. * - * 2002-02-05: Sergey S. Kostyliov added binary search withing + * 2002-02-05: Sergey S. Kostyliov added binary search within * btree nodes. * * Many thanks to: diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 06457ed8f3e7..54b8c28bebc8 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -734,7 +734,7 @@ parse_options(char *options, befs_mount_options * opts) /* This function has the responsibiltiy of getting the * filesystem ready for unmounting. - * Basicly, we free everything that we allocated in + * Basically, we free everything that we allocated in * befs_read_inode */ static void diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 811384bec8de..397d3057d336 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -717,7 +717,7 @@ static int load_flat_file(struct linux_binprm * bprm, * help simplify all this mumbo jumbo * * We've got two different sections of relocation entries. - * The first is the GOT which resides at the begining of the data segment + * The first is the GOT which resides at the beginning of the data segment * and is terminated with a -1. This one can be relocated in place. * The second is the extra relocation entries tacked after the image's * data segment. These require a little more processing as the entry is diff --git a/fs/bio.c b/fs/bio.c index 4d6d4b6c2bf1..840a0d755248 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1436,7 +1436,7 @@ EXPORT_SYMBOL(bio_flush_dcache_pages); * preferred way to end I/O on a bio, it takes care of clearing * BIO_UPTODATE on error. @error is 0 on success, and and one of the * established -Exxxx (-EIO, for instance) error values in case - * something went wrong. Noone should call bi_end_io() directly on a + * something went wrong. No one should call bi_end_io() directly on a * bio unless they own it and thus know that it has an end_io * function. **/ diff --git a/fs/block_dev.c b/fs/block_dev.c index c1511c674f53..5147bdd3b8e1 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -653,7 +653,7 @@ void bd_forget(struct inode *inode) * @whole: whole block device containing @bdev, may equal @bdev * @holder: holder trying to claim @bdev * - * Test whther @bdev can be claimed by @holder. + * Test whether @bdev can be claimed by @holder. * * CONTEXT: * spin_lock(&bdev_lock). diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 2b6c12e983b3..a24a3f2fa13e 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -243,7 +243,7 @@ out: * Insert @em into @tree or perform a simple forward/backward merge with * existing mappings. The extent_map struct passed in will be inserted * into the tree directly, with an additional reference taken, or a - * reference dropped if the merge attempt was successfull. + * reference dropped if the merge attempt was successful. */ int add_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 93c28a1d6bdc..80920bce01ab 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2324,7 +2324,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) /* * if ret == 0 means we found what we were searching for, which - * is weird, but possible, so only screw with path if we didnt + * is weird, but possible, so only screw with path if we didn't * find the key and see if we have stuff that matches */ if (ret > 0) { diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 58250e09eb05..199a80134312 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2346,7 +2346,7 @@ struct btrfs_root *select_one_root(struct btrfs_trans_handle *trans, root = next->root; BUG_ON(!root); - /* no other choice for non-refernce counted tree */ + /* no other choice for non-references counted tree */ if (!root->ref_cows) return root; diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 37fe101a4e0d..1064805e653b 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -197,7 +197,7 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object) } /* - * update the auxilliary data for an object object on disk + * update the auxiliary data for an object object on disk */ static void cachefiles_update_object(struct fscache_object *_object) { diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 37368ba2e67c..e159c529fd2b 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -24,7 +24,7 @@ * context needs to be associated with the osd write during writeback. * * Similarly, struct ceph_inode_info maintains a set of counters to - * count dirty pages on the inode. In the absense of snapshots, + * count dirty pages on the inode. In the absence of snapshots, * i_wrbuffer_ref == i_wrbuffer_ref_head == the dirty page count. * * When a snapshot is taken (that is, when the client receives diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 6b61ded701e1..5323c330bbf3 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -765,7 +765,7 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) if (touch) { struct rb_node *q; - /* touch this + preceeding caps */ + /* touch this + preceding caps */ __touch_cap(cap); for (q = rb_first(&ci->i_caps); q != p; q = rb_next(q)) { diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 0aee66b92af3..e86ec1155f8f 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -342,7 +342,7 @@ static int build_snap_context(struct ceph_snap_realm *realm) num = 0; snapc->seq = realm->seq; if (parent) { - /* include any of parent's snaps occuring _after_ my + /* include any of parent's snaps occurring _after_ my parent became my parent */ for (i = 0; i < parent->cached_context->num_snaps; i++) if (parent->cached_context->snaps[i] >= diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index 7f7fa3c302af..ea940b1db77b 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS @@ -35,7 +35,7 @@ Adrian Bunk (kcalloc cleanups) Miklos Szeredi Kazeon team for various fixes especially for 2.4 version. Asser Ferno (Change Notify support) -Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup +Shaggy (Dave Kleikamp) for innumerable small fs suggestions and some good cleanup Gunter Kukkukk (testing and suggestions for support of old servers) Igor Mammedov (DFS support) Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code) diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 0a265ad9e426..2b68ac57d97d 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -53,7 +53,7 @@ void cifs_dfs_release_automount_timer(void) * * Extracts sharename form full UNC. * i.e. strips from UNC trailing path that is not part of share - * name and fixup missing '\' in the begining of DFS node refferal + * name and fixup missing '\' in the beginning of DFS node refferal * if necessary. * Returns pointer to share name on success or ERR_PTR on error. * Caller is responsible for freeing returned string. diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 904aa47e3515..2644a5d6cc67 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5247,7 +5247,7 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, * Samba server ignores set of file size to zero due to bugs in some * older clients, but we should be precise - we use SetFileSize to * set file size and do not want to truncate file size to zero - * accidently as happened on one Samba server beta by putting + * accidentally as happened on one Samba server beta by putting * zero instead of -1 here */ data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8d6c17ab593d..6e2b2addfc78 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1572,7 +1572,7 @@ match_security(struct TCP_Server_Info *server, struct smb_vol *vol) return false; } - /* now check if signing mode is acceptible */ + /* now check if signing mode is acceptable */ if ((secFlags & CIFSSEC_MAY_SIGN) == 0 && (server->secMode & SECMODE_SIGN_REQUIRED)) return false; @@ -2933,7 +2933,7 @@ mount_fail_check: if (mount_data != mount_data_global) kfree(mount_data); /* If find_unc succeeded then rc == 0 so we can not end */ - /* up accidently freeing someone elses tcon struct */ + /* up accidentally freeing someone elses tcon struct */ if (tcon) cifs_put_tcon(tcon); else if (pSesInfo) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index dd5f22918c33..9ea65cf36714 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -189,7 +189,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); /* EIO could indicate that (posix open) operation is not supported, despite what server claimed in capability - negotation. EREMOTE indicates DFS junction, which is not + negotiation. EREMOTE indicates DFS junction, which is not handled in posix open */ if (rc == 0) { diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 90ff3cb10de3..3313dd19f543 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -990,7 +990,7 @@ static int configfs_dump(struct configfs_dirent *sd, int level) * This describes these functions and their helpers. * * Allow another kernel system to depend on a config_item. If this - * happens, the item cannot go away until the dependant can live without + * happens, the item cannot go away until the dependent can live without * it. The idea is to give client modules as simple an interface as * possible. When a system asks them to depend on an item, they just * call configfs_depend_item(). If the item is live and the client diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 04b8c449303f..56d6bfcc1e48 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -519,7 +519,7 @@ static void toss_rsb(struct kref *kref) } } -/* When all references to the rsb are gone it's transfered to +/* When all references to the rsb are gone it's transferred to the tossed list for later disposal. */ static void put_rsb(struct dlm_rsb *r) diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index bffa1e73b9a9..5e2c71f05e46 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -810,7 +810,7 @@ static int tcp_accept_from_sock(struct connection *con) /* * Add it to the active queue in case we got data - * beween processing the accept adding the socket + * between processing the accept adding the socket * to the read_sockets list */ if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags)) diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index eda43f362616..14638235f7b2 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c @@ -304,7 +304,7 @@ static void set_master_lkbs(struct dlm_rsb *r) } /* - * Propogate the new master nodeid to locks + * Propagate the new master nodeid to locks * The NEW_MASTER flag tells dlm_recover_locks() which rsb's to consider. * The NEW_MASTER2 flag tells recover_lvb() and set_locks_purged() which * rsb's to consider. diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index c27c0ecf90bc..fdb2eb0ad09e 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -276,7 +276,7 @@ static void ecryptfs_init_mount_crypt_stat( /** * ecryptfs_parse_options * @sb: The ecryptfs super block - * @options: The options pased to the kernel + * @options: The options passed to the kernel * * Parse mount options: * debug=N - ecryptfs_verbosity level for debug output @@ -840,7 +840,7 @@ static int __init ecryptfs_init(void) } rc = ecryptfs_init_messaging(); if (rc) { - printk(KERN_ERR "Failure occured while attempting to " + printk(KERN_ERR "Failure occurred while attempting to " "initialize the communications channel to " "ecryptfsd\n"); goto out_destroy_kthread; diff --git a/fs/eventpoll.c b/fs/eventpoll.c index ed38801b57a7..f9cfd168fbe2 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -181,7 +181,7 @@ struct eventpoll { /* * This is a single linked list that chains all the "struct epitem" that - * happened while transfering ready events to userspace w/out + * happened while transferring ready events to userspace w/out * holding ->lock. */ struct epitem *ovflist; @@ -606,7 +606,7 @@ static void ep_free(struct eventpoll *ep) * We do not need to hold "ep->mtx" here because the epoll file * is on the way to be removed and no one has references to it * anymore. The only hit might come from eventpoll_release_file() but - * holding "epmutex" is sufficent here. + * holding "epmutex" is sufficient here. */ mutex_lock(&epmutex); @@ -720,7 +720,7 @@ void eventpoll_release_file(struct file *file) /* * We don't want to get "file->f_lock" because it is not * necessary. It is not necessary because we're in the "struct file" - * cleanup path, and this means that noone is using this file anymore. + * cleanup path, and this means that no one is using this file anymore. * So, for example, epoll_ctl() cannot hit here since if we reach this * point, the file counter already went to zero and fget() would fail. * The only hit might come from ep_free() but by holding the mutex @@ -1112,7 +1112,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, * Trigger mode, we need to insert back inside * the ready list, so that the next call to * epoll_wait() will check again the events - * availability. At this point, noone can insert + * availability. At this point, no one can insert * into ep->rdllist besides us. The epoll_ctl() * callers are locked out by * ep_scan_ready_list() holding "mtx" and the diff --git a/fs/exofs/common.h b/fs/exofs/common.h index 5e74ad3d4009..3bbd46956d77 100644 --- a/fs/exofs/common.h +++ b/fs/exofs/common.h @@ -115,7 +115,7 @@ struct exofs_sb_stats { * Describes the raid used in the FS. It is part of the device table. * This here is taken from the pNFS-objects definition. In exofs we * use one raid policy through-out the filesystem. (NOTE: the funny - * alignment at begining. We take care of it at exofs_device_table. + * alignment at beginning. We take care of it at exofs_device_table. */ struct exofs_dt_data_map { __le32 cb_num_comps; @@ -136,7 +136,7 @@ struct exofs_dt_device_info { u8 systemid[OSD_SYSTEMID_LEN]; __le64 long_name_offset; /* If !0 then offset-in-file */ __le32 osdname_len; /* */ - u8 osdname[44]; /* Embbeded, Ususally an asci uuid */ + u8 osdname[44]; /* Embbeded, Usually an asci uuid */ } __packed; /* diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 0d06f4e75699..8f44cef1b3ef 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -850,7 +850,7 @@ static int find_next_reservable_window( rsv_window_remove(sb, my_rsv); /* - * Let's book the whole avaliable window for now. We will check the + * Let's book the whole available window for now. We will check the * disk bitmap later and then, if there are free blocks then we adjust * the window size if it's larger than requested. * Otherwise, we will remove this node from the tree next time @@ -1357,9 +1357,9 @@ retry_alloc: goto allocated; } /* - * We may end up a bogus ealier ENOSPC error due to + * We may end up a bogus earlier ENOSPC error due to * filesystem is "full" of reservations, but - * there maybe indeed free blocks avaliable on disk + * there maybe indeed free blocks available on disk * In this case, we just forget about the reservations * just do block allocation as without reservations. */ diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index c47f706878b5..788e09a07f7e 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -305,7 +305,7 @@ static ext2_fsblk_t ext2_find_near(struct inode *inode, Indirect *ind) return ind->bh->b_blocknr; /* - * It is going to be refered from inode itself? OK, just put it into + * It is going to be referred from inode itself? OK, just put it into * the same cylinder group then. */ bg_start = ext2_group_first_block_no(inode->i_sb, ei->i_block_group); @@ -913,7 +913,7 @@ static inline int all_zeroes(__le32 *p, __le32 *q) * * When we do truncate() we may have to clean the ends of several indirect * blocks but leave the blocks themselves alive. Block is partially - * truncated if some data below the new i_size is refered from it (and + * truncated if some data below the new i_size is referred from it (and * it is on the path to the first completely truncated data block, indeed). * We have to free the top of that path along with everything to the right * of the path. Since no allocation past the truncation point is possible @@ -990,7 +990,7 @@ no_top: * @p: array of block numbers * @q: points immediately past the end of array * - * We are freeing all blocks refered from that array (numbers are + * We are freeing all blocks referred from that array (numbers are * stored as little-endian 32-bit) and updating @inode->i_blocks * appropriately. */ @@ -1030,7 +1030,7 @@ static inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q) * @q: pointer immediately past the end of array * @depth: depth of the branches to free * - * We are freeing all blocks refered from these branches (numbers are + * We are freeing all blocks referred from these branches (numbers are * stored as little-endian 32-bit) and updating @inode->i_blocks * appropriately. */ diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7731695e65d9..0a78dae7e2cb 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1382,7 +1382,7 @@ static struct dentry *ext2_mount(struct file_system_type *fs_type, /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code - * itself serializes the operations (and noone else should touch the files) + * itself serializes the operations (and no one else should touch the files) * we don't have to be afraid of races */ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off) diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index c2e4dce984d2..529970617a21 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -35,7 +35,7 @@ * +------------------+ * * The block header is followed by multiple entry descriptors. These entry - * descriptors are variable in size, and alligned to EXT2_XATTR_PAD + * descriptors are variable in size, and aligned to EXT2_XATTR_PAD * byte boundaries. The entry descriptors are sorted by attribute name, * so that two extended attribute blocks can be compared efficiently. * diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 153242187fce..fe52297e31ad 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -590,7 +590,7 @@ do_more: BUFFER_TRACE(debug_bh, "Deleted!"); if (!bh2jh(bitmap_bh)->b_committed_data) BUFFER_TRACE(debug_bh, - "No commited data in bitmap"); + "No committed data in bitmap"); BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap"); __brelse(debug_bh); } @@ -1063,7 +1063,7 @@ static int find_next_reservable_window( rsv_window_remove(sb, my_rsv); /* - * Let's book the whole avaliable window for now. We will check the + * Let's book the whole available window for now. We will check the * disk bitmap later and then, if there are free blocks then we adjust * the window size if it's larger than requested. * Otherwise, we will remove this node from the tree next time @@ -1456,7 +1456,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi) * * ext3_should_retry_alloc() is called when ENOSPC is returned, and if * it is profitable to retry the operation, this function will wait - * for the current or commiting transaction to complete, and then + * for the current or committing transaction to complete, and then * return TRUE. * * if the total number of retries exceed three times, return FALSE. @@ -1632,9 +1632,9 @@ retry_alloc: goto allocated; } /* - * We may end up a bogus ealier ENOSPC error due to + * We may end up a bogus earlier ENOSPC error due to * filesystem is "full" of reservations, but - * there maybe indeed free blocks avaliable on disk + * there maybe indeed free blocks available on disk * In this case, we just forget about the reservations * just do block allocation as without reservations. */ diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index fe2541d250e4..b5c2f3c97d71 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2055,7 +2055,7 @@ static inline int all_zeroes(__le32 *p, __le32 *q) * * When we do truncate() we may have to clean the ends of several * indirect blocks but leave the blocks themselves alive. Block is - * partially truncated if some data below the new i_size is refered + * partially truncated if some data below the new i_size is referred * from it (and it is on the path to the first completely truncated * data block, indeed). We have to free the top of that path along * with everything to the right of the path. Since no allocation @@ -2184,7 +2184,7 @@ static void ext3_clear_blocks(handle_t *handle, struct inode *inode, * @first: array of block numbers * @last: points immediately past the end of array * - * We are freeing all blocks refered from that array (numbers are stored as + * We are freeing all blocks referred from that array (numbers are stored as * little-endian 32-bit) and updating @inode->i_blocks appropriately. * * We accumulate contiguous runs of blocks to free. Conveniently, if these @@ -2272,7 +2272,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode, * @last: pointer immediately past the end of array * @depth: depth of the branches to free * - * We are freeing all blocks refered from these branches (numbers are + * We are freeing all blocks referred from these branches (numbers are * stored as little-endian 32-bit) and updating @inode->i_blocks * appropriately. */ diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 108b142e11ed..7916e4ce166a 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -1009,7 +1009,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, if (test_opt(sb, DEBUG)) printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK - " upto "E3FSBLK" blocks\n", + " up to "E3FSBLK" blocks\n", o_blocks_count, n_blocks_count); if (n_blocks_count == 0 || n_blocks_count == o_blocks_count) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 071689f86e18..3c6a9e0eadc1 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2925,7 +2925,7 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code - * itself serializes the operations (and noone else should touch the files) + * itself serializes the operations (and no one else should touch the files) * we don't have to be afraid of races */ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 97b970e7dd13..1c67139ad4b4 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -547,7 +547,7 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, * * ext4_should_retry_alloc() is called when ENOSPC is returned, and if * it is profitable to retry the operation, this function will wait - * for the current or commiting transaction to complete, and then + * for the current or committing transaction to complete, and then * return TRUE. * * if the total number of retries exceed three times, return FALSE. diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index dd2cb5076ff9..4890d6f3ad15 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1729,7 +1729,7 @@ repeat: BUG_ON(npath->p_depth != path->p_depth); eh = npath[depth].p_hdr; if (le16_to_cpu(eh->eh_entries) < le16_to_cpu(eh->eh_max)) { - ext_debug("next leaf isnt full(%d)\n", + ext_debug("next leaf isn't full(%d)\n", le16_to_cpu(eh->eh_entries)); path = npath; goto repeat; @@ -2533,7 +2533,7 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) /* * This function is called by ext4_ext_map_blocks() if someone tries to write * to an uninitialized extent. It may result in splitting the uninitialized - * extent into multiple extents (upto three - one initialized and two + * extent into multiple extents (up to three - one initialized and two * uninitialized). * There are three possibilities: * a> There is no split required: Entire extent should be initialized @@ -3174,7 +3174,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, path, flags); /* * Flag the inode(non aio case) or end_io struct (aio case) - * that this IO needs to convertion to written when IO is + * that this IO needs to conversion to written when IO is * completed */ if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) { @@ -3460,10 +3460,10 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ext4_ext_mark_uninitialized(&newex); /* * io_end structure was created for every IO write to an - * uninitialized extent. To avoid unecessary conversion, + * uninitialized extent. To avoid unnecessary conversion, * here we flag the IO that really needs the conversion. * For non asycn direct IO case, flag the inode state - * that we need to perform convertion when IO is done. + * that we need to perform conversion when IO is done. */ if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) { diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 7f74019d6d77..4673bc05274f 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -101,7 +101,7 @@ extern int ext4_flush_completed_IO(struct inode *inode) * to the work-to-be schedule is freed. * * Thus we need to keep the io structure still valid here after - * convertion finished. The io structure has a flag to + * conversion finished. The io structure has a flag to * avoid double converting from both fsync and background work * queue work. */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1a86282b9024..ad8e303c0d29 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2588,7 +2588,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); * because we should have holes filled from ext4_page_mkwrite(). We even don't * need to file the inode to the transaction's list in ordered mode because if * we are writing back data added by write(), the inode is already there and if - * we are writing back data modified via mmap(), noone guarantees in which + * we are writing back data modified via mmap(), no one guarantees in which * transaction the data will hit the disk. In case we are journaling data, we * cannot start transaction directly because transaction start ranks above page * lock so we have to do some magic. @@ -2690,7 +2690,7 @@ static int ext4_writepage(struct page *page, /* * This is called via ext4_da_writepages() to - * calulate the total number of credits to reserve to fit + * calculate the total number of credits to reserve to fit * a single extent allocation into a single transaction, * ext4_da_writpeages() will loop calling this before * the block allocation. @@ -3304,7 +3304,7 @@ int ext4_alloc_da_blocks(struct inode *inode) * the pages by calling redirty_page_for_writepage() but that * would be ugly in the extreme. So instead we would need to * replicate parts of the code in the above functions, - * simplifying them becuase we wouldn't actually intend to + * simplifying them because we wouldn't actually intend to * write out the pages, but rather only collect contiguous * logical block extents, call the multi-block allocator, and * then update the buffer heads with the block allocations. @@ -3694,7 +3694,7 @@ retry: * * The unwrritten extents will be converted to written when DIO is completed. * For async direct IO, since the IO may still pending when return, we - * set up an end_io call back function, which will do the convertion + * set up an end_io call back function, which will do the conversion * when async direct IO completed. * * If the O_DIRECT write will extend the file then add this inode to the @@ -3717,7 +3717,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, * We could direct write to holes and fallocate. * * Allocated blocks to fill the hole are marked as uninitialized - * to prevent paralel buffered read to expose the stale data + * to prevent parallel buffered read to expose the stale data * before DIO complete the data IO. * * As to previously fallocated extents, ext4 get_block @@ -3778,7 +3778,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, int err; /* * for non AIO case, since the IO is already - * completed, we could do the convertion right here + * completed, we could do the conversion right here */ err = ext4_convert_unwritten_extents(inode, offset, ret); @@ -4025,7 +4025,7 @@ static inline int all_zeroes(__le32 *p, __le32 *q) * * When we do truncate() we may have to clean the ends of several * indirect blocks but leave the blocks themselves alive. Block is - * partially truncated if some data below the new i_size is refered + * partially truncated if some data below the new i_size is referred * from it (and it is on the path to the first completely truncated * data block, indeed). We have to free the top of that path along * with everything to the right of the path. Since no allocation @@ -4169,7 +4169,7 @@ out_err: * @first: array of block numbers * @last: points immediately past the end of array * - * We are freeing all blocks refered from that array (numbers are stored as + * We are freeing all blocks referred from that array (numbers are stored as * little-endian 32-bit) and updating @inode->i_blocks appropriately. * * We accumulate contiguous runs of blocks to free. Conveniently, if these @@ -4261,7 +4261,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, * @last: pointer immediately past the end of array * @depth: depth of the branches to free * - * We are freeing all blocks refered from these branches (numbers are + * We are freeing all blocks referred from these branches (numbers are * stored as little-endian 32-bit) and updating @inode->i_blocks * appropriately. */ @@ -5478,7 +5478,7 @@ static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) } /* - * Calulate the total number of credits to reserve to fit + * Calculate the total number of credits to reserve to fit * the modification of a single pages into a single transaction, * which may include multiple chunks of block allocations. * diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index a5837a837a8b..d8a16eecf1d5 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -92,7 +92,7 @@ * between CPUs. It is possible to get scheduled at this point. * * The locality group prealloc space is used looking at whether we have - * enough free space (pa_free) withing the prealloc space. + * enough free space (pa_free) within the prealloc space. * * If we can't allocate blocks via inode prealloc or/and locality group * prealloc then we look at the buddy cache. The buddy cache is represented diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index d1bafa57f483..92816b4e0f16 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -517,7 +517,7 @@ int ext4_ext_migrate(struct inode *inode) * start with one credit accounted for * superblock modification. * - * For the tmp_inode we already have commited the + * For the tmp_inode we already have committed the * trascation that created the inode. Later as and * when we add extents we extent the journal */ diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 22546ad7f0ae..056474b7b8e0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -617,7 +617,7 @@ __acquires(bitlock) * filesystem will have already been marked read/only and the * journal has been aborted. We return 1 as a hint to callers * who might what to use the return value from - * ext4_grp_locked_error() to distinguish beween the + * ext4_grp_locked_error() to distinguish between the * ERRORS_CONT and ERRORS_RO case, and perhaps return more * aggressively from the ext4 function in question, with a * more appropriate error code. @@ -4624,7 +4624,7 @@ static int ext4_quota_off(struct super_block *sb, int type) /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code - * itself serializes the operations (and noone else should touch the files) + * itself serializes the operations (and no one else should touch the files) * we don't have to be afraid of races */ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off) diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c index 78948b4b1894..c9a6a94e58e9 100644 --- a/fs/freevxfs/vxfs_fshead.c +++ b/fs/freevxfs/vxfs_fshead.c @@ -164,7 +164,7 @@ vxfs_read_fshead(struct super_block *sbp) goto out_free_pfp; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { - printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", + printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n", VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); goto out_iput_stilist; } diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 6c5131d592f0..3360f1e678ad 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -162,7 +162,7 @@ vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) /** * vxfs_inode_by_name - find inode number for dentry * @dip: directory to search in - * @dp: dentry we seach for + * @dp: dentry we search for * * Description: * vxfs_inode_by_name finds out the inode number of diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h index d8324296486f..b7b3af502615 100644 --- a/fs/freevxfs/vxfs_olt.h +++ b/fs/freevxfs/vxfs_olt.h @@ -60,7 +60,7 @@ enum { * * The Object Location Table header is placed at the beginning of each * OLT extent. It is used to fing certain filesystem-wide metadata, e.g. - * the inital inode list, the fileset header or the device configuration. + * the initial inode list, the fileset header or the device configuration. */ struct vxfs_olt { u_int32_t olt_magic; /* magic number */ diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index b5ed541fb137..34591ee804b5 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -144,7 +144,7 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, * * Description: * This does WB_SYNC_NONE opportunistic writeback. The IO is only - * started when this function returns, we make no guarentees on + * started when this function returns, we make no guarantees on * completion. Caller need not hold sb s_umount semaphore. * */ diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6ea00734984e..82a66466a24c 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -523,7 +523,7 @@ static int fuse_readpage(struct file *file, struct page *page) goto out; /* - * Page writeback can extend beyond the liftime of the + * Page writeback can extend beyond the lifetime of the * page-cache page, so make sure we read a properly synced * page. */ diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index ef3dc4b9fae2..74add2ddcc3f 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1136,7 +1136,7 @@ void gfs2_trim_blocks(struct inode *inode) * earlier versions of GFS2 have a bug in the stuffed file reading * code which will result in a buffer overrun if the size is larger * than the max stuffed file size. In order to prevent this from - * occuring, such files are unstuffed, but in other cases we can + * occurring, such files are unstuffed, but in other cases we can * just update the inode size directly. * * Returns: 0 on success, or -ve on error diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index e2431313491f..f07643e21bfa 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1123,7 +1123,7 @@ void gfs2_glock_dq_uninit(struct gfs2_holder *gh) * @number: the lock number * @glops: the glock operations for the type of glock * @state: the state to acquire the glock in - * @flags: modifier flags for the aquisition + * @flags: modifier flags for the acquisition * @gh: the struct gfs2_holder * * Returns: errno diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index ec73ed70bae1..a4e23d68a398 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -657,7 +657,7 @@ out: * @sdp: the file system * * This function flushes data and meta data for all machines by - * aquiring the transaction log exclusively. All journals are + * acquiring the transaction log exclusively. All journals are * ensured to be in a clean state as well. * * Returns: errno diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index da871ee084d3..69b180459463 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -362,7 +362,7 @@ void journal_commit_transaction(journal_t *journal) * we do not require it to remember exactly which old buffers it * has reserved. This is consistent with the existing behaviour * that multiple journal_get_write_access() calls to the same - * buffer are perfectly permissable. + * buffer are perfectly permissible. */ while (commit_transaction->t_reserved_list) { jh = commit_transaction->t_reserved_list; diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index eb11601f2e00..b3713afaaa9e 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -770,7 +770,7 @@ journal_t * journal_init_dev(struct block_device *bdev, journal->j_wbufsize = n; journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { - printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", + printk(KERN_ERR "%s: Can't allocate bhs for commit thread\n", __func__); goto out_err; } @@ -831,7 +831,7 @@ journal_t * journal_init_inode (struct inode *inode) journal->j_wbufsize = n; journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { - printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", + printk(KERN_ERR "%s: Can't allocate bhs for commit thread\n", __func__); goto out_err; } diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index d29018307e2e..305a90763154 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c @@ -71,7 +71,7 @@ * switching hash tables under them. For operations on the lists of entries in * the hash table j_revoke_lock is used. * - * Finally, also replay code uses the hash tables but at this moment noone else + * Finally, also replay code uses the hash tables but at this moment no one else * can touch them (filesystem isn't mounted yet) and hence no locking is * needed. */ diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 5b2e4c30a2a1..60d2319651b2 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1392,7 +1392,7 @@ int journal_stop(handle_t *handle) * by 30x or more... * * We try and optimize the sleep time against what the underlying disk - * can do, instead of having a static sleep time. This is usefull for + * can do, instead of having a static sleep time. This is useful for * the case where our storage is so fast that it is more optimal to go * ahead and force a flush and wait for the transaction to be committed * than it is to wait for an arbitrary amount of time for new writers to diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index fa36d7662b21..20af62f4304b 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -403,7 +403,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) * we do not require it to remember exactly which old buffers it * has reserved. This is consistent with the existing behaviour * that multiple jbd2_journal_get_write_access() calls to the same - * buffer are perfectly permissable. + * buffer are perfectly permissible. */ while (commit_transaction->t_reserved_list) { jh = commit_transaction->t_reserved_list; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 90407b8fece7..aba8ebaec25c 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -917,7 +917,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, journal->j_wbufsize = n; journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { - printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", + printk(KERN_ERR "%s: Can't allocate bhs for commit thread\n", __func__); goto out_err; } @@ -983,7 +983,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) journal->j_wbufsize = n; journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { - printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", + printk(KERN_ERR "%s: Can't allocate bhs for commit thread\n", __func__); goto out_err; } diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 9ad321fd63fd..69fd93588118 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c @@ -71,7 +71,7 @@ * switching hash tables under them. For operations on the lists of entries in * the hash table j_revoke_lock is used. * - * Finally, also replay code uses the hash tables but at this moment noone else + * Finally, also replay code uses the hash tables but at this moment no one else * can touch them (filesystem isn't mounted yet) and hence no locking is * needed. */ diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 1d1191050f99..05fa77a23711 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1403,7 +1403,7 @@ int jbd2_journal_stop(handle_t *handle) /* * Once we drop t_updates, if it goes to zero the transaction - * could start commiting on us and eventually disappear. So + * could start committing on us and eventually disappear. So * once we do this, we must not dereference transaction * pointer again. */ diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO index 5d3ea4070f01..ca28964abd4b 100644 --- a/fs/jffs2/TODO +++ b/fs/jffs2/TODO @@ -11,7 +11,7 @@ - checkpointing (do we need this? scan is quite fast) - make the scan code populate real inodes so read_inode just after mount doesn't have to read the flash twice for large files. - Make this a per-inode option, changable with chattr, so you can + Make this a per-inode option, changeable with chattr, so you can decide which inodes should be in-core immediately after mount. - test, test, test diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index d32ee9412cb9..2ab1a0d91210 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -24,7 +24,7 @@ * * Returns: 0 if the data CRC is correct; * 1 - if incorrect; - * error code if an error occured. + * error code if an error occurred. */ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) { diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 800171dca53b..e537fb0e0184 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -121,7 +121,7 @@ int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, temp->nodetype = ri->nodetype; temp->inode = ri->ino; temp->version = ri->version; - temp->offset = cpu_to_je32(ofs); /* relative offset from the begining of the jeb */ + temp->offset = cpu_to_je32(ofs); /* relative offset from the beginning of the jeb */ temp->totlen = ri->totlen; temp->next = NULL; @@ -139,7 +139,7 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r temp->nodetype = rd->nodetype; temp->totlen = rd->totlen; - temp->offset = cpu_to_je32(ofs); /* relative from the begining of the jeb */ + temp->offset = cpu_to_je32(ofs); /* relative from the beginning of the jeb */ temp->pino = rd->pino; temp->version = rd->version; temp->ino = rd->ino; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 07ee1546b2fa..4515bea0268f 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1116,7 +1116,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, /* * On NAND we try to mark this block bad. If the block was erased more - * than MAX_ERASE_FAILURES we mark it finaly bad. + * than MAX_ERASE_FAILURES we mark it finally bad. * Don't care about failures. This block remains on the erase-pending * or badblock list as long as nobody manipulates the flash with * a bootloader or something like that. diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index c92ea3b3ea5e..4496872cf4e7 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -1649,7 +1649,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno) } /* search the tree within the dmap control page for - * sufficent free space. if sufficient free space is found, + * sufficient free space. if sufficient free space is found, * dbFindLeaf() returns the index of the leaf at which * free space was found. */ @@ -2744,7 +2744,7 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval) /* check which (leafno or buddy) is the left buddy. * the left buddy gets to claim the blocks resulting * from the join while the right gets to claim none. - * the left buddy is also eligable to participate in + * the left buddy is also eligible to participate in * a join at the next higher level while the right * is not. * diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c index 5d3bbd10f8db..e5fe8506ed16 100644 --- a/fs/jfs/jfs_extent.c +++ b/fs/jfs/jfs_extent.c @@ -126,7 +126,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) /* allocate the disk blocks for the extent. initially, extBalloc() * will try to allocate disk blocks for the requested size (xlen). - * if this fails (xlen contiguous free blocks not avaliable), it'll + * if this fails (xlen contiguous free blocks not available), it'll * try to allocate a smaller number of blocks (producing a smaller * extent), with this smaller number of blocks consisting of the * requested number of blocks rounded down to the next smaller @@ -481,7 +481,7 @@ int extFill(struct inode *ip, xad_t * xp) * * initially, we will try to allocate disk blocks for the * requested size (nblocks). if this fails (nblocks - * contiguous free blocks not avaliable), we'll try to allocate + * contiguous free blocks not available), we'll try to allocate * a smaller number of blocks (producing a smaller extent), with * this smaller number of blocks consisting of the requested * number of blocks rounded down to the next smaller power of 2 @@ -575,7 +575,7 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) * to a new set of blocks. If moving the extent, we initially * will try to allocate disk blocks for the requested size * (newnblks). if this fails (new contiguous free blocks not - * avaliable), we'll try to allocate a smaller number of + * available), we'll try to allocate a smaller number of * blocks (producing a smaller extent), with this smaller * number of blocks consisting of the requested number of * blocks rounded down to the next smaller power of 2 diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 3a09423b6c22..ed53a4740168 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -1069,7 +1069,7 @@ int diFree(struct inode *ip) */ if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) { /* in preparation for removing the iag from the - * ag extent free list, read the iags preceeding + * ag extent free list, read the iags preceding * and following the iag on the ag extent free * list. */ @@ -1095,7 +1095,7 @@ int diFree(struct inode *ip) int inofreefwd = le32_to_cpu(iagp->inofreefwd); /* in preparation for removing the iag from the - * ag inode free list, read the iags preceeding + * ag inode free list, read the iags preceding * and following the iag on the ag inode free * list. before reading these iags, we must make * sure that we already don't have them in hand @@ -1681,7 +1681,7 @@ diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip) * try to allocate a new extent of free inodes. */ if (addext) { - /* if free space is not avaliable for this new extent, try + /* if free space is not available for this new extent, try * below to allocate a free and existing (already backed) * inode from the ag. */ @@ -2036,7 +2036,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) /* check if this is the last free inode within the iag. * if so, it will have to be removed from the ag free - * inode list, so get the iags preceeding and following + * inode list, so get the iags preceding and following * it on the list. */ if (iagp->nfreeinos == cpu_to_le32(1)) { @@ -2208,7 +2208,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) /* check if this is the last free extent within the * iag. if so, the iag must be removed from the ag - * free extent list, so get the iags preceeding and + * free extent list, so get the iags preceding and * following the iag on this list. */ if (iagp->nfreeexts == cpu_to_le32(1)) { @@ -2504,7 +2504,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) } - /* get the next avaliable iag number */ + /* get the next available iag number */ iagno = imap->im_nextiag; /* make sure that we have not exceeded the maximum inode @@ -2615,7 +2615,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) duplicateIXtree(sb, blkno, xlen, &xaddr); - /* update the next avaliable iag number */ + /* update the next available iag number */ imap->im_nextiag += 1; /* Add the iag to the iag free list so we don't lose the iag diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h index 9236bc49ae7f..e38c21598850 100644 --- a/fs/jfs/jfs_logmgr.h +++ b/fs/jfs/jfs_logmgr.h @@ -288,7 +288,7 @@ struct lrd { /* * SYNCPT: log sync point * - * replay log upto syncpt address specified; + * replay log up to syncpt address specified; */ struct { __le32 sync; /* 4: syncpt address (0 = here) */ diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h index d94f8d9e87d7..a78beda85f68 100644 --- a/fs/jfs/jfs_metapage.h +++ b/fs/jfs/jfs_metapage.h @@ -75,7 +75,7 @@ extern void grab_metapage(struct metapage *); extern void force_metapage(struct metapage *); /* - * hold_metapage and put_metapage are used in conjuction. The page lock + * hold_metapage and put_metapage are used in conjunction. The page lock * is not dropped between the two, so no other threads can get or release * the metapage */ diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 9466957ec841..f6cc0c09ec63 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -636,7 +636,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, * the inode of the page and available to all anonymous * transactions until txCommit() time at which point * they are transferred to the transaction tlock list of - * the commiting transaction of the inode) + * the committing transaction of the inode) */ if (xtid == 0) { tlck->tid = tid; diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 1aba0039f1c9..8ea5efb5a34e 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c @@ -57,7 +57,7 @@ * 2. compute new FSCKSize from new LVSize; * 3. set new FSSize as MIN(FSSize, LVSize-(LogSize+FSCKSize)) where * assert(new FSSize >= old FSSize), - * i.e., file system must not be shrinked; + * i.e., file system must not be shrunk; */ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) { @@ -182,7 +182,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) */ newFSSize = newLVSize - newLogSize - newFSCKSize; - /* file system cannot be shrinked */ + /* file system cannot be shrunk */ if (newFSSize < bmp->db_mapsize) { rc = -EINVAL; goto out; diff --git a/fs/jfs/super.c b/fs/jfs/super.c index eeca48a031ab..06c8a67cbe76 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -644,7 +644,7 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code - * itself serializes the operations (and noone else should touch the files) + * itself serializes the operations (and no one else should touch the files) * we don't have to be afraid of races */ static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off) diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index 7466e9dcc8c5..339e17e9133d 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -60,7 +60,7 @@ static int mtd_write(struct super_block *sb, loff_t ofs, size_t len, void *buf) * asynchronous properties. So just to prevent the first implementor of such * a thing from breaking logfs in 2350, we do the usual pointless dance to * declare a completion variable and wait for completion before returning - * from mtd_erase(). What an excercise in futility! + * from mtd_erase(). What an exercise in futility! */ static void logfs_erase_callback(struct erase_info *ei) { diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index f9ddf0c388c8..9ed89d1663f8 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -92,7 +92,7 @@ static int beyond_eof(struct inode *inode, loff_t bix) * so short names (len <= 9) don't even occupy the complete 32bit name * space. A prime >256 ensures short names quickly spread the 32bit * name space. Add about 26 for the estimated amount of information - * of each character and pick a prime nearby, preferrably a bit-sparse + * of each character and pick a prime nearby, preferably a bit-sparse * one. */ static u32 hash_32(const char *s, int len, u32 seed) diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index ee99a9f5dfd3..9e22085231b3 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -1616,7 +1616,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, err = logfs_write_buf(inode, page, flags); if (!err && shrink_level(gc_level) == 0) { /* Rewrite cannot mark the inode dirty but has to - * write it immediatly. + * write it immediately. * Q: Can't we just create an alias for the inode * instead? And if not, why not? */ diff --git a/fs/mbcache.c b/fs/mbcache.c index a25444ab2baf..2f174be06555 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -542,7 +542,7 @@ __mb_cache_entry_find(struct list_head *l, struct list_head *head, * mb_cache_entry_find_first() * * Find the first cache entry on a given device with a certain key in - * an additional index. Additonal matches can be found with + * an additional index. Additional matches can be found with * mb_cache_entry_find_next(). Returns NULL if no match was found. The * returned cache entry is locked for shared access ("multiple readers"). * diff --git a/fs/namei.c b/fs/namei.c index 3cb616d38d9c..e6cd6113872c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -70,7 +70,7 @@ * name indicated by the symlink. The old code always complained that the * name already exists, due to not following the symlink even if its target * is nonexistent. The new semantics affects also mknod() and link() when - * the name is a symlink pointing to a non-existant name. + * the name is a symlink pointing to a non-existent name. * * I don't know which semantics is the right one, since I have no access * to standards. But I found by trial that HP-UX 9.0 has the full "new" diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 00a1d1c3d3a4..0250e4ce4893 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -596,7 +596,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) /* server->priv.data = NULL; */ server->m = data; - /* Althought anything producing this is buggy, it happens + /* Although anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 1) { server->m.time_out = 10; diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 14e0f9371d14..00ecf62ce7c1 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -241,7 +241,7 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp, args->cbl_layout_type = ntohl(*p++); /* Depite the spec's xdr, iomode really belongs in the FILE switch, - * as it is unuseable and ignored with the other types. + * as it is unusable and ignored with the other types. */ iomode = ntohl(*p++); args->cbl_layoutchanged = ntohl(*p++); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 3ac5bd695e5e..2f093ed16980 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -301,7 +301,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) * disk, but it retrieves and clears ctx->error after synching, despite * the two being set at the same time in nfs_context_set_write_error(). * This is because the former is used to notify the _next_ call to - * nfs_file_write() that a write error occured, and hence cause it to + * nfs_file_write() that a write error occurred, and hence cause it to * fall back to doing a synchronous write. */ static int diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 085a354e0f08..7c44579f5832 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h @@ -33,7 +33,7 @@ #include "pnfs.h" /* - * Field testing shows we need to support upto 4096 stripe indices. + * Field testing shows we need to support up to 4096 stripe indices. * We store each index as a u8 (u32 on the wire) to keep the memory footprint * reasonable. This in turn means we support a maximum of 256 * RFC 5661 multipath_list4 structures. diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index ec0f277be7f5..6940439bd609 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -173,7 +173,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) return -EINVAL; break; case ACL_MASK: - /* Solaris sometimes sets additonal bits in the mask */ + /* Solaris sometimes sets additional bits in the mask */ entry->e_perm &= S_IRWXO; break; default: diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 7e84a852cdae..ad48faca20fc 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -702,7 +702,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p, *p++ = htonl(resp->eof); *p++ = htonl(resp->count); /* xdr opaque count */ xdr_ressize_check(rqstp, p); - /* now update rqstp->rq_res to reflect data aswell */ + /* now update rqstp->rq_res to reflect data as well */ rqstp->rq_res.page_len = resp->count; if (resp->count & 3) { /* need to pad the tail */ diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fbde6f79922e..4b36ec3eb8ea 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3055,7 +3055,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) if (ONE_STATEID(stateid) && (flags & RD_STATE)) return nfs_ok; else if (locks_in_grace()) { - /* Answer in remaining cases depends on existance of + /* Answer in remaining cases depends on existence of * conflicting state; so we must wait out the grace period. */ return nfserr_grace; } else if (flags & WR_STATE) @@ -3675,7 +3675,7 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid, /* * Alloc a lock owner structure. * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has - * occured. + * occurred. * * strhashval = lock_ownerstr_hashval */ diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 4ce005dbf3e6..65ec595e2226 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -451,7 +451,7 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p, *p++ = htonl(resp->count); xdr_ressize_check(rqstp, p); - /* now update rqstp->rq_res to reflect data aswell */ + /* now update rqstp->rq_res to reflect data as well */ rqstp->rq_res.page_len = resp->count; if (resp->count & 3) { /* need to pad the tail */ diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 6b1305dc26c0..9fde1c00a296 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -164,7 +164,7 @@ static int process_access_response(struct fsnotify_group *group, fd, response); /* * make sure the response is valid, if invalid we do nothing and either - * userspace can send a valid responce or we will clean it up after the + * userspace can send a valid response or we will clean it up after the * timeout */ switch (response) { diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index a91b69a6a291..7400898c0339 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -194,7 +194,7 @@ static int idr_callback(int id, void *p, void *data) static void inotify_free_group_priv(struct fsnotify_group *group) { - /* ideally the idr is empty and we won't hit the BUG in teh callback */ + /* ideally the idr is empty and we won't hit the BUG in the callback */ idr_for_each(&group->inotify_data.idr, idr_callback, group); idr_remove_all(&group->inotify_data.idr); idr_destroy(&group->inotify_data.idr); diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 50c00856f730..252ab1f6452b 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -24,7 +24,7 @@ * referencing this object. The object typically will live inside the kernel * with a refcnt of 2, one for each list it is on (i_list, g_list). Any task * which can find this object holding the appropriete locks, can take a reference - * and the object itself is guarenteed to survive until the reference is dropped. + * and the object itself is guaranteed to survive until the reference is dropped. * * LOCKING: * There are 3 spinlocks involved with fsnotify inode marks and they MUST diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index f5094ee224c1..f14fde2b03d6 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -197,7 +197,7 @@ err_out: } else if (ctx_needs_reset) { /* * If there is no attribute list, restoring the search context - * is acomplished simply by copying the saved context back over + * is accomplished simply by copying the saved context back over * the caller supplied context. If there is an attribute list, * things are more complicated as we need to deal with mapping * of mft records and resulting potential changes in pointers. @@ -1181,7 +1181,7 @@ not_found: * for, i.e. if one wants to add the attribute to the mft record this is the * correct place to insert its attribute list entry into. * - * When -errno != -ENOENT, an error occured during the lookup. @ctx->attr is + * When -errno != -ENOENT, an error occurred during the lookup. @ctx->attr is * then undefined and in particular you should not rely on it not changing. */ int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index ef9ed854255c..ee4144ce5d7c 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -501,7 +501,7 @@ int ntfs_read_compressed_block(struct page *page) VCN start_vcn = (((s64)index << PAGE_CACHE_SHIFT) & ~cb_size_mask) >> vol->cluster_size_bits; /* - * The first vcn after the last wanted vcn (minumum alignment is again + * The first vcn after the last wanted vcn (minimum alignment is again * PAGE_CACHE_SIZE. */ VCN end_vcn = ((((s64)(index + 1UL) << PAGE_CACHE_SHIFT) + cb_size - 1) diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 0b56c6b7ec01..c05d6dcf77a4 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -622,7 +622,7 @@ static int ntfs_read_locked_inode(struct inode *vi) */ /* Everyone gets all permissions. */ vi->i_mode |= S_IRWXUGO; - /* If read-only, noone gets write permissions. */ + /* If read-only, no one gets write permissions. */ if (IS_RDONLY(vi)) vi->i_mode &= ~S_IWUGO; if (m->flags & MFT_RECORD_IS_DIRECTORY) { @@ -2529,7 +2529,7 @@ retry_truncate: * specifies that the behaviour is unspecified thus we do not * have to do anything. This means that in our implementation * in the rare case that the file is mmap()ped and a write - * occured into the mmap()ped region just beyond the file size + * occurred into the mmap()ped region just beyond the file size * and writepage has not yet been called to write out the page * (which would clear the area beyond the file size) and we now * extend the file size to incorporate this dirty region diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 8b2549f672bf..faece7190866 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -286,7 +286,7 @@ typedef le16 MFT_RECORD_FLAGS; * fragmented. Volume free space includes the empty part of the mft zone and * when the volume's free 88% are used up, the mft zone is shrunk by a factor * of 2, thus making more space available for more files/data. This process is - * repeated everytime there is no more free space except for the mft zone until + * repeated every time there is no more free space except for the mft zone until * there really is no more free space. */ @@ -1657,13 +1657,13 @@ typedef enum { * pointed to by the Owner field was provided by a defaulting mechanism * rather than explicitly provided by the original provider of the * security descriptor. This may affect the treatment of the SID with - * respect to inheritence of an owner. + * respect to inheritance of an owner. * * SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the SID in * the Group field was provided by a defaulting mechanism rather than * explicitly provided by the original provider of the security * descriptor. This may affect the treatment of the SID with respect to - * inheritence of a primary group. + * inheritance of a primary group. * * SE_DACL_PRESENT - This boolean flag, when set, indicates that the security * descriptor contains a discretionary ACL. If this flag is set and the @@ -1674,7 +1674,7 @@ typedef enum { * pointed to by the Dacl field was provided by a defaulting mechanism * rather than explicitly provided by the original provider of the * security descriptor. This may affect the treatment of the ACL with - * respect to inheritence of an ACL. This flag is ignored if the + * respect to inheritance of an ACL. This flag is ignored if the * DaclPresent flag is not set. * * SE_SACL_PRESENT - This boolean flag, when set, indicates that the security @@ -1686,7 +1686,7 @@ typedef enum { * pointed to by the Sacl field was provided by a defaulting mechanism * rather than explicitly provided by the original provider of the * security descriptor. This may affect the treatment of the ACL with - * respect to inheritence of an ACL. This flag is ignored if the + * respect to inheritance of an ACL. This flag is ignored if the * SaclPresent flag is not set. * * SE_SELF_RELATIVE - This boolean flag, when set, indicates that the security @@ -2283,7 +2283,7 @@ typedef struct { // the key_length is zero, then the vcn immediately // follows the INDEX_ENTRY_HEADER. Regardless of // key_length, the address of the 8-byte boundary - // alligned vcn of INDEX_ENTRY{_HEADER} *ie is given by + // aligned vcn of INDEX_ENTRY{_HEADER} *ie is given by // (char*)ie + le16_to_cpu(ie*)->length) - sizeof(VCN), // where sizeof(VCN) can be hardcoded as 8 if wanted. */ } __attribute__ ((__packed__)) INDEX_ENTRY; diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 4dadcdf3d451..c71de292c5ad 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c @@ -669,7 +669,7 @@ err_out: * of cases where we think that a volume is dirty when in fact it is clean. * This should only affect volumes that have not been shutdown cleanly but did * not have any pending, non-check-pointed i/o, i.e. they were completely idle - * at least for the five seconds preceeding the unclean shutdown. + * at least for the five seconds preceding the unclean shutdown. * * This function assumes that the $LogFile journal has already been consistency * checked by a call to ntfs_check_logfile() and in particular if the $LogFile diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h index b5a6f08bd35c..aa2b6ac3f0a4 100644 --- a/fs/ntfs/logfile.h +++ b/fs/ntfs/logfile.h @@ -222,7 +222,7 @@ typedef struct { /* 24*/ sle64 file_size; /* Usable byte size of the log file. If the restart_area_offset + the offset of the file_size are > 510 then corruption has - occured. This is the very first check when + occurred. This is the very first check when starting with the restart_area as if it fails it means that some of the above values will be corrupted by the multi sector diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 326e7475a22a..382857f9c7db 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -73,7 +73,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) if (index > end_index || (i_size & ~PAGE_CACHE_MASK) < ofs + vol->mft_record_size) { page = ERR_PTR(-ENOENT); - ntfs_error(vol->sb, "Attemt to read mft record 0x%lx, " + ntfs_error(vol->sb, "Attempt to read mft record 0x%lx, " "which is beyond the end of the mft. " "This is probably a bug in the ntfs " "driver.", ni->mft_no); @@ -1442,7 +1442,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) // Note: It will need to be a special mft record and if none of // those are available it gets rather complicated... ntfs_error(vol->sb, "Not enough space in this mft record to " - "accomodate extended mft bitmap attribute " + "accommodate extended mft bitmap attribute " "extent. Cannot handle this yet."); ret = -EOPNOTSUPP; goto undo_alloc; @@ -1879,7 +1879,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) // and we would then need to update all references to this mft // record appropriately. This is rather complicated... ntfs_error(vol->sb, "Not enough space in this mft record to " - "accomodate extended mft data attribute " + "accommodate extended mft data attribute " "extent. Cannot handle this yet."); ret = -EOPNOTSUPP; goto undo_alloc; @@ -2357,7 +2357,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, } #ifdef DEBUG read_lock_irqsave(&mftbmp_ni->size_lock, flags); - ntfs_debug("Status of mftbmp after initialized extention: " + ntfs_debug("Status of mftbmp after initialized extension: " "allocated_size 0x%llx, data_size 0x%llx, " "initialized_size 0x%llx.", (long long)mftbmp_ni->allocated_size, diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 56a9a6d25a2a..eac7d6788a10 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -1243,7 +1243,7 @@ err_out: * write. * * This is used when building the mapping pairs array of a runlist to compress - * a given logical cluster number (lcn) or a specific run length to the minumum + * a given logical cluster number (lcn) or a specific run length to the minimum * size possible. * * Return the number of bytes written on success. On error, i.e. the diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 29099a07b9fe..b52706da4645 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -458,7 +458,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) * the volume on boot and updates them. * * When remounting read-only, mark the volume clean if no volume errors - * have occured. + * have occurred. */ if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { static const char *es = ". Cannot remount read-write."; @@ -1269,7 +1269,7 @@ static int check_windows_hibernation_status(ntfs_volume *vol) "hibernated on the volume."); return 0; } - /* A real error occured. */ + /* A real error occurred. */ ntfs_error(vol->sb, "Failed to find inode number for " "hiberfil.sys."); return ret; @@ -1370,7 +1370,7 @@ static bool load_and_init_quota(ntfs_volume *vol) NVolSetQuotaOutOfDate(vol); return true; } - /* A real error occured. */ + /* A real error occurred. */ ntfs_error(vol->sb, "Failed to find inode number for $Quota."); return false; } @@ -1454,7 +1454,7 @@ not_enabled: NVolSetUsnJrnlStamped(vol); return true; } - /* A real error occured. */ + /* A real error occurred. */ ntfs_error(vol->sb, "Failed to find inode number for " "$UsnJrnl."); return false; @@ -2292,7 +2292,7 @@ static void ntfs_put_super(struct super_block *sb) ntfs_commit_inode(vol->mft_ino); /* - * If a read-write mount and no volume errors have occured, mark the + * If a read-write mount and no volume errors have occurred, mark the * volume clean. Also, re-commit all affected inodes. */ if (!(sb->s_flags & MS_RDONLY)) { @@ -2496,7 +2496,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) if (vol->nr_clusters & 63) nr_free += 64 - (vol->nr_clusters & 63); up_read(&vol->lcnbmp_lock); - /* If errors occured we may well have gone below zero, fix this. */ + /* If errors occurred we may well have gone below zero, fix this. */ if (nr_free < 0) nr_free = 0; ntfs_debug("Exiting."); @@ -2561,7 +2561,7 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, } ntfs_debug("Finished reading $MFT/$BITMAP, last index = 0x%lx.", index - 1); - /* If errors occured we may well have gone below zero, fix this. */ + /* If errors occurred we may well have gone below zero, fix this. */ if (nr_free < 0) nr_free = 0; ntfs_debug("Exiting."); diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index b27a0d86f8c5..48aa9c7401c7 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -4519,7 +4519,7 @@ set_tail_append: } /* - * Helper function called at the begining of an insert. + * Helper function called at the beginning of an insert. * * This computes a few things that are commonly used in the process of * inserting into the btree: diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index eceb456037c1..75cf3ad987a6 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h @@ -71,7 +71,7 @@ static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level) /* * Using a named enum representing lock types in terms of #N bit stored in - * iocb->private, which is going to be used for communication bewteen + * iocb->private, which is going to be used for communication between * ocfs2_dio_end_io() and ocfs2_file_aio_write/read(). */ enum ocfs2_iocb_lock_bits { diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 2461eb3272ed..643720209a98 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -2275,7 +2275,7 @@ void o2hb_free_hb_set(struct config_group *group) kfree(hs); } -/* hb callback registration and issueing */ +/* hb callback registration and issuing */ static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type) { diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c index a87366750f23..8f9cea1597af 100644 --- a/fs/ocfs2/cluster/quorum.c +++ b/fs/ocfs2/cluster/quorum.c @@ -89,7 +89,7 @@ static void o2quo_fence_self(void) }; } -/* Indicate that a timeout occured on a hearbeat region write. The +/* Indicate that a timeout occurred on a hearbeat region write. The * other nodes in the cluster may consider us dead at that time so we * want to "fence" ourselves so that we don't scribble on the disk * after they think they've recovered us. This can't solve all @@ -261,7 +261,7 @@ void o2quo_hb_still_up(u8 node) spin_unlock(&qs->qs_lock); } -/* This is analagous to hb_up. as a node's connection comes up we delay the +/* This is analogous to hb_up. as a node's connection comes up we delay the * quorum decision until we see it heartbeating. the hold will be droped in * hb_up or hb_down. it might be perpetuated by con_err until hb_down. if * it's already heartbeating we we might be dropping a hold that conn_up got. diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index ee04ff5ee603..db5ee4b4f47a 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -565,7 +565,7 @@ static void o2net_set_nn_state(struct o2net_node *nn, * the work queue actually being up. */ if (!valid && o2net_wq) { unsigned long delay; - /* delay if we're withing a RECONNECT_DELAY of the + /* delay if we're within a RECONNECT_DELAY of the * last attempt */ delay = (nn->nn_last_connect_attempt + msecs_to_jiffies(o2net_reconnect_delay())) diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 9d67610dfc74..fede57ed005f 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -808,7 +808,7 @@ lookup: dlm_mle_detach_hb_events(dlm, mle); dlm_put_mle(mle); mle = NULL; - /* this is lame, but we cant wait on either + /* this is lame, but we can't wait on either * the mle or lockres waitqueue here */ if (mig) msleep(100); @@ -843,7 +843,7 @@ lookup: /* finally add the lockres to its hash bucket */ __dlm_insert_lockres(dlm, res); - /* since this lockres is new it doesnt not require the spinlock */ + /* since this lockres is new it doesn't not require the spinlock */ dlm_lockres_grab_inflight_ref_new(dlm, res); /* if this node does not become the master make sure to drop diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 177d3a6c2a5f..b4c8bb6b8d28 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -835,7 +835,7 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) /* If we have allowd wipe of this inode for another node, it * will be marked here so we can safely skip it. Recovery will - * cleanup any inodes we might inadvertantly skip here. */ + * cleanup any inodes we might inadvertently skip here. */ if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) goto bail_unlock; @@ -917,7 +917,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, * the inode open lock in ocfs2_read_locked_inode(). When we * get to ->delete_inode(), each node tries to convert it's * lock to an exclusive. Trylocks are serialized by the inode - * meta data lock. If the upconvert suceeds, we know the inode + * meta data lock. If the upconvert succeeds, we know the inode * is no longer live and can be deleted. * * Though we call this with the meta data lock held, the diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index dcc2d9327150..b141a44605ca 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1368,7 +1368,7 @@ skip_recovery: mlog_errno(status); /* Now it is right time to recover quotas... We have to do this under - * superblock lock so that noone can start using the slot (and crash) + * superblock lock so that no one can start using the slot (and crash) * before we recover it */ for (i = 0; i < rm_quota_used; i++) { qrec = ocfs2_begin_quota_recovery(osb, rm_quota[i]); diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 6180da1e37e6..68cf2f6d3c6a 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -215,7 +215,7 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) /* WARNING: This only kicks off a single * checkpoint. If someone races you and adds more * metadata to the journal, you won't know, and will - * wind up waiting *alot* longer than necessary. Right + * wind up waiting *a lot* longer than necessary. Right * now we only use this in clear_inode so that's * OK. */ ocfs2_start_checkpoint(osb); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 28f2cc1080d8..e5d738cd9cc0 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -2128,7 +2128,7 @@ leave: } /** - * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to recieve a newly + * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to receive a newly * allocated file. This is different from the typical 'add to orphan dir' * operation in that the inode does not yet exist. This is a problem because * the orphan dir stringifies the inode block number to come up with it's diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index bf2e7764920e..b68f87a83924 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -441,7 +441,7 @@ static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = { struct ocfs2_block_check { /*00*/ __le32 bc_crc32e; /* 802.3 Ethernet II CRC32 */ __le16 bc_ecc; /* Single-error-correction parity vector. - This is a simple Hamming code dependant + This is a simple Hamming code dependent on the blocksize. OCFS2's maximum blocksize, 4K, requires 16 parity bits, so we fit in __le16. */ @@ -750,7 +750,7 @@ struct ocfs2_dinode { after an unclean shutdown */ } journal1; - } id1; /* Inode type dependant 1 */ + } id1; /* Inode type dependent 1 */ /*C0*/ union { struct ocfs2_super_block i_super; struct ocfs2_local_alloc i_lab; diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 279aef68025b..92fcd575775a 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -556,7 +556,7 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing) spin_unlock(&dq_data_lock); err = ocfs2_qinfo_lock(info, freeing); if (err < 0) { - mlog(ML_ERROR, "Failed to lock quota info, loosing quota write" + mlog(ML_ERROR, "Failed to lock quota info, losing quota write" " (type=%d, id=%u)\n", dquot->dq_type, (unsigned)dquot->dq_id); goto out; diff --git a/fs/ocfs2/reservations.h b/fs/ocfs2/reservations.h index 1e49cc29d06c..42c2b804f3fd 100644 --- a/fs/ocfs2/reservations.h +++ b/fs/ocfs2/reservations.h @@ -29,7 +29,7 @@ struct ocfs2_alloc_reservation { struct rb_node r_node; - unsigned int r_start; /* Begining of current window */ + unsigned int r_start; /* Beginning of current window */ unsigned int r_len; /* Length of the window */ unsigned int r_last_len; /* Length of most recent alloc */ diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h index 8ce7398ae1d2..1ec56fdb8d0d 100644 --- a/fs/ocfs2/stackglue.h +++ b/fs/ocfs2/stackglue.h @@ -126,7 +126,7 @@ struct ocfs2_stack_operations { * * ->connect() must not return until it is guaranteed that * - * - Node down notifications for the filesystem will be recieved + * - Node down notifications for the filesystem will be received * and passed to conn->cc_recovery_handler(). * - Locking requests for the filesystem will be processed. */ diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index ab6e2061074f..ba5d97e4a73e 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -1511,7 +1511,7 @@ static int ocfs2_cluster_group_search(struct inode *inode, max_bits = le16_to_cpu(gd->bg_bits); /* Tail groups in cluster bitmaps which aren't cpg - * aligned are prone to partial extention by a failed + * aligned are prone to partial extension by a failed * fs resize. If the file system resize never got to * update the dinode cluster count, then we don't want * to trust any clusters past it, regardless of what @@ -2459,7 +2459,7 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, /* The alloc_bh comes from ocfs2_free_dinode() or * ocfs2_free_clusters(). The callers have all locked the * allocator and gotten alloc_bh from the lock call. This - * validates the dinode buffer. Any corruption that has happended + * validates the dinode buffer. Any corruption that has happened * is a code bug. */ BUG_ON(!OCFS2_IS_VALID_DINODE(fe)); BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl)); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 69fa11b35aa4..5a521c748859 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -78,7 +78,7 @@ static struct kmem_cache *ocfs2_inode_cachep = NULL; struct kmem_cache *ocfs2_dquot_cachep; struct kmem_cache *ocfs2_qf_chunk_cachep; -/* OCFS2 needs to schedule several differnt types of work which +/* OCFS2 needs to schedule several different types of work which * require cluster locking, disk I/O, recovery waits, etc. Since these * types of work tend to be heavy we avoid using the kernel events * workqueue and schedule on our own. */ diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 57a215dc2d9b..81ecf9c0bf0a 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -3554,7 +3554,7 @@ int ocfs2_xattr_set(struct inode *inode, down_write(&OCFS2_I(inode)->ip_xattr_sem); /* * Scan inode and external block to find the same name - * extended attribute and collect search infomation. + * extended attribute and collect search information. */ ret = ocfs2_xattr_ibody_find(inode, name_index, name, &xis); if (ret) @@ -3578,7 +3578,7 @@ int ocfs2_xattr_set(struct inode *inode, goto cleanup; } - /* Check whether the value is refcounted and do some prepartion. */ + /* Check whether the value is refcounted and do some preparation. */ if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL && (!xis.not_found || !xbs.not_found)) { ret = ocfs2_prepare_refcount_xattr(inode, di, &xi, diff --git a/fs/partitions/check.c b/fs/partitions/check.c index ac546975031f..d545e97d99c3 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -500,7 +500,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, /* everything is up and running, commence */ rcu_assign_pointer(ptbl->part[partno], p); - /* suppress uevent if the disk supresses it */ + /* suppress uevent if the disk suppresses it */ if (!dev_get_uevent_suppress(ddev)) kobject_uevent(&pdev->kobj, KOBJ_ADD); @@ -585,7 +585,7 @@ rescan: /* * If any partition code tried to read beyond EOD, try * unlocking native capacity even if partition table is - * sucessfully read as we could be missing some partitions. + * successfully read as we could be missing some partitions. */ if (state->access_beyond_eod) { printk(KERN_WARNING diff --git a/fs/proc/base.c b/fs/proc/base.c index 5a670c11aeac..dd6628d3ba42 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -220,7 +220,7 @@ static struct mm_struct *__check_mem_permission(struct task_struct *task) } /* - * Noone else is allowed. + * No one else is allowed. */ mmput(mm); return ERR_PTR(-EPERM); diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 867d0ac026ce..8007ae7c0d8c 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -1,5 +1,5 @@ config PSTORE - bool "Persistant store support" + bool "Persistent store support" default n help This option enables generic access to platform level diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index fcc8ae75d874..a925bf205497 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -956,7 +956,7 @@ static inline int dqput_blocks(struct dquot *dquot) /* * Remove references to dquots from inode and add dquot to list for freeing - * if we have the last referece to dquot + * if we have the last reference to dquot * We can't race with anybody because we hold dqptr_sem for writing... */ static int remove_inode_dquot_ref(struct inode *inode, int type, diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index c77514bd5776..c5e82ece7c6c 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1,7 +1,7 @@ /* ** Write ahead logging implementation copyright Chris Mason 2000 ** -** The background commits make this code very interelated, and +** The background commits make this code very interrelated, and ** overly complex. I need to rethink things a bit....The major players: ** ** journal_begin -- call with the number of blocks you expect to log. @@ -2725,7 +2725,7 @@ int journal_init(struct super_block *sb, const char *j_dev_name, REISERFS_DISK_OFFSET_IN_BYTES / sb->s_blocksize + 2); - /* Sanity check to see is the standard journal fitting withing first bitmap + /* Sanity check to see is the standard journal fitting within first bitmap (actual for small blocksizes) */ if (!SB_ONDISK_JOURNAL_DEVICE(sb) && (SB_JOURNAL_1st_RESERVED_BLOCK(sb) + diff --git a/fs/reiserfs/lock.c b/fs/reiserfs/lock.c index b87aa2c1afc1..7df1ce48203a 100644 --- a/fs/reiserfs/lock.c +++ b/fs/reiserfs/lock.c @@ -15,7 +15,7 @@ * for this mutex, no need for a system wide mutex facility. * * Also this lock is often released before a call that could block because - * reiserfs performances were partialy based on the release while schedule() + * reiserfs performances were partially based on the release while schedule() * property of the Bkl. */ void reiserfs_write_lock(struct super_block *s) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 0aab04f46827..b216ff6be1c9 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -393,7 +393,7 @@ void add_save_link(struct reiserfs_transaction_handle *th, /* body of "save" link */ link = INODE_PKEY(inode)->k_dir_id; - /* put "save" link inot tree, don't charge quota to anyone */ + /* put "save" link into tree, don't charge quota to anyone */ retval = reiserfs_insert_item(th, &path, &key, &ih, NULL, (char *)&link); if (retval) { @@ -2104,7 +2104,7 @@ out: /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code - * itself serializes the operations (and noone else should touch the files) + * itself serializes the operations (and no one else should touch the files) * we don't have to be afraid of races */ static ssize_t reiserfs_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off) diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 5c11ca82b782..47d2a4498b03 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -396,7 +396,7 @@ static struct page *reiserfs_get_page(struct inode *dir, size_t n) struct address_space *mapping = dir->i_mapping; struct page *page; /* We can deadlock if we try to free dentries, - and an unlink/rmdir has just occured - GFP_NOFS avoids this */ + and an unlink/rmdir has just occurred - GFP_NOFS avoids this */ mapping_set_gfp_mask(mapping, GFP_NOFS); page = read_mapping_page(mapping, n >> PAGE_CACHE_SHIFT, NULL); if (!IS_ERR(page)) { diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c index 26b15ae34d6f..c37b520132ff 100644 --- a/fs/squashfs/cache.c +++ b/fs/squashfs/cache.c @@ -104,7 +104,7 @@ struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb, entry = &cache->entry[i]; /* - * Initialise choosen cache entry, and fill it in from + * Initialise chosen cache entry, and fill it in from * disk. */ cache->unused--; @@ -286,7 +286,7 @@ cleanup: /* - * Copy upto length bytes from cache entry to buffer starting at offset bytes + * Copy up to length bytes from cache entry to buffer starting at offset bytes * into the cache entry. If there's not length bytes then copy the number of * bytes available. In all cases return the number of bytes copied. */ diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index c8ff0d1ae5d3..8b3a7da531eb 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -147,7 +147,7 @@ static int make_free_space(struct ubifs_info *c) if (liab2 < liab1) return -EAGAIN; - dbg_budg("new liability %lld (not shrinked)", liab2); + dbg_budg("new liability %lld (not shrunk)", liab2); /* Liability did not shrink again, try GC */ dbg_budg("Run GC"); diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 27a4babe7df0..e765743cf9f3 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -78,7 +78,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off /* * Returns the location of the fragment from - * the begining of the filesystem. + * the beginning of the filesystem. */ static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 7693d6293404..3915ade6f9a8 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -483,9 +483,9 @@ static int ufs_parse_options (char * options, unsigned * mount_options) } /* - * Diffrent types of UFS hold fs_cstotal in different - * places, and use diffrent data structure for it. - * To make things simplier we just copy fs_cstotal to ufs_sb_private_info + * Different types of UFS hold fs_cstotal in different + * places, and use different data structure for it. + * To make things simpler we just copy fs_cstotal to ufs_sb_private_info */ static void ufs_setup_cstotal(struct super_block *sb) { diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 52dbd14260ba..79ce38be15a1 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1295,7 +1295,7 @@ xfs_get_blocks_direct( * If the private argument is non-NULL __xfs_get_blocks signals us that we * need to issue a transaction to convert the range from unwritten to written * extents. In case this is regular synchronous I/O we just call xfs_end_io - * to do this and we are done. But in case this was a successfull AIO + * to do this and we are done. But in case this was a successful AIO * request this handler is called from interrupt context, from which we * can't start transactions. In that case offload the I/O completion to * the workqueues we also use for buffered I/O completion. diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 596bb2c9de42..5ea402023ebd 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -120,7 +120,7 @@ xfs_buf_lru_add( * The unlocked check is safe here because it only occurs when there are not * b_lru_ref counts left on the inode under the pag->pag_buf_lock. it is there * to optimise the shrinker removing the buffer from the LRU and calling - * xfs_buf_free(). i.e. it removes an unneccessary round trip on the + * xfs_buf_free(). i.e. it removes an unnecessary round trip on the * bt_lru_lock. */ STATIC void @@ -380,7 +380,7 @@ out_free_pages: } /* - * Map buffer into kernel address-space if nessecary. + * Map buffer into kernel address-space if necessary. */ STATIC int _xfs_buf_map_pages( diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 52aadfbed132..f4213ba1ff85 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -381,7 +381,7 @@ xfs_aio_write_isize_update( /* * If this was a direct or synchronous I/O that failed (such as ENOSPC) then - * part of the I/O may have been written to disk before the error occured. In + * part of the I/O may have been written to disk before the error occurred. In * this case the on-disk file size may have been adjusted beyond the in-memory * file size and now needs to be truncated back. */ diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 9ff7fc603d2f..dd21784525a8 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -70,7 +70,7 @@ xfs_synchronize_times( /* * If the linux inode is valid, mark it dirty. - * Used when commiting a dirty inode into a transaction so that + * Used when committing a dirty inode into a transaction so that * the inode will get written back by the linux code */ void diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 594cd822d84d..9cf35a688f53 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -401,7 +401,7 @@ xfs_quiesce_fs( /* * Second stage of a quiesce. The data is already synced, now we have to take * care of the metadata. New transactions are already blocked, so we need to - * wait for any remaining transactions to drain out before proceding. + * wait for any remaining transactions to drain out before proceeding. */ void xfs_quiesce_attr( diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 7e2416478503..6fa214603819 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -600,7 +600,7 @@ xfs_qm_dqread( /* * Reservation counters are defined as reservation plus current usage - * to avoid having to add everytime. + * to avoid having to add every time. */ dqp->q_res_bcount = be64_to_cpu(ddqp->d_bcount); dqp->q_res_icount = be64_to_cpu(ddqp->d_icount); diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 774d7ec6df8e..a0a829addca9 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -134,7 +134,7 @@ xfs_qm_newmount( */ if (quotaondisk && !XFS_QM_NEED_QUOTACHECK(mp)) { /* - * If an error occured, qm_mount_quotas code + * If an error occurred, qm_mount_quotas code * has already disabled quotas. So, just finish * mounting, and get on with the boring life * without disk quotas. diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index c82f06778a27..0d62a07b7fd8 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -172,7 +172,7 @@ xfs_qm_scall_quotaoff( /* * Next we make the changes in the quota flag in the mount struct. * This isn't protected by a particular lock directly, because we - * don't want to take a mrlock everytime we depend on quotas being on. + * don't want to take a mrlock every time we depend on quotas being on. */ mp->m_qflags &= ~(flags); @@ -354,7 +354,7 @@ xfs_qm_scall_quotaon( return XFS_ERROR(EINVAL); } /* - * If everything's upto-date incore, then don't waste time. + * If everything's up to-date incore, then don't waste time. */ if ((mp->m_qflags & flags) == flags) return XFS_ERROR(EEXIST); diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index e5413d96f1af..7b7e005e3dcc 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -992,7 +992,7 @@ xfs_buf_iodone_callbacks( lasttarg = XFS_BUF_TARGET(bp); /* - * If the write was asynchronous then noone will be looking for the + * If the write was asynchronous then no one will be looking for the * error. Clear the error state and write the buffer out again. * * During sync or umount we'll write all pending buffers again diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 742c8330994a..a37480a6e023 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2789,7 +2789,7 @@ xfs_iflush( /* * We can't flush the inode until it is unpinned, so wait for it if we - * are allowed to block. We know noone new can pin it, because we are + * are allowed to block. We know no one new can pin it, because we are * holding the inode lock shared and you need to hold it exclusively to * pin the inode. * diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index f753200cef8d..ff4e2a30227d 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -111,7 +111,7 @@ struct xfs_imap { * Generally, we do not want to hold the i_rlock while holding the * i_ilock. Hierarchy is i_iolock followed by i_rlock. * - * xfs_iptr_t contains all the inode fields upto and including the + * xfs_iptr_t contains all the inode fields up to and including the * i_mnext and i_mprev fields, it is used as a marker in the inode * chain off the mount structure by xfs_sync calls. */ @@ -336,7 +336,7 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags) /* * Project quota id helpers (previously projid was 16bit only - * and using two 16bit values to hold new 32bit projid was choosen + * and using two 16bit values to hold new 32bit projid was chosen * to retain compatibility with "old" filesystems). */ static inline prid_t diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 15dbf1f9c2be..ffae692c9832 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -570,7 +570,7 @@ int xlog_write(struct log *log, struct xfs_log_vec *log_vector, * When we crack an atomic LSN, we sample it first so that the value will not * change while we are cracking it into the component values. This means we * will always get consistent component values to work from. This should always - * be used to smaple and crack LSNs taht are stored and updated in atomic + * be used to sample and crack LSNs that are stored and updated in atomic * variables. */ static inline void diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 0c4a5618e7af..5cc464a17c93 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -101,7 +101,7 @@ xlog_get_bp( /* * We do log I/O in units of log sectors (a power-of-2 * multiple of the basic block size), so we round up the - * requested size to acommodate the basic blocks required + * requested size to accommodate the basic blocks required * for complete log sectors. * * In addition, the buffer may be used for a non-sector- @@ -112,7 +112,7 @@ xlog_get_bp( * an issue. Nor will this be a problem if the log I/O is * done in basic blocks (sector size 1). But otherwise we * extend the buffer by one extra log sector to ensure - * there's space to accomodate this possiblility. + * there's space to accommodate this possibility. */ if (nbblks > 1 && log->l_sectBBsize > 1) nbblks += log->l_sectBBsize; diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 16084d8ea231..048b0c689d3e 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -81,7 +81,7 @@ xfs_trans_ijoin( * * * Grabs a reference to the inode which will be dropped when the transaction - * is commited. The inode will also be unlocked at that point. The inode + * is committed. The inode will also be unlocked at that point. The inode * must be locked, and it cannot be associated with any transaction. */ void diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c48b4217ec47..b7a5fe7c52c8 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -953,7 +953,7 @@ xfs_release( * If we previously truncated this file and removed old data * in the process, we want to initiate "early" writeout on * the last close. This is an attempt to combat the notorious - * NULL files problem which is particularly noticable from a + * NULL files problem which is particularly noticeable from a * truncate down, buffered (re-)write (delalloc), followed by * a crash. What we are effectively doing here is * significantly reducing the time window where we'd otherwise @@ -982,7 +982,7 @@ xfs_release( * * Further, check if the inode is being opened, written and * closed frequently and we have delayed allocation blocks - * oustanding (e.g. streaming writes from the NFS server), + * outstanding (e.g. streaming writes from the NFS server), * truncating the blocks past EOF will cause fragmentation to * occur. * diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index d41c94885211..f1380287ed4d 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -290,7 +290,7 @@ struct acpi_table_fadt { #define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: [V4] All local APICs must use cluster model (ACPI 3.0) */ #define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: [V4] All local x_aPICs must use physical dest mode (ACPI 3.0) */ -/* Values for preferred_profile (Prefered Power Management Profiles) */ +/* Values for preferred_profile (Preferred Power Management Profiles) */ enum acpi_prefered_pm_profiles { PM_UNSPECIFIED = 0, diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 942d30b5aab1..0dd4e87f6fba 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h @@ -192,7 +192,7 @@ typedef struct siginfo { * SIGBUS si_codes */ #define BUS_ADRALN (__SI_FAULT|1) /* invalid address alignment */ -#define BUS_ADRERR (__SI_FAULT|2) /* non-existant physical address */ +#define BUS_ADRERR (__SI_FAULT|2) /* non-existent physical address */ #define BUS_OBJERR (__SI_FAULT|3) /* object specific hardware error */ /* hardware memory error consumed on a machine check: action required */ #define BUS_MCEERR_AR (__SI_FAULT|4) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 32c45e5fe0ab..bd297a20ab98 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -773,7 +773,7 @@ * the sections that has this restriction (or similar) * is located before the ones requiring PAGE_SIZE alignment. * NOSAVE_DATA starts and ends with a PAGE_SIZE alignment which - * matches the requirment of PAGE_ALIGNED_DATA. + * matches the requirement of PAGE_ALIGNED_DATA. * * use 0 as page_align if page_aligned data is not used */ #define RW_DATA_SECTION(cacheline, pagealigned, inittask) \ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index ad5770f2315c..202424d17ed7 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -95,7 +95,7 @@ struct drm_device; * drm_core, drm_driver, drm_kms * drm_core level can be used in the generic drm code. For example: * drm_ioctl, drm_mm, drm_memory - * The macro definiton of DRM_DEBUG is used. + * The macro definition of DRM_DEBUG is used. * DRM_DEBUG(fmt, args...) * The debug info by using the DRM_DEBUG can be obtained by adding * the boot option of "drm.debug=1". @@ -808,7 +808,7 @@ struct drm_driver { * * \return Flags, or'ed together as follows: * - * DRM_SCANOUTPOS_VALID = Query successfull. + * DRM_SCANOUTPOS_VALID = Query successful. * DRM_SCANOUTPOS_INVBL = Inside vblank. * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of * this flag means that returned position may be offset by a constant diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 60edf9be31e5..e2ed98b175f6 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -65,7 +65,7 @@ enum drm_mode_status { MODE_H_ILLEGAL, /* mode has illegal horizontal timings */ MODE_V_ILLEGAL, /* mode has illegal horizontal timings */ MODE_BAD_WIDTH, /* requires an unsupported linepitch */ - MODE_NOMODE, /* no mode with a maching name */ + MODE_NOMODE, /* no mode with a matching name */ MODE_NO_INTERLACE, /* interlaced mode not supported */ MODE_NO_DBLESCAN, /* doublescan mode not supported */ MODE_NO_VSCAN, /* multiscan mode not supported */ @@ -321,7 +321,7 @@ struct drm_crtc_funcs { /* * Flip to the given framebuffer. This implements the page - * flip ioctl descibed in drm_mode.h, specifically, the + * flip ioctl described in drm_mode.h, specifically, the * implementation must return immediately and block all * rendering to the current fb until the flip has completed. * If userspace set the event flag in the ioctl, the event diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index b1e7809e5e15..c2f93a8ae2e1 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -56,7 +56,7 @@ struct drm_mm_node { }; struct drm_mm { - /* List of all memory nodes that immediatly preceed a free hole. */ + /* List of all memory nodes that immediately precede a free hole. */ struct list_head hole_stack; /* head_node.node_list is the list of all memory nodes, ordered * according to the (increasing) start address of the memory node. */ diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index ae6b7a3dbec7..c4961ea50a49 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -277,7 +277,7 @@ struct drm_mode_mode_cmd { #define DRM_MODE_CURSOR_MOVE (1<<1) /* - * depending on the value in flags diffrent members are used. + * depending on the value in flags different members are used. * * CURSOR_BO uses * crtc diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index c16097f99be0..fca817009e13 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -107,7 +107,7 @@ */ #define MGA_NR_SAREA_CLIPRECTS 8 -/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 3dec41cf8342..3bce1a4fc305 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -641,7 +641,7 @@ typedef struct drm_radeon_vertex2 { } drm_radeon_vertex2_t; /* v1.3 - obsoletes drm_radeon_vertex2 - * - allows arbitarily large cliprect list + * - allows arbitrarily large cliprect list * - allows updating of tcl packet, vector and scalar state * - allows memory-efficient description of state updates * - allows state to be emitted without a primitive diff --git a/include/drm/savage_drm.h b/include/drm/savage_drm.h index 4863cf6bf96f..818d49be2e6e 100644 --- a/include/drm/savage_drm.h +++ b/include/drm/savage_drm.h @@ -29,7 +29,7 @@ #ifndef __SAVAGE_SAREA_DEFINES__ #define __SAVAGE_SAREA_DEFINES__ -/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 50852aad260a..94e2ce43488d 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -50,10 +50,10 @@ struct drm_mm_node; * * @fpfn: first valid page frame number to put the object * @lpfn: last valid page frame number to put the object - * @num_placement: number of prefered placements - * @placement: prefered placements - * @num_busy_placement: number of prefered placements when need to evict buffer - * @busy_placement: prefered placements when need to evict buffer + * @num_placement: number of preferred placements + * @placement: preferred placements + * @num_busy_placement: number of preferred placements when need to evict buffer + * @busy_placement: preferred placements when need to evict buffer * * Structure indicating the placement you request for an object. */ @@ -160,7 +160,7 @@ struct ttm_tt; * @mem: structure describing current placement. * @persistant_swap_storage: Usually the swap storage is deleted for buffers * pinned in physical memory. If this behaviour is not desired, this member - * holds a pointer to a persistant shmem object. + * holds a pointer to a persistent shmem object. * @ttm: TTM structure holding system pages. * @evicted: Whether the object was evicted without user-space knowing. * @cpu_writes: For synchronization. Number of cpu writers. @@ -461,7 +461,7 @@ extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); * sleep interruptible. * @persistant_swap_storage: Usually the swap storage is deleted for buffers * pinned in physical memory. If this behaviour is not desired, this member - * holds a pointer to a persistant shmem object. Typically, this would + * holds a pointer to a persistent shmem object. Typically, this would * point to the shmem object backing a GEM object if TTM is used to back a * GEM user interface. * @acc_size: Accounted size for this object. @@ -508,7 +508,7 @@ extern int ttm_bo_init(struct ttm_bo_device *bdev, * sleep interruptible. * @persistant_swap_storage: Usually the swap storage is deleted for buffers * pinned in physical memory. If this behaviour is not desired, this member - * holds a pointer to a persistant shmem object. Typically, this would + * holds a pointer to a persistent shmem object. Typically, this would * point to the shmem object backing a GEM object if TTM is used to back a * GEM user interface. * @p_bo: On successful completion *p_bo points to the created object. diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index efed0820d9fa..8b52c9ab350b 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -223,9 +223,9 @@ struct ttm_mem_type_manager_func { * @mem::mm_node should be set to a non-null value, and * @mem::start should be set to a value identifying the beginning * of the range allocated, and the function should return zero. - * If the memory region accomodate the buffer object, @mem::mm_node + * If the memory region accommodate the buffer object, @mem::mm_node * should be set to NULL, and the function should return 0. - * If a system error occured, preventing the request to be fulfilled, + * If a system error occurred, preventing the request to be fulfilled, * the function should return a negative error code. * * Note that @mem::mm_node will only be dereferenced by @@ -841,7 +841,7 @@ extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); * different order, either by will or as a result of a buffer being evicted * to make room for a buffer already reserved. (Buffers are reserved before * they are evicted). The following algorithm prevents such deadlocks from - * occuring: + * occurring: * 1) Buffers are reserved with the lru spinlock held. Upon successful * reservation they are removed from the lru list. This stops a reserved buffer * from being evicted. However the lru spinlock is released between the time diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h index 650e6bf6f69f..5c36432d9ce5 100644 --- a/include/drm/vmwgfx_drm.h +++ b/include/drm/vmwgfx_drm.h @@ -592,7 +592,7 @@ struct drm_vmw_stream_arg { /** * DRM_VMW_UPDATE_LAYOUT - Update layout * - * Updates the prefered modes and connection status for connectors. The + * Updates the preferred modes and connection status for connectors. The * command conisits of one drm_vmw_update_layout_arg pointing out a array * of num_outputs drm_vmw_rect's. */ diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h index 24d26efd1432..e82e3ee2c54a 100644 --- a/include/linux/amba/clcd.h +++ b/include/linux/amba/clcd.h @@ -136,7 +136,7 @@ struct clcd_board { int (*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var); /* - * Compulsary. Decode fb->fb.var into regs->*. In the case of + * Compulsory. Decode fb->fb.var into regs->*. In the case of * fixed timing, set regs->* to the register values required. */ void (*decode)(struct clcd_fb *fb, struct clcd_regs *regs); diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h index f60227088b7b..21114810c7c0 100644 --- a/include/linux/amba/mmci.h +++ b/include/linux/amba/mmci.h @@ -30,15 +30,15 @@ struct dma_chan; * @cd_invert: true if the gpio_cd pin value is active low * @capabilities: the capabilities of the block as implemented in * this platform, signify anything MMC_CAP_* from mmc/host.h - * @dma_filter: function used to select an apropriate RX and TX + * @dma_filter: function used to select an appropriate RX and TX * DMA channel to be used for DMA, if and only if you're deploying the * generic DMA engine * @dma_rx_param: parameter passed to the DMA allocation - * filter in order to select an apropriate RX channel. If + * filter in order to select an appropriate RX channel. If * there is a bidirectional RX+TX channel, then just specify * this and leave dma_tx_param set to NULL * @dma_tx_param: parameter passed to the DMA allocation - * filter in order to select an apropriate TX channel. If this + * filter in order to select an appropriate TX channel. If this * is NULL the driver will attempt to use the RX channel as a * bidirectional channel */ diff --git a/include/linux/can/error.h b/include/linux/can/error.h index d4127fd9e681..5958074302a4 100644 --- a/include/linux/can/error.h +++ b/include/linux/can/error.h @@ -51,7 +51,7 @@ #define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */ #define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */ #define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */ -#define CAN_ERR_PROT_TX 0x80 /* error occured on transmission */ +#define CAN_ERR_PROT_TX 0x80 /* error occurred on transmission */ /* error in CAN protocol (location) / data[3] */ #define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */ diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h index 3250de935e1a..34542d374dd8 100644 --- a/include/linux/can/netlink.h +++ b/include/linux/can/netlink.h @@ -17,7 +17,7 @@ /* * CAN bit-timing parameters * - * For futher information, please read chapter "8 BIT TIMING + * For further information, please read chapter "8 BIT TIMING * REQUIREMENTS" of the "Bosch CAN Specification version 2.0" * at http://www.semiconductors.bosch.de/pdf/can2spec.pdf. */ diff --git a/include/linux/cdk.h b/include/linux/cdk.h index 0908daf7bf56..80093a8d4f64 100644 --- a/include/linux/cdk.h +++ b/include/linux/cdk.h @@ -149,7 +149,7 @@ typedef struct cdkhdr { /* * Define the memory mapping structure. This structure is pointed to by * the memp field in the stlcdkhdr struct. As many as these structures - * as required are layed out in shared memory to define how the rest of + * as required are laid out in shared memory to define how the rest of * shared memory is divided up. There will be one for each port. */ typedef struct cdkmem { diff --git a/include/linux/cfag12864b.h b/include/linux/cfag12864b.h index 6f9f19d66591..b454dfce60d9 100644 --- a/include/linux/cfag12864b.h +++ b/include/linux/cfag12864b.h @@ -44,7 +44,7 @@ extern unsigned char * cfag12864b_buffer; /* * Get the refresh rate of the LCD * - * Returns the refresh rate (hertzs). + * Returns the refresh rate (hertz). */ extern unsigned int cfag12864b_getrate(void); diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index e654fa239916..5ac7ebc36dbb 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -240,7 +240,7 @@ struct cgroup { /* For RCU-protected deletion */ struct rcu_head rcu_head; - /* List of events which userspace want to recieve */ + /* List of events which userspace want to receive */ struct list_head event_list; spinlock_t event_list_lock; }; diff --git a/include/linux/cm4000_cs.h b/include/linux/cm4000_cs.h index 72bfefdbd767..3c4aac406175 100644 --- a/include/linux/cm4000_cs.h +++ b/include/linux/cm4000_cs.h @@ -20,7 +20,7 @@ typedef struct atreq { } atreq_t; -/* what is particularly stupid in the original driver is the arch-dependant +/* what is particularly stupid in the original driver is the arch-dependent * member sizes. This leads to CONFIG_COMPAT breakage, since 32bit userspace * will lay out the structure members differently than the 64bit kernel. * diff --git a/include/linux/configfs.h b/include/linux/configfs.h index ddb7a97c78c2..645778ad899b 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h @@ -218,7 +218,7 @@ static ssize_t _item##_attr_store(struct config_item *item, \ * group children. default_groups may coexist alongsize make_group() or * make_item(), but if the group wishes to have only default_groups * children (disallowing mkdir(2)), it need not provide either function. - * If the group has commit(), it supports pending and commited (active) + * If the group has commit(), it supports pending and committed (active) * items. */ struct configfs_item_operations { diff --git a/include/linux/cper.h b/include/linux/cper.h index 372a25839fd1..c23049496531 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h @@ -310,7 +310,7 @@ struct cper_sec_proc_ia { __u8 cpuid[48]; }; -/* IA32/X64 Processor Error Infomation Structure */ +/* IA32/X64 Processor Error Information Structure */ struct cper_ia_err_info { uuid_le err_type; __u64 validation_bits; diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h index 4cb72b920c74..7925bf0ee836 100644 --- a/include/linux/decompress/mm.h +++ b/include/linux/decompress/mm.h @@ -16,7 +16,7 @@ /* * Some architectures want to ensure there is no local data in their - * pre-boot environment, so that data can arbitarily relocated (via + * pre-boot environment, so that data can arbitrarily relocated (via * GOT references). This is achieved by defining STATIC_RW_DATA to * be null. */ diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9bebd7f16ef1..eee7addec282 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -434,7 +434,7 @@ struct dma_tx_state { * zero or error code * @device_tx_status: poll for transaction completion, the optional * txstate parameter can be supplied with a pointer to get a - * struct with auxilary transfer status information, otherwise the call + * struct with auxiliary transfer status information, otherwise the call * will just return a simple status code * @device_issue_pending: push pending transactions to hardware */ diff --git a/include/linux/drbd.h b/include/linux/drbd.h index d18d673ebc78..cec467f5d676 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -36,7 +36,7 @@ #include #include -/* Altough the Linux source code makes a difference between +/* Although the Linux source code makes a difference between generic endianness and the bitfields' endianness, there is no architecture as of Linux-2.6.24-rc4 where the bitfileds' endianness does not match the generic endianness. */ @@ -184,7 +184,7 @@ enum drbd_conns { /* These temporal states are all used on the way * from >= C_CONNECTED to Unconnected. * The 'disconnect reason' states - * I do not allow to change beween them. */ + * I do not allow to change between them. */ C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE, diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h index bb264a5732de..246f576c981d 100644 --- a/include/linux/drbd_limits.h +++ b/include/linux/drbd_limits.h @@ -43,7 +43,7 @@ /* net { */ /* timeout, unit centi seconds - * more than one minute timeout is not usefull */ + * more than one minute timeout is not useful */ #define DRBD_TIMEOUT_MIN 1 #define DRBD_TIMEOUT_MAX 600 #define DRBD_TIMEOUT_DEF 60 /* 6 seconds */ @@ -68,7 +68,7 @@ #define DRBD_MAX_EPOCH_SIZE_MAX 20000 #define DRBD_MAX_EPOCH_SIZE_DEF 2048 - /* I don't think that a tcp send buffer of more than 10M is usefull */ + /* I don't think that a tcp send buffer of more than 10M is useful */ #define DRBD_SNDBUF_SIZE_MIN 0 #define DRBD_SNDBUF_SIZE_MAX (10<<20) #define DRBD_SNDBUF_SIZE_DEF 0 @@ -101,7 +101,7 @@ #define DRBD_RATE_MAX (4 << 20) #define DRBD_RATE_DEF 250 /* kb/second */ - /* less than 7 would hit performance unneccessarily. + /* less than 7 would hit performance unnecessarily. * 3833 is the largest prime that still does fit * into 64 sectors of activity log */ #define DRBD_AL_EXTENTS_MIN 7 diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c8fcbdd2b0e7..dc80d8294247 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -614,7 +614,7 @@ struct ethtool_sfeatures { * values of corresponding bits in features[].requested. Bits in .requested * not set in .valid or not changeable are ignored. * - * Returns %EINVAL when .valid contains undefined or never-changable bits + * Returns %EINVAL when .valid contains undefined or never-changeable bits * or size is not equal to required number of features words (32-bit blocks). * Returns >= 0 if request was completed; bits set in the value mean: * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index f6856a5a1d4b..f362733186a5 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -1,5 +1,5 @@ /* - * include/linux/eventpoll.h ( Efficent event polling implementation ) + * include/linux/eventpoll.h ( Efficient event polling implementation ) * Copyright (C) 2001,...,2006 Davide Libenzi * * This program is free software; you can redistribute it and/or modify diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 33a42f24b275..3a4cef5322dc 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -120,7 +120,7 @@ struct fid { * encode_fh: * @encode_fh should store in the file handle fragment @fh (using at most * @max_len bytes) information that can be used by @decode_fh to recover the - * file refered to by the &struct dentry @de. If the @connectable flag is + * file referred to by the &struct dentry @de. If the @connectable flag is * set, the encode_fh() should store sufficient information so that a good * attempt can be made to find not only the file but also it's place in the * filesystem. This typically means storing a reference to de->d_parent in diff --git a/include/linux/fb.h b/include/linux/fb.h index b2a36391d2a1..df728c1c29ed 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -534,14 +534,14 @@ struct fb_cursor_user { #define FB_EVENT_GET_CONSOLE_MAP 0x07 /* CONSOLE-SPECIFIC: set console to framebuffer mapping */ #define FB_EVENT_SET_CONSOLE_MAP 0x08 -/* A hardware display blank change occured */ +/* A hardware display blank change occurred */ #define FB_EVENT_BLANK 0x09 /* Private modelist is to be replaced */ #define FB_EVENT_NEW_MODELIST 0x0A /* The resolution of the passed in fb_info about to change and all vc's should be changed */ #define FB_EVENT_MODE_CHANGE_ALL 0x0B -/* A software display blank change occured */ +/* A software display blank change occurred */ #define FB_EVENT_CONBLANK 0x0C /* Get drawing requirements */ #define FB_EVENT_GET_REQ 0x0D @@ -805,7 +805,7 @@ struct fb_tile_ops { /* A driver may set this flag to indicate that it does want a set_par to be * called every time when fbcon_switch is executed. The advantage is that with * this flag set you can really be sure that set_par is always called before - * any of the functions dependant on the correct hardware state or altering + * any of the functions dependent on the correct hardware state or altering * that state, even if you are using some broken X releases. The disadvantage * is that it introduces unwanted delays to every console switch if set_par * is slow. It is a good idea to try this flag in the drivers initialization @@ -877,7 +877,7 @@ struct fb_info { void *fbcon_par; /* fbcon use-only private area */ /* From here on everything is device dependent */ void *par; - /* we need the PCI or similiar aperture base/size not + /* we need the PCI or similar aperture base/size not smem_start/size as smem_start may just be an object allocated inside the aperture so may not actually overlap */ struct apertures_struct { diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 59ea406be7f6..4ff09889c5c0 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -900,7 +900,7 @@ struct fw_cdev_get_cycle_timer2 { /** * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth - * @closure: Passed back to userspace in correponding iso resource events + * @closure: Passed back to userspace in corresponding iso resource events * @channels: Isochronous channels of which one is to be (de)allocated * @bandwidth: Isochronous bandwidth units to be (de)allocated * @handle: Handle to the allocation, written by the kernel (only valid in diff --git a/include/linux/fs.h b/include/linux/fs.h index 52f283c1edb2..f03632d2ac18 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -465,7 +465,7 @@ struct iattr { struct timespec ia_ctime; /* - * Not an attribute, but an auxilary info for filesystems wanting to + * Not an attribute, but an auxiliary info for filesystems wanting to * implement an ftruncate() like method. NOTE: filesystem should * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). */ @@ -647,7 +647,7 @@ struct address_space { } __attribute__((aligned(sizeof(long)))); /* * On most architectures that alignment is already the case; but - * must be enforced here for CRIS, to let the least signficant bit + * must be enforced here for CRIS, to let the least significant bit * of struct page's "mapping" pointer be used for PAGE_MAPPING_ANON. */ diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index b8581c09d19f..76427e688d15 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -236,7 +236,7 @@ struct fscache_cache_ops { /* unpin an object in the cache */ void (*unpin_object)(struct fscache_object *object); - /* store the updated auxilliary data on an object */ + /* store the updated auxiliary data on an object */ void (*update_object)(struct fscache_object *object); /* discard the resources pinned by an object and effect retirement if diff --git a/include/linux/fscache.h b/include/linux/fscache.h index ec0dad5ab90f..7c4d72f5581f 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -102,9 +102,9 @@ struct fscache_cookie_def { */ void (*get_attr)(const void *cookie_netfs_data, uint64_t *size); - /* get the auxilliary data from netfs data + /* get the auxiliary data from netfs data * - this function can be absent if the index carries no state data - * - should store the auxilliary data in the buffer + * - should store the auxiliary data in the buffer * - should return the amount of amount stored * - not permitted to return an error * - the netfs data from the cookie being used as the source is @@ -117,7 +117,7 @@ struct fscache_cookie_def { /* consult the netfs about the state of an object * - this function can be absent if the index carries no state data * - the netfs data from the cookie being used as the target is - * presented, as is the auxilliary data + * presented, as is the auxiliary data */ enum fscache_checkaux (*check_aux)(void *cookie_netfs_data, const void *data, diff --git a/include/linux/hid.h b/include/linux/hid.h index bb29bb1dbd2f..42f7e2fb501f 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -799,7 +799,7 @@ static inline int __must_check hid_parse(struct hid_device *hdev) * * Call this in probe function *after* hid_parse. This will setup HW buffers * and start the device (if not deffered to device open). hid_hw_stop must be - * called if this was successfull. + * called if this was successful. */ static inline int __must_check hid_hw_start(struct hid_device *hdev, unsigned int connect_mask) diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h index 9db3d454887f..d392975d8887 100644 --- a/include/linux/hp_sdc.h +++ b/include/linux/hp_sdc.h @@ -101,7 +101,7 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this); #define HP_SDC_STATUS_REG 0x40 /* Data from an i8042 register */ #define HP_SDC_STATUS_HILCMD 0x50 /* Command from HIL MLC */ #define HP_SDC_STATUS_HILDATA 0x60 /* Data from HIL MLC */ -#define HP_SDC_STATUS_PUP 0x70 /* Sucessful power-up self test */ +#define HP_SDC_STATUS_PUP 0x70 /* Successful power-up self test */ #define HP_SDC_STATUS_KCOOKED 0x80 /* Key from cooked kbd */ #define HP_SDC_STATUS_KRPG 0xc0 /* Key from Repeat Gen */ #define HP_SDC_STATUS_KMOD_SUP 0x10 /* Shift key is up */ diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 9e7a12d6385d..a6deef4f4f67 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -826,7 +826,7 @@ static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct * @c: I2O controller * * This function tries to get a message frame. If no message frame is - * available do not wait until one is availabe (see also i2o_msg_get_wait). + * available do not wait until one is available (see also i2o_msg_get_wait). * The returned pointer to the message frame is not in I/O memory, it is * allocated from a mempool. But because a MFA is allocated from the * controller too it is guaranteed that i2o_msg_post() will never fail. diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 943c9b53695c..bea0ac750712 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -98,7 +98,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); * @next: pointer to the next irqaction for shared interrupts * @irq: interrupt number * @dir: pointer to the proc/irq/NN/name entry - * @thread_fn: interupt handler function for threaded interrupts + * @thread_fn: interrupt handler function for threaded interrupts * @thread: thread pointer for threaded interrupts * @thread_flags: flags related to @thread * @thread_mask: bitmask for keeping track of @thread activity @@ -484,7 +484,7 @@ extern void __send_remote_softirq(struct call_single_data *cp, int cpu, Properties: * If tasklet_schedule() is called, then tasklet is guaranteed to be executed on some cpu at least once after this. - * If the tasklet is already scheduled, but its excecution is still not + * If the tasklet is already scheduled, but its execution is still not started, it will be executed only once. * If this tasklet is already running on another CPU (or schedule is called from tasklet itself), it is rescheduled for later. diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 045f2f275cd0..ca85cf894e33 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -111,7 +111,7 @@ struct ipmi_ipmb_addr { * A LAN Address. This is an address to/from a LAN interface bridged * by the BMC, not an address actually out on the LAN. * - * A concious decision was made here to deviate slightly from the IPMI + * A conscious decision was made here to deviate slightly from the IPMI * spec. We do not use rqSWID and rsSWID like it shows in the * message. Instead, we use remote_SWID and local_SWID. This means * that any message (a request or response) from another device will @@ -259,7 +259,7 @@ struct ipmi_recv_msg { void (*done)(struct ipmi_recv_msg *msg); /* Place-holder for the data, don't make any assumptions about - the size or existance of this, since it may change. */ + the size or existence of this, since it may change. */ unsigned char msg_data[IPMI_MAX_MSG_LENGTH]; }; diff --git a/include/linux/isdn/hdlc.h b/include/linux/isdn/hdlc.h index 4b3ecc40889a..96521370c782 100644 --- a/include/linux/isdn/hdlc.h +++ b/include/linux/isdn/hdlc.h @@ -2,7 +2,7 @@ * hdlc.h -- General purpose ISDN HDLC decoder. * * Implementation of a HDLC decoder/encoder in software. - * Neccessary because some ISDN devices don't have HDLC + * Necessary because some ISDN devices don't have HDLC * controllers. * * Copyright (C) diff --git a/include/linux/ixjuser.h b/include/linux/ixjuser.h index 88b45895746d..94ab5e942e53 100644 --- a/include/linux/ixjuser.h +++ b/include/linux/ixjuser.h @@ -50,7 +50,7 @@ * IOCTL's used for the Quicknet Telephony Cards * * If you use the IXJCTL_TESTRAM command, the card must be power cycled to -* reset the SRAM values before futher use. +* reset the SRAM values before further use. * ******************************************************************************/ diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 922aa313c9f9..f97672a36fa8 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -42,7 +42,7 @@ /* LATCH is used in the interval timer and ftape setup. */ #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ -/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, then we can +/* Suppose we want to divide two numbers NOM and DEN: NOM/DEN, then we can * improve accuracy by shifting LSH bits, hence calculating: * (NOM << LSH) / DEN * This however means trouble for large NOM, because (NOM << LSH) may no diff --git a/include/linux/ktime.h b/include/linux/ktime.h index e1ceaa9b36bb..603bec2913b0 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -35,7 +35,7 @@ * * On 32-bit CPUs an optimized representation of the timespec structure * is used to avoid expensive conversions from and to timespecs. The - * endian-aware order of the tv struct members is choosen to allow + * endian-aware order of the tv struct members is chosen to allow * mathematical operations on the tv64 member of the union too, which * for certain operations produces better code. * @@ -158,7 +158,7 @@ static inline ktime_t ktime_set(const long secs, const unsigned long nsecs) * @lhs: minuend * @rhs: subtrahend * - * Returns the remainder of the substraction + * Returns the remainder of the subtraction */ static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs) { diff --git a/include/linux/led-lm3530.h b/include/linux/led-lm3530.h index bb69d20da0dc..58592fa67d24 100644 --- a/include/linux/led-lm3530.h +++ b/include/linux/led-lm3530.h @@ -41,7 +41,7 @@ #define LM3530_RAMP_TIME_8s (7) /* ALS Resistor Select */ -#define LM3530_ALS_IMPD_Z (0x00) /* ALS Impedence */ +#define LM3530_ALS_IMPD_Z (0x00) /* ALS Impedance */ #define LM3530_ALS_IMPD_13_53kOhm (0x01) #define LM3530_ALS_IMPD_9_01kOhm (0x02) #define LM3530_ALS_IMPD_5_41kOhm (0x03) diff --git a/include/linux/libata.h b/include/linux/libata.h index c71f46960f39..7f675aa81d87 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -364,7 +364,7 @@ enum { ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 6, /* Horkage types. May be set by libata or controller on drives - (some horkage may be drive/controller pair dependant */ + (some horkage may be drive/controller pair dependent */ ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */ diff --git a/include/linux/lru_cache.h b/include/linux/lru_cache.h index 78fbf24f357a..6a4fab7c6e09 100644 --- a/include/linux/lru_cache.h +++ b/include/linux/lru_cache.h @@ -148,7 +148,7 @@ write intent log information, three of which are mentioned here. * * DRBD currently (May 2009) only uses 61 elements on the resync lru_cache * (total memory usage 2 pages), and up to 3833 elements on the act_log - * lru_cache, totalling ~215 kB for 64bit architechture, ~53 pages. + * lru_cache, totalling ~215 kB for 64bit architecture, ~53 pages. * * We usually do not actually free these objects again, but only "recycle" * them, as the change "index: -old_label, +LC_FREE" would need a transaction diff --git a/include/linux/mfd/wm8350/pmic.h b/include/linux/mfd/wm8350/pmic.h index e786fe9841ef..579b50ca2e02 100644 --- a/include/linux/mfd/wm8350/pmic.h +++ b/include/linux/mfd/wm8350/pmic.h @@ -1,5 +1,5 @@ /* - * pmic.h -- Power Managment Driver for Wolfson WM8350 PMIC + * pmic.h -- Power Management Driver for Wolfson WM8350 PMIC * * Copyright 2007 Wolfson Microelectronics PLC * diff --git a/include/linux/mm.h b/include/linux/mm.h index 7606d7db96c9..692dbae6ffa7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -608,7 +608,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma) #endif /* - * Define the bit shifts to access each section. For non-existant + * Define the bit shifts to access each section. For non-existent * sections we define the shift as 0; that plus a 0 mask ensures * the compiler will optimise away reference to them. */ diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index c0207a770476..bdd7ceeb99e4 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -98,7 +98,7 @@ struct mmc_data; * EVENT_DATA_COMPLETE is set in @pending_events, all data-related * interrupts must be disabled and @data_status updated with a * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the - * CMDRDY interupt must be disabled and @cmd_status updated with a + * CMDRDY interrupt must be disabled and @cmd_status updated with a * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the * bytes_xfered field of @data must be written. This is ensured by * using barriers. @@ -172,7 +172,7 @@ struct dw_mci_dma_ops { #define DW_MCI_QUIRK_IDMAC_DTO BIT(0) /* delay needed between retries on some 2.11a implementations */ #define DW_MCI_QUIRK_RETRY_DELAY BIT(1) -/* High Speed Capable - Supports HS cards (upto 50MHz) */ +/* High Speed Capable - Supports HS cards (up to 50MHz) */ #define DW_MCI_QUIRK_HIGHSPEED BIT(2) /* Unreliable card detection */ #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h index 9d2deb200f54..a3759cb0ac10 100644 --- a/include/linux/mroute6.h +++ b/include/linux/mroute6.h @@ -249,7 +249,7 @@ static inline int ip6mr_sk_done(struct sock *sk) * Structure used to communicate from kernel to multicast router. * We'll overlay the structure onto an MLD header (not an IPv6 heder like igmpmsg{} * used for IPv4 implementation). This is because this structure will be passed via an - * IPv6 raw socket, on wich an application will only receiver the payload i.e the data after + * IPv6 raw socket, on which an application will only receiver the payload i.e the data after * the IPv6 header and all the extension headers. (See section 3 of RFC 3542) */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 0d823f2dd667..d24925492972 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -308,7 +308,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, addr = (cmd_ofs * type) * interleave; - /* Modify the unlock address if we are in compatiblity mode. + /* Modify the unlock address if we are in compatibility mode. * For 16bit devices on 8 bit busses * and 32bit devices on 16 bit busses * set the low bit of the alternating bit sequence of the address. diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index ae67ef56a8f5..d44192740f6f 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -416,9 +416,9 @@ struct nand_buffers { * @select_chip: [REPLACEABLE] select chip nr * @block_bad: [REPLACEABLE] check, if the block is bad * @block_markbad: [REPLACEABLE] mark the block bad - * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling + * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling * ALE/CLE/nCE. Also used to write command and address - * @init_size: [BOARDSPECIFIC] hardwarespecific funtion for setting + * @init_size: [BOARDSPECIFIC] hardwarespecific function for setting * mtd->oobsize, mtd->writesize and so on. * @id_data contains the 8 bytes values of NAND_CMD_READID. * Return with the bus width. @@ -437,7 +437,7 @@ struct nand_buffers { * @erase_cmd: [INTERN] erase command write function, selectable due * to AND support. * @scan_bbt: [REPLACEABLE] function to scan bad block table - * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering + * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transferring * data from array to read regs (tR). * @state: [INTERN] the current state of the NAND device * @oob_poi: poison value buffer diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 36efcba15ecd..abed4dec5c2f 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -51,7 +51,7 @@ * return in usecs the elapsed timebetween now and the reference x as * returned by xip_currtime(). * - * note 1: convertion to usec can be approximated, as long as the + * note 1: conversion to usec can be approximated, as long as the * returned value is <= the real elapsed time. * note 2: this should be able to cope with a few seconds without * overflowing. diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h index 2a10efda17fb..6a0664c0c451 100644 --- a/include/linux/netfilter/nf_conntrack_proto_gre.h +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h @@ -60,7 +60,7 @@ struct gre_hdr_pptp { __be16 payload_len; /* size of ppp payload, not inc. gre header */ __be16 call_id; /* peer's call_id for this session */ __be32 seq; /* sequence number. Present if S==1 */ - __be32 ack; /* seq number of highest packet recieved by */ + __be32 ack; /* seq number of highest packet received by */ /* sender in this session */ }; diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 1c6f0c5f530e..8797ed16feb2 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -92,7 +92,7 @@ struct ebt_entries { /* This is a hack to make a difference between an ebt_entry struct and an * ebt_entries struct when traversing the entries from start to end. - * Using this simplifies the code alot, while still being able to use + * Using this simplifies the code a lot, while still being able to use * ebt_entries. * Contrary, iptables doesn't use something like ebt_entries and therefore uses * different techniques for naming the policy and such. So, iptables doesn't diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index b528f6d4b860..178fafe0ff93 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -359,7 +359,7 @@ enum nfsstat4 { /* Error 10073 is unused. */ NFS4ERR_CLIENTID_BUSY = 10074, /* clientid has state */ NFS4ERR_PNFS_IO_HOLE = 10075, /* IO to _SPARSE file hole */ - NFS4ERR_SEQ_FALSE_RETRY = 10076, /* retry not origional */ + NFS4ERR_SEQ_FALSE_RETRY = 10076, /* retry not original */ NFS4ERR_BAD_HIGH_SLOT = 10077, /* sequence arg bad */ NFS4ERR_DEADSESSION = 10078, /* persistent session dead */ NFS4ERR_ENCR_ALG_UNSUPP = 10079, /* SSV alg mismatch */ diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index bd316159278c..84058ec69390 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -80,7 +80,7 @@ struct nfsd4_fs_locations { /* * We keep an array of pseudoflavors with the export, in order from most - * to least preferred. For the forseeable future, we don't expect more + * to least preferred. For the foreseeable future, we don't expect more * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3, * spkm3i, and spkm3p (and using all 8 at once should be rare). */ diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index 80d55bbc5365..f76d80ccec10 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h @@ -49,7 +49,7 @@ struct nfs_fhbase_old { * * The auth_type field specifies how the filehandle can be authenticated * This might allow a file to be confirmed to be in a writable part of a - * filetree without checking the path from it upto the root. + * filetree without checking the path from it up to the root. * Current values: * 0 - No authentication. fb_auth is 0 bytes long * Possible future values: diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 30022189104d..bbfa1093f606 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -414,7 +414,7 @@ * @__NL80211_CMD_AFTER_LAST: internal use */ enum nl80211_commands { -/* don't change the order or add anything inbetween, this is ABI! */ +/* don't change the order or add anything between, this is ABI! */ NL80211_CMD_UNSPEC, NL80211_CMD_GET_WIPHY, /* can dump */ @@ -860,7 +860,7 @@ enum nl80211_commands { * This can be used to mask out antennas which are not attached or should * not be used for receiving. If an antenna is not selected in this bitmap * the hardware should not be configured to receive on this antenna. - * For a more detailed descripton see @NL80211_ATTR_WIPHY_ANTENNA_TX. + * For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX. * * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: Bitmap of antennas which are available * for configuration as TX antennas via the above parameters. @@ -891,7 +891,7 @@ enum nl80211_commands { * @__NL80211_ATTR_AFTER_LAST: internal use */ enum nl80211_attrs { -/* don't change the order or add anything inbetween, this is ABI! */ +/* don't change the order or add anything between, this is ABI! */ NL80211_ATTR_UNSPEC, NL80211_ATTR_WIPHY, @@ -1419,7 +1419,7 @@ enum nl80211_bitrate_attr { * 802.11 country information element with regulatory information it * thinks we should consider. cfg80211 only processes the country * code from the IE, and relies on the regulatory domain information - * structure pased by userspace (CRDA) from our wireless-regdb. + * structure passed by userspace (CRDA) from our wireless-regdb. * If a channel is enabled but the country code indicates it should * be disabled we disable the channel and re-enable it upon disassociation. */ @@ -1598,7 +1598,7 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in * millisecond units, used by the Peer Link Open message * - * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in + * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in * millisecond units, used by the peer link management to close a peer link * * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 2026f9e1ceb8..621dfa16acc0 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -237,7 +237,7 @@ static inline int notifier_to_errno(int ret) * enabling interrupts. Must not sleep, * must not fail */ -/* Used for CPU hotplug events occuring while tasks are frozen due to a suspend +/* Used for CPU hotplug events occurring while tasks are frozen due to a suspend * operation in progress */ #define CPU_TASKS_FROZEN 0x0010 diff --git a/include/linux/omap3isp.h b/include/linux/omap3isp.h index 150822b4dbff..b6111f8cd49a 100644 --- a/include/linux/omap3isp.h +++ b/include/linux/omap3isp.h @@ -250,7 +250,7 @@ enum omap3isp_h3a_af_rgbpos { /* Contains the information regarding the Horizontal Median Filter */ struct omap3isp_h3a_af_hmf { __u8 enable; /* Status of Horizontal Median Filter */ - __u8 threshold; /* Threshhold Value for Horizontal Median Filter */ + __u8 threshold; /* Threshold Value for Horizontal Median Filter */ }; /* Contains the information regarding the IIR Filters */ diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h index f5de21de31dd..961ecc7d30bc 100644 --- a/include/linux/page_cgroup.h +++ b/include/linux/page_cgroup.h @@ -138,7 +138,7 @@ static inline void move_unlock_page_cgroup(struct page_cgroup *pc, #define PCG_ARRAYID_OFFSET (BITS_PER_LONG - PCG_ARRAYID_WIDTH) /* - * Zero the shift count for non-existant fields, to prevent compiler + * Zero the shift count for non-existent fields, to prevent compiler * warnings and ensure references are optimized away. */ #define PCG_ARRAYID_SHIFT (PCG_ARRAYID_OFFSET * (PCG_ARRAYID_WIDTH != 0)) diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 5b7e6b1ba54f..be01380f798a 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -223,7 +223,7 @@ #define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ #define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ #define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ -#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */ +#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxiliary power support mask */ #define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ #define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ #define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ @@ -435,7 +435,7 @@ #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ #define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */ #define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* L1 Clock Power Management */ -#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Suprise Down Error Reporting Capable */ +#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Surprise Down Error Reporting Capable */ #define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */ #define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */ #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 311b4dc785a1..393b60c71732 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -662,7 +662,7 @@ struct pmu { int (*commit_txn) (struct pmu *pmu); /* optional */ /* * Will cancel the transaction, assumes ->del() is called - * for each successfull ->add() during the transaction. + * for each successful ->add() during the transaction. */ void (*cancel_txn) (struct pmu *pmu); /* optional */ }; diff --git a/include/linux/pid.h b/include/linux/pid.h index efceda0a51b1..31afb7ecbe1f 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -21,7 +21,7 @@ enum pid_type * quickly from the numeric pid value. The attached processes may be * quickly accessed by following pointers from struct pid. * - * Storing pid_t values in the kernel and refering to them later has a + * Storing pid_t values in the kernel and referring to them later has a * problem. The process originally with that pid may have exited and the * pid allocator wrapped, and another process could have come along * and been assigned that pid. diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index b1032a3fafdc..3a02e0208575 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -223,7 +223,7 @@ struct tc_gred_qopt { __u32 limit; /* HARD maximal queue length (bytes) */ __u32 qth_min; /* Min average length threshold (bytes) */ __u32 qth_max; /* Max average length threshold (bytes) */ - __u32 DP; /* upto 2^32 DPs */ + __u32 DP; /* up to 2^32 DPs */ __u32 backlog; __u32 qave; __u32 forced; diff --git a/include/linux/poll.h b/include/linux/poll.h index 1a2ccd6f3823..cf40010ce0cd 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -82,7 +82,7 @@ static inline int poll_schedule(struct poll_wqueues *pwq, int state) } /* - * Scaleable version of the fd_set. + * Scalable version of the fd_set. */ typedef struct { diff --git a/include/linux/prefetch.h b/include/linux/prefetch.h index af7c36a5a521..a3bfbdf63d32 100644 --- a/include/linux/prefetch.h +++ b/include/linux/prefetch.h @@ -29,7 +29,7 @@ prefetchw(x) - prefetches the cacheline at "x" for write spin_lock_prefetch(x) - prefetches the spinlock *x for taking - there is also PREFETCH_STRIDE which is the architecure-prefered + there is also PREFETCH_STRIDE which is the architecure-preferred "lookahead" size for prefetching streamed operations. */ diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index 2f691e4e6222..44835fb39793 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h @@ -122,7 +122,7 @@ #define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */ #define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */ #define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */ -#define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interupt Enable */ +#define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interrupt Enable */ #define SSCR1_IFS (1 << 16) /* Invert Frame Signal */ #define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */ #define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */ diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index ffa2efbbe382..75cbf4f62fe8 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h @@ -251,7 +251,7 @@ struct mdp_superblock_1 { __le64 utime; /* 40 bits second, 24 btes microseconds */ __le64 events; /* incremented when superblock updated */ __le64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ - __le32 sb_csum; /* checksum upto devs[max_dev] */ + __le32 sb_csum; /* checksum up to devs[max_dev] */ __le32 max_dev; /* size of devs[] array to consider */ __u8 pad3[64-32]; /* set to 0 when writing */ diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 0a3842aacba9..eca75df00fed 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1557,7 +1557,7 @@ struct tree_balance { /* When inserting an item. */ #define M_INSERT 'i' /* When inserting into (directories only) or appending onto an already - existant item. */ + existent item. */ #define M_PASTE 'p' /* When deleting an item. */ #define M_DELETE 'd' diff --git a/include/linux/sched.h b/include/linux/sched.h index 83bd2e2982fc..4ec2c027e92c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -854,7 +854,7 @@ extern int __weak arch_sd_sibiling_asym_packing(void); /* * Optimise SD flags for power savings: - * SD_BALANCE_NEWIDLE helps agressive task consolidation and power savings. + * SD_BALANCE_NEWIDLE helps aggressive task consolidation and power savings. * Keep default SD flags if sched_{smt,mc}_power_saving=0 */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 239083bfea13..b759896d9754 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -474,7 +474,7 @@ static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst) extern void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst); /** - * skb_dst_is_noref - Test if skb dst isnt refcounted + * skb_dst_is_noref - Test if skb dst isn't refcounted * @skb: buffer */ static inline bool skb_dst_is_noref(const struct sk_buff *skb) diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h index bc21db598c06..76199b75d584 100644 --- a/include/linux/smc91x.h +++ b/include/linux/smc91x.h @@ -21,7 +21,7 @@ #define RPC_LED_10 (0x02) /* LED = 10Mbps link detect */ #define RPC_LED_FD (0x03) /* LED = Full Duplex Mode */ #define RPC_LED_TX_RX (0x04) /* LED = TX or RX packet occurred */ -#define RPC_LED_100 (0x05) /* LED = 100Mbps link dectect */ +#define RPC_LED_100 (0x05) /* LED = 100Mbps link detect */ #define RPC_LED_TX (0x06) /* LED = TX packet occurred */ #define RPC_LED_RX (0x07) /* LED = RX packet occurred */ diff --git a/include/linux/socket.h b/include/linux/socket.h index edbb1d07ddf4..d2b5e982f079 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -88,7 +88,7 @@ struct cmsghdr { }; /* - * Ancilliary data object information MACROS + * Ancillary data object information MACROS * Table 5-14 of POSIX 1003.1g */ diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h index 1904afedb82f..fe204fe39f7c 100644 --- a/include/linux/soundcard.h +++ b/include/linux/soundcard.h @@ -1231,7 +1231,7 @@ void seqbuf_dump(void); /* This function must be provided by programs */ #define SEQ_PANNING(dev, voice, pos) SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2) /* - * Timing and syncronization macros + * Timing and synchronization macros */ #define _TIMER_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\ diff --git a/include/linux/spi/spidev.h b/include/linux/spi/spidev.h index bf0570a84f7a..52d9ed01855f 100644 --- a/include/linux/spi/spidev.h +++ b/include/linux/spi/spidev.h @@ -66,7 +66,7 @@ * are in a different address space (and may be of different sizes in some * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel). * Zero-initialize the structure, including currently unused fields, to - * accomodate potential future updates. + * accommodate potential future updates. * * SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync(). * Pass it an array of related transfers, they'll execute together. diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 80e535897de6..0b22d51258e6 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -81,7 +81,7 @@ #include /* - * Pull the arch_spin*() functions/declarations (UP-nondebug doesnt need them): + * Pull the arch_spin*() functions/declarations (UP-nondebug doesn't need them): */ #ifdef CONFIG_SMP # include diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index e10352915698..f29197a4b227 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -26,7 +26,7 @@ #ifndef __STMMAC_PLATFORM_DATA #define __STMMAC_PLATFORM_DATA -/* platfrom data for platfrom device structure's platfrom_data field */ +/* platform data for platform device structure's platform_data field */ /* Private data for the STM on-board ethernet driver */ struct plat_stmmacenet_data { diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index 1808960c5059..092dc9b1ce7d 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -105,7 +105,7 @@ static inline int try_stop_cpus(const struct cpumask *cpumask, * @cpus: the cpus to run the @fn() on (NULL = any online cpu) * * Description: This causes a thread to be scheduled on every cpu, - * each of which disables interrupts. The result is that noone is + * each of which disables interrupts. The result is that no one is * holding a spinlock or inside any other preempt-disabled region when * @fn() runs. * diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 7898ea13de70..8d2eef1a8582 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -35,10 +35,10 @@ * Each cache must be registered so that it can be cleaned regularly. * When the cache is unregistered, it is flushed completely. * - * Entries have a ref count and a 'hashed' flag which counts the existance + * Entries have a ref count and a 'hashed' flag which counts the existence * in the hash table. * We only expire entries when refcount is zero. - * Existance in the cache is counted the refcount. + * Existence in the cache is counted the refcount. */ /* Every cache item has a common header that is used diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h index ca7d725861fc..83bbee3f089c 100644 --- a/include/linux/sunrpc/svcauth_gss.h +++ b/include/linux/sunrpc/svcauth_gss.h @@ -2,7 +2,7 @@ * linux/include/linux/sunrpc/svcauth_gss.h * * Bruce Fields - * Copyright (c) 2002 The Regents of the Unviersity of Michigan + * Copyright (c) 2002 The Regents of the University of Michigan */ #ifndef _LINUX_SUNRPC_SVCAUTH_GSS_H diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index 8a75da551e4e..dfb078db8ebb 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -7,13 +7,13 @@ * We still have a notion of a driver for a system device, because we still * want to perform basic operations on these devices. * - * We also support auxillary drivers binding to devices of a certain class. + * We also support auxiliary drivers binding to devices of a certain class. * * This allows configurable drivers to register themselves for devices of * a certain type. And, it allows class definitions to reside in generic * code while arch-specific code can register specific drivers. * - * Auxillary drivers registered with a NULL cls are registered as drivers + * Auxiliary drivers registered with a NULL cls are registered as drivers * for all system devices, and get notification calls for each device. */ @@ -70,7 +70,7 @@ extern int sysdev_class_create_file(struct sysdev_class *, extern void sysdev_class_remove_file(struct sysdev_class *, struct sysdev_class_attribute *); /** - * Auxillary system device drivers. + * Auxiliary system device drivers. */ struct sysdev_driver { diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h index d24aabaca474..a520fd70a59f 100644 --- a/include/linux/timerqueue.h +++ b/include/linux/timerqueue.h @@ -24,7 +24,7 @@ extern struct timerqueue_node *timerqueue_iterate_next( struct timerqueue_node *node); /** - * timerqueue_getnext - Returns the timer with the earlies expiration time + * timerqueue_getnext - Returns the timer with the earliest expiration time * * @head: head of timerqueue * diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 3a2e66d88a32..ebcfa4ebdbf8 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -169,7 +169,7 @@ static inline int tracehook_unsafe_exec(struct task_struct *task) * tracehook_tracer_task - return the task that is tracing the given task * @tsk: task to consider * - * Returns NULL if noone is tracing @task, or the &struct task_struct + * Returns NULL if no one is tracing @task, or the &struct task_struct * pointer to its tracer. * * Must called under rcu_read_lock(). The pointer returned might be kept @@ -448,7 +448,7 @@ static inline int tracehook_force_sigpending(void) * * Return zero to check for a real pending signal normally. * Return -1 after releasing the siglock to repeat the check. - * Return a signal number to induce an artifical signal delivery, + * Return a signal number to induce an artificial signal delivery, * setting *@info and *@return_ka to specify its details and behavior. * * The @return_ka->sa_handler value controls the disposition of the diff --git a/include/linux/ucb1400.h b/include/linux/ucb1400.h index 1b4790911052..5c75153f9441 100644 --- a/include/linux/ucb1400.h +++ b/include/linux/ucb1400.h @@ -8,7 +8,7 @@ * Copyright: MontaVista Software, Inc. * * Spliting done by: Marek Vasut - * If something doesnt work and it worked before spliting, e-mail me, + * If something doesn't work and it worked before spliting, e-mail me, * dont bother Nicolas please ;-) * * This program is free software; you can redistribute it and/or modify diff --git a/include/linux/usb.h b/include/linux/usb.h index e63efeb378e3..65f78ca5d88e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -623,7 +623,7 @@ extern struct usb_host_interface *usb_find_alt_setting( * USB hubs. That makes it stay the same until systems are physically * reconfigured, by re-cabling a tree of USB devices or by moving USB host * controllers. Adding and removing devices, including virtual root hubs - * in host controller driver modules, does not change these path identifers; + * in host controller driver modules, does not change these path identifiers; * neither does rebooting or re-enumerating. These are more useful identifiers * than changeable ("unstable") ones like bus numbers or device addresses. * @@ -793,7 +793,7 @@ struct usbdrv_wrap { * usb_set_intfdata() to associate driver-specific data with the * interface. It may also use usb_set_interface() to specify the * appropriate altsetting. If unwilling to manage the interface, - * return -ENODEV, if genuine IO errors occured, an appropriate + * return -ENODEV, if genuine IO errors occurred, an appropriate * negative errno value. * @disconnect: Called when the interface is no longer accessible, usually * because its device has been (or is being) disconnected or the diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3d29a7dcac2d..882a084a8411 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -188,7 +188,7 @@ ep_choose(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, * @bind() method is then used to initialize all the functions and then * call @usb_add_function() for them. * - * Those functions would normally be independant of each other, but that's + * Those functions would normally be independent of each other, but that's * not mandatory. CDC WMC devices are an example where functions often * depend on other functions, with some functions subsidiary to others. * Such interdependency may be managed in any way, so long as all of the diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h index 656380245198..e49dfd45baa4 100644 --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -159,7 +159,7 @@ struct ehci_regs { #define USBMODE_CM_IDLE (0<<0) /* idle state */ /* Moorestown has some non-standard registers, partially due to the fact that - * its EHCI controller has both TT and LPM support. HOSTPCx are extentions to + * its EHCI controller has both TT and LPM support. HOSTPCx are extensions to * PORTSCx */ #define HOSTPC0 0x84 /* HOSTPC extension */ diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h index 6f649c13193b..7587ef934ba8 100644 --- a/include/linux/usb/functionfs.h +++ b/include/linux/usb/functionfs.h @@ -45,7 +45,7 @@ struct usb_functionfs_descs_head { * | off | name | type | description | * |-----+-----------+--------------+--------------------------------------| * | 0 | magic | LE32 | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC | - * | 4 | lenght | LE32 | length of the whole data chunk | + * | 4 | length | LE32 | length of the whole data chunk | * | 8 | fs_count | LE32 | number of full-speed descriptors | * | 12 | hs_count | LE32 | number of high-speed descriptors | * | 16 | fs_descrs | Descriptor[] | list of full-speed descriptors | @@ -86,7 +86,7 @@ struct usb_functionfs_strings_head { * | 0 | lang | LE16 | language code | * | 2 | strings | String[str_count] | array of strings in given language | * - * For each string ther is one strings entry (ie. there are str_count + * For each string there is one strings entry (ie. there are str_count * string entries). Each String is a NUL terminated string encoded in * UTF-8. */ diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 006412ce2303..e538172c0f64 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -72,7 +72,7 @@ struct usb_ep; * Bulk endpoints can use any size buffers, and can also be used for interrupt * transfers. interrupt-only endpoints can be much less functional. * - * NOTE: this is analagous to 'struct urb' on the host side, except that + * NOTE: this is analogous to 'struct urb' on the host side, except that * it's thinner and promotes more pre-allocation. */ @@ -269,7 +269,7 @@ static inline void usb_ep_free_request(struct usb_ep *ep, * * Control endpoints ... after getting a setup() callback, the driver queues * one response (even if it would be zero length). That enables the - * status ack, after transfering data as specified in the response. Setup + * status ack, after transferring data as specified in the response. Setup * functions may return negative error codes to generate protocol stalls. * (Note that some USB device controllers disallow protocol stall responses * in some cases.) When control responses are deferred (the response is diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h index 1d1040865661..c8c52e3c91de 100644 --- a/include/linux/usb/midi.h +++ b/include/linux/usb/midi.h @@ -70,7 +70,7 @@ struct usb_midi_out_jack_descriptor { __u8 bJackID; __u8 bNrInputPins; /* p */ struct usb_midi_source_pin pins[]; /* [p] */ - /*__u8 iJack; -- ommitted due to variable-sized pins[] */ + /*__u8 iJack; -- omitted due to variable-sized pins[] */ } __attribute__ ((packed)); #define USB_DT_MIDI_OUT_SIZE(p) (7 + 2 * (p)) diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h index 63ebdcc5dda6..0c4d4ca370ec 100644 --- a/include/linux/usb/wusb.h +++ b/include/linux/usb/wusb.h @@ -126,7 +126,7 @@ enum { /** * WUSB IE: Channel Stop (WUSB1.0[7.5.8]) * - * Tells devices the host is going to stop sending MMCs and will dissapear. + * Tells devices the host is going to stop sending MMCs and will disappear. */ struct wuie_channel_stop { struct wuie_hdr hdr; diff --git a/include/linux/uwb.h b/include/linux/uwb.h index 7fc9746f22cd..b0c564ec2160 100644 --- a/include/linux/uwb.h +++ b/include/linux/uwb.h @@ -274,7 +274,7 @@ static inline void uwb_mas_bm_copy_le(void *dst, const struct uwb_mas_bm *mas) /** * struct uwb_drp_avail - a radio controller's view of MAS usage - * @global: MAS unused by neighbors (excluding reservations targetted + * @global: MAS unused by neighbors (excluding reservations targeted * or owned by the local radio controller) or the beaon period * @local: MAS unused by local established reservations * @pending: MAS unused by local pending reservations @@ -702,10 +702,10 @@ void edc_init(struct edc *edc) edc->timestart = jiffies; } -/* Called when an error occured. +/* Called when an error occurred. * This is way to determine if the number of acceptable errors per time * period has been exceeded. It is not accurate as there are cases in which - * this scheme will not work, for example if there are periodic occurences + * this scheme will not work, for example if there are periodic occurrences * of errors that straddle updates to the start time. This scheme is * sufficient for our usage. * diff --git a/include/linux/uwb/umc.h b/include/linux/uwb/umc.h index 4b4fc0f43855..7b4842028ca7 100644 --- a/include/linux/uwb/umc.h +++ b/include/linux/uwb/umc.h @@ -132,7 +132,7 @@ int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc); * * FIXME: This is as dirty as it gets, but we need some way to check * the correct type of umc_dev->parent (so that for example, we can - * cast to pci_dev). Casting to pci_dev is necesary because at some + * cast to pci_dev). Casting to pci_dev is necessary because at some * point we need to request resources from the device. Mapping is * easily over come (ioremap and stuff are bus agnostic), but hooking * up to some error handlers (such as pci error handlers) might need diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index e9e1524b582c..9c3120dca294 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -78,7 +78,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev, * wether the card is doing legacy decoding for that type of resource. If * yes, the lock is "converted" into a legacy resource lock. * The arbiter will first look for all VGA cards that might conflict - * and disable their IOs and/or Memory access, inlcuding VGA forwarding + * and disable their IOs and/or Memory access, including VGA forwarding * on P2P bridges if necessary, so that the requested resources can * be used. Then, the card is marked as locking these resources and * the IO and/or Memory accesse are enabled on the card (including @@ -187,7 +187,7 @@ extern struct pci_dev *vga_default_device(void); * vga_conflicts * * Architectures should define this if they have several - * independant PCI domains that can afford concurrent VGA + * independent PCI domains that can afford concurrent VGA * decoding */ diff --git a/include/linux/wimax.h b/include/linux/wimax.h index 4fdcc5635518..9f6b77af2f6d 100644 --- a/include/linux/wimax.h +++ b/include/linux/wimax.h @@ -114,7 +114,7 @@ enum { WIMAX_GNL_RESET_IFIDX = 1, }; -/* Atributes for wimax_state_get() */ +/* Attributes for wimax_state_get() */ enum { WIMAX_GNL_STGET_IFIDX = 1, }; diff --git a/include/linux/xilinxfb.h b/include/linux/xilinxfb.h index f2463f559fb9..5a155a968054 100644 --- a/include/linux/xilinxfb.h +++ b/include/linux/xilinxfb.h @@ -16,7 +16,7 @@ /* ML300/403 reference design framebuffer driver platform data struct */ struct xilinxfb_platform_data { u32 rotate_screen; /* Flag to rotate display 180 degrees */ - u32 screen_height_mm; /* Physical dimentions of screen in mm */ + u32 screen_height_mm; /* Physical dimensions of screen in mm */ u32 screen_width_mm; u32 xres, yres; /* resolution of screen in pixels */ u32 xvirt, yvirt; /* resolution of memory buffer */ diff --git a/include/media/davinci/dm355_ccdc.h b/include/media/davinci/dm355_ccdc.h index df8a7b107477..adf2fe4bf0bb 100644 --- a/include/media/davinci/dm355_ccdc.h +++ b/include/media/davinci/dm355_ccdc.h @@ -193,7 +193,7 @@ struct ccdc_dft_corr_mem_ctl { #define CCDC_DFT_TABLE_SIZE 16 /* * Main Structure for vertical defect correction. Vertical defect - * correction can correct upto 16 defects if defects less than 16 + * correction can correct up to 16 defects if defects less than 16 * then pad the rest with 0 */ struct ccdc_vertical_dft { diff --git a/include/media/davinci/isif.h b/include/media/davinci/isif.h index b0b74ad618cc..7f3d76a4b9e3 100644 --- a/include/media/davinci/isif.h +++ b/include/media/davinci/isif.h @@ -199,7 +199,7 @@ struct isif_black_clamp { }; /************************************************************************* -** Color Space Convertion (CSC) +** Color Space Conversion (CSC) *************************************************************************/ #define ISIF_CSC_NUM_COEFF 16 struct isif_color_space_conv { diff --git a/include/media/lirc.h b/include/media/lirc.h index 6678a169fd9e..4b3ab2966b5a 100644 --- a/include/media/lirc.h +++ b/include/media/lirc.h @@ -137,7 +137,7 @@ */ #define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) /* - * if filter cannot be set independantly for pulse/space, this should + * if filter cannot be set independently for pulse/space, this should * be used */ #define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 6b75a6971346..cdf2e8ac4309 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -119,7 +119,7 @@ do { \ * @P9_TREAD: request to transfer data from a file or directory * @P9_RREAD: response with data requested * @P9_TWRITE: reuqest to transfer data to a file - * @P9_RWRITE: response with out much data was transfered to file + * @P9_RWRITE: response with out much data was transferred to file * @P9_TCLUNK: forget about a handle to an entity within the file system * @P9_RCLUNK: response when server has forgotten about the handle * @P9_TREMOVE: request to remove an entity from the hierarchy @@ -294,7 +294,7 @@ enum p9_perm_t { * * QID types are a subset of permissions - they are primarily * used to differentiate semantics for a file system entity via - * a jump-table. Their value is also the most signifigant 16 bits + * a jump-table. Their value is also the most significant 16 bits * of the permission_t * * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat @@ -366,8 +366,8 @@ struct p9_qid { /** * struct p9_stat - file system metadata information * @size: length prefix for this stat structure instance - * @type: the type of the server (equivilent to a major number) - * @dev: the sub-type of the server (equivilent to a minor number) + * @type: the type of the server (equivalent to a major number) + * @dev: the sub-type of the server (equivalent to a minor number) * @qid: unique id from the server of type &p9_qid * @mode: Plan 9 format permissions of type &p9_perm_t * @atime: Last access/read time diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 0a30977e3c1f..85c1413f054d 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -101,7 +101,7 @@ enum p9_req_status_t { * Transport use an array to track outstanding requests * instead of a list. While this may incurr overhead during initial * allocation or expansion, it makes request lookup much easier as the - * tag id is a index into an array. (We use tag+1 so that we can accomodate + * tag id is a index into an array. (We use tag+1 so that we can accommodate * the -1 tag for the T_VERSION request). * This also has the nice effect of only having to allocate wait_queues * once, instead of constantly allocating and freeing them. Its possible diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 82868f18c573..8f08c736c4c3 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -30,7 +30,7 @@ /* Default. Add Payload to PDU before sending it down to transport layer */ #define P9_TRANS_PREF_PAYLOAD_DEF 0x0 -/* Send pay load seperately to transport layer along with PDU.*/ +/* Send pay load separately to transport layer along with PDU.*/ #define P9_TRANS_PREF_PAYLOAD_SEP 0x1 /** diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h index f688478bfb84..f33d36341132 100644 --- a/include/net/caif/cfcnfg.h +++ b/include/net/caif/cfcnfg.h @@ -69,7 +69,7 @@ void cfcnfg_remove(struct cfcnfg *cfg); * cfcnfg_add_adapt_layer to specify PHY for the link. * @pref: The phy (link layer) preference. * @fcs: Specify if checksum is used in CAIF Framing Layer. - * @stx: Specify if Start Of Frame eXtention is used. + * @stx: Specify if Start Of Frame extension is used. */ void diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index fa157712e982..a79b6cfb02a8 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -11,7 +11,7 @@ struct gnet_dump { struct sk_buff * skb; struct nlattr * tail; - /* Backward compatability */ + /* Backward compatibility */ int compat_tc_stats; int compat_xstats; void * xstats; diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 30b49ed72f0d..814b434db749 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -92,7 +92,7 @@ static inline struct net *skb_sknet(const struct sk_buff *skb) } /* * This one needed for single_open_net since net is stored directly in - * private not as a struct i.e. seq_file_net cant be used. + * private not as a struct i.e. seq_file_net can't be used. */ static inline struct net *seq_file_single_net(struct seq_file *seq) { diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h index 17fcd964f9d9..fb4b76d5d7f1 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h @@ -204,7 +204,7 @@ struct irlap_cb { notify_t notify; /* Callbacks to IrLMP */ - int mtt_required; /* Minumum turnaround time required */ + int mtt_required; /* Minimum turnaround time required */ int xbofs_delay; /* Nr of XBOF's used to MTT */ int bofs_count; /* Negotiated extra BOFs */ int next_bofs; /* Negotiated extra BOFs after next frame */ diff --git a/include/net/irda/wrapper.h b/include/net/irda/wrapper.h index 2942ad6ab932..eef53ebe3d76 100644 --- a/include/net/irda/wrapper.h +++ b/include/net/irda/wrapper.h @@ -42,7 +42,7 @@ #define IRDA_TRANS 0x20 /* Asynchronous transparency modifier */ -/* States for receving a frame in async mode */ +/* States for receiving a frame in async mode */ enum { OUTSIDE_FRAME, BEGIN_FRAME, diff --git a/include/net/iucv/iucv.h b/include/net/iucv/iucv.h index 205a3360156e..1121baa9f695 100644 --- a/include/net/iucv/iucv.h +++ b/include/net/iucv/iucv.h @@ -173,7 +173,7 @@ struct iucv_handler { /* * The message_pending function is called after an icuv interrupt * type 0x06 or type 0x07 has been received. A new message is - * availabe and can be received with iucv_message_receive. + * available and can be received with iucv_message_receive. */ void (*message_pending)(struct iucv_path *, struct iucv_message *); /* diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index 3afdb21cc31d..5d5a6a4732ef 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -91,7 +91,7 @@ * -------------------- * The implementation goals were as follow : * o Obvious : you should not need a PhD to understand what's happening, - * the benefit is easier maintainance. + * the benefit is easier maintenance. * o Flexible : it should accommodate a wide variety of driver * implementations and be as flexible as the old API. * o Lean : it should be efficient memory wise to minimise the impact @@ -129,7 +129,7 @@ * * Functions prototype uses union iwreq_data * ----------------------------------------- - * Some would have prefered functions defined this way : + * Some would have preferred functions defined this way : * static int mydriver_ioctl_setrate(struct net_device *dev, * long rate, int auto) * 1) The kernel code doesn't "validate" the content of iwreq_data, and diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cefe1b37c493..cb13239fe8e3 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1294,7 +1294,7 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key * handler. * The update_tkip_key() call updates the driver with the new phase 1 key. - * This happens everytime the iv16 wraps around (every 65536 packets). The + * This happens every time the iv16 wraps around (every 65536 packets). The * set_key() call will happen only once for each key (unless the AP did * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is * provided by update_tkip_key only. The trigger that makes mac80211 call this diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index d9549af6929a..65afc4966204 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -32,7 +32,7 @@ static inline void *qdisc_priv(struct Qdisc *q) The result: [34]86 is not good choice for QoS router :-( - The things are not so bad, because we may use artifical + The things are not so bad, because we may use artificial clock evaluated by integration of network data flow in the most critical places. */ diff --git a/include/net/sock.h b/include/net/sock.h index da0534d3401c..01810a3f19df 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1749,7 +1749,7 @@ void sock_net_set(struct sock *sk, struct net *net) /* * Kernel sockets, f.e. rtnl or icmp_socket, are a part of a namespace. - * They should not hold a referrence to a namespace in order to allow + * They should not hold a reference to a namespace in order to allow * to stop it. * Sockets after sk_change_net should be released using sk_release_kernel */ diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index eeb077dd735f..a8122dc56410 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -16,7 +16,7 @@ extern struct proto tcpv6_prot; struct flowi6; -/* extention headers */ +/* extension headers */ extern int ipv6_exthdrs_init(void); extern void ipv6_exthdrs_exit(void); extern int ipv6_frag_init(void); diff --git a/include/net/wimax.h b/include/net/wimax.h index 3461aa1df1e0..c799ba7b708b 100644 --- a/include/net/wimax.h +++ b/include/net/wimax.h @@ -286,7 +286,7 @@ struct wimax_dev; * does not disconnect the device from the bus and return 0. * If that fails, it should resort to some sort of cold or bus * reset (even if it implies a bus disconnection and device - * dissapearance). In that case, -ENODEV should be returned to + * disappearance). In that case, -ENODEV should be returned to * indicate the device is gone. * This operation has to be synchronous, and return only when the * reset is complete. In case of having had to resort to bus/cold diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h index 85926231c07a..d86fffd3c03c 100644 --- a/include/net/wpan-phy.h +++ b/include/net/wpan-phy.h @@ -28,7 +28,7 @@ struct wpan_phy { struct mutex pib_lock; /* - * This is a PIB acording to 802.15.4-2006. + * This is a PIB according to 802.15.4-2006. * We do not provide timing-related variables, as they * aren't used outside of driver */ diff --git a/include/rxrpc/packet.h b/include/rxrpc/packet.h index 9b2c30897e50..f2902ef7ab75 100644 --- a/include/rxrpc/packet.h +++ b/include/rxrpc/packet.h @@ -148,7 +148,7 @@ struct rxkad_challenge { * Kerberos security type-2 response packet */ struct rxkad_response { - __be32 version; /* version of this reponse type */ + __be32 version; /* version of this response type */ __be32 __pad; /* encrypted bit of the response */ diff --git a/include/scsi/fc/fc_fcp.h b/include/scsi/fc/fc_fcp.h index 8a143ca79878..652dec230514 100644 --- a/include/scsi/fc/fc_fcp.h +++ b/include/scsi/fc/fc_fcp.h @@ -75,7 +75,7 @@ struct fcp_cmnd32 { #define FCP_PTA_SIMPLE 0 /* simple task attribute */ #define FCP_PTA_HEADQ 1 /* head of queue task attribute */ #define FCP_PTA_ORDERED 2 /* ordered task attribute */ -#define FCP_PTA_ACA 4 /* auto. contigent allegiance */ +#define FCP_PTA_ACA 4 /* auto. contingent allegiance */ #define FCP_PTA_MASK 7 /* mask for task attribute field */ #define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */ #define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */ diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index c3e1cbcc2ad2..ddb04568a509 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -292,7 +292,7 @@ enum iscsi_param { ISCSI_PARAM_PERSISTENT_PORT, ISCSI_PARAM_SESS_RECOVERY_TMO, - /* pased in through bind conn using transport_fd */ + /* passed in through bind conn using transport_fd */ ISCSI_PARAM_CONN_PORT, ISCSI_PARAM_CONN_ADDRESS, diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 24193c1b0da0..a3cbda4ddb5c 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -260,7 +260,7 @@ struct fcoe_dev_stats { /** * struct fc_seq_els_data - ELS data used for passing ELS specific responses * @reason: The reason for rejection - * @explan: The explaination of the rejection + * @explan: The explanation of the rejection * * Mainly used by the exchange manager layer. */ @@ -525,7 +525,7 @@ struct libfc_function_template { struct fc_frame *); /* - * Send an ELS response using infomation from the received frame. + * Send an ELS response using information from the received frame. * * STATUS: OPTIONAL */ @@ -663,7 +663,7 @@ struct libfc_function_template { int (*rport_logoff)(struct fc_rport_priv *); /* - * Recieve a request from a remote port. + * Receive a request from a remote port. * * STATUS: OPTIONAL */ @@ -704,7 +704,7 @@ struct libfc_function_template { void *)); /* - * Cleanup the FCP layer, used durring link down and reset + * Cleanup the FCP layer, used during link down and reset * * STATUS: OPTIONAL */ diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h index e6b9fd2eea34..ac0cc1d925ef 100644 --- a/include/scsi/libiscsi_tcp.h +++ b/include/scsi/libiscsi_tcp.h @@ -52,7 +52,7 @@ struct iscsi_segment { iscsi_segment_done_fn_t *done; }; -/* Socket connection recieve helper */ +/* Socket connection receive helper */ struct iscsi_tcp_recv { struct iscsi_hdr *hdr; struct iscsi_segment segment; diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index 53a9e886612b..0a5079974fe9 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -265,7 +265,7 @@ int osd_execute_request_async(struct osd_request *or, * @osi - Recievs a more detailed error report information (optional). * @silent - Do not print to dmsg (Even if enabled) * @bad_obj_list - Some commands act on multiple objects. Failed objects will - * be recieved here (optional) + * be received here (optional) * @max_obj - Size of @bad_obj_list. * @bad_attr_list - List of failing attributes (optional) * @max_attr - Size of @bad_attr_list. diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index e7e385842a38..f1f2644137b8 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -46,7 +46,7 @@ struct blk_queue_tags; enum { SCSI_QDEPTH_DEFAULT, /* default requested change, e.g. from sysfs */ SCSI_QDEPTH_QFULL, /* scsi-ml requested due to queue full */ - SCSI_QDEPTH_RAMP_UP, /* scsi-ml requested due to threshhold event */ + SCSI_QDEPTH_RAMP_UP, /* scsi-ml requested due to threshold event */ }; struct scsi_host_template { diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 59816fe31e68..2a65167a8f10 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -192,9 +192,9 @@ struct fc_vport_identifiers { * * This structure exists for each FC port is a virtual FC port. Virtual * ports share the physical link with the Physical port. Each virtual - * ports has a unique presense on the SAN, and may be instantiated via + * ports has a unique presence on the SAN, and may be instantiated via * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a - * unique presense, each vport has it's own view of the fabric, + * unique presence, each vport has it's own view of the fabric, * authentication privilege, and priorities. * * A virtual port may support 1 or more FC4 roles. Typically it is a @@ -370,7 +370,7 @@ struct fc_rport { /* aka fc_starget_attrs */ /* * FC SCSI Target Attributes * - * The SCSI Target is considered an extention of a remote port (as + * The SCSI Target is considered an extension of a remote port (as * a remote port can be more than a SCSI Target). Within the scsi * subsystem, we leave the Target as a separate entity. Doing so * provides backward compatibility with prior FC transport api's, diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index f1dcefe4532b..02cbb50225bb 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -385,7 +385,7 @@ #define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */ #define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */ #define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */ -#define AC97_SCAP_POWER_SAVE (1<<11) /* capable for aggresive power-saving */ +#define AC97_SCAP_POWER_SAVE (1<<11) /* capable for aggressive power-saving */ /* ac97->flags */ #define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */ diff --git a/include/sound/control.h b/include/sound/control.h index e67db2869360..404acb859cee 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -191,7 +191,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, * Returns zero if successful or a negative error code. * * All slaves must be the same type (returning the same information - * via info callback). The fucntion doesn't check it, so it's your + * via info callback). The function doesn't check it, so it's your * responsibility. * * Also, some additional limitations: diff --git a/include/sound/cs46xx_dsp_spos.h b/include/sound/cs46xx_dsp_spos.h index 49b03c9e5e55..8008c59288a6 100644 --- a/include/sound/cs46xx_dsp_spos.h +++ b/include/sound/cs46xx_dsp_spos.h @@ -147,7 +147,7 @@ struct dsp_pcm_channel_descriptor { }; struct dsp_spos_instance { - struct dsp_symbol_desc symbol_table; /* currently availble loaded symbols in SP */ + struct dsp_symbol_desc symbol_table; /* currently available loaded symbols in SP */ int nmodules; struct dsp_module_desc * modules; /* modules loaded into SP */ diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h index 1774ff5ff632..1f59ea2a4a76 100644 --- a/include/sound/hdspm.h +++ b/include/sound/hdspm.h @@ -193,7 +193,7 @@ struct hdspm_version { * 32768 Bytes */ -/* organisation is 64 channelfader in a continous memory block */ +/* organisation is 64 channelfader in a continuous memory block */ /* equivalent to hardware definition, maybe for future feature of mmap of * them */ diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 979ed84e07d6..5534fdf4d670 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -23,7 +23,7 @@ /* * SoC dynamic audio power management * - * We can have upto 4 power domains + * We can have up to 4 power domains * 1. Codec domain - VREF, VMID * Usually controlled at codec probe/remove, although can be set * at stream time if power is not needed for sidetone, etc. diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index c15ed5026fb5..1d3b5b2f0dbc 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -22,7 +22,7 @@ * Note that both include/scsi/scsi_cmnd.h:MAX_COMMAND_SIZE and * include/linux/blkdev.h:BLOCK_MAX_CDB as of v2.6.36-rc4 still use * 16-byte CDBs by default and require an extra allocation for - * 32-byte CDBs to becasue of legacy issues. + * 32-byte CDBs to because of legacy issues. * * Within TCM Core there are no such legacy limitiations, so we go ahead * use 32-byte CDBs by default and use include/scsi/scsi.h:scsi_command_size() @@ -302,7 +302,7 @@ struct t10_wwn { /* - * Used by TCM Core internally to signal if >= SPC-3 peristent reservations + * Used by TCM Core internally to signal if >= SPC-3 persistent reservations * emulation is enabled or disabled, or running in with TCM/pSCSI passthrough * mode */ @@ -934,7 +934,7 @@ struct se_portal_group { struct list_head acl_node_list; struct se_lun *tpg_lun_list; struct se_lun tpg_virt_lun0; - /* List of TCM sessions assoicated wth this TPG */ + /* List of TCM sessions associated wth this TPG */ struct list_head tpg_sess_list; /* Pointer to $FABRIC_MOD dependent code */ struct target_core_fabric_ops *se_tpg_tfo; diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index 5eb8b1ae59d1..dc78f77f9450 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h @@ -35,7 +35,7 @@ struct target_core_fabric_ops { /* * Optional function pointer for TCM to perform command map * from TCM processing thread context, for those struct se_cmd - * initally allocated in interrupt context. + * initially allocated in interrupt context. */ int (*new_cmd_map)(struct se_cmd *); /* diff --git a/include/video/kyro.h b/include/video/kyro.h index dba7de2ee4a8..c563968e926c 100644 --- a/include/video/kyro.h +++ b/include/video/kyro.h @@ -32,7 +32,7 @@ struct kyrofb_info { u32 PIXCLK; /* Pixel Clock */ u32 HCLK; /* Hor Clock */ - /* Usefull to hold depth here for Linux */ + /* Useful to hold depth here for Linux */ u8 PIXDEPTH; #ifdef CONFIG_MTRR diff --git a/include/video/neomagic.h b/include/video/neomagic.h index 08b663782956..bc5013e8059d 100644 --- a/include/video/neomagic.h +++ b/include/video/neomagic.h @@ -129,7 +129,7 @@ struct neofb_par { unsigned char CRTC[25]; /* Crtc Controller */ unsigned char Sequencer[5]; /* Video Sequencer */ unsigned char Graphics[9]; /* Video Graphics */ - unsigned char Attribute[21]; /* Video Atribute */ + unsigned char Attribute[21]; /* Video Attribute */ unsigned char GeneralLockReg; unsigned char ExtCRTDispAddr; diff --git a/include/video/newport.h b/include/video/newport.h index 001b935e71c4..3d7c4b492ec6 100644 --- a/include/video/newport.h +++ b/include/video/newport.h @@ -5,7 +5,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * Ulf Carlsson - Compability with the IRIX structures added + * Ulf Carlsson - Compatibility with the IRIX structures added */ #ifndef _SGI_NEWPORT_H diff --git a/include/video/sisfb.h b/include/video/sisfb.h index fdd74f1a6791..6dc5df9e43f3 100644 --- a/include/video/sisfb.h +++ b/include/video/sisfb.h @@ -151,7 +151,7 @@ struct sisfb_cmd { __u32 sisfb_result[4]; }; -/* Addtional IOCTLs for communication sisfb <> X driver */ +/* Additional IOCTLs for communication sisfb <> X driver */ /* If changing this, vgatypes.h must also be changed (for X driver) */ /* ioctl for identifying and giving some info (esp. memory heap start) */ diff --git a/include/video/sstfb.h b/include/video/sstfb.h index b52f07381243..c449eace12cd 100644 --- a/include/video/sstfb.h +++ b/include/video/sstfb.h @@ -156,7 +156,7 @@ #define DAC_READ FBIINIT2 /* in remap mode */ #define FBIINIT3 0x021c /* fbi controls */ # define DISABLE_TEXTURE BIT(6) -# define Y_SWAP_ORIGIN_SHIFT 22 /* Y swap substraction value */ +# define Y_SWAP_ORIGIN_SHIFT 22 /* Y swap subtraction value */ #define HSYNC 0x0220 #define VSYNC 0x0224 #define DAC_DATA 0x022c @@ -212,9 +212,9 @@ # define DACREG_CR0_24BPP 0x50 /* mode 5 */ #define DACREG_CR1_I 0x05 #define DACREG_CC_I 0x06 -# define DACREG_CC_CLKA BIT(7) /* clk A controled by regs */ +# define DACREG_CC_CLKA BIT(7) /* clk A controlled by regs */ # define DACREG_CC_CLKA_C (2<<4) /* clk A uses reg C */ -# define DACREG_CC_CLKB BIT(3) /* clk B controled by regs */ +# define DACREG_CC_CLKB BIT(3) /* clk B controlled by regs */ # define DACREG_CC_CLKB_D 3 /* clkB uses reg D */ #define DACREG_AC0_I 0x48 /* clock A reg C */ #define DACREG_AC1_I 0x49 diff --git a/include/xen/interface/elfnote.h b/include/xen/interface/elfnote.h index 7a8262c375cc..0360b15f4883 100644 --- a/include/xen/interface/elfnote.h +++ b/include/xen/interface/elfnote.h @@ -51,7 +51,7 @@ /* * The offset of the ELF paddr field from the acutal required - * psuedo-physical address (numeric). + * pseudo-physical address (numeric). * * This is used to maintain backwards compatibility with older kernels * which wrote __PAGE_OFFSET into that field. This field defaults to 0 diff --git a/init/do_mounts.c b/init/do_mounts.c index 3e0112157795..c0851a8e030c 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -186,7 +186,7 @@ dev_t name_to_dev_t(char *name) goto done; /* - * try non-existant, but valid partition, which may only exist + * try non-existent, but valid partition, which may only exist * after revalidating the disk, like partitioned md devices */ while (p > s && isdigit(p[-1])) diff --git a/ipc/msg.c b/ipc/msg.c index 0e732e92e22f..7385de25788a 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -704,7 +704,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext, msq->q_stime = get_seconds(); if (!pipelined_send(msq, msg)) { - /* noone is waiting for this message, enqueue it */ + /* no one is waiting for this message, enqueue it */ list_add_tail(&msg->m_list, &msq->q_messages); msq->q_cbytes += msgsz; msq->q_qnum++; @@ -842,7 +842,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, * Disable preemption. We don't hold a reference to the queue * and getting a reference would defeat the idea of a lockless * operation, thus the code relies on rcu to guarantee the - * existance of msq: + * existence of msq: * Prior to destruction, expunge_all(-EIRDM) changes r_msg. * Thus if r_msg is -EAGAIN, then the queue not yet destroyed. * rcu_read_lock() prevents preemption between reading r_msg diff --git a/ipc/sem.c b/ipc/sem.c index ae040a0727c2..34193ed69fbe 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1362,7 +1362,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, * semid identifiers are not unique - find_alloc_undo may have * allocated an undo structure, it was invalidated by an RMID * and now a new array with received the same id. Check and fail. - * This case can be detected checking un->semid. The existance of + * This case can be detected checking un->semid. The existence of * "un" itself is guaranteed by rcu. */ error = -EIDRM; diff --git a/ipc/shm.c b/ipc/shm.c index 8644452f5c4c..729acb7e3148 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1056,7 +1056,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr) /* * We need look no further than the maximum address a fragment * could possibly have landed at. Also cast things to loff_t to - * prevent overflows and make comparisions vs. equal-width types. + * prevent overflows and make comparisons vs. equal-width types. */ size = PAGE_ALIGN(size); while (vma && (loff_t)(vma->vm_end - addr) <= size) { diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 37b2bea170c8..e99dda04b126 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -607,7 +607,7 @@ void audit_trim_trees(void) spin_lock(&hash_lock); list_for_each_entry(node, &tree->chunks, list) { struct audit_chunk *chunk = find_chunk(node); - /* this could be NULL if the watch is dieing else where... */ + /* this could be NULL if the watch is dying else where... */ struct inode *inode = chunk->mark.i.inode; node->index |= 1U<<31; if (iterate_mounts(compare_root, inode, root_mnt)) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f49a0318c2ed..b33513a08beb 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1011,7 +1011,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, /* * to_send and len_sent accounting are very loose estimates. We aren't * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being - * within about 500 bytes (next page boundry) + * within about 500 bytes (next page boundary) * * why snprintf? an int is up to 12 digits long. if we just assumed when * logging that a[%d]= was going to be 16 characters long we would be wasting diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e31b220a743d..25c7eb52de1a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -157,7 +157,7 @@ struct css_id { }; /* - * cgroup_event represents events which userspace want to recieve. + * cgroup_event represents events which userspace want to receive. */ struct cgroup_event { /* diff --git a/kernel/cpu.c b/kernel/cpu.c index c95fc4df0faa..12b7458f23b1 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -126,7 +126,7 @@ static void cpu_hotplug_done(void) #else /* #if CONFIG_HOTPLUG_CPU */ static void cpu_hotplug_begin(void) {} static void cpu_hotplug_done(void) {} -#endif /* #esle #if CONFIG_HOTPLUG_CPU */ +#endif /* #else #if CONFIG_HOTPLUG_CPU */ /* Need to know about CPUs going up/down? */ int __ref register_cpu_notifier(struct notifier_block *nb) diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index cefd4a11f6d9..bad6786dee88 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -538,7 +538,7 @@ return_normal: /* * For single stepping, try to only enter on the processor - * that was single stepping. To gaurd against a deadlock, the + * that was single stepping. To guard against a deadlock, the * kernel will only try for the value of sstep_tries before * giving up and continuing on. */ diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 6bc6e3bc4f9c..be14779bcef6 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -441,9 +441,9 @@ static int kdb_check_regs(void) * symbol name, and offset to the caller. * * The argument may consist of a numeric value (decimal or - * hexidecimal), a symbol name, a register name (preceeded by the + * hexidecimal), a symbol name, a register name (preceded by the * percent sign), an environment variable with a numeric value - * (preceeded by a dollar sign) or a simple arithmetic expression + * (preceded by a dollar sign) or a simple arithmetic expression * consisting of a symbol name, +/-, and a numeric constant value * (offset). * Parameters: @@ -1335,7 +1335,7 @@ void kdb_print_state(const char *text, int value) * error The hardware-defined error code * reason2 kdb's current reason code. * Initially error but can change - * acording to kdb state. + * according to kdb state. * db_result Result code from break or debug point. * regs The exception frame at time of fault/breakpoint. * should always be valid. diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index 6b2485dcb050..5532dd37aa86 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c @@ -545,7 +545,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size) * Mask for process state. * Notes: * The mask folds data from several sources into a single long value, so - * be carefull not to overlap the bits. TASK_* bits are in the LSB, + * be careful not to overlap the bits. TASK_* bits are in the LSB, * special cases like UNRUNNABLE are in the MSB. As of 2.6.10-rc1 there * is no overlap between TASK_* and EXIT_* but that may not always be * true, so EXIT_* bits are shifted left 16 bits before being stored in diff --git a/kernel/exit.c b/kernel/exit.c index 6a488ad2dce5..f5d2f63bae0b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -841,7 +841,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead) /* Let father know we died * * Thread signals are configurable, but you aren't going to use - * that to send signals to arbitary processes. + * that to send signals to arbitrary processes. * That stops right now. * * If the parent exec id doesn't match the exec id we saved diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 1dafc8652bd8..4af1e2b244cb 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -415,7 +415,7 @@ out: * @desc: the interrupt description structure for this irq * * Interrupt occures on the falling and/or rising edge of a hardware - * signal. The occurence is latched into the irq controller hardware + * signal. The occurrence is latched into the irq controller hardware * and must be acked in order to be reenabled. After the ack another * interrupt can happen on the same source even before the first one * is handled by the associated event handler. If this happens it diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index bc6194698dfd..47420908fba0 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c @@ -35,7 +35,7 @@ void irq_move_masked_irq(struct irq_data *idata) * do the disable, re-program, enable sequence. * This is *not* particularly important for level triggered * but in a edge trigger case, we might be setting rte - * when an active trigger is comming in. This could + * when an active trigger is coming in. This could * cause some ioapics to mal-function. * Being paranoid i guess! * diff --git a/kernel/kexec.c b/kernel/kexec.c index ec19b92c7ebd..e7e3d9788dc3 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -144,7 +144,7 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, /* Initialize the list of destination pages */ INIT_LIST_HEAD(&image->dest_pages); - /* Initialize the list of unuseable pages */ + /* Initialize the list of unusable pages */ INIT_LIST_HEAD(&image->unuseable_pages); /* Read in the segments */ @@ -454,7 +454,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image, /* Deal with the destination pages I have inadvertently allocated. * * Ideally I would convert multi-page allocations into single - * page allocations, and add everyting to image->dest_pages. + * page allocations, and add everything to image->dest_pages. * * For now it is simpler to just free the pages. */ @@ -602,7 +602,7 @@ static void kimage_free_extra_pages(struct kimage *image) /* Walk through and free any extra destination pages I may have */ kimage_free_page_list(&image->dest_pages); - /* Walk through and free any unuseable pages I have cached */ + /* Walk through and free any unusable pages I have cached */ kimage_free_page_list(&image->unuseable_pages); } diff --git a/kernel/kthread.c b/kernel/kthread.c index 684ab3f7dd72..3b34d2732bce 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -139,7 +139,7 @@ static void create_kthread(struct kthread_create_info *create) * in @node, to get NUMA affinity for kthread stack, or else give -1. * When woken, the thread will run @threadfn() with @data as its * argument. @threadfn() can either call do_exit() directly if it is a - * standalone thread for which noone will call kthread_stop(), or + * standalone thread for which no one will call kthread_stop(), or * return when 'kthread_should_stop()' is true (which means * kthread_stop() has been called). The return value should be zero * or a negative error number; it will be passed to kthread_stop(). diff --git a/kernel/latencytop.c b/kernel/latencytop.c index ee74b35e528d..376066e10413 100644 --- a/kernel/latencytop.c +++ b/kernel/latencytop.c @@ -153,7 +153,7 @@ static inline void store_stacktrace(struct task_struct *tsk, } /** - * __account_scheduler_latency - record an occured latency + * __account_scheduler_latency - record an occurred latency * @tsk - the task struct of the task hitting the latency * @usecs - the duration of the latency in microseconds * @inter - 1 if the sleep was interruptible, 0 if uninterruptible diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 0d2058da80f5..53a68956f131 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2309,7 +2309,7 @@ void trace_hardirqs_on_caller(unsigned long ip) if (unlikely(curr->hardirqs_enabled)) { /* * Neither irq nor preemption are disabled here - * so this is racy by nature but loosing one hit + * so this is racy by nature but losing one hit * in a stat is not a big deal. */ __debug_atomic_inc(redundant_hardirqs_on); @@ -2620,7 +2620,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, if (!graph_lock()) return 0; /* - * Make sure we didnt race: + * Make sure we didn't race: */ if (unlikely(hlock_class(this)->usage_mask & new_mask)) { graph_unlock(); diff --git a/kernel/module.c b/kernel/module.c index 1f9f7bc56ca1..d5938a5c19c4 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -809,7 +809,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, wait_for_zero_refcount(mod); mutex_unlock(&module_mutex); - /* Final destruction now noone is using it. */ + /* Final destruction now no one is using it. */ if (mod->exit != NULL) mod->exit(); blocking_notifier_call_chain(&module_notify_list, @@ -2777,7 +2777,7 @@ static struct module *load_module(void __user *umod, mod->state = MODULE_STATE_COMING; /* Now sew it into the lists so we can get lockdep and oops - * info during argument parsing. Noone should access us, since + * info during argument parsing. No one should access us, since * strong_try_module_get() will fail. * lockdep/oops can run asynchronous, so use the RCU list insertion * function to insert in a way safe to concurrent readers. @@ -2971,7 +2971,7 @@ static const char *get_ksymbol(struct module *mod, else nextval = (unsigned long)mod->module_core+mod->core_text_size; - /* Scan for closest preceeding symbol, and next symbol. (ELF + /* Scan for closest preceding symbol, and next symbol. (ELF starts real symbols at 1). */ for (i = 1; i < mod->num_symtab; i++) { if (mod->symtab[i].st_shndx == SHN_UNDEF) diff --git a/kernel/mutex.c b/kernel/mutex.c index a5889fb28ecf..c4195fa98900 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -245,7 +245,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, } __set_task_state(task, state); - /* didnt get the lock, go to sleep: */ + /* didn't get the lock, go to sleep: */ spin_unlock_mutex(&lock->wait_lock, flags); preempt_enable_no_resched(); schedule(); diff --git a/kernel/padata.c b/kernel/padata.c index 751019415d23..b91941df5e63 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -262,7 +262,7 @@ static void padata_reorder(struct parallel_data *pd) /* * This cpu has to do the parallel processing of the next * object. It's waiting in the cpu's parallelization queue, - * so exit imediately. + * so exit immediately. */ if (PTR_ERR(padata) == -ENODATA) { del_timer(&pd->timer); @@ -284,7 +284,7 @@ static void padata_reorder(struct parallel_data *pd) /* * The next object that needs serialization might have arrived to * the reorder queues in the meantime, we will be called again - * from the timer function if noone else cares for it. + * from the timer function if no one else cares for it. */ if (atomic_read(&pd->reorder_objects) && !(pinst->flags & PADATA_RESET)) @@ -515,7 +515,7 @@ static void __padata_stop(struct padata_instance *pinst) put_online_cpus(); } -/* Replace the internal control stucture with a new one. */ +/* Replace the internal control structure with a new one. */ static void padata_replace(struct padata_instance *pinst, struct parallel_data *pd_new) { @@ -768,7 +768,7 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) } /** - * padata_remove_cpu - remove a cpu from the one or both(serial and paralell) + * padata_remove_cpu - remove a cpu from the one or both(serial and parallel) * padata cpumasks. * * @pinst: padata instance diff --git a/kernel/params.c b/kernel/params.c index 0da1411222b9..7ab388a48a2e 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -95,7 +95,7 @@ static int parse_one(char *param, /* Find parameter */ for (i = 0; i < num_params; i++) { if (parameq(param, params[i].name)) { - /* Noone handled NULL, so do it here. */ + /* No one handled NULL, so do it here. */ if (!val && params[i].ops->set != param_set_bool) return -EINVAL; DEBUGP("They are equal! Calling %p\n", diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 67fea9d25d55..0791b13df7bf 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1347,7 +1347,7 @@ void run_posix_cpu_timers(struct task_struct *tsk) /* * Now that all the timers on our list have the firing flag, - * noone will touch their list entries but us. We'll take + * no one will touch their list entries but us. We'll take * each timer's lock before clearing its firing flag, so no * timer call will interfere. */ diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 4c0124919f9a..e5498d7405c3 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -313,7 +313,7 @@ static void schedule_next_timer(struct k_itimer *timr) * restarted (i.e. we have flagged this in the sys_private entry of the * info block). * - * To protect aginst the timer going away while the interrupt is queued, + * To protect against the timer going away while the interrupt is queued, * we require that the it_requeue_pending flag be set. */ void do_schedule_next_timer(struct siginfo *info) diff --git a/kernel/power/main.c b/kernel/power/main.c index 8eaba5f27b10..de9aef8742f4 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -224,7 +224,7 @@ power_attr(state); * writing to 'state'. It first should read from 'wakeup_count' and store * the read value. Then, after carrying out its own preparations for the system * transition to a sleep state, it should write the stored value to - * 'wakeup_count'. If that fails, at least one wakeup event has occured since + * 'wakeup_count'. If that fails, at least one wakeup event has occurred since * 'wakeup_count' was read and 'state' should not be written to. Otherwise, it * is allowed to write to 'state', but the transition will be aborted if there * are any wakeup events detected after 'wakeup_count' was written to. diff --git a/kernel/sched.c b/kernel/sched.c index f592ce6f8616..865b433fac5b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2309,7 +2309,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * Cause a process which is running on another CPU to enter * kernel-mode, without any delay. (to get signals handled.) * - * NOTE: this function doesnt have to take the runqueue lock, + * NOTE: this function doesn't have to take the runqueue lock, * because all it wants to ensure is that the remote task enters * the kernel. If the IPI races and the task has been migrated * to another CPU then no harm is done and the purpose has been @@ -4997,7 +4997,7 @@ recheck: */ raw_spin_lock_irqsave(&p->pi_lock, flags); /* - * To be able to change p->policy safely, the apropriate + * To be able to change p->policy safely, the appropriate * runqueue lock must be held. */ rq = __task_rq_lock(p); @@ -5705,7 +5705,7 @@ void show_state_filter(unsigned long state_filter) do_each_thread(g, p) { /* * reset the NMI-timeout, listing all files on a slow - * console might take alot of time: + * console might take a lot of time: */ touch_nmi_watchdog(); if (!state_filter || (p->state & state_filter)) diff --git a/kernel/sched_autogroup.c b/kernel/sched_autogroup.c index 5946ac515602..429242f3c484 100644 --- a/kernel/sched_autogroup.c +++ b/kernel/sched_autogroup.c @@ -179,7 +179,7 @@ void sched_autogroup_create_attach(struct task_struct *p) struct autogroup *ag = autogroup_create(); autogroup_move_group(p, ag); - /* drop extra refrence added by autogroup_create() */ + /* drop extra reference added by autogroup_create() */ autogroup_kref_put(ag); } EXPORT_SYMBOL(sched_autogroup_create_attach); diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 3f7ec9e27ee1..3cb7f07887a1 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -3061,7 +3061,7 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu, /* * if *imbalance is less than the average load per runnable task - * there is no gaurantee that any tasks will be moved so we'll have + * there is no guarantee that any tasks will be moved so we'll have * a think about bumping its value to force at least one task to be * moved */ diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index db308cb08b75..e7cebdc65f82 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1378,7 +1378,7 @@ retry: task = pick_next_pushable_task(rq); if (task_cpu(next_task) == rq->cpu && task == next_task) { /* - * If we get here, the task hasnt moved at all, but + * If we get here, the task hasn't moved at all, but * it has failed to push. We will not try again, * since the other cpus will pull from us when they * are ready. @@ -1488,7 +1488,7 @@ static int pull_rt_task(struct rq *this_rq) /* * We continue with the search, just in * case there's an even higher prio task - * in another runqueue. (low likelyhood + * in another runqueue. (low likelihood * but possible) */ } diff --git a/kernel/signal.c b/kernel/signal.c index 1186cf7fac77..f486d10f3b8e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1885,7 +1885,7 @@ relock: for (;;) { struct k_sigaction *ka; /* - * Tracing can induce an artifical signal and choose sigaction. + * Tracing can induce an artificial signal and choose sigaction. * The return value in @signr determines the default action, * but @info->si_signo is the signal number we will report. */ diff --git a/kernel/softirq.c b/kernel/softirq.c index 735d87095172..174f976c2874 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -567,7 +567,7 @@ static void __tasklet_hrtimer_trampoline(unsigned long data) /** * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks * @ttimer: tasklet_hrtimer which is initialized - * @function: hrtimer callback funtion which gets called from softirq context + * @function: hrtimer callback function which gets called from softirq context * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME) * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL) */ diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c index b2fa506667c0..a470154e0408 100644 --- a/kernel/time/jiffies.c +++ b/kernel/time/jiffies.c @@ -34,7 +34,7 @@ * inaccuracies caused by missed or lost timer * interrupts and the inability for the timer * interrupt hardware to accuratly tick at the - * requested HZ value. It is also not reccomended + * requested HZ value. It is also not recommended * for "tick-less" systems. */ #define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index 2f3b585b8d7d..a5d0a3a85dd8 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -236,7 +236,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf, unsigned int timer_flag) { /* - * It doesnt matter which lock we take: + * It doesn't matter which lock we take: */ raw_spinlock_t *lock; struct entry *entry, input; diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index c075f4ea6b94..ee24fa1935ac 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1268,7 +1268,7 @@ static int ftrace_update_code(struct module *mod) p->flags = 0L; /* - * Do the initial record convertion from mcount jump + * Do the initial record conversion from mcount jump * to the NOP instructions. */ if (!ftrace_code_disable(mod, p)) { @@ -3425,7 +3425,7 @@ graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) atomic_set(&t->tracing_graph_pause, 0); atomic_set(&t->trace_overrun, 0); t->ftrace_timestamp = 0; - /* make curr_ret_stack visable before we add the ret_stack */ + /* make curr_ret_stack visible before we add the ret_stack */ smp_wmb(); t->ret_stack = ret_stack; } diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index d9c8bcafb120..0ef7b4b2a1f7 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1478,7 +1478,7 @@ static inline unsigned long rb_page_entries(struct buffer_page *bpage) return local_read(&bpage->entries) & RB_WRITE_MASK; } -/* Size is determined by what has been commited */ +/* Size is determined by what has been committed */ static inline unsigned rb_page_size(struct buffer_page *bpage) { return rb_page_commit(bpage); @@ -2932,7 +2932,7 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) /* * cpu_buffer->pages just needs to point to the buffer, it * has no specific buffer page to point to. Lets move it out - * of our way so we don't accidently swap it. + * of our way so we don't accidentally swap it. */ cpu_buffer->pages = reader->list.prev; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9541c27c1cf2..d38c16a06a6f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3239,7 +3239,7 @@ waitagain: trace_seq_init(&iter->seq); /* - * If there was nothing to send to user, inspite of consuming trace + * If there was nothing to send to user, in spite of consuming trace * entries, go back to wait for more entries. */ if (sret == -EBUSY) diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c index 685a67d55db0..6302747a1398 100644 --- a/kernel/trace/trace_clock.c +++ b/kernel/trace/trace_clock.c @@ -46,7 +46,7 @@ u64 notrace trace_clock_local(void) } /* - * trace_clock(): 'inbetween' trace clock. Not completely serialized, + * trace_clock(): 'between' trace clock. Not completely serialized, * but not completely incorrect when crossing CPUs either. * * This is based on cpu_clock(), which will allow at most ~1 jiffy of diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index 1516cb3ec549..e32744c84d94 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -27,7 +27,7 @@ * in the structure. * * * for structures within structures, the format of the internal - * structure is layed out. This allows the internal structure + * structure is laid out. This allows the internal structure * to be deciphered for the format file. Although these macros * may become out of sync with the internal structure, they * will create a compile error if it happens. Since the diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 76b05980225c..962cdb24ed81 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -905,7 +905,7 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, * * returns 1 if * - we are inside irq code - * - we just extered irq code + * - we just entered irq code * * retunns 0 if * - funcgraph-interrupts option is set diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 92b6e1e12d98..a4969b47afc1 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -80,7 +80,7 @@ static struct tracer_flags tracer_flags = { * skip the latency if the sequence has changed - some other section * did a maximum and could disturb our measurement with serial console * printouts, etc. Truly coinciding maximum latencies should be rare - * and what happens together happens separately as well, so this doesnt + * and what happens together happens separately as well, so this doesn't * decrease the validity of the maximum found: */ static __cacheline_aligned_in_smp unsigned long max_sequence; diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 8435b43b1782..35d55a386145 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1839,7 +1839,7 @@ static void unregister_probe_event(struct trace_probe *tp) kfree(tp->call.print_fmt); } -/* Make a debugfs interface for controling probe points */ +/* Make a debugfs interface for controlling probe points */ static __init int init_kprobe_trace(void) { struct dentry *d_tracer; diff --git a/kernel/user-return-notifier.c b/kernel/user-return-notifier.c index eb27fd3430a2..92cb706c7fc8 100644 --- a/kernel/user-return-notifier.c +++ b/kernel/user-return-notifier.c @@ -20,7 +20,7 @@ EXPORT_SYMBOL_GPL(user_return_notifier_register); /* * Removes a registered user return notifier. Must be called from atomic - * context, and from the same cpu registration occured in. + * context, and from the same cpu registration occurred in. */ void user_return_notifier_unregister(struct user_return_notifier *urn) { diff --git a/kernel/wait.c b/kernel/wait.c index b0310eb6cc1e..f45ea8d2a1ce 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -142,7 +142,7 @@ EXPORT_SYMBOL(finish_wait); * woken up through the queue. * * This prevents waiter starvation where an exclusive waiter - * aborts and is woken up concurrently and noone wakes up + * aborts and is woken up concurrently and no one wakes up * the next waiter. */ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 04ef830690ec..8859a41806dd 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1291,7 +1291,7 @@ __acquires(&gcwq->lock) return true; spin_unlock_irq(&gcwq->lock); - /* CPU has come up inbetween, retry migration */ + /* CPU has come up in between, retry migration */ cpu_relax(); } } diff --git a/lib/bitmap.c b/lib/bitmap.c index 741fae905ae3..91e0ccfdb424 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -830,7 +830,7 @@ EXPORT_SYMBOL(bitmap_bitremap); * @orig (i.e. bits 3, 5, 7 and 9) were also set. * * When bit 11 is set in @orig, it means turn on the bit in - * @dst corresponding to whatever is the twelth bit that is + * @dst corresponding to whatever is the twelfth bit that is * turned on in @relmap. In the above example, there were * only ten bits turned on in @relmap (30..39), so that bit * 11 was set in @orig had no affect on @dst. diff --git a/lib/btree.c b/lib/btree.c index c9c6f0351526..2a34392bcecc 100644 --- a/lib/btree.c +++ b/lib/btree.c @@ -11,7 +11,7 @@ * see http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch * * A relatively simple B+Tree implementation. I have written it as a learning - * excercise to understand how B+Trees work. Turned out to be useful as well. + * exercise to understand how B+Trees work. Turned out to be useful as well. * * B+Trees can be used similar to Linux radix trees (which don't have anything * in common with textbook radix trees, beware). Prerequisite for them working @@ -541,7 +541,7 @@ static void rebalance(struct btree_head *head, struct btree_geo *geo, int i, no_left, no_right; if (fill == 0) { - /* Because we don't steal entries from a neigbour, this case + /* Because we don't steal entries from a neighbour, this case * can happen. Parent node contains a single child, this * node, so merging with a sibling never happens. */ diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c index cecd23df2b9a..9f34eb56854d 100644 --- a/lib/decompress_unxz.c +++ b/lib/decompress_unxz.c @@ -83,7 +83,7 @@ * safety_margin = 128 + uncompressed_size * 8 / 32768 + 65536 * = 128 + (uncompressed_size >> 12) + 65536 * - * For comparision, according to arch/x86/boot/compressed/misc.c, the + * For comparison, according to arch/x86/boot/compressed/misc.c, the * equivalent formula for Deflate is this: * * safety_margin = 18 + (uncompressed_size >> 12) + 32768 diff --git a/lib/parser.c b/lib/parser.c index 6e89eca5cca0..dcbaaef6cf11 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -13,7 +13,7 @@ /** * match_one: - Determines if a string matches a simple pattern - * @s: the string to examine for presense of the pattern + * @s: the string to examine for presence of the pattern * @p: the string containing the pattern * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match * locations. diff --git a/lib/timerqueue.c b/lib/timerqueue.c index e3a1050e6820..191176a43e9a 100644 --- a/lib/timerqueue.c +++ b/lib/timerqueue.c @@ -5,7 +5,7 @@ * Uses rbtrees for quick list adds and expiration. * * NOTE: All of the following functions need to be serialized - * to avoid races. No locking is done by this libary code. + * to avoid races. No locking is done by this library code. * * 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 diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 0d9a036ada66..befc87531e4f 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -787,7 +787,7 @@ EXPORT_SYMBOL(congestion_wait); * jiffies for either a BDI to exit congestion of the given @sync queue * or a write to complete. * - * In the absense of zone congestion, cond_resched() is called to yield + * In the absence of zone congestion, cond_resched() is called to yield * the processor if necessary but otherwise does not sleep. * * The return value is 0 if the sleep is for the full timeout. Otherwise, diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 06de5aa4d644..8ee3bd8ec5b5 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -146,7 +146,7 @@ static long region_chg(struct list_head *head, long f, long t) if (rg->from > t) return chg; - /* We overlap with this area, if it extends futher than + /* We overlap with this area, if it extends further than * us then we must extend ourselves. Account for its * existing reservation. */ if (rg->to > t) { @@ -842,7 +842,7 @@ struct page *alloc_huge_page_node(struct hstate *h, int nid) } /* - * Increase the hugetlb pool such that it can accomodate a reservation + * Increase the hugetlb pool such that it can accommodate a reservation * of size 'delta'. */ static int gather_surplus_pages(struct hstate *h, int delta) @@ -890,7 +890,7 @@ retry: /* * The surplus_list now contains _at_least_ the number of extra pages - * needed to accomodate the reservation. Add the appropriate number + * needed to accommodate the reservation. Add the appropriate number * of pages to the hugetlb pool and free the extras back to the buddy * allocator. Commit the entire reservation here to prevent another * process from stealing the pages as they are added to the pool but @@ -2043,7 +2043,7 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma) * This new VMA should share its siblings reservation map if present. * The VMA will only ever have a valid reservation map pointer where * it is being copied for another still existing VMA. As that VMA - * has a reference to the reservation map it cannot dissappear until + * has a reference to the reservation map it cannot disappear until * after this open call completes. It is therefore safe to take a * new reference here without additional locking. */ @@ -2490,7 +2490,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, /* * Currently, we are forced to kill the process in the event the * original mapper has unmapped pages from the child due to a failed - * COW. Warn that such a situation has occured as it may not be obvious + * COW. Warn that such a situation has occurred as it may not be obvious */ if (is_vma_resv_set(vma, HPAGE_RESV_UNMAPPED)) { printk(KERN_WARNING diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c index 0948f1072d6b..c7fc7fd00e32 100644 --- a/mm/hwpoison-inject.c +++ b/mm/hwpoison-inject.c @@ -1,4 +1,4 @@ -/* Inject a hwpoison memory failure on a arbitary pfn */ +/* Inject a hwpoison memory failure on a arbitrary pfn */ #include #include #include diff --git a/mm/internal.h b/mm/internal.h index 3438dd43a062..9d0ced8e505e 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -162,7 +162,7 @@ static inline struct page *mem_map_offset(struct page *base, int offset) } /* - * Iterator over all subpages withing the maximally aligned gigantic + * Iterator over all subpages within the maximally aligned gigantic * page 'base'. Handle any discontiguity in the mem_map. */ static inline struct page *mem_map_next(struct page *iter, diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 84225f3b7190..c1d5867543e4 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -265,7 +265,7 @@ static void kmemleak_disable(void); } while (0) /* - * Macro invoked when a serious kmemleak condition occured and cannot be + * Macro invoked when a serious kmemleak condition occurred and cannot be * recovered from. Kmemleak will be disabled and further allocation/freeing * tracing no longer available. */ @@ -1006,7 +1006,7 @@ static bool update_checksum(struct kmemleak_object *object) /* * Memory scanning is a long process and it needs to be interruptable. This - * function checks whether such interrupt condition occured. + * function checks whether such interrupt condition occurred. */ static int scan_should_stop(void) { @@ -1733,7 +1733,7 @@ static int __init kmemleak_late_init(void) if (atomic_read(&kmemleak_error)) { /* - * Some error occured and kmemleak was disabled. There is a + * Some error occurred and kmemleak was disabled. There is a * small chance that kmemleak_disable() was called immediately * after setting kmemleak_initialized and we may end up with * two clean-up threads but serialized by scan_mutex. diff --git a/mm/ksm.c b/mm/ksm.c index 1bbe785aa559..942dfc73a2ff 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -720,7 +720,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, swapped = PageSwapCache(page); flush_cache_page(vma, addr, page_to_pfn(page)); /* - * Ok this is tricky, when get_user_pages_fast() run it doesnt + * Ok this is tricky, when get_user_pages_fast() run it doesn't * take any lock, therefore the check that we are going to make * with the pagecount against the mapcount is racey and * O_DIRECT can happen right after the check. diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 1f0b460fe58c..010f9166fa6e 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1466,7 +1466,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, break; } /* - * We want to do more targetted reclaim. + * We want to do more targeted reclaim. * excess >> 2 is not to excessive so as to * reclaim too much, nor too less that we keep * coming back to reclaim from this cgroup @@ -2265,7 +2265,7 @@ void mem_cgroup_split_huge_fixup(struct page *head, struct page *tail) * - compound_lock is held when nr_pages > 1 * * This function doesn't do "charge" nor css_get to new cgroup. It should be - * done by a caller(__mem_cgroup_try_charge would be usefull). If @uncharge is + * done by a caller(__mem_cgroup_try_charge would be useful). If @uncharge is * true, this function does "uncharge" from old cgroup, but it doesn't if * @uncharge is false, so a caller should do "uncharge". */ @@ -2318,7 +2318,7 @@ static int mem_cgroup_move_account(struct page *page, * We charges against "to" which may not have any tasks. Then, "to" * can be under rmdir(). But in current implementation, caller of * this function is just force_empty() and move charge, so it's - * garanteed that "to" is never removed. So, we don't check rmdir + * guaranteed that "to" is never removed. So, we don't check rmdir * status here. */ move_unlock_page_cgroup(pc, &flags); @@ -2648,7 +2648,7 @@ static void mem_cgroup_do_uncharge(struct mem_cgroup *mem, batch->memcg = mem; /* * do_batch > 0 when unmapping pages or inode invalidate/truncate. - * In those cases, all pages freed continously can be expected to be in + * In those cases, all pages freed continuously can be expected to be in * the same cgroup and we have chance to coalesce uncharges. * But we do uncharge one by one if this is killed by OOM(TIF_MEMDIE) * because we want to do uncharge as soon as possible. diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 37feb9fec228..2b9a5eef39e0 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -208,7 +208,7 @@ static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno, * Don't use force here, it's convenient if the signal * can be temporarily blocked. * This could cause a loop when the user sets SIGBUS - * to SIG_IGN, but hopefully noone will do that? + * to SIG_IGN, but hopefully no one will do that? */ ret = send_sig_info(SIGBUS, &si, t); /* synchronous? */ if (ret < 0) @@ -634,7 +634,7 @@ static int me_pagecache_dirty(struct page *p, unsigned long pfn) * when the page is reread or dropped. If an * application assumes it will always get error on * fsync, but does other operations on the fd before - * and the page is dropped inbetween then the error + * and the page is dropped between then the error * will not be properly reported. * * This can already happen even without hwpoisoned @@ -728,7 +728,7 @@ static int me_huge_page(struct page *p, unsigned long pfn) * The table matches them in order and calls the right handler. * * This is quite tricky because we can access page at any time - * in its live cycle, so all accesses have to be extremly careful. + * in its live cycle, so all accesses have to be extremely careful. * * This is not complete. More states could be added. * For any missing state don't attempt recovery. diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 321fc7455df7..a2acaf820fe5 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -724,7 +724,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) pfn); dump_page(page); #endif - /* Becasue we don't have big zone->lock. we should + /* Because we don't have big zone->lock. we should check this again here. */ if (page_count(page)) { not_managed++; diff --git a/mm/migrate.c b/mm/migrate.c index b0406d739ea7..34132f8e9109 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -375,7 +375,7 @@ void migrate_page_copy(struct page *newpage, struct page *page) * redo the accounting that clear_page_dirty_for_io undid, * but we can't use set_page_dirty because that function * is actually a signal that all of the page has become dirty. - * Wheras only part of our page may be dirty. + * Whereas only part of our page may be dirty. */ __set_page_dirty_nobuffers(newpage); } diff --git a/mm/nobootmem.c b/mm/nobootmem.c index e99f6cd1da1f..9109049f0bbc 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -150,7 +150,7 @@ unsigned long __init free_all_bootmem(void) { /* * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id - * because in some case like Node0 doesnt have RAM installed + * because in some case like Node0 doesn't have RAM installed * low ram will be on Node1 * Use MAX_NUMNODES will make sure all ranges in early_node_map[] * will be used instead of only Node0 related diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d6e7ba7373be..2747f5e5abc1 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -942,7 +942,7 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype) * If breaking a large block of pages, move all free * pages to the preferred allocation list. If falling * back for a reclaimable kernel allocation, be more - * agressive about taking ownership of free pages + * aggressive about taking ownership of free pages */ if (unlikely(current_order >= (pageblock_order >> 1)) || start_migratetype == MIGRATE_RECLAIMABLE || @@ -3926,7 +3926,7 @@ static void __init find_usable_zone_for_movable(void) /* * The zone ranges provided by the architecture do not include ZONE_MOVABLE - * because it is sized independant of architecture. Unlike the other zones, + * because it is sized independent of architecture. Unlike the other zones, * the starting point for ZONE_MOVABLE is not fixed. It may be different * in each node depending on the size of each node and how evenly kernelcore * is distributed. This helper function adjusts the zone ranges diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index a12cc3fa9859..99055010cece 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c @@ -377,7 +377,7 @@ not_enough_page: * @new: new id * * Returns old id at success, 0 at failure. - * (There is no mem_cgroup useing 0 as its id) + * (There is no mem_cgroup using 0 as its id) */ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent, unsigned short old, unsigned short new) diff --git a/mm/percpu.c b/mm/percpu.c index 55d4d113fbd3..a160db39b810 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -342,7 +342,7 @@ static void pcpu_chunk_relocate(struct pcpu_chunk *chunk, int oslot) * @chunk: chunk of interest * * Determine whether area map of @chunk needs to be extended to - * accomodate a new allocation. + * accommodate a new allocation. * * CONTEXT: * pcpu_lock. @@ -431,7 +431,7 @@ out_unlock: * depending on @head, is reduced by @tail bytes and @tail byte block * is inserted after the target block. * - * @chunk->map must have enough free slots to accomodate the split. + * @chunk->map must have enough free slots to accommodate the split. * * CONTEXT: * pcpu_lock. @@ -1435,7 +1435,7 @@ static struct pcpu_alloc_info * __init pcpu_build_alloc_info( /* * Determine min_unit_size, alloc_size and max_upa such that * alloc_size is multiple of atom_size and is the smallest - * which can accomodate 4k aligned segments which are equal to + * which can accommodate 4k aligned segments which are equal to * or larger than min_unit_size. */ min_unit_size = max_t(size_t, size_sum, PCPU_MIN_UNIT_SIZE); @@ -1550,7 +1550,7 @@ static struct pcpu_alloc_info * __init pcpu_build_alloc_info( * @atom_size: allocation atom size * @cpu_distance_fn: callback to determine distance between cpus, optional * @alloc_fn: function to allocate percpu page - * @free_fn: funtion to free percpu page + * @free_fn: function to free percpu page * * This is a helper to ease setting up embedded first percpu chunk and * can be called where pcpu_setup_first_chunk() is expected. @@ -1678,7 +1678,7 @@ out_free: * pcpu_page_first_chunk - map the first chunk using PAGE_SIZE pages * @reserved_size: the size of reserved percpu area in bytes * @alloc_fn: function to allocate percpu page, always called with PAGE_SIZE - * @free_fn: funtion to free percpu page, always called with PAGE_SIZE + * @free_fn: function to free percpu page, always called with PAGE_SIZE * @populate_pte_fn: function to populate pte * * This is a helper to ease setting up page-remapped first percpu diff --git a/mm/slab.c b/mm/slab.c index 568803f121a8..46a9c163a92f 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -878,7 +878,7 @@ static struct array_cache *alloc_arraycache(int node, int entries, nc = kmalloc_node(memsize, gfp, node); /* * The array_cache structures contain pointers to free object. - * However, when such objects are allocated or transfered to another + * However, when such objects are allocated or transferred to another * cache the pointers are not cleared and they could be counted as * valid references during a kmemleak scan. Therefore, kmemleak must * not scan such objects. @@ -2606,7 +2606,7 @@ EXPORT_SYMBOL(kmem_cache_shrink); * * The cache must be empty before calling this function. * - * The caller must guarantee that noone will allocate memory from the cache + * The caller must guarantee that no one will allocate memory from the cache * during the kmem_cache_destroy(). */ void kmem_cache_destroy(struct kmem_cache *cachep) diff --git a/mm/slub.c b/mm/slub.c index f881874843a5..94d2a33a866e 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -64,7 +64,7 @@ * we must stay away from it for a while since we may cause a bouncing * cacheline if we try to acquire the lock. So go onto the next slab. * If all pages are busy then we may allocate a new slab instead of reusing - * a partial slab. A new slab has noone operating on it and thus there is + * a partial slab. A new slab has no one operating on it and thus there is * no danger of cacheline contention. * * Interrupts are disabled during allocation and deallocation in order to @@ -1929,7 +1929,7 @@ redo: else { #ifdef CONFIG_CMPXCHG_LOCAL /* - * The cmpxchg will only match if there was no additonal + * The cmpxchg will only match if there was no additional * operation and if we are on the right processor. * * The cmpxchg does the following atomically (without lock semantics!) @@ -3547,7 +3547,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller) ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, caller); - /* Honor the call site pointer we recieved. */ + /* Honor the call site pointer we received. */ trace_kmalloc(caller, ret, size, s->size, gfpflags); return ret; @@ -3577,7 +3577,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, ret = slab_alloc(s, gfpflags, node, caller); - /* Honor the call site pointer we recieved. */ + /* Honor the call site pointer we received. */ trace_kmalloc_node(caller, ret, size, s->size, gfpflags, node); return ret; diff --git a/mm/sparse.c b/mm/sparse.c index 93250207c5cf..aa64b12831a2 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -500,7 +500,7 @@ void __init sparse_init(void) * so alloc 2M (with 2M align) and 24 bytes in turn will * make next 2M slip to one more 2M later. * then in big system, the memory will have a lot of holes... - * here try to allocate 2M pages continously. + * here try to allocate 2M pages continuously. * * powerpc need to call sparse_init_one_section right after each * sparse_early_mem_map_alloc, so allocate usemap_map at first. diff --git a/mm/util.c b/mm/util.c index f126975ef23e..e7b103a6fd21 100644 --- a/mm/util.c +++ b/mm/util.c @@ -227,7 +227,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm) /* * Like get_user_pages_fast() except its IRQ-safe in that it won't fall * back to the regular GUP. - * If the architecture not support this fucntion, simply return with no + * If the architecture not support this function, simply return with no * page pinned */ int __attribute__((weak)) __get_user_pages_fast(unsigned long start, diff --git a/mm/vmscan.c b/mm/vmscan.c index f73b8657c2d0..c7f5a6d4b75b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1065,7 +1065,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, * surrounding the tag page. Only take those pages of * the same active state as that tag page. We may safely * round the target page pfn down to the requested order - * as the mem_map is guarenteed valid out to MAX_ORDER, + * as the mem_map is guaranteed valid out to MAX_ORDER, * where that page is in a different zone we will detect * it from its zone id and abort this block scan. */ @@ -2224,7 +2224,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, * o a 16M DMA zone that is balanced will not balance a zone on any * reasonable sized machine * o On all other machines, the top zone must be at least a reasonable - * precentage of the middle zones. For example, on 32-bit x86, highmem + * percentage of the middle zones. For example, on 32-bit x86, highmem * would need to be at least 256M for it to be balance a whole node. * Similarly, on x86-64 the Normal zone would need to be at least 1G * to balance a node on its own. These seemed like reasonable ratios. diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index d1314cf18adf..d940c49d168a 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -54,7 +54,7 @@ static const char name_conf[] = "config"; /* * Structures for interfacing with the /proc filesystem. - * VLAN creates its own directory /proc/net/vlan with the folowing + * VLAN creates its own directory /proc/net/vlan with the following * entries: * config device status/configuration * entry for each device diff --git a/net/9p/client.c b/net/9p/client.c index 2ccbf04d37df..48b8e084e710 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -178,7 +178,7 @@ free_and_return: * @tag: numeric id for transaction * * this is a simple array lookup, but will grow the - * request_slots as necessary to accomodate transaction + * request_slots as necessary to accommodate transaction * ids which did not previously have a slot. * * this code relies on the client spinlock to manage locks, its diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index 9172ab78fcb0..d47880e971dd 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c @@ -36,7 +36,7 @@ p9_release_req_pages(struct trans_rpage_info *rpinfo) EXPORT_SYMBOL(p9_release_req_pages); /** - * p9_nr_pages - Return number of pages needed to accomodate the payload. + * p9_nr_pages - Return number of pages needed to accommodate the payload. */ int p9_nr_pages(struct p9_req_t *req) @@ -55,7 +55,7 @@ EXPORT_SYMBOL(p9_nr_pages); * @req: Request to be sent to server. * @pdata_off: data offset into the first page after translation (gup). * @pdata_len: Total length of the IO. gup may not return requested # of pages. - * @nr_pages: number of pages to accomodate the payload + * @nr_pages: number of pages to accommodate the payload * @rw: Indicates if the pages are for read or write. */ int diff --git a/net/9p/util.c b/net/9p/util.c index b84619b5ba22..da6af81e59d9 100644 --- a/net/9p/util.c +++ b/net/9p/util.c @@ -67,7 +67,7 @@ EXPORT_SYMBOL(p9_idpool_create); /** * p9_idpool_destroy - create a new per-connection id pool - * @p: idpool to destory + * @p: idpool to destroy */ void p9_idpool_destroy(struct p9_idpool *p) diff --git a/net/atm/br2684.c b/net/atm/br2684.c index fce2eae8d476..2252c2085dac 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -509,7 +509,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) write_lock_irq(&devs_lock); net_dev = br2684_find_dev(&be.ifspec); if (net_dev == NULL) { - pr_err("tried to attach to non-existant device\n"); + pr_err("tried to attach to non-existent device\n"); err = -ENXIO; goto error; } diff --git a/net/atm/lec.h b/net/atm/lec.h index 9d14d196cc1d..dfc071966463 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -35,7 +35,7 @@ struct lecdatahdr_8025 { * Operations that LANE2 capable device can do. Two first functions * are used to make the device do things. See spec 3.1.3 and 3.1.4. * - * The third function is intented for the MPOA component sitting on + * The third function is intended for the MPOA component sitting on * top of the LANE device. The MPOA component assigns it's own function * to (*associate_indicator)() and the LANE device will use that * function to tell about TLVs it sees floating through. diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9ed26140a269..824e1f6e50f2 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -474,7 +474,7 @@ void interface_rx(struct net_device *soft_iface, goto dropped; skb->protocol = eth_type_trans(skb, soft_iface); - /* should not be neccesary anymore as we use skb_pull_rcsum() + /* should not be necessary anymore as we use skb_pull_rcsum() * TODO: please verify this and remove this TODO * -- Dec 21st 2009, Simon Wunderlich */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b372fb8bcdcf..42d5ff02cb59 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1877,7 +1877,7 @@ static void hci_tx_task(unsigned long arg) read_unlock(&hci_task_lock); } -/* ----- HCI RX task (incoming data proccessing) ----- */ +/* ----- HCI RX task (incoming data processing) ----- */ /* ACL data packet */ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index fc85e7ae33c7..36b9c5d0ebe3 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -679,7 +679,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch if (opt == BT_FLUSHABLE_OFF) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; - /* proceed futher only when we have l2cap_conn and + /* proceed further only when we have l2cap_conn and No Flush support in the LM */ if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { err = -EINVAL; diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 88485cc74dc3..cc4d3c5ab1c6 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -169,7 +169,7 @@ void br_fdb_flush(struct net_bridge *br) spin_unlock_bh(&br->hash_lock); } -/* Flush all entries refering to a specific port. +/* Flush all entries referring to a specific port. * if do_all is set also flush static entries */ void br_fdb_delete_by_port(struct net_bridge *br, diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index cb43312b846e..3d9fca0e3370 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -106,7 +106,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) /* * Legacy ioctl's through SIOCDEVPRIVATE * This interface is deprecated because it was too difficult to - * to do the translation for 32/64bit ioctl compatability. + * to do the translation for 32/64bit ioctl compatibility. */ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 8184c031d028..37a4034dfc29 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -852,7 +852,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTING; sk->sk_state = CAIF_CONNECTING; - /* Check priority value comming from socket */ + /* Check priority value coming from socket */ /* if priority value is out of range it will be ajusted */ if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) cf_sk->conn_req.priority = CAIF_PRIO_MAX; diff --git a/net/can/bcm.c b/net/can/bcm.c index 871a0ad51025..57b1aed79014 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -387,7 +387,7 @@ static void bcm_tx_timeout_tsklet(unsigned long data) } /* - * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions + * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */ static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) { diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 02212ed50852..8d4ee7e01793 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -917,7 +917,7 @@ EXPORT_SYMBOL(ceph_osdc_set_request_linger); /* * Pick an osd (the first 'up' osd in the pg), allocate the osd struct * (as needed), and set the request r_osd appropriately. If there is - * no up osd, set r_osd to NULL. Move the request to the appropiate list + * no up osd, set r_osd to NULL. Move the request to the appropriate list * (unsent, homeless) or leave on in-flight lru. * * Return 0 if unchanged, 1 if changed, or negative on error. diff --git a/net/core/dev.c b/net/core/dev.c index 563ddc28139d..56c3e00098c0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2071,7 +2071,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, u32 features; /* - * If device doesnt need skb->dst, release it right now while + * If device doesn't need skb->dst, release it right now while * its hot in this cpu cache */ if (dev->priv_flags & IFF_XMIT_DST_RELEASE) @@ -2131,7 +2131,7 @@ gso: nskb->next = NULL; /* - * If device doesnt need nskb->dst, release it right now while + * If device doesn't need nskb->dst, release it right now while * its hot in this cpu cache */ if (dev->priv_flags & IFF_XMIT_DST_RELEASE) @@ -2950,8 +2950,8 @@ EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions * a compare and 2 stores extra right now if we dont have it on * but have CONFIG_NET_CLS_ACT - * NOTE: This doesnt stop any functionality; if you dont have - * the ingress scheduler, you just cant add policies on ingress. + * NOTE: This doesn't stop any functionality; if you dont have + * the ingress scheduler, you just can't add policies on ingress. * */ static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq) @@ -3780,7 +3780,7 @@ static void net_rx_action(struct softirq_action *h) * with netpoll's poll_napi(). Only the entity which * obtains the lock and sees NAPI_STATE_SCHED set will * actually make the ->poll() call. Therefore we avoid - * accidently calling ->poll() when NAPI is not scheduled. + * accidentally calling ->poll() when NAPI is not scheduled. */ work = 0; if (test_bit(NAPI_STATE_SCHED, &n->state)) { @@ -6316,7 +6316,7 @@ static void __net_exit default_device_exit(struct net *net) if (dev->rtnl_link_ops) continue; - /* Push remaing network devices to init_net */ + /* Push remaining network devices to init_net */ snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); err = dev_change_net_namespace(dev, &init_net, fb_name); if (err) { diff --git a/net/core/filter.c b/net/core/filter.c index 232b1873bb28..afb8afb066bb 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -425,7 +425,7 @@ EXPORT_SYMBOL(sk_run_filter); * As we dont want to clear mem[] array for each packet going through * sk_run_filter(), we check that filter loaded by user never try to read * a cell if not previously written, and we check all branches to be sure - * a malicious user doesnt try to abuse us. + * a malicious user doesn't try to abuse us. */ static int check_load_and_stores(struct sock_filter *filter, int flen) { diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 01a1101b5936..a7b342131869 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -129,7 +129,7 @@ static void linkwatch_schedule_work(int urgent) if (!cancel_delayed_work(&linkwatch_work)) return; - /* Otherwise we reschedule it again for immediate exection. */ + /* Otherwise we reschedule it again for immediate execution. */ schedule_delayed_work(&linkwatch_work, 0); } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 49f7ea5b4c75..d7c4bb4b1820 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(__rtnl_register); * as failure of this function is very unlikely, it can only happen due * to lack of memory when allocating the chain to store all message * handlers for a protocol. Meant for use in init functions where lack - * of memory implies no sense in continueing. + * of memory implies no sense in continuing. */ void rtnl_register(int protocol, int msgtype, rtnl_doit_func doit, rtnl_dumpit_func dumpit) @@ -1440,7 +1440,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, errout: if (err < 0 && modified && net_ratelimit()) printk(KERN_WARNING "A link change request failed with " - "some changes comitted already. Interface %s may " + "some changes committed already. Interface %s may " "have been left with an inconsistent configuration, " "please check.\n", dev->name); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 801dd08908f9..7ebeed0a877c 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2267,7 +2267,7 @@ EXPORT_SYMBOL(skb_prepare_seq_read); * of bytes already consumed and the next call to * skb_seq_read() will return the remaining part of the block. * - * Note 1: The size of each block of data returned can be arbitary, + * Note 1: The size of each block of data returned can be arbitrary, * this limitation is the cost for zerocopy seqeuental * reads of potentially non linear data. * diff --git a/net/core/sock.c b/net/core/sock.c index 7dfed792434d..6e819780c232 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -215,7 +215,7 @@ __u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; -/* Maximal space eaten by iovec or ancilliary data plus some space */ +/* Maximal space eaten by iovec or ancillary data plus some space */ int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); EXPORT_SYMBOL(sysctl_optmem_max); @@ -1175,7 +1175,7 @@ static void __sk_free(struct sock *sk) void sk_free(struct sock *sk) { /* - * We substract one from sk_wmem_alloc and can know if + * We subtract one from sk_wmem_alloc and can know if * some packets are still in some tx queue. * If not null, sock_wfree() will call __sk_free(sk) later */ @@ -1185,10 +1185,10 @@ void sk_free(struct sock *sk) EXPORT_SYMBOL(sk_free); /* - * Last sock_put should drop referrence to sk->sk_net. It has already - * been dropped in sk_change_net. Taking referrence to stopping namespace + * Last sock_put should drop reference to sk->sk_net. It has already + * been dropped in sk_change_net. Taking reference to stopping namespace * is not an option. - * Take referrence to a socket to remove it from hash _alive_ and after that + * Take reference to a socket to remove it from hash _alive_ and after that * destroy it in the context of init_net. */ void sk_release_kernel(struct sock *sk) diff --git a/net/dccp/output.c b/net/dccp/output.c index 784d30210543..136d41cbcd02 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -143,7 +143,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) } /** - * dccp_determine_ccmps - Find out about CCID-specfic packet-size limits + * dccp_determine_ccmps - Find out about CCID-specific packet-size limits * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), * since the RX CCID is restricted to feedback packets (Acks), which are small * in comparison with the data traffic. A value of 0 means "no current CCMPS". diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index bb2b41bc854e..d951f93644bf 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c @@ -124,7 +124,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) * Ignore removed tag data on doubly tagged packets, disable * flow control messages, force flow control priority to the * highest, and send all special multicast frames to the CPU - * port at the higest priority. + * port at the highest priority. */ REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 094e150c6260..a0af7ea87870 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -112,7 +112,7 @@ int cipso_v4_rbm_strictvalid = 1; /* The maximum number of category ranges permitted in the ranged category tag * (tag #5). You may note that the IETF draft states that the maximum number * of category ranges is 7, but if the low end of the last category range is - * zero then it is possibile to fit 8 category ranges because the zero should + * zero then it is possible to fit 8 category ranges because the zero should * be omitted. */ #define CIPSO_V4_TAG_RNG_CAT_MAX 8 @@ -438,7 +438,7 @@ cache_add_failure: * * Description: * Search the DOI definition list for a DOI definition with a DOI value that - * matches @doi. The caller is responsibile for calling rcu_read_[un]lock(). + * matches @doi. The caller is responsible for calling rcu_read_[un]lock(). * Returns a pointer to the DOI definition on success and NULL on failure. */ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) @@ -1293,7 +1293,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, return ret_val; /* This will send packets using the "optimized" format when - * possibile as specified in section 3.4.2.6 of the + * possible as specified in section 3.4.2.6 of the * CIPSO draft. */ if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) tag_len = 14; @@ -1752,7 +1752,7 @@ validate_return: } /** - * cipso_v4_error - Send the correct reponse for a bad packet + * cipso_v4_error - Send the correct response for a bad packet * @skb: the packet * @error: the error code * @gateway: CIPSO gateway flag diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index b92c86f6e9b3..e9013d6c1f51 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -12,7 +12,7 @@ * * Hans Liss Uppsala Universitet * - * This work is based on the LPC-trie which is originally descibed in: + * This work is based on the LPC-trie which is originally described in: * * An experimental study of compression methods for dynamic tries * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a91dc1611081..e5f8a71d3a2a 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -704,7 +704,7 @@ static void icmp_unreach(struct sk_buff *skb) */ /* - * Check the other end isnt violating RFC 1122. Some routers send + * Check the other end isn't violating RFC 1122. Some routers send * bogus responses to broadcast frames. If you see this message * first check your netmask matches at both ends, if it does then * get the other vendor to fix their kit. diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 67f241b97649..459c011b1d4a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -603,7 +603,7 @@ slow_path: /* IF: it doesn't fit, use 'mtu' - the data space left */ if (len > mtu) len = mtu; - /* IF: we are not sending upto and including the packet end + /* IF: we are not sending up to and including the packet end then align the next start on an eight byte boundary */ if (len < left) { len &= ~7; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 2b097752426b..cbff2ecccf3d 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1444,7 +1444,7 @@ static int __init ip_auto_config(void) root_server_addr = addr; /* - * Use defaults whereever applicable. + * Use defaults wherever applicable. */ if (ic_defaults() < 0) return -1; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4b5d457c2d76..89bc7e66d598 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -76,7 +76,7 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, } /* - * Unfortunatly, _b and _mask are not aligned to an int (or long int) + * Unfortunately, _b and _mask are not aligned to an int (or long int) * Some arches dont care, unrolling the loop is a win on them. * For other arches, we only have a 16bit alignement. */ @@ -1874,7 +1874,7 @@ static int __init arp_tables_init(void) if (ret < 0) goto err1; - /* Noone else will be downing sem now, so we won't sleep */ + /* No one else will be downing sem now, so we won't sleep */ ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); if (ret < 0) goto err2; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index ffcea0d1678e..704915028009 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -2233,7 +2233,7 @@ static int __init ip_tables_init(void) if (ret < 0) goto err1; - /* Noone else will be downing sem now, so we won't sleep */ + /* No one else will be downing sem now, so we won't sleep */ ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); if (ret < 0) goto err2; diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 21bcf471b25a..9c71b2755ce3 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -521,7 +521,7 @@ int nf_nat_protocol_register(const struct nf_nat_protocol *proto) } EXPORT_SYMBOL(nf_nat_protocol_register); -/* Noone stores the protocol anywhere; simply delete it. */ +/* No one stores the protocol anywhere; simply delete it. */ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) { spin_lock_bh(&nf_nat_lock); @@ -532,7 +532,7 @@ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) } EXPORT_SYMBOL(nf_nat_protocol_unregister); -/* Noone using conntrack by the time this called. */ +/* No one using conntrack by the time this called. */ static void nf_nat_cleanup_conntrack(struct nf_conn *ct) { struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2d3c72e5bbbf..bceaec42c37d 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -622,7 +622,7 @@ do_confirm: static void raw_close(struct sock *sk, long timeout) { /* - * Raw sockets may have direct kernel refereneces. Kill them. + * Raw sockets may have direct kernel references. Kill them. */ ip_ra_control(sk, 0, NULL); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4b0c81180804..ea107515c53e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -821,7 +821,7 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) } /* - * Pertubation of rt_genid by a small quantity [1..256] + * Perturbation of rt_genid by a small quantity [1..256] * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() * many times (2^24) without giving recent rt_genid. * Jenkins hash is strong enough that litle changes of rt_genid are OK. @@ -1191,7 +1191,7 @@ restart: #endif /* * Since lookup is lockfree, we must make sure - * previous writes to rt are comitted to memory + * previous writes to rt are committed to memory * before making rt visible to other CPUS. */ rcu_assign_pointer(rt_hash_table[hash].chain, rt); diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index 656d431c99ad..72f7218b03f5 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c @@ -12,7 +12,7 @@ * within cong_avoid. * o Error correcting in remote HZ, therefore remote HZ will be keeped * on checking and updating. - * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne + * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, since * OWD have a similar meaning as RTT. Also correct the buggy formular. * o Handle reaction for Early Congestion Indication (ECI) within * pkts_acked, as mentioned within pseudo code. diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index dfa5beb0c1c8..64f30eca1c67 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -73,7 +73,7 @@ static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb) tcp_advance_send_head(sk, skb); tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; - /* Don't override Nagle indefinately with F-RTO */ + /* Don't override Nagle indefinitely with F-RTO */ if (tp->frto_counter == 2) tp->frto_counter = 3; diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index dc7f43179c9a..05c3b6f0e8e1 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c @@ -20,7 +20,7 @@ #define TCP_YEAH_DELTA 3 //log minimum fraction of cwnd to be removed on loss #define TCP_YEAH_EPSILON 1 //log maximum fraction to be removed on early decongestion #define TCP_YEAH_PHY 8 //lin maximum delta from base -#define TCP_YEAH_RHO 16 //lin minumum number of consecutive rtt to consider competition on loss +#define TCP_YEAH_RHO 16 //lin minimum number of consecutive rtt to consider competition on loss #define TCP_YEAH_ZETA 50 //lin minimum number of state switchs to reset reno_count #define TCP_SCALABLE_AI_CNT 100U diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 588f47af5faf..f87a8eb76f3b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -189,7 +189,7 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, * @sk: socket struct in question * @snum: port number to look up * @saddr_comp: AF-dependent comparison of bound local IP addresses - * @hash2_nulladdr: AF-dependant hash value in secondary hash chains, + * @hash2_nulladdr: AF-dependent hash value in secondary hash chains, * with NULL address */ int udp_lib_get_port(struct sock *sk, unsigned short snum, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3daaf3c7703c..1493534116df 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1084,7 +1084,7 @@ static int ipv6_get_saddr_eval(struct net *net, case IPV6_SADDR_RULE_PRIVACY: { /* Rule 7: Prefer public address - * Note: prefer temprary address if use_tempaddr >= 2 + * Note: prefer temporary address if use_tempaddr >= 2 */ int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? !!(dst->prefs & IPV6_PREFER_SRC_TMP) : @@ -1968,7 +1968,7 @@ ok: * to the stored lifetime since we'll * be updating the timestamp below, * else we'll set it back to the - * minumum. + * minimum. */ if (prefered_lft != ifp->prefered_lft) { valid_lft = stored_lft; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 4b13d5d8890e..afcc7099f96d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -1113,7 +1113,7 @@ static int __init inet6_init(void) /* * ipngwg API draft makes clear that the correct semantics * for TCP and UDP is to consider one TCP and UDP instance - * in a host availiable by both INET and INET6 APIs and + * in a host available by both INET and INET6 APIs and * able to communicate via both network protocols. */ diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 18208876aa8a..46cf7bea6769 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -779,7 +779,7 @@ slow_path: /* IF: it doesn't fit, use 'mtu' - the data space left */ if (len > mtu) len = mtu; - /* IF: we are not sending upto and including the packet end + /* IF: we are not sending up to and including the packet end then align the next start on an eight byte boundary */ if (len < left) { len &= ~7; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 0b2af9b85cec..5a1c6f27ffaf 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -2248,7 +2248,7 @@ static int __init ip6_tables_init(void) if (ret < 0) goto err1; - /* Noone else will be downing sem now, so we won't sleep */ + /* No one else will be downing sem now, so we won't sleep */ ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); if (ret < 0) goto err2; diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 97c5b21b9674..cdd6d045e42e 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c @@ -71,7 +71,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum, if (reasm == NULL) return NF_STOLEN; - /* error occured or not fragmented */ + /* error occurred or not fragmented */ if (reasm == skb) return NF_ACCEPT; diff --git a/net/irda/irlap.c b/net/irda/irlap.c index 783c5f367d29..005b424494a0 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c @@ -165,7 +165,7 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos, irlap_apply_default_connection_parameters(self); - self->N3 = 3; /* # connections attemts to try before giving up */ + self->N3 = 3; /* # connections attempts to try before giving up */ self->state = LAP_NDM; diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index d434c8880745..bb47021c9a55 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -708,7 +708,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, self->frame_sent = TRUE; } - /* Readjust our timer to accomodate devices + /* Readjust our timer to accommodate devices * doing faster or slower discovery than us... * Jean II */ irlap_start_query_timer(self, info->S, info->s); @@ -931,7 +931,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, irlap_send_rr_frame(self, CMD_FRAME); /* The timer is set to half the normal timer to quickly - * detect a failure to negociate the new connection + * detect a failure to negotiate the new connection * parameters. IrLAP 6.11.3.2, note 3. * Note that currently we don't process this failure * properly, as we should do a quick disconnect. @@ -1052,7 +1052,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, return -EPROTO; } - /* Substract space used by this skb */ + /* Subtract space used by this skb */ self->bytes_left -= skb->len; #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ /* Window has been adjusted for the max packet @@ -1808,7 +1808,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, return -EPROTO; /* Try again later */ } - /* Substract space used by this skb */ + /* Subtract space used by this skb */ self->bytes_left -= skb->len; #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ /* Window has been adjusted for the max packet diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 688222cbf55b..8c004161a843 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -848,7 +848,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) * though IrLAP is currently sending the *last* frame of the * tx-window, the driver most likely has only just started * sending the *first* frame of the same tx-window. - * I.e. we are always at the very begining of or Tx window. + * I.e. we are always at the very beginning of or Tx window. * Now, we are supposed to set the final timer from the end * of our tx-window to let the other peer reply. So, we need * to add extra time to compensate for the fact that we diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c index c1fb5db81042..9505a7d06f1a 100644 --- a/net/irda/irlmp_event.c +++ b/net/irda/irlmp_event.c @@ -498,7 +498,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event, switch (event) { #ifdef CONFIG_IRDA_ULTRA case LM_UDATA_INDICATION: - /* This is most bizzare. Those packets are aka unreliable + /* This is most bizarre. Those packets are aka unreliable * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA. * Why do we pass them as Ultra ??? Jean II */ irlmp_connless_data_indication(self, skb); diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index 0d82ff5aeff1..979ecb2435a7 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h @@ -73,7 +73,7 @@ * Infinite thanks to those brave souls for providing the infrastructure * upon which IrNET is built. * - * Thanks to all my collegues in HP for helping me. In particular, + * Thanks to all my colleagues in HP for helping me. In particular, * thanks to Salil Pradhan and Bill Serra for W2k testing... * Thanks to Luiz Magalhaes for irnetd and much testing... * diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index 849aaf0dabb5..9715e6e5900b 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c @@ -40,7 +40,7 @@ * o the hash function for ints is pathetic (but could be changed) * o locking is sometime suspicious (especially during enumeration) * o most users have only a few elements (== overhead) - * o most users never use seach, so don't benefit from hashing + * o most users never use search, so don't benefit from hashing * Problem already fixed : * o not 64 bit compliant (most users do hashv = (int) self) * o hashbin_remove() is broken => use hashbin_remove_this() diff --git a/net/irda/irttp.c b/net/irda/irttp.c index f6054f9ccbe3..9d9af4606970 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -1193,7 +1193,7 @@ EXPORT_SYMBOL(irttp_connect_request); /* * Function irttp_connect_confirm (handle, qos, skb) * - * Sevice user confirms TSAP connection with peer. + * Service user confirms TSAP connection with peer. * */ static void irttp_connect_confirm(void *instance, void *sap, diff --git a/net/irda/qos.c b/net/irda/qos.c index 2b00974e5bae..1b51bcf42394 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c @@ -39,16 +39,16 @@ #include /* - * Maximum values of the baud rate we negociate with the other end. + * Maximum values of the baud rate we negotiate with the other end. * Most often, you don't have to change that, because Linux-IrDA will * use the maximum offered by the link layer, which usually works fine. * In some very rare cases, you may want to limit it to lower speeds... */ int sysctl_max_baud_rate = 16000000; /* - * Maximum value of the lap disconnect timer we negociate with the other end. + * Maximum value of the lap disconnect timer we negotiate with the other end. * Most often, the value below represent the best compromise, but some user - * may want to keep the LAP alive longuer or shorter in case of link failure. + * may want to keep the LAP alive longer or shorter in case of link failure. * Remember that the threshold time (early warning) is fixed to 3s... */ int sysctl_max_noreply_time = 12; @@ -411,7 +411,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos) * Fix tx data size according to user limits - Jean II */ if (qos->data_size.value > sysctl_max_tx_data_size) - /* Allow non discrete adjustement to avoid loosing capacity */ + /* Allow non discrete adjustement to avoid losing capacity */ qos->data_size.value = sysctl_max_tx_data_size; /* * Override Tx window if user request it. - Jean II diff --git a/net/irda/timer.c b/net/irda/timer.c index 0335ba0cc593..f418cb2ad49c 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c @@ -59,7 +59,7 @@ void irlap_start_query_timer(struct irlap_cb *self, int S, int s) * slot time, plus add some extra time to properly receive the last * discovery packet (which is longer due to extra discovery info), * to avoid messing with for incomming connections requests and - * to accomodate devices that perform discovery slower than us. + * to accommodate devices that perform discovery slower than us. * Jean II */ timeout = ((sysctl_slot_timeout * HZ / 1000) * (S - s) + XIDEXTRA_TIMEOUT + SMALLBUSY_TIMEOUT); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 9637e45744fa..986b2a5e8769 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -250,7 +250,7 @@ static struct device *af_iucv_dev; * PRMDATA[0..6] socket data (max 7 bytes); * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) * - * The socket data length is computed by substracting the socket data length + * The socket data length is computed by subtracting the socket data length * value from 0xFF. * If the socket data len is greater 7, then PRMDATA can be used for special * notifications (see iucv_sock_shutdown); and further, diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 1ee5dab3cfae..8f156bd86be7 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -735,7 +735,7 @@ static void iucv_cleanup_queue(void) struct iucv_irq_list *p, *n; /* - * When a path is severed, the pathid can be reused immediatly + * When a path is severed, the pathid can be reused immediately * on a iucv connect or a connection pending interrupt. Remove * all entries from the task queue that refer to a stale pathid * (iucv_path_table[ix] == NULL). Only then do the iucv connect @@ -807,7 +807,7 @@ void iucv_unregister(struct iucv_handler *handler, int smp) spin_lock_bh(&iucv_table_lock); /* Remove handler from the iucv_handler_list. */ list_del_init(&handler->list); - /* Sever all pathids still refering to the handler. */ + /* Sever all pathids still referring to the handler. */ list_for_each_entry_safe(p, n, &handler->paths, list) { iucv_sever_pathid(p->pathid, NULL); iucv_path_table[p->pathid] = NULL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a40401701424..c18396c248d7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -97,7 +97,7 @@ struct ieee80211_bss { size_t supp_rates_len; /* - * During assocation, we save an ERP value from a probe response so + * During association, we save an ERP value from a probe response so * that we can feed ERP info to the driver when handling the * association completes. these fields probably won't be up-to-date * otherwise, you probably don't want to use them. diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 8d65b47d9837..336ca9d0c5c4 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -628,7 +628,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, * * @mpath: mesh path whose queue has to be freed * - * Locking: the function must me called withing a rcu_read_lock region + * Locking: the function must me called within a rcu_read_lock region */ void mesh_path_flush_pending(struct mesh_path *mpath) { diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 8212a8bebf06..78e67d22dc1f 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -259,7 +259,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) } } - /* try to sample up to half of the availble rates during each interval */ + /* try to sample up to half of the available rates during each interval */ mi->sample_count *= 4; cur_prob = 0; diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 6510f8ee738e..19111c7bf454 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h @@ -77,7 +77,7 @@ union rc_pid_event_data { }; struct rc_pid_event { - /* The time when the event occured */ + /* The time when the event occurred */ unsigned long timestamp; /* Event ID number */ diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5c1930ba8ebe..c50b68423c7b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -381,7 +381,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) * specs were sane enough this time around to require padding each A-MSDU * subframe to a length that is a multiple of four. * - * Padding like Atheros hardware adds which is inbetween the 802.11 header and + * Padding like Atheros hardware adds which is between the 802.11 header and * the payload is not supported, the driver is required to move the 802.11 * header to be directly in front of the payload in that case. */ diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d0311a322ddd..13e8c30adf01 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -47,9 +47,9 @@ * Station entries are added by mac80211 when you establish a link with a * peer. This means different things for the different type of interfaces * we support. For a regular station this mean we add the AP sta when we - * receive an assocation response from the AP. For IBSS this occurs when + * receive an association response from the AP. For IBSS this occurs when * get to know about a peer on the same IBSS. For WDS we add the sta for - * the peer imediately upon device open. When using AP mode we add stations + * the peer immediately upon device open. When using AP mode we add stations * for each respective station upon request from userspace through nl80211. * * In order to remove a STA info structure, various sta_info_destroy_*() diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 57681149e37f..b2f95966c7f4 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -173,7 +173,7 @@ struct sta_ampdu_mlme { /** * enum plink_state - state of a mesh peer link finite state machine * - * @PLINK_LISTEN: initial state, considered the implicit state of non existant + * @PLINK_LISTEN: initial state, considered the implicit state of non existent * mesh peer links * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index d6b48230a540..253326e8d990 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -893,7 +893,7 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, to = ip_set_list[to_id]; /* Features must not change. - * Not an artifical restriction anymore, as we must prevent + * Not an artificial restriction anymore, as we must prevent * possible loops created by swapping in setlist type of sets. */ if (!(from->type->features == to->type->features && from->type->family == to->type->family)) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index f289306cbf12..c97bd45975be 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -595,7 +595,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) atomic_inc(&dest->inactconns); } else { /* It is a persistent connection/template, so increase - the peristent connection counter */ + the persistent connection counter */ atomic_inc(&dest->persistconns); } @@ -657,7 +657,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) } } else { /* It is a persistent connection/template, so decrease - the peristent connection counter */ + the persistent connection counter */ atomic_dec(&dest->persistconns); } diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index f276df9896b3..87e40ea77a95 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -131,7 +131,7 @@ static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en) { list_del(&en->list); /* - * We don't kfree dest because it is refered either by its service + * We don't kfree dest because it is referred either by its service * or the trash dest list. */ atomic_dec(&en->dest->refcnt); diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index cb1c9913d38b..90f618ab6dda 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -152,7 +152,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) write_lock(&set->lock); list_for_each_entry_safe(e, ep, &set->list, list) { /* - * We don't kfree dest because it is refered either + * We don't kfree dest because it is referred either * by its service or by the trash dest list. */ atomic_dec(&e->dest->refcnt); diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index b027ccc49f43..d12ed53ec95f 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -566,7 +566,7 @@ static struct ipvs_sctp_nextstate * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server */ /* - * We recieved the data chuck, keep the state unchanged. I assume + * We received the data chuck, keep the state unchanged. I assume * that still data chuncks can be received by both the peers in * SHUDOWN state */ @@ -633,7 +633,7 @@ static struct ipvs_sctp_nextstate * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client */ /* - * We recieved the data chuck, keep the state unchanged. I assume + * We received the data chuck, keep the state unchanged. I assume * that still data chuncks can be received by both the peers in * SHUDOWN state */ @@ -701,7 +701,7 @@ static struct ipvs_sctp_nextstate * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server */ /* - * We recieved the data chuck, keep the state unchanged. I assume + * We received the data chuck, keep the state unchanged. I assume * that still data chuncks can be received by both the peers in * SHUDOWN state */ @@ -771,7 +771,7 @@ static struct ipvs_sctp_nextstate * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client */ /* - * We recieved the data chuck, keep the state unchanged. I assume + * We received the data chuck, keep the state unchanged. I assume * that still data chuncks can be received by both the peers in * SHUDOWN state */ diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 941286ca911d..2e1c11f78419 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -453,7 +453,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) REJECT will give spurious warnings here. */ /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ - /* No external references means noone else could have + /* No external references means no one else could have confirmed us. */ NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); pr_debug("Confirming conntrack %p\n", ct); @@ -901,7 +901,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, ret = l3proto->get_l4proto(skb, skb_network_offset(skb), &dataoff, &protonum); if (ret <= 0) { - pr_debug("not prepared to track yet or error occured\n"); + pr_debug("not prepared to track yet or error occurred\n"); NF_CT_STAT_INC_ATOMIC(net, error); NF_CT_STAT_INC_ATOMIC(net, invalid); ret = -ret; diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 9ae57c57c50e..2e664a69d7db 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -98,7 +98,7 @@ static const char * const dccp_state_names[] = { #define sIV CT_DCCP_INVALID /* - * DCCP state transistion table + * DCCP state transition table * * The assumption is the same as for TCP tracking: * diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 6f4ee70f460b..6772b1154654 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -107,9 +107,9 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA}, /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA}, -/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/ +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't have Stale cookie*/ /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */ -/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */ +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't come in orig dir */ /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL} }, { @@ -121,7 +121,7 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA}, /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA}, /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA}, -/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */ +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't come in reply dir */ /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA}, /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL} } diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index bcf47eb518ef..237cc1981b89 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -707,7 +707,7 @@ static const char *ct_sdp_header_search(const char *dptr, const char *limit, } /* Locate a SDP header (optionally a substring within the header value), - * optionally stopping at the first occurence of the term header, parse + * optionally stopping at the first occurrence of the term header, parse * it and return the offset and length of the data we're interested in. */ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 5ab22e2bbd7d..5b466cd1272f 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -134,7 +134,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; - /* QUEUE == DROP if noone is waiting, to be safe. */ + /* QUEUE == DROP if no one is waiting, to be safe. */ rcu_read_lock(); qh = rcu_dereference(queue_handler[pf]); diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index d37b7f80fa37..de0d8e4cbfb6 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -109,7 +109,7 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) * * Description: * This is the hashing function for the domain hash table, it returns the - * correct bucket number for the domain. The caller is responsibile for + * correct bucket number for the domain. The caller is responsible for * ensuring that the hash table is protected with either a RCU read lock or the * hash table lock. * @@ -134,7 +134,7 @@ static u32 netlbl_domhsh_hash(const char *key) * * Description: * Searches the domain hash table and returns a pointer to the hash table - * entry if found, otherwise NULL is returned. The caller is responsibile for + * entry if found, otherwise NULL is returned. The caller is responsible for * ensuring that the hash table is protected with either a RCU read lock or the * hash table lock. * @@ -165,7 +165,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) * Searches the domain hash table and returns a pointer to the hash table * entry if an exact match is found, if an exact match is not present in the * hash table then the default entry is returned if valid otherwise NULL is - * returned. The caller is responsibile ensuring that the hash table is + * returned. The caller is responsible ensuring that the hash table is * protected with either a RCU read lock or the hash table lock. * */ @@ -193,7 +193,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) * * Description: * Generate an audit record for adding a new NetLabel/LSM mapping entry with - * the given information. Caller is responsibile for holding the necessary + * the given information. Caller is responsible for holding the necessary * locks. * */ @@ -605,7 +605,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) * * Description: * Look through the domain hash table searching for an entry to match @domain, - * return a pointer to a copy of the entry or NULL. The caller is responsibile + * return a pointer to a copy of the entry or NULL. The caller is responsible * for ensuring that rcu_read_[un]lock() is called. * */ diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 998e85e895d0..4f251b19fbcc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -259,7 +259,7 @@ add_failure: * * Description: * This function is a helper function used by the LISTALL and LISTDEF command - * handlers. The caller is responsibile for ensuring that the RCU read lock + * handlers. The caller is responsible for ensuring that the RCU read lock * is held. Returns zero on success, negative values on failure. * */ diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index c47a511f203d..7c4dce8fa5e6 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -355,7 +355,7 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) * * Conceptually, we have two counters: * - send credits: this tells us how many WRs we're allowed - * to submit without overruning the reciever's queue. For + * to submit without overruning the receiver's queue. For * each SEND WR we post, we decrement this by one. * * - posted credits: this tells us how many WRs we recently diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index 712cf2d1f28e..3a60a15d1b4a 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c @@ -181,7 +181,7 @@ static int rds_iw_init_qp_attrs(struct ib_qp_init_attr *attr, unsigned int send_size, recv_size; int ret; - /* The offset of 1 is to accomodate the additional ACK WR. */ + /* The offset of 1 is to accommodate the additional ACK WR. */ send_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_send_wr + 1); recv_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_recv_wr + 1); rds_iw_ring_resize(send_ring, send_size - 1); diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c index 59509e9a9e72..6deaa77495e3 100644 --- a/net/rds/iw_rdma.c +++ b/net/rds/iw_rdma.c @@ -122,7 +122,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd #else /* FIXME - needs to compare the local and remote * ipaddr/port tuple, but the ipaddr is the only - * available infomation in the rds_sock (as the rest are + * available information in the rds_sock (as the rest are * zero'ed. It doesn't appear to be properly populated * during connection setup... */ diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 6280ea020d4e..545d8ee3efb1 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c @@ -307,7 +307,7 @@ void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context) * * Conceptually, we have two counters: * - send credits: this tells us how many WRs we're allowed - * to submit without overruning the reciever's queue. For + * to submit without overruning the receiver's queue. For * each SEND WR we post, we decrement this by one. * * - posted credits: this tells us how many WRs we recently diff --git a/net/rds/send.c b/net/rds/send.c index 35b9c2e9caf1..d58ae5f9339e 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -116,7 +116,7 @@ static void release_in_xmit(struct rds_connection *conn) } /* - * We're making the concious trade-off here to only send one message + * We're making the conscious trade-off here to only send one message * down the connection at a time. * Pro: * - tx queueing is a simple fifo list diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 08dcd2f29cdc..479cae57d187 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -587,7 +587,7 @@ static int rose_clear_routes(void) /* * Check that the device given is a valid AX.25 interface that is "up". - * called whith RTNL + * called with RTNL */ static struct net_device *rose_ax25_dev_find(char *devname) { diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 15873e14cb54..14b42f4ad791 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -999,7 +999,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) switch (n->nlmsg_type) { case RTM_NEWACTION: /* we are going to assume all other flags - * imply create only if it doesnt exist + * imply create only if it doesn't exist * Note that CREATE | EXCL implies that * but since we want avoid ambiguity (eg when flags * is zero) then just set this diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 50c7c06c019d..7affe9a92757 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -161,7 +161,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, } if (offset > 0 && offset > skb->len) { pr_info("tc filter pedit" - " offset %d cant exceed pkt length %d\n", + " offset %d can't exceed pkt length %d\n", offset, skb->len); goto bad; } diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index a4de67eca824..49130e8abff0 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -47,7 +47,7 @@ * on the meta type. Obviously, the length of the data must also * be provided for non-numeric types. * - * Additionaly, type dependant modifiers such as shift operators + * Additionally, type dependent modifiers such as shift operators * or mask may be applied to extend the functionaliy. As of now, * the variable length type supports shifting the byte string to * the right, eating up any number of octets and thus supporting diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index e1429a85091f..29b942ce9e82 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -183,7 +183,7 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) * filters in qdisc and in inner nodes (if higher filter points to the inner * node). If we end up with classid MAJOR:0 we enqueue the skb into special * internal fifo (direct). These packets then go directly thru. If we still - * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull + * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful * then finish and return direct queue. */ #define HTB_DIRECT ((struct htb_class *)-1L) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index edbbf7ad6623..69c35f6cd13f 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -160,7 +160,7 @@ static bool loss_4state(struct netem_sched_data *q) u32 rnd = net_random(); /* - * Makes a comparision between rnd and the transition + * Makes a comparison between rnd and the transition * probabilities outgoing from the current state, then decides the * next state and if the next packet has to be transmitted or lost. * The four states correspond to: @@ -212,9 +212,9 @@ static bool loss_4state(struct netem_sched_data *q) * Generates losses according to the Gilbert-Elliot loss model or * its special cases (Gilbert or Simple Gilbert) * - * Makes a comparision between random number and the transition + * Makes a comparison between random number and the transition * probabilities outgoing from the current state, then decides the - * next state. A second random number is extracted and the comparision + * next state. A second random number is extracted and the comparison * with the loss probability of the current state decides if the next * packet will be transmitted or lost. */ diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 6b04287913cd..0698cad61763 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1593,7 +1593,7 @@ void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc) struct sctp_chunk *ack; struct sctp_chunk *tmp; - /* We can remove all the entries from the queue upto + /* We can remove all the entries from the queue up to * the "Peer-Sequence-Number". */ list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list, diff --git a/net/sctp/auth.c b/net/sctp/auth.c index ddbbf7c81fa1..865e68fef21c 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -113,7 +113,7 @@ struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) return new; } -/* Free the shared key stucture */ +/* Free the shared key structure */ static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) { BUG_ON(!list_empty(&sh_key->key_list)); @@ -122,7 +122,7 @@ static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) kfree(sh_key); } -/* Destory the entire key list. This is done during the +/* Destroy the entire key list. This is done during the * associon and endpoint free process. */ void sctp_auth_destroy_keys(struct list_head *keys) @@ -324,7 +324,7 @@ static struct sctp_auth_bytes *sctp_auth_asoc_create_secret( if (!peer_key_vector || !local_key_vector) goto out; - /* Figure out the order in wich the key_vectors will be + /* Figure out the order in which the key_vectors will be * added to the endpoint shared key. * SCTP-AUTH, Section 6.1: * This is performed by selecting the numerically smaller key diff --git a/net/sctp/input.c b/net/sctp/input.c index 826661be73e7..5436c6921167 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -1034,7 +1034,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( * association. * * This means that any chunks that can help us identify the association need -* to be looked at to find this assocation. +* to be looked at to find this association. */ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, const union sctp_addr *laddr, diff --git a/net/sctp/output.c b/net/sctp/output.c index 60600d337a3a..b4f3cf06d8da 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -510,7 +510,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) sh->checksum = sctp_end_cksum(crc32); } else { if (dst->dev->features & NETIF_F_SCTP_CSUM) { - /* no need to seed psuedo checksum for SCTP */ + /* no need to seed pseudo checksum for SCTP */ nskb->ip_summed = CHECKSUM_PARTIAL; nskb->csum_start = (skb_transport_header(nskb) - nskb->head); diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 26dc005113a0..bf92a5b68f8b 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -177,13 +177,13 @@ static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn) * 3) If the missing report count for TSN t is to be * incremented according to [RFC2960] and * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, - * then the sender MUST futher execute steps 3.1 and + * then the sender MUST further execute steps 3.1 and * 3.2 to determine if the missing report count for * TSN t SHOULD NOT be incremented. * * 3.3) If 3.1 and 3.2 do not dictate that the missing * report count for t should not be incremented, then - * the sender SOULD increment missing report count for + * the sender SHOULD increment missing report count for * t (according to [RFC2960] and [SCTP_STEWART_2002]). */ static inline int sctp_cacc_skip(struct sctp_transport *primary, @@ -843,7 +843,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) case SCTP_CID_ECN_CWR: case SCTP_CID_ASCONF_ACK: one_packet = 1; - /* Fall throught */ + /* Fall through */ case SCTP_CID_SACK: case SCTP_CID_HEARTBEAT: diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index b21b218d564f..5f86ee4b54c1 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -482,7 +482,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, * If the timer was a heartbeat, we only increment error counts * when we already have an outstanding HEARTBEAT that has not * been acknowledged. - * Additionaly, some tranport states inhibit error increments. + * Additionally, some tranport states inhibit error increments. */ if (!is_hb) { asoc->overall_error_count++; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 4b4eb7c96bbd..76792083c379 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -551,7 +551,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, * * This means that if we only want to abort associations * in an authenticated way (i.e AUTH+ABORT), then we - * can't destroy this association just becuase the packet + * can't destroy this association just because the packet * was malformed. */ if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) @@ -1546,7 +1546,7 @@ cleanup: } /* - * Handle simultanous INIT. + * Handle simultaneous INIT. * This means we started an INIT and then we got an INIT request from * our peer. * @@ -2079,7 +2079,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( * RFC 2960, Section 3.3.7 * If an endpoint receives an ABORT with a format error or for an * association that doesn't exist, it MUST silently discard it. - * Becasue the length is "invalid", we can't really discard just + * Because the length is "invalid", we can't really discard just * as we do not know its true length. So, to be safe, discard the * packet. */ @@ -2120,7 +2120,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, * RFC 2960, Section 3.3.7 * If an endpoint receives an ABORT with a format error or for an * association that doesn't exist, it MUST silently discard it. - * Becasue the length is "invalid", we can't really discard just + * Because the length is "invalid", we can't really discard just * as we do not know its true length. So, to be safe, discard the * packet. */ @@ -2381,7 +2381,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, * RFC 2960, Section 3.3.7 * If an endpoint receives an ABORT with a format error or for an * association that doesn't exist, it MUST silently discard it. - * Becasue the length is "invalid", we can't really discard just + * Because the length is "invalid", we can't really discard just * as we do not know its true length. So, to be safe, discard the * packet. */ @@ -2448,7 +2448,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, * RFC 2960, Section 3.3.7 * If an endpoint receives an ABORT with a format error or for an * association that doesn't exist, it MUST silently discard it. - * Becasue the length is "invalid", we can't really discard just + * Because the length is "invalid", we can't really discard just * as we do not know its true length. So, to be safe, discard the * packet. */ @@ -3855,7 +3855,7 @@ gen_shutdown: } /* - * SCTP-AUTH Section 6.3 Receving authenticated chukns + * SCTP-AUTH Section 6.3 Receiving authenticated chukns * * The receiver MUST use the HMAC algorithm indicated in the HMAC * Identifier field. If this algorithm was not specified by the @@ -4231,7 +4231,7 @@ static sctp_disposition_t sctp_sf_abort_violation( * * This means that if we only want to abort associations * in an authenticated way (i.e AUTH+ABORT), then we - * can't destroy this association just becuase the packet + * can't destroy this association just because the packet * was malformed. */ if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) @@ -4402,9 +4402,9 @@ static sctp_disposition_t sctp_sf_violation_ctsn( } /* Handle protocol violation of an invalid chunk bundling. For example, - * when we have an association and we recieve bundled INIT-ACK, or + * when we have an association and we receive bundled INIT-ACK, or * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" - * statement from the specs. Additinally, there might be an attacker + * statement from the specs. Additionally, there might be an attacker * on the path and we may not want to continue this communication. */ static sctp_disposition_t sctp_sf_violation_chunk( diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3951a10605bc..deb82e35a107 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1193,7 +1193,7 @@ out_free: * an endpoint that is multi-homed. Much like sctp_bindx() this call * allows a caller to specify multiple addresses at which a peer can be * reached. The way the SCTP stack uses the list of addresses to set up - * the association is implementation dependant. This function only + * the association is implementation dependent. This function only * specifies that the stack will try to make use of all the addresses in * the list when needed. * diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index aa72e89c3ee1..dff27d5e22fd 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -554,7 +554,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed( memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); /* Per TSVWG discussion with Randy. Allow the application to - * ressemble a fragmented message. + * resemble a fragmented message. */ ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 17678189d054..f2d1de7f2ffb 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -240,7 +240,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) } else { /* * If fragment interleave is enabled, we - * can queue this to the recieve queue instead + * can queue this to the receive queue instead * of the lobby. */ if (sctp_sk(sk)->frag_interleave) diff --git a/net/socket.c b/net/socket.c index 5212447c86e7..310d16b1b3c9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2986,7 +2986,7 @@ out: /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE * for some operations; this forces use of the newer bridge-utils that - * use compatiable ioctls + * use compatible ioctls */ static int old_bridge_ioctl(compat_ulong_t __user *argp) { diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index bcdae78fdfc6..8d0f7d3c71c8 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1101,7 +1101,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) /* credential is: * version(==1), proc(0,1,2,3), seq, service (1,2,3), handle - * at least 5 u32s, and is preceeded by length, so that makes 6. + * at least 5 u32s, and is preceded by length, so that makes 6. */ if (argv->iov_len < 5 * 4) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 1e336a06d3e6..bf005d3c65ef 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -504,7 +504,7 @@ static int xs_nospace(struct rpc_task *task) * EAGAIN: The socket was blocked, please call again later to * complete the request * ENOTCONN: Caller needs to invoke connect logic then call again - * other: Some other error occured, the request was not sent + * other: Some other error occurred, the request was not sent */ static int xs_udp_send_request(struct rpc_task *task) { @@ -590,7 +590,7 @@ static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) * EAGAIN: The socket was blocked, please call again later to * complete the request * ENOTCONN: Caller needs to invoke connect logic then call again - * other: Some other error occured, the request was not sent + * other: Some other error occurred, the request was not sent * * XXX: In the case of soft timeouts, should we eventually give up * if sendmsg is not able to make progress? diff --git a/net/tipc/link.c b/net/tipc/link.c index 43639ff1cbec..ebf338f7b14e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2471,7 +2471,7 @@ exit: * A pending message being re-assembled must store certain values * to handle subsequent fragments correctly. The following functions * help storing these values in unused, available fields in the - * pending message. This makes dynamic memory allocation unecessary. + * pending message. This makes dynamic memory allocation unnecessary. */ static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index c9fa6dfcf287..80025a1b3bfd 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -160,7 +160,7 @@ void tipc_named_withdraw(struct publication *publ) buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); if (!buf) { - warn("Withdrawl distribution failure\n"); + warn("Withdrawal distribution failure\n"); return; } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1663e1a2efdd..3a43a8304768 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -207,7 +207,7 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) /* * This may look like an off by one error but it is a bit more * subtle. 108 is the longest valid AF_UNIX path for a binding. - * sun_path[108] doesnt as such exist. However in kernel space + * sun_path[108] doesn't as such exist. However in kernel space * we are guaranteed that it is a valid memory location in our * kernel address buffer. */ diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 11f25c7a7a05..f346395314ba 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -51,7 +51,7 @@ /* * Structures for interfacing with the /proc filesystem. - * Router creates its own directory /proc/net/router with the folowing + * Router creates its own directory /proc/net/router with the following * entries: * config device configuration * status global device statistics diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3332d5bce317..ab801a1097b2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -809,7 +809,7 @@ static void handle_channel(struct wiphy *wiphy, if (r) { /* * We will disable all channels that do not match our - * recieved regulatory rule unless the hint is coming + * received regulatory rule unless the hint is coming * from a Country IE and the Country IE had no information * about a band. The IEEE 802.11 spec allows for an AP * to send only a subset of the regulatory rules allowed, @@ -838,7 +838,7 @@ static void handle_channel(struct wiphy *wiphy, request_wiphy && request_wiphy == wiphy && request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { /* - * This gaurantees the driver's requested regulatory domain + * This guarantees the driver's requested regulatory domain * will always be used as a base for further regulatory * settings */ diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 406207515b5e..f77e4e75f914 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -31,7 +31,7 @@ * x25_parse_facilities - Parse facilities from skb into the facilities structs * * @skb: sk_buff to parse - * @facilities: Regular facilites, updated as facilities are found + * @facilities: Regular facilities, updated as facilities are found * @dte_facs: ITU DTE facilities, updated as DTE facilities are found * @vc_fac_mask: mask is updated with all facilities found * diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index 25a810793968..c541b622ae16 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c @@ -31,7 +31,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, goto out_no_route; if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { - /* This shouldnt happen, if it occurs somehow + /* This shouldn't happen, if it occurs somehow * do something sensible */ goto out_put_route; @@ -45,7 +45,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, } /* Remote end sending a call request on an already - * established LCI? It shouldnt happen, just in case.. + * established LCI? It shouldn't happen, just in case.. */ read_lock_bh(&x25_forward_list_lock); list_for_each(entry, &x25_forward_list) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 3d15d3e1b2c4..5d1d60d3ca83 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -894,7 +894,7 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, u32 *f; nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); - if (nlh == NULL) /* shouldnt really happen ... */ + if (nlh == NULL) /* shouldn't really happen ... */ return -EMSGSIZE; f = nlmsg_data(nlh); @@ -954,7 +954,7 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, u32 *f; nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); - if (nlh == NULL) /* shouldnt really happen ... */ + if (nlh == NULL) /* shouldn't really happen ... */ return -EMSGSIZE; f = nlmsg_data(nlh); @@ -1361,7 +1361,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (!xp) return err; - /* shouldnt excl be based on nlh flags?? + /* shouldn't excl be based on nlh flags?? * Aha! this is anti-netlink really i.e more pfkey derived * in netlink excl is a flag and you wouldnt need * a type XFRM_MSG_UPDPOLICY - JHS */ diff --git a/samples/Kconfig b/samples/Kconfig index e03cf0e374d7..41063e7592d2 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -55,7 +55,7 @@ config SAMPLE_KFIFO If in doubt, say "N" here. config SAMPLE_KDB - tristate "Build kdb command exmaple -- loadable modules only" + tristate "Build kdb command example -- loadable modules only" depends on KGDB_KDB && m help Build an example of how to dynamically add the hello diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c index bd0f337afcab..063653955f9f 100644 --- a/samples/hw_breakpoint/data_breakpoint.c +++ b/samples/hw_breakpoint/data_breakpoint.c @@ -19,7 +19,7 @@ * * This file is a kernel module that places a breakpoint over ksym_name kernel * variable using Hardware Breakpoint register. The corresponding handler which - * prints a backtrace is invoked everytime a write operation is performed on + * prints a backtrace is invoked every time a write operation is performed on * that variable. * * Copyright (C) IBM Corporation, 2009 diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 7d22056582c1..56dfafc73c1a 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -35,14 +35,14 @@ # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined # symbols in the final module linking stage # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. -# This is solely usefull to speed up test compiles +# This is solely useful to speed up test compiles PHONY := _modpost _modpost: __modpost include include/config/auto.conf include scripts/Kbuild.include -# When building external modules load the Kbuild file to retreive EXTRA_SYMBOLS info +# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info ifneq ($(KBUILD_EXTMOD),) # set src + obj - they may be used when building the .mod.c file diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8f9e394298cd..d8670810db65 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1946,13 +1946,13 @@ sub process { # printk should use KERN_* levels. Note that follow on printk's on the # same line do not need a level, so we use the current block context # to try and find and validate the current printk. In summary the current -# printk includes all preceeding printk's which have no newline on the end. +# printk includes all preceding printk's which have no newline on the end. # we assume the first bad printk is the one to report. if ($line =~ /\bprintk\((?!KERN_)\s*"/) { my $ok = 0; for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { #print "CHECK<$lines[$ln - 1]\n"; - # we have a preceeding printk if it ends + # we have a preceding printk if it ends # with "\n" ignore it, else it is to blame if ($lines[$ln - 1] =~ m{\bprintk\(}) { if ($rawlines[$ln - 1] !~ m{\\n"}) { @@ -2044,7 +2044,7 @@ sub process { for (my $n = 0; $n < $#elements; $n += 2) { $off += length($elements[$n]); - # Pick up the preceeding and succeeding characters. + # Pick up the preceding and succeeding characters. my $ca = substr($opline, 0, $off); my $cc = ''; if (length($opline) >= ($off + length($elements[$n + 1]))) { diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ce80e4fb41b2..ff6246f000ce 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -61,7 +61,7 @@ #define FDT_ERR_NOTFOUND 1 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ #define FDT_ERR_EXISTS 2 - /* FDT_ERR_EXISTS: Attemped to create a node or property which + /* FDT_ERR_EXISTS: Attempted to create a node or property which * already exists */ #define FDT_ERR_NOSPACE 3 /* FDT_ERR_NOSPACE: Operation needed to expand the device diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index c9209d5c999e..26d0e1e60c0c 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -155,7 +155,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) } } - /* if no collision occured, add child to the old node. */ + /* if no collision occurred, add child to the old node. */ if (new_child) add_child(old_node, new_child); } diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 55caecdad995..e12b1a7525cf 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -284,7 +284,7 @@ while [ $# -gt 0 ]; do done # If output_file is set we will generate cpio archive and compress it -# we are carefull to delete tmp files +# we are careful to delete tmp files if [ ! -z ${output_file} ]; then if [ -z ${cpio_file} ]; then cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)" diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9f85012acf0d..d793001929cf 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1705,7 +1705,7 @@ sub push_parameter($$$) { $param = xml_escape($param); - # strip spaces from $param so that it is one continous string + # strip spaces from $param so that it is one continuous string # on @parameterlist; # this fixes a problem where check_sections() cannot find # a parameter like "addr[6 + 2]" because it actually appears diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 83c9c04102f2..8a7b15598ea9 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -92,7 +92,7 @@ case "${ARCH}" in echo "" >&2 echo '** ** ** WARNING ** ** **' >&2 echo "" >&2 - echo "Your architecture did not define any architecture-dependant files" >&2 + echo "Your architecture did not define any architecture-dependent files" >&2 echo "to be placed into the tarball. Please add those to ${0} ..." >&2 echo "" >&2 sleep 5 diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py index 8c81d76959ee..34186cac1d2f 100644 --- a/scripts/rt-tester/rt-tester.py +++ b/scripts/rt-tester/rt-tester.py @@ -180,7 +180,7 @@ while 1: for s in stat: s = s.strip() if s.startswith(testop[0]): - # Seperate status value + # Separate status value val = s[2:].strip() query = analyse(val, testop, dat) break diff --git a/security/apparmor/match.c b/security/apparmor/match.c index 5cb4dc1f6992..06d764ccbbe5 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -195,7 +195,7 @@ void aa_dfa_free_kref(struct kref *kref) * * Unpack a dfa that has been serialized. To find information on the dfa * format look in Documentation/apparmor.txt - * Assumes the dfa @blob stream has been aligned on a 8 byte boundry + * Assumes the dfa @blob stream has been aligned on a 8 byte boundary * * Returns: an unpacked dfa ready for matching or ERR_PTR on failure */ diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index eb3700e9fd37..e33aaf7e5744 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -359,7 +359,7 @@ fail: * @e: serialized data extent information (NOT NULL) * @profile: profile to add the accept table to (NOT NULL) * - * Returns: 1 if table succesfully unpacked + * Returns: 1 if table successfully unpacked */ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) { diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 1c2fc46544bf..c3bf3ed07b06 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -151,7 +151,7 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) * * Description: * Called when the NetLabel state of a sk_security_struct needs to be reset. - * The caller is responsibile for all the NetLabel sk_security_struct locking. + * The caller is responsible for all the NetLabel sk_security_struct locking. * */ void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ea7c01f4a2bf..6ef4af47dac4 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2806,7 +2806,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) case AUDIT_SUBJ_CLR: case AUDIT_OBJ_LEV_LOW: case AUDIT_OBJ_LEV_HIGH: - /* we do not allow a range, indicated by the presense of '-' */ + /* we do not allow a range, indicated by the presence of '-' */ if (strchr(rulestr, '-')) return -EINVAL; break; @@ -3075,7 +3075,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, * Description: * Convert the given NetLabel security attributes in @secattr into a * SELinux SID. If the @secattr field does not contain a full SELinux - * SID/context then use SECINITSID_NETMSG as the foundation. If possibile the + * SID/context then use SECINITSID_NETMSG as the foundation. If possible the * 'cache' field of @secattr is set and the CACHE flag is set; this is to * allow the @secattr to be used by NetLabel to cache the secattr to SID * conversion for future lookups. Returns zero on success, negative values on diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 86453db4333d..9637e107f7ea 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -431,7 +431,7 @@ char *smk_import(const char *string, int len) * smack_from_secid - find the Smack label associated with a secid * @secid: an integer that might be associated with a Smack label * - * Returns a pointer to the appropraite Smack label if there is one, + * Returns a pointer to the appropriate Smack label if there is one, * otherwise a pointer to the invalid Smack label. */ char *smack_from_secid(const u32 secid) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 23c7a6d0c80c..c6f8fcadae07 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1794,7 +1794,7 @@ static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap) * Casey says that CIPSO is good enough for now. * It can be used to effect. * It can also be abused to effect when necessary. - * Appologies to the TSIG group in general and GW in particular. + * Apologies to the TSIG group in general and GW in particular. */ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) { @@ -2530,7 +2530,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) switch (sbp->s_magic) { case SMACK_MAGIC: /* - * Casey says that it's a little embarassing + * Casey says that it's a little embarrassing * that the smack file system doesn't do * extended attributes. */ @@ -3084,7 +3084,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, /* * We need to decide if we want to label the incoming connection here * if we do we only need to label the request_sock and the stack will - * propogate the wire-label to the sock when it is created. + * propagate the wire-label to the sock when it is created. */ hdr = ip_hdr(skb); addr.sin_addr.s_addr = hdr->saddr; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 90d1bbaaa6f3..f93460156dce 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -208,7 +208,7 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf, if (*ppos != 0) return -EINVAL; /* - * Minor hack for backward compatability + * Minor hack for backward compatibility */ if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN) return -EINVAL; @@ -223,7 +223,7 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf, } /* - * More on the minor hack for backward compatability + * More on the minor hack for backward compatibility */ if (count == (SMK_OLOADLEN)) data[SMK_OLOADLEN] = '-'; @@ -927,7 +927,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, } } else { /* we delete the unlabeled entry, only if the previous label - * wasnt the special CIPSO option */ + * wasn't the special CIPSO option */ if (skp->smk_label != smack_cipso_option) rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, &skp->smk_host.sin_addr, &skp->smk_mask, diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c index bbada7ca1b91..3312e5624f24 100644 --- a/security/tomoyo/load_policy.c +++ b/security/tomoyo/load_policy.c @@ -23,7 +23,7 @@ static bool tomoyo_policy_loader_exists(void) * If the initrd includes /sbin/init but real-root-dev has not * mounted on / yet, activating MAC will block the system since * policies are not loaded yet. - * Thus, let do_execve() call this function everytime. + * Thus, let do_execve() call this function every time. */ struct path path; diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index fd2188c3df2b..58804c7acfcf 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -170,7 +170,7 @@ static void tas_set_volume(struct tas *tas) /* analysing the volume and mixer tables shows * that they are similar enough when we shift * the mixer table down by 4 bits. The error - * is miniscule, in just one item the error + * is minuscule, in just one item the error * is 1, at a value of 0x07f17b (mixer table * value is 0x07f17a) */ tmp = tas_gaintable[left]; diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 917e4055ee30..150cb7edffee 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -253,7 +253,7 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream, * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type * @substream: the pcm substream instance * @type: DMA type (SNDRV_DMA_TYPE_*) - * @data: DMA type dependant data + * @data: DMA type dependent data * @size: the requested pre-allocation size in bytes * @max: the max. allowed pre-allocation size * @@ -278,10 +278,10 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); /** - * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams) + * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continuous memory type (all substreams) * @pcm: the pcm instance * @type: DMA type (SNDRV_DMA_TYPE_*) - * @data: DMA type dependant data + * @data: DMA type dependent data * @size: the requested pre-allocation size in bytes * @max: the max. allowed pre-allocation size * diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index fe5c8036beba..1a07750f3836 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -460,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, PM_QOS_CPU_DMA_LATENCY, usecs); return 0; _error: - /* hardware might be unuseable from this time, + /* hardware might be unusable from this time, so we force application to retry to set the correct hardware parameter settings */ runtime->status->state = SNDRV_PCM_STATE_OPEN; diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index f3bdc54b429a..1d7d90ca455e 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -50,7 +50,7 @@ option snd-seq-dummy ports=4 - The modle option "duplex=1" enables duplex operation to the port. + The model option "duplex=1" enables duplex operation to the port. In duplex mode, a pair of ports are created instead of single port, and events are tunneled between pair-ports. For example, input to port A is sent to output port of another port B and vice versa. diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index a89948ae9e8d..a39d3d8c2f9c 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -233,7 +233,7 @@ static void slave_free(struct snd_kcontrol *kcontrol) * Add a slave control to the group with the given master control * * All slaves must be the same type (returning the same information - * via info callback). The fucntion doesn't check it, so it's your + * via info callback). The function doesn't check it, so it's your * responsibility. * * Also, some additional limitations: diff --git a/sound/drivers/pcm-indirect2.c b/sound/drivers/pcm-indirect2.c index 3c93c23e4883..e73fafd761b3 100644 --- a/sound/drivers/pcm-indirect2.c +++ b/sound/drivers/pcm-indirect2.c @@ -264,7 +264,7 @@ snd_pcm_indirect2_playback_transfer(struct snd_pcm_substream *substream, if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) diff += runtime->boundary; /* number of bytes "added" by ALSA increases the number of - * bytes which are ready to "be transfered to HW"/"played" + * bytes which are ready to "be transferred to HW"/"played" * Then, set rec->appl_ptr to not count bytes twice next time. */ rec->sw_ready += (int)frames_to_bytes(runtime, diff); @@ -330,7 +330,7 @@ snd_pcm_indirect2_playback_transfer(struct snd_pcm_substream *substream, /* copy bytes from intermediate buffer position sw_data to the * HW and return number of bytes actually written * Furthermore, set hw_ready to 0, if the fifo isn't empty - * now => more could be transfered to fifo + * now => more could be transferred to fifo */ bytes = copy(substream, rec, bytes); rec->bytes2hw += bytes; diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 35a2f71a6af5..5e897b236cec 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -1189,7 +1189,7 @@ void vx_pcm_update_intr(struct vx_core *chip, unsigned int events) /* - * vx_init_audio_io - check the availabe audio i/o and allocate pipe arrays + * vx_init_audio_io - check the available audio i/o and allocate pipe arrays */ static int vx_init_audio_io(struct vx_core *chip) { diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 0c40951b6523..5d61f5a29130 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -370,7 +370,7 @@ init_arrays(struct snd_emu8000 *emu) /* * Size the onboard memory. - * This is written so as not to need arbitary delays after the write. It + * This is written so as not to need arbitrary delays after the write. It * seems that the only way to do this is to use the one channel and keep * reallocating between read and write. */ diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index f14a7c0b6998..65329f3abc30 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c @@ -537,7 +537,7 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) } /* Turn on Virtual MIDI, but first *always* turn it off, - since otherwise consectutive reloads of the driver will + since otherwise consecutive reloads of the driver will never cause the hardware to generate the initial "internal" or "external" source bytes in the MIDI data stream. This is pretty important, since the internal hardware generally will diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 9191b32d9130..2a42cc377957 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -424,7 +424,7 @@ void snd_wss_mce_down(struct snd_wss *chip) /* * Wait for (possible -- during init auto-calibration may not be set) - * calibration process to start. Needs upto 5 sample periods on AD1848 + * calibration process to start. Needs up to 5 sample periods on AD1848 * which at the slowest possible rate of 5.5125 kHz means 907 us. */ msleep(1); diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c index 854c303264dc..0cd23d94888f 100644 --- a/sound/oss/ac97_codec.c +++ b/sound/oss/ac97_codec.c @@ -28,7 +28,7 @@ * * History * May 02, 2003 Liam Girdwood - * Removed non existant WM9700 + * Removed non existent WM9700 * Added support for WM9705, WM9708, WM9709, WM9710, WM9711 * WM9712 and WM9717 * Mar 28, 2002 Randolph Bentson @@ -441,7 +441,7 @@ static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, uns } /* read or write the recmask, the ac97 can really have left and right recording - inputs independantly set, but OSS doesn't seem to want us to express that to + inputs independently set, but OSS doesn't seem to want us to express that to the user. the caller guarantees that we have a supported bit set, and they must be holding the card's spinlock */ static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask) @@ -754,7 +754,7 @@ int ac97_probe_codec(struct ac97_codec *codec) if((codec->codec_ops == &null_ops) && (f & 4)) codec->codec_ops = &default_digital_ops; - /* A device which thinks its a modem but isnt */ + /* A device which thinks its a modem but isn't */ if(codec->flags & AC97_DELUDED_MODEM) codec->modem = 0; diff --git a/sound/oss/audio.c b/sound/oss/audio.c index 7df48a25c4ee..4b958b1c497c 100644 --- a/sound/oss/audio.c +++ b/sound/oss/audio.c @@ -514,7 +514,7 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg) count += dmap->bytes_in_use; /* Pointer wrap not handled yet */ count += dmap->byte_counter; - /* Substract current count from the number of bytes written by app */ + /* Subtract current count from the number of bytes written by app */ count = dmap->user_counter - count; if (count < 0) count = 0; @@ -931,7 +931,7 @@ static int dma_ioctl(int dev, unsigned int cmd, void __user *arg) if (count < dmap_out->fragment_size && dmap_out->qhead != 0) count += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ count += dmap_out->byte_counter; - /* Substract current count from the number of bytes written by app */ + /* Subtract current count from the number of bytes written by app */ count = dmap_out->user_counter - count; if (count < 0) count = 0; diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index 87e2c72651f5..c918313c2206 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -1021,7 +1021,7 @@ static int sq_ioctl(struct file *file, u_int cmd, u_long arg) case SNDCTL_DSP_SYNC: /* This call, effectively, has the same behaviour as SNDCTL_DSP_RESET except that it waits for output to finish before resetting - everything - read, however, is killed imediately. + everything - read, however, is killed immediately. */ result = 0 ; if (file->f_mode & FMODE_WRITE) { diff --git a/sound/oss/midibuf.c b/sound/oss/midibuf.c index ceedb1eff203..8cdb2cfe65c8 100644 --- a/sound/oss/midibuf.c +++ b/sound/oss/midibuf.c @@ -295,7 +295,7 @@ int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count) for (i = 0; i < n; i++) { - /* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */ + /* BROKE BROKE BROKE - CAN'T DO THIS WITH CLI !! */ /* yes, think the same, so I removed the cli() brackets QUEUE_BYTE is protected against interrupts */ if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) { diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c index 84ef4d06c1c2..fb5d7250de38 100644 --- a/sound/oss/sb_card.c +++ b/sound/oss/sb_card.c @@ -1,7 +1,7 @@ /* * sound/oss/sb_card.c * - * Detection routine for the ISA Sound Blaster and compatable sound + * Detection routine for the ISA Sound Blaster and compatible sound * cards. * * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) diff --git a/sound/oss/sb_ess.c b/sound/oss/sb_ess.c index 9890cf2066ff..5c773dff5ac5 100644 --- a/sound/oss/sb_ess.c +++ b/sound/oss/sb_ess.c @@ -168,7 +168,7 @@ * corresponding playback levels, unless recmask says they aren't recorded. In * the latter case the recording volumes are 0. * Now recording levels of inputs can be controlled, by changing the playback - * levels. Futhermore several devices can be recorded together (which is not + * levels. Furthermore several devices can be recorded together (which is not * possible with the ES1688). * Besides the separate recording level control for each input, the common * recording level can also be controlled by RECLEV as described above. diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 44357d877a27..09d46484bc1a 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -875,7 +875,7 @@ static void start_adc(struct cs4297a_state *s) if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) { // // now only use 16 bit capture, due to truncation issue - // in the chip, noticable distortion occurs. + // in the chip, noticeable distortion occurs. // allocate buffer and then convert from 16 bit to // 8 bit for the user buffer. // diff --git a/sound/oss/vidc.c b/sound/oss/vidc.c index f0e0caa53200..12ba28e7b933 100644 --- a/sound/oss/vidc.c +++ b/sound/oss/vidc.c @@ -227,7 +227,7 @@ static int vidc_audio_set_speed(int dev, int rate) } else { /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/ hwctrl=0x00000003; - /* Allow rougly 0.4% tolerance */ + /* Allow roughly 0.4% tolerance */ if (diff_int > (rate/256)) rate=rate_int; } diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 4382d0fa6b9a..d8f6fd65ebbb 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -29,7 +29,7 @@ * PM support * MIDI support * Game Port support - * SG DMA support (this will need *alot* of work) + * SG DMA support (this will need *a lot* of work) */ #include diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index f53a31e939c1..f8ccc9677c6f 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -963,7 +963,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) /*? also check ASI5000 samplerate source If external, only support external rate. - If internal and other stream playing, cant switch + If internal and other stream playing, can't switch */ init_timer(&dpcm->timer); diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h index 6fc025c448de..255429c32c1c 100644 --- a/sound/pci/asihpi/hpi.h +++ b/sound/pci/asihpi/hpi.h @@ -725,7 +725,7 @@ enum HPI_AESEBU_ERRORS { #define HPI_PAD_TITLE_LEN 64 /** The text string containing the comment. */ #define HPI_PAD_COMMENT_LEN 256 -/** The PTY when the tuner has not recieved any PTY. */ +/** The PTY when the tuner has not received any PTY. */ #define HPI_PAD_PROGRAM_TYPE_INVALID 0xffff /** \} */ diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 3e3c2ef6efd8..8c8aac4c567e 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c @@ -423,7 +423,7 @@ static void subsys_create_adapter(struct hpi_message *phm, ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); if (!ao.priv) { - HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); + HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); phr->error = HPI_ERROR_MEMORY_ALLOC; return; } diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 620525bdac59..22e9f08dea6d 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c @@ -466,7 +466,7 @@ static void subsys_create_adapter(struct hpi_message *phm, ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); if (!ao.priv) { - HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); + HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); phr->error = HPI_ERROR_MEMORY_ALLOC; return; } diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index af678be0aa15..3b9fd115da36 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h @@ -607,7 +607,7 @@ struct hpi_data_compat32 { #endif struct hpi_buffer { - /** placehoder for backward compatability (see dwBufferSize) */ + /** placehoder for backward compatibility (see dwBufferSize) */ struct hpi_msg_format reserved; u32 command; /**< HPI_BUFFER_CMD_xxx*/ u32 pci_address; /**< PCI physical address of buffer for DSP DMA */ diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index bcbdf30a6aa0..360028b9abf5 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c @@ -722,7 +722,7 @@ static u16 HPIMSGX__init(struct hpi_message *phm, return phr->error; } if (hr.error == 0) { - /* the adapter was created succesfully + /* the adapter was created successfully save the mapping for future use */ hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; /* prepare adapter (pre-open streams etc.) */ diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index ecb8f4daf408..02f6e08f7592 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h @@ -104,7 +104,7 @@ #define MIX_PLAYB(x) (vortex->mixplayb[x]) #define MIX_SPDIF(x) (vortex->mixspdif[x]) -#define NR_WTPB 0x20 /* WT channels per eahc bank. */ +#define NR_WTPB 0x20 /* WT channels per each bank. */ /* Structs */ typedef struct { diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c index f4aa8ff6f5f9..9ae8b3b17651 100644 --- a/sound/pci/au88x0/au88x0_a3d.c +++ b/sound/pci/au88x0/au88x0_a3d.c @@ -53,7 +53,7 @@ a3dsrc_GetTimeConsts(a3dsrc_t * a, short *HrtfTrack, short *ItdTrack, } #endif -/* Atmospheric absorbtion. */ +/* Atmospheric absorption. */ static void a3dsrc_SetAtmosTarget(a3dsrc_t * a, short aa, short b, short c, short d, @@ -835,7 +835,7 @@ snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol, params[i] = ucontrol->value.integer.value[i]; /* Translate generic filter params to a3d filter params. */ vortex_a3d_translate_filter(a->filter, params); - /* Atmospheric absorbtion and filtering. */ + /* Atmospheric absorption and filtering. */ a3dsrc_SetAtmosTarget(a, a->filter[0], a->filter[1], a->filter[2], a->filter[3], a->filter[4]); diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index 5439d662d104..33f0ba5559a7 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c @@ -515,7 +515,7 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) return -ENODEV; /* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the - * same dma engine. WT uses it own separate dma engine whcih cant capture. */ + * same dma engine. WT uses it own separate dma engine which can't capture. */ if (idx == VORTEX_PCM_ADB) nr_capt = nr; else diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 5715c4d05573..9b7a6346037a 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -140,7 +140,7 @@ * Possible remedies: * - use speaker (amplifier) output instead of headphone output * (in case crackling is due to overloaded output clipping) - * - plug card into a different PCI slot, preferrably one that isn't shared + * - plug card into a different PCI slot, preferably one that isn't shared * too much (this helps a lot, but not completely!) * - get rid of PCI VGA card, use AGP instead * - upgrade or downgrade BIOS diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index fc53b9bca26d..e8e8ccc96403 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -51,7 +51,7 @@ * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) * * - * This code was initally based on code from ALSA's emu10k1x.c which is: + * This code was initially based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * * This program is free software; you can redistribute it and/or modify @@ -175,7 +175,7 @@ /* CA0106 pointer-offset register set, accessed through the PTR and DATA registers */ /********************************************************************************************************/ -/* Initally all registers from 0x00 to 0x3f have zero contents. */ +/* Initially all registers from 0x00 to 0x3f have zero contents. */ #define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ /* One list entry: 4 bytes for DMA address, * 4 bytes for period_size << 16. @@ -223,7 +223,7 @@ * The jack has 4 poles. I will call 1 - Tip, 2 - Next to 1, 3 - Next to 2, 4 - Next to 3 * For Analogue: 1 -> Center Speaker, 2 -> Sub Woofer, 3 -> Ground, 4 -> Ground * For Digital: 1 -> Front SPDIF, 2 -> Rear SPDIF, 3 -> Center/Subwoofer SPDIF, 4 -> Ground. - * Standard 4 pole Video A/V cable with RCA outputs: 1 -> White, 2 -> Yellow, 3 -> Sheild on all three, 4 -> Red. + * Standard 4 pole Video A/V cable with RCA outputs: 1 -> White, 2 -> Yellow, 3 -> Shield on all three, 4 -> Red. * So, from this you can see that you cannot use a Standard 4 pole Video A/V cable with the SB Audigy LS card. */ /* The Front SPDIF PCM gets mixed with samples from the AC97 codec, so can only work for Stereo PCM and not AC3/DTS diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 01b49388fafd..437759239694 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -117,7 +117,7 @@ * DAC: Unknown * Trying to handle it like the SB0410. * - * This code was initally based on code from ALSA's emu10k1x.c which is: + * This code was initially based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * * This program is free software; you can redistribute it and/or modify diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 630aa4998189..84f3f92436b5 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -42,7 +42,7 @@ * 0.0.18 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) * - * This code was initally based on code from ALSA's emu10k1x.c which is: + * This code was initially based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * * This program is free software; you can redistribute it and/or modify diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index ba96428c9f4c..c694464b1168 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c @@ -42,7 +42,7 @@ * 0.0.18 * Implement support for Line-in capture on SB Live 24bit. * - * This code was initally based on code from ALSA's emu10k1x.c which is: + * This code was initially based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * * This program is free software; you can redistribute it and/or modify diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index b5bb036ef73c..f4e573555da3 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -73,7 +73,7 @@ MODULE_PARM_DESC(mpu_port, "MPU-401 port."); module_param_array(fm_port, long, NULL, 0444); MODULE_PARM_DESC(fm_port, "FM port."); module_param_array(soft_ac3, bool, NULL, 0444); -MODULE_PARM_DESC(soft_ac3, "Sofware-conversion of raw SPDIF packets (model 033 only)."); +MODULE_PARM_DESC(soft_ac3, "Software-conversion of raw SPDIF packets (model 033 only)."); #ifdef SUPPORT_JOYSTICK module_param_array(joystick_port, int, NULL, 0444); MODULE_PARM_DESC(joystick_port, "Joystick port address."); @@ -656,8 +656,8 @@ out: } /* - * Program pll register bits, I assume that the 8 registers 0xf8 upto 0xff - * are mapped onto the 8 ADC/DAC sampling frequency which can be choosen + * Program pll register bits, I assume that the 8 registers 0xf8 up to 0xff + * are mapped onto the 8 ADC/DAC sampling frequency which can be chosen * at the register CM_REG_FUNCTRL1 (0x04). * Problem: other ways are also possible (any information about that?) */ @@ -666,7 +666,7 @@ static void snd_cmipci_set_pll(struct cmipci *cm, unsigned int rate, unsigned in unsigned int reg = CM_REG_PLL + slot; /* * Guess that this programs at reg. 0x04 the pos 15:13/12:10 - * for DSFC/ASFC (000 upto 111). + * for DSFC/ASFC (000 up to 111). */ /* FIXME: Init (Do we've to set an other register first before programming?) */ diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index b9321544c31c..13f33c0719d3 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1627,7 +1627,7 @@ static struct ct_atc atc_preset __devinitdata = { * Creates and initializes a hardware manager. * * Creates kmallocated ct_atc structure. Initializes hardware. - * Returns 0 if suceeds, or negative error code if fails. + * Returns 0 if succeeds, or negative error code if fails. */ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 0cf400f879f9..a5c957db5cea 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1285,7 +1285,7 @@ static int hw_trn_init(struct hw *hw, const struct trn_conf *info) hw_write_20kx(hw, PTPALX, ptp_phys_low); hw_write_20kx(hw, PTPAHX, ptp_phys_high); hw_write_20kx(hw, TRNCTL, trnctl); - hw_write_20kx(hw, TRNIS, 0x200c01); /* realy needed? */ + hw_write_20kx(hw, TRNIS, 0x200c01); /* really needed? */ return 0; } diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 957a311514c8..c250614dadd0 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -248,7 +248,7 @@ static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr) /* * map the given memory block on PTB. * if the block is already mapped, update the link order. - * if no empty pages are found, tries to release unsed memory blocks + * if no empty pages are found, tries to release unused memory blocks * and retry the mapping. */ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 61b8ab39800f..a81dc44228ea 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -69,7 +69,7 @@ * ADC: Philips 1361T (Stereo 24bit) * DAC: CS4382-K (8-channel, 24bit, 192Khz) * - * This code was initally based on code from ALSA's emu10k1x.c which is: + * This code was initially based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * * This program is free software; you can redistribute it and/or modify diff --git a/sound/pci/emu10k1/p16v.h b/sound/pci/emu10k1/p16v.h index 00f4817533b1..4e0ee1a9747a 100644 --- a/sound/pci/emu10k1/p16v.h +++ b/sound/pci/emu10k1/p16v.h @@ -59,7 +59,7 @@ * ADC: Philips 1361T (Stereo 24bit) * DAC: CS4382-K (8-channel, 24bit, 192Khz) * - * This code was initally based on code from ALSA's emu10k1x.c which is: + * This code was initially based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes * * This program is free software; you can redistribute it and/or modify @@ -86,7 +86,7 @@ * The sample rate is also controlled by the same registers that control the rate of the EMU10K2 sample rate converters. */ -/* Initally all registers from 0x00 to 0x3f have zero contents. */ +/* Initially all registers from 0x00 to 0x3f have zero contents. */ #define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ /* One list entry: 4 bytes for DMA address, * 4 bytes for period_size << 16. diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 2c79e96d0324..430f41db6044 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3661,7 +3661,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) * with the proper parameters for set up. * ops.cleanup should be called in hw_free for clean up of streams. * - * This function returns 0 if successfull, or a negative error code. + * This function returns 0 if successful, or a negative error code. */ int __devinit snd_hda_build_pcms(struct hda_bus *bus) { @@ -4851,7 +4851,7 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend); * * Returns 0 if successful. * - * This fucntion is defined only when POWER_SAVE isn't set. + * This function is defined only when POWER_SAVE isn't set. * In the power-save mode, the codec is resumed dynamically. */ int snd_hda_resume(struct hda_bus *bus) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0ef0035fe99f..1e5a786c8c27 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -549,7 +549,7 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, /* * Control the mode of pin widget settings via the mixer. "pc" is used - * instead of "%" to avoid consequences of accidently treating the % as + * instead of "%" to avoid consequences of accidentally treating the % as * being part of a format specifier. Maximum allowed length of a value is * 63 characters plus NULL terminator. * @@ -9836,7 +9836,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), - SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), + SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavilion", ALC883_6ST_DIG), SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 05fcd60cc46f..1395991c39f2 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2475,7 +2475,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0; - /* check to be sure that the ports are upto date with + /* check to be sure that the ports are up to date with * switch changes */ stac_issue_unsol_event(codec, nid); diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 2f6252266a02..3e4f8c12ffce 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -148,7 +148,7 @@ static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg, udelay(100); /* * send device address, command and value, - * skipping ack cycles inbetween + * skipping ack cycles in between */ for (j = 0; j < 3; j++) { switch (j) { @@ -2143,7 +2143,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) ice->num_total_adcs = 2; } - /* to remeber the register values of CS8415 */ + /* to remember the register values of CS8415 */ ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (!ice->akm) return -ENOMEM; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 4fc6d8bc637e..f4594d76b6ea 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2755,7 +2755,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, return err; } if (c->mpu401_1_name) - /* Prefered name available in card_info */ + /* Preferred name available in card_info */ snprintf(ice->rmidi[0]->name, sizeof(ice->rmidi[0]->name), "%s %d", c->mpu401_1_name, card->number); @@ -2772,7 +2772,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, return err; } if (c->mpu401_2_name) - /* Prefered name available in card_info */ + /* Preferred name available in card_info */ snprintf(ice->rmidi[1]->name, sizeof(ice->rmidi[1]->name), "%s %d", c->mpu401_2_name, diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index cdb873f5da50..92c1160d7ab5 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c @@ -768,7 +768,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice) ice->num_total_dacs = 2; ice->num_total_adcs = 2; - /* to remeber the register values */ + /* to remember the register values */ ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ice->akm) return -ENOMEM; diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 6a9fee3ee78f..764cc93dbca4 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -1046,7 +1046,7 @@ static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice) * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten */ ice->gpio.saved[0] = 0; - /* to remeber the register values */ + /* to remember the register values */ ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ice->akm) @@ -1128,7 +1128,7 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten */ ice->gpio.saved[0] = 0; - /* to remeber the register values */ + /* to remember the register values */ ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ice->akm) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 629a5494347a..6c896dbfd796 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -534,7 +534,7 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code udelay(10); } while (time--); - /* access to some forbidden (non existant) ac97 registers will not + /* access to some forbidden (non existent) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 2ae8d29500a8..27709f0cd2a6 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -331,7 +331,7 @@ static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int co udelay(10); } while (time--); - /* access to some forbidden (non existant) ac97 registers will not + /* access to some forbidden (non existent) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index d3350f383966..3df0f530f67c 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -265,7 +265,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int if (! timeout) { /* error - no ack */ mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: no reponse on msg %x\n", msg_frame); + snd_printk(KERN_ERR "error: no response on msg %x\n", msg_frame); return -EIO; } @@ -278,7 +278,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int err = get_msg(mgr, &resp, msg_frame); if( request->message_id != resp.message_id ) - snd_printk(KERN_ERR "REPONSE ERROR!\n"); + snd_printk(KERN_ERR "RESPONSE ERROR!\n"); mutex_unlock(&mgr->msg_mutex); return err; diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 833e7180ad2d..304411c1fe4b 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -1042,11 +1042,11 @@ void pcxhr_msg_tasklet(unsigned long arg) int i, j; if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) - snd_printdd("TASKLET : PCXHR_IRQ_FREQ_CHANGE event occured\n"); + snd_printdd("TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) - snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occured\n"); + snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) - snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occured\n"); + snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { /* clear events FREQ_CHANGE and TIME_CODE */ pcxhr_init_rmh(prmh, CMD_TEST_IT); @@ -1055,7 +1055,7 @@ void pcxhr_msg_tasklet(unsigned long arg) err, prmh->stat[0]); } if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { - snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occured\n"); + snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); pcxhr_init_rmh(prmh, CMD_ASYNC); prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ @@ -1233,7 +1233,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) reg = PCXHR_INPL(mgr, PCXHR_PLX_L2PCIDB); PCXHR_OUTPL(mgr, PCXHR_PLX_L2PCIDB, reg); - /* timer irq occured */ + /* timer irq occurred */ if (reg & PCXHR_IRQ_TIMER) { int timer_toggle = reg & PCXHR_IRQ_TIMER; /* is a 24 bit counter */ @@ -1288,7 +1288,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) if (reg & PCXHR_IRQ_MASK) { if (reg & PCXHR_IRQ_ASYNC) { /* as we didn't request any async notifications, - * some kind of xrun error will probably occured + * some kind of xrun error will probably occurred */ /* better resynchronize all streams next interrupt : */ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index d5f5b440fc40..9ff247fc8871 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -150,7 +150,7 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard."); #define RME96_RCR_BITPOS_F1 28 #define RME96_RCR_BITPOS_F2 29 -/* Additonal register bits */ +/* Additional register bits */ #define RME96_AR_WSEL (1 << 0) #define RME96_AR_ANALOG (1 << 1) #define RME96_AR_FREQPAD_0 (1 << 2) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index a323eafb9e03..949691a876d3 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -391,7 +391,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); /* Status2 Register bits */ /* MADI ONLY */ -#define HDSPM_version0 (1<<0) /* not realy defined but I guess */ +#define HDSPM_version0 (1<<0) /* not really defined but I guess */ #define HDSPM_version1 (1<<1) /* in former cards it was ??? */ #define HDSPM_version2 (1<<2) @@ -936,7 +936,7 @@ struct hdspm { struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */ struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; - /* full mixer accessable over mixer ioctl or hwdep-device */ + /* full mixer accessible over mixer ioctl or hwdep-device */ struct hdspm_mixer *mixer; struct hdspm_tco *tco; /* NULL if no TCO detected */ diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 1b8f6742b5fa..2b5c7a95ae1f 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -308,7 +308,7 @@ static irqreturn_t sis_interrupt(int irq, void *dev) u32 intr, status; /* We only use the DMA interrupts, and we don't enable any other - * source of interrupts. But, it is possible to see an interupt + * source of interrupts. But, it is possible to see an interrupt * status that didn't actually interrupt us, so eliminate anything * we're not expecting to avoid falsely claiming an IRQ, and an * ensuing endless loop. @@ -773,7 +773,7 @@ static void sis_prepare_timing_voice(struct voice *voice, vperiod = 0; } - /* The interrupt handler implements the timing syncronization, so + /* The interrupt handler implements the timing synchronization, so * setup its state. */ timing->flags |= VOICE_SYNC_TIMING; @@ -1139,7 +1139,7 @@ static int sis_chip_init(struct sis7019 *sis) */ outl(SIS_DMA_CSR_PCI_SETTINGS, io + SIS_DMA_CSR); - /* Reset the syncronization groups for all of the channels + /* Reset the synchronization groups for all of the channels * to be asyncronous. If we start doing SPDIF or 5.1 sound, etc. * we'll need to change how we handle these. Until then, we just * assign sub-mixer 0 to all playback channels, and avoid any diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index edce8a27e3ee..bc823a547550 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -358,7 +358,7 @@ static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id) * filling dummy data, serial automatically start to * consume them and then will generate normal buffer * empty interrupts. - * If both buffer underflow and buffer empty are occured, + * If both buffer underflow and buffer empty are occurred, * it is better to do nomal data transfer than empty one */ snd_ps3_program_dma(card, diff --git a/sound/ppc/snd_ps3_reg.h b/sound/ppc/snd_ps3_reg.h index 03fdee4aaaf2..2e6302079566 100644 --- a/sound/ppc/snd_ps3_reg.h +++ b/sound/ppc/snd_ps3_reg.h @@ -125,7 +125,7 @@ transfers. Any interrupts associated with the canceled transfers will occur as if the transfer had finished. Since this bit is designed to recover from DMA related issues - which are caused by unpredictable situations, it is prefered to wait + which are caused by unpredictable situations, it is preferred to wait for normal DMA transfer end without using this bit. */ #define PS3_AUDIO_CONFIG_CLEAR (1 << 8) /* RWIVF */ @@ -316,13 +316,13 @@ DISABLED=Interrupt generation disabled. /* Audio Port Interrupt Status Register -Indicates Interrupt status, which interrupt has occured, and can clear +Indicates Interrupt status, which interrupt has occurred, and can clear each interrupt in this register. Writing 1b to a field containing 1b clears field and de-asserts interrupt. Writing 0b to a field has no effect. Field vaules are the following: -0 - Interrupt hasn't occured. -1 - Interrupt has occured. +0 - Interrupt hasn't occurred. +1 - Interrupt has occurred. 31 24 23 16 15 8 7 0 @@ -473,7 +473,7 @@ Channel N is out of action by setting 0 to asoen. /* Sampling Rate Specifies the divide ratio of the bit clock (clock output -from bclko) used by the 3-wire Audio Output Clock, whcih +from bclko) used by the 3-wire Audio Output Clock, which is applied to the master clock selected by mcksel. Data output is synchronized with this clock. */ @@ -756,7 +756,7 @@ The STATUS field can be used to monitor the progress of a DMA request. DONE indicates the previous request has completed. EVENT indicates that the DMA engine is waiting for the EVENT to occur. PENDING indicates that the DMA engine has not started processing this -request, but the EVENT has occured. +request, but the EVENT has occurred. DMA indicates that the data transfer is in progress. NOTIFY indicates that the notifier signalling end of transfer is being written. CLEAR indicated that the previous transfer was cleared. @@ -824,7 +824,7 @@ AUDIOFIFO = Audio WriteData FIFO, /* PS3_AUDIO_DMASIZE specifies the number of 128-byte blocks + 1 to transfer. -So a value of 0 means 128-bytes will get transfered. +So a value of 0 means 128-bytes will get transferred. 31 24 23 16 15 8 7 0 diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 5d230cee3fa7..7fbfa051f6e1 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -672,7 +672,7 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) /* re-enable interrupts */ ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr); - /* Re-enable recieve and transmit as appropriate */ + /* Re-enable receive and transmit as appropriate */ cr = 0; cr |= (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0; diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 4f377c9e868d..eecffb548947 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -481,7 +481,7 @@ struct _pll_div { }; /* Note : pll code from original alc5623 driver. Not sure of how good it is */ -/* usefull only for master mode */ +/* useful only for master mode */ static const struct _pll_div codec_master_pll_div[] = { { 2048000, 8192000, 0x0ea0}, diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 72de47e5d040..2c2a681da0d7 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -161,7 +161,7 @@ static const struct snd_kcontrol_new lm4857_controls[] = { lm4857_get_mode, lm4857_set_mode), }; -/* There is a demux inbetween the the input signal and the output signals. +/* There is a demux between the input signal and the output signals. * Currently there is no easy way to model it in ASoC and since it does not make * much of a difference in practice simply connect the input direclty to the * outputs. */ diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 62b1f2261429..67f19c3bebe6 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h @@ -14,14 +14,14 @@ #define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset) #define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0) -/* Page 0: Auxillary data registers */ +/* Page 0: Auxiliary data registers */ #define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05) #define AIC26_REG_BAT2 AIC26_PAGE_ADDR(0, 0x06) #define AIC26_REG_AUX AIC26_PAGE_ADDR(0, 0x07) #define AIC26_REG_TEMP1 AIC26_PAGE_ADDR(0, 0x09) #define AIC26_REG_TEMP2 AIC26_PAGE_ADDR(0, 0x0A) -/* Page 1: Auxillary control registers */ +/* Page 1: Auxiliary control registers */ #define AIC26_REG_AUX_ADC AIC26_PAGE_ADDR(1, 0x00) #define AIC26_REG_STATUS AIC26_PAGE_ADDR(1, 0x01) #define AIC26_REG_REFERENCE AIC26_PAGE_ADDR(1, 0x03) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 3bedab26892f..6c43c13f0430 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -884,7 +884,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, if (bypass_pll) return 0; - /* Use PLL, compute apropriate setup for j, d, r and p, the closest + /* Use PLL, compute appropriate setup for j, d, r and p, the closest * one wins the game. Try with d==0 first, next with d!=0. * Constraints for j are according to the datasheet. * The sysclk is divided by 1000 to prevent integer overflows. diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 00b6d87e7bdb..f01f1417da41 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1020,7 +1020,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) /* * For FIFO bypass mode: * Enable the FIFO bypass (Disable the FIFO use) - * Set the BCLK as continous + * Set the BCLK as continuous */ fifoctrl_a |= DAC33_FBYPAS; aictrl_b |= DAC33_BCLKON; diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 8512800f6326..575238d68e5e 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -281,7 +281,7 @@ static inline void twl4030_check_defaults(struct snd_soc_codec *codec) i, val, twl4030_reg[i]); } } - dev_dbg(codec->dev, "Found %d non maching registers. %s\n", + dev_dbg(codec->dev, "Found %d non-matching registers. %s\n", difference, difference ? "Not OK" : "OK"); } @@ -2018,7 +2018,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, u8 mode; /* If the system master clock is not 26MHz, the voice PCM interface is - * not avilable. + * not available. */ if (twl4030->sysclk != 26000) { dev_err(codec->dev, "The board is configured for %u Hz, while" @@ -2028,7 +2028,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, } /* If the codec mode is not option2, the voice PCM interface is not - * avilable. + * available. */ mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) & TWL4030_OPT_MODE; diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 8f6b5ee6645b..4bbc0a79f01e 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -772,7 +772,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); snd_soc_write(codec, WM8580_PWRDN1, reg); - /* Make VMID high impedence */ + /* Make VMID high impedance */ reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); reg &= ~0x100; snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 3f09deea8d9d..ffa2ffe5ec11 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1312,7 +1312,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, SNDRV_PCM_FMTBIT_S24_LE) /* - * The WM8753 supports upto 4 different and mutually exclusive DAI + * The WM8753 supports up to 4 different and mutually exclusive DAI * configurations. This gives 2 PCM's available for use, hifi and voice. * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI * is connected between the wm8753 and a BT codec or GSM modem. diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 443ae580445c..9b3bba4df5b3 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1895,7 +1895,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, pr_debug("Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ + /* Find an appropriate FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { fll_div->fll_fratio = fll_fratios[i].fll_fratio; diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 5e0214d6293e..3c7198779c31 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -176,7 +176,7 @@ static int wm8995_pll_factors(struct device *dev, return 0; } -/* Lookup table specifiying SRATE (table 25 in datasheet); some of the +/* Lookup table specifying SRATE (table 25 in datasheet); some of the * output frequencies have been rounded to the standard frequencies * they are intended to match where the error is slight. */ static struct { diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 3b71dd65c966..500011eb8b2b 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3137,7 +3137,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, pr_debug("FLL Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ + /* Find an appropriate FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { fll_div->fll_fratio = fll_fratios[i].fll_fratio; diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 28fdfd66661d..3c2ee1bb73cd 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -981,7 +981,7 @@ static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, reg = snd_soc_read(codec, WM8991_CLOCKING_2); snd_soc_write(codec, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC); - /* set up N , fractional mode and pre-divisor if neccessary */ + /* set up N , fractional mode and pre-divisor if necessary */ snd_soc_write(codec, WM8991_PLL1, pll_div.n | WM8991_SDM | (pll_div.div2 ? WM8991_PRESCALE : 0)); snd_soc_write(codec, WM8991_PLL2, (u8)(pll_div.k>>8)); diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 379fa22c5b6c..056aef904347 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -324,7 +324,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, pr_debug("Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ + /* Find an appropriate FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { fll_div->fll_fratio = fll_fratios[i].fll_fratio; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 3dc64c8b6a5c..3290333b2bb9 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -82,18 +82,18 @@ struct wm8994_priv { int mbc_ena[3]; - /* Platform dependant DRC configuration */ + /* Platform dependent DRC configuration */ const char **drc_texts; int drc_cfg[WM8994_NUM_DRC]; struct soc_enum drc_enum; - /* Platform dependant ReTune mobile configuration */ + /* Platform dependent ReTune mobile configuration */ int num_retune_mobile_texts; const char **retune_mobile_texts; int retune_mobile_cfg[WM8994_NUM_EQ]; struct soc_enum retune_mobile_enum; - /* Platform dependant MBC configuration */ + /* Platform dependent MBC configuration */ int mbc_cfg; const char **mbc_texts; struct soc_enum mbc_enum; diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 55cdf2982020..91c6b39de50c 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -305,7 +305,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol, /* * Stop any attempts to change speaker mode while the speaker is enabled. * - * We also have some special anti-pop controls dependant on speaker + * We also have some special anti-pop controls dependent on speaker * mode which must be changed along with the mode. */ static int speaker_mode_put(struct snd_kcontrol *kcontrol, @@ -456,7 +456,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, pr_debug("Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ + /* Find an appropriate FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { fll_div->fll_fratio = fll_fratios[i].fll_fratio; diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index bc92ec620004..ac2ded969253 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -16,7 +16,7 @@ * sane processor vendors have a FIFO per AC97 slot, the i.MX has only * one FIFO which combines all valid receive slots. We cannot even select * which slots we want to receive. The WM9712 with which this driver - * was developped with always sends GPIO status data in slot 12 which + * was developed with always sends GPIO status data in slot 12 which * we receive in our (PCM-) data stream. The only chance we have is to * manually skip this data in the FIQ handler. With sampling rates different * from 48000Hz not every frame has valid receive data, so the ratio diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index 0fd6a630db01..e13c6ce46328 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -132,7 +132,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) priv = snd_soc_dai_get_dma_data(cpu_dai, substream); snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); - /* Ensure that all constraints linked to dma burst are fullfilled */ + /* Ensure that all constraints linked to dma burst are fulfilled */ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, priv->burst * 2, @@ -170,7 +170,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) /* * Enable Error interrupts. We're only ack'ing them but - * it's usefull for diagnostics + * it's useful for diagnostics */ writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK); } diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index ee2c22475a76..b2e9198a983a 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c @@ -440,7 +440,7 @@ static int sst_platform_remove(struct platform_device *pdev) snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai)); snd_soc_unregister_platform(&pdev->dev); - pr_debug("sst_platform_remove sucess\n"); + pr_debug("sst_platform_remove success\n"); return 0; } @@ -463,7 +463,7 @@ module_init(sst_soc_platform_init); static void __exit sst_soc_platform_exit(void) { platform_driver_unregister(&sst_platform_driver); - pr_debug("sst_soc_platform_exit sucess\n"); + pr_debug("sst_soc_platform_exit success\n"); } module_exit(sst_soc_platform_exit); diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 3167be689621..462cbcbea74a 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -248,7 +248,7 @@ static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = { */ /* To actually apply any modem controlled configuration changes to the codec, - * we must connect codec DAI pins to the modem for a moment. Be carefull not + * we must connect codec DAI pins to the modem for a moment. Be careful not * to interfere with our digital mute function that shares the same hardware. */ static struct timer_list cx81801_timer; static bool cx81801_cmd_pending; @@ -402,9 +402,9 @@ static struct tty_ldisc_ops cx81801_ops = { /* - * Even if not very usefull, the sound card can still work without any of the + * Even if not very useful, the sound card can still work without any of the * above functonality activated. You can still control its audio input/output - * constellation and speakerphone gain from userspace by issueing AT commands + * constellation and speakerphone gain from userspace by issuing AT commands * over the modem port. */ diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 78bfdb3f5d7e..452230975632 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -228,7 +228,7 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { SOC_DAPM_PIN_SWITCH("Handset Mic"), }; -/* GTA02 specific routes and controlls */ +/* GTA02 specific routes and controls */ #ifdef CONFIG_MACH_NEO1973_GTA02 @@ -372,7 +372,7 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) return 0; } -/* GTA01 specific controlls */ +/* GTA01 specific controls */ #ifdef CONFIG_MACH_NEO1973_GTA01 diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 9081a54a9c6c..86c1a3103760 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -76,7 +76,7 @@ struct ihex_record { u16 address; u8 len; u8 data[256]; - char error; /* true if an error occured parsing this record */ + char error; /* true if an error occurred parsing this record */ u8 max_len; /* maximum record length in whole ihex */ @@ -107,7 +107,7 @@ static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc) /* * returns true if record is available, false otherwise. - * iff an error occured, false will be returned and record->error will be true. + * iff an error occurred, false will be returned and record->error will be true. */ static bool usb6fire_fw_ihex_next_record(struct ihex_record *record) { diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 5e4775716607..6ec33b62e6cf 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1182,7 +1182,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, /* * parse a feature unit * - * most of controlls are defined here. + * most of controls are defined here. */ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) { diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 355759bad581..ec07e62e53f3 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -266,7 +266,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, * audio-interface quirks * * returns zero if no standard audio/MIDI parsing is needed. - * returns a postive value if standard audio/midi interfaces are parsed + * returns a positive value if standard audio/midi interfaces are parsed * after this. * returns a negative value at error. */ diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 287ef73b1237..a51340f6f2db 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -20,7 +20,7 @@ at standard samplerates, what led to this part of the usx2y module: It provides the alsa kernel half of the usx2y-alsa-jack driver pair. - The pair uses a hardware dependant alsa-device for mmaped pcm transport. + The pair uses a hardware dependent alsa-device for mmaped pcm transport. Advantage achieved: The usb_hc moves pcm data from/into memory via DMA. That memory is mmaped by jack's usx2y driver. @@ -38,7 +38,7 @@ 2periods works but is useless cause of crackling). This is a first "proof of concept" implementation. - Later, functionalities should migrate to more apropriate places: + Later, functionalities should migrate to more appropriate places: Userland: - The jackd could mmap its float-pcm buffers directly from alsa-lib. - alsa-lib could provide power of 2 period sized shaping combined with int/float diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 8fc0bd3a3a4a..b9a985dadd08 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -85,7 +85,7 @@ out: /* * Helper function for splitting a string into an argv-like array. - * originaly copied from lib/argv_split.c + * originally copied from lib/argv_split.c */ static const char *skip_sep(const char *cp) { diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c index d9678a34dd70..2618ef2ba31f 100644 --- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c +++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c @@ -46,7 +46,7 @@ int cpu = -1; * * performance * Performance is paramount. - * Unwilling to sacrafice any performance + * Unwilling to sacrifice any performance * for the sake of energy saving. (hardware default) * * normal diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index 3656849f78a0..36d8092dbb3f 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -578,7 +578,7 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) mutex_lock(&kvm->slots_lock); - /* Verify that there isnt a match already */ + /* Verify that there isn't a match already */ if (ioeventfd_check_collision(kvm, p)) { ret = -EEXIST; goto unlock_fail; -- cgit v1.2.3 From b522f02184b413955f3bc952e3776ce41edc6355 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Thu, 14 Apr 2011 20:55:19 +0400 Subject: agp: fix OOM and buffer overflow page_count is copied from userspace. agp_allocate_memory() tries to check whether this number is too big, but doesn't take into account the wrap case. Also agp_create_user_memory() doesn't check whether alloc_size is calculated from num_agp_pages variable without overflow. This may lead to allocation of too small buffer with following buffer overflow. Another problem in agp code is not addressed in the patch - kernel memory exhaustion (AGPIOC_RESERVE and AGPIOC_ALLOCATE ioctls). It is not checked whether requested pid is a pid of the caller (no check in agpioc_reserve_wrap()). Each allocation is limited to 16KB, though, there is no per-process limit. This might lead to OOM situation, which is not even solved in case of the caller death by OOM killer - the memory is allocated for another (faked) process. Signed-off-by: Vasiliy Kulikov Signed-off-by: Dave Airlie --- drivers/char/agp/generic.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 012cba0d6d96..850a643ad694 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -115,6 +115,9 @@ static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages) struct agp_memory *new; unsigned long alloc_size = num_agp_pages*sizeof(struct page *); + if (INT_MAX/sizeof(struct page *) < num_agp_pages) + return NULL; + new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL); if (new == NULL) return NULL; @@ -234,11 +237,14 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, int scratch_pages; struct agp_memory *new; size_t i; + int cur_memory; if (!bridge) return NULL; - if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp) + cur_memory = atomic_read(&bridge->current_memory_agp); + if ((cur_memory + page_count > bridge->max_memory_agp) || + (cur_memory + page_count < page_count)) return NULL; if (type >= AGP_USER_TYPES) { -- cgit v1.2.3 From 194b3da873fd334ef183806db751473512af29ce Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Thu, 14 Apr 2011 20:55:16 +0400 Subject: agp: fix arbitrary kernel memory writes pg_start is copied from userspace on AGPIOC_BIND and AGPIOC_UNBIND ioctl cmds of agp_ioctl() and passed to agpioc_bind_wrap(). As said in the comment, (pg_start + mem->page_count) may wrap in case of AGPIOC_BIND, and it is not checked at all in case of AGPIOC_UNBIND. As a result, user with sufficient privileges (usually "video" group) may generate either local DoS or privilege escalation. Signed-off-by: Vasiliy Kulikov Signed-off-by: Dave Airlie --- drivers/char/agp/generic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 850a643ad694..b072648dc3f6 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -1095,8 +1095,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) return -EINVAL; } - /* AK: could wrap */ - if ((pg_start + mem->page_count) > num_entries) + if (((pg_start + mem->page_count) > num_entries) || + ((pg_start + mem->page_count) < pg_start)) return -EINVAL; j = pg_start; @@ -1130,7 +1130,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { size_t i; struct agp_bridge_data *bridge; - int mask_type; + int mask_type, num_entries; bridge = mem->bridge; if (!bridge) @@ -1142,6 +1142,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) if (type != mem->type) return -EINVAL; + num_entries = agp_num_entries(); + if (((pg_start + mem->page_count) > num_entries) || + ((pg_start + mem->page_count) < pg_start)) + return -EINVAL; + mask_type = bridge->driver->agp_type_to_mask_type(bridge, type); if (mask_type != 0) { /* The generic routines know nothing of memory types */ -- cgit v1.2.3 From afa2689e19073cd2e762d0f2c1358fab1ab9f18c Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 14 Mar 2011 17:45:48 +0530 Subject: virtio: console: Enable call to hvc_remove() on console port remove This call was disabled as hot-unplugging one virtconsole port led to another virtconsole port freezing. Upon testing it again, this now works, so enable it. In addition, a bug was found in qemu wherein removing a port of one type caused the guest output from another port to stop working. I doubt it was just this bug that caused it (since disabling the hvc_remove() call did allow other ports to continue working), but since it's all solved now, we're fine with hot-unplugging of virtconsole ports. Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 84b164d1eb2b..838568a7dbf5 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1280,18 +1280,7 @@ static void unplug_port(struct port *port) spin_lock_irq(&pdrvdata_lock); list_del(&port->cons.list); spin_unlock_irq(&pdrvdata_lock); -#if 0 - /* - * hvc_remove() not called as removing one hvc port - * results in other hvc ports getting frozen. - * - * Once this is resolved in hvc, this functionality - * will be enabled. Till that is done, the -EPIPE - * return from get_chars() above will help - * hvc_console.c to clean up on ports we remove here. - */ hvc_remove(port->cons.hvc); -#endif } /* Remove unused data this port might have received. */ -- cgit v1.2.3