You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'tty-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull TTY updates from Greg Kroah-Hartman: "Here's the big TTY/serial driver pull request for the 3.5-rc1 merge window. Nothing major in here, just lots of incremental changes from Alan and Jiri reworking some tty core things to behave better and to get a more solid grasp on some of the nasty tty locking issues. There are a few tty and serial driver updates in here as well. All of this has been in the linux-next releases for a while with no problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" * tag 'tty-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (115 commits) serial: bfin_uart: Make MMR access compatible with 32 bits bf609 style controller. serial: bfin_uart: RTS and CTS MMRs can be either 16-bit width or 32-bit width. serial: bfin_uart: narrow the reboot condition in DMA tx interrupt serial: bfin_uart: Adapt bf5xx serial driver to bf60x serial4 controller. Revert "serial_core: Update buffer overrun statistics." tty: hvc_xen: NULL dereference on allocation failure tty: Fix LED error return tty: Allow uart_register/unregister/register tty: move global ldisc idle waitqueue to the individual ldisc serial8250-em: Add DT support serial8250-em: clk_get() IS_ERR() error handling fix serial_core: Update buffer overrun statistics. tty: drop the pty lock during hangup cris: fix missing tty arg in wait_event_interruptible_tty call tty/amiserial: Add missing argument for tty_unlock() tty_lock: Localise the lock pty: Lock the devpts bits privately tty_lock: undo the old tty_lock use on the ctty serial8250-em: Emma Mobile UART driver V2 Add missing call to uart_update_timeout() ...
This commit is contained in:
+76
-66
@@ -20,6 +20,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/serial.h> /* ASYNC_* flags */
|
||||
#include <linux/slab.h>
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/cio.h>
|
||||
@@ -44,14 +45,11 @@
|
||||
#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */
|
||||
|
||||
#define RAW3215_FIXED 1 /* 3215 console device is not be freed */
|
||||
#define RAW3215_ACTIVE 2 /* set if the device is in use */
|
||||
#define RAW3215_WORKING 4 /* set if a request is being worked on */
|
||||
#define RAW3215_THROTTLED 8 /* set if reading is disabled */
|
||||
#define RAW3215_STOPPED 16 /* set if writing is disabled */
|
||||
#define RAW3215_CLOSING 32 /* set while in close process */
|
||||
#define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */
|
||||
#define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */
|
||||
#define RAW3215_FROZEN 256 /* set if 3215 is frozen for suspend */
|
||||
|
||||
#define TAB_STOP_SIZE 8 /* tab stop size */
|
||||
|
||||
@@ -76,6 +74,7 @@ struct raw3215_req {
|
||||
} __attribute__ ((aligned(8)));
|
||||
|
||||
struct raw3215_info {
|
||||
struct tty_port port;
|
||||
struct ccw_device *cdev; /* device for tty driver */
|
||||
spinlock_t *lock; /* pointer to irq lock */
|
||||
int flags; /* state flags */
|
||||
@@ -84,7 +83,6 @@ struct raw3215_info {
|
||||
int head; /* first free byte in output buffer */
|
||||
int count; /* number of bytes in output buffer */
|
||||
int written; /* number of bytes in write requests */
|
||||
struct tty_struct *tty; /* pointer to tty structure if present */
|
||||
struct raw3215_req *queued_read; /* pointer to queued read requests */
|
||||
struct raw3215_req *queued_write;/* pointer to queued write requests */
|
||||
struct tasklet_struct tlet; /* tasklet to invoke tty_wakeup */
|
||||
@@ -293,7 +291,7 @@ static void raw3215_timeout(unsigned long __data)
|
||||
if (raw->flags & RAW3215_TIMER_RUNS) {
|
||||
del_timer(&raw->timer);
|
||||
raw->flags &= ~RAW3215_TIMER_RUNS;
|
||||
if (!(raw->flags & RAW3215_FROZEN)) {
|
||||
if (!(raw->port.flags & ASYNC_SUSPENDED)) {
|
||||
raw3215_mk_write_req(raw);
|
||||
raw3215_start_io(raw);
|
||||
}
|
||||
@@ -309,7 +307,8 @@ static void raw3215_timeout(unsigned long __data)
|
||||
*/
|
||||
static inline void raw3215_try_io(struct raw3215_info *raw)
|
||||
{
|
||||
if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FROZEN))
|
||||
if (!(raw->port.flags & ASYNC_INITIALIZED) ||
|
||||
(raw->port.flags & ASYNC_SUSPENDED))
|
||||
return;
|
||||
if (raw->queued_read != NULL)
|
||||
raw3215_start_io(raw);
|
||||
@@ -324,10 +323,7 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
|
||||
}
|
||||
} else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
|
||||
/* delay small writes */
|
||||
init_timer(&raw->timer);
|
||||
raw->timer.expires = RAW3215_TIMEOUT + jiffies;
|
||||
raw->timer.data = (unsigned long) raw;
|
||||
raw->timer.function = raw3215_timeout;
|
||||
add_timer(&raw->timer);
|
||||
raw->flags |= RAW3215_TIMER_RUNS;
|
||||
}
|
||||
@@ -340,17 +336,21 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
|
||||
static void raw3215_wakeup(unsigned long data)
|
||||
{
|
||||
struct raw3215_info *raw = (struct raw3215_info *) data;
|
||||
tty_wakeup(raw->tty);
|
||||
struct tty_struct *tty;
|
||||
|
||||
tty = tty_port_tty_get(&raw->port);
|
||||
tty_wakeup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to start the next IO and wake up processes waiting on the tty.
|
||||
*/
|
||||
static void raw3215_next_io(struct raw3215_info *raw)
|
||||
static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
|
||||
{
|
||||
raw3215_mk_write_req(raw);
|
||||
raw3215_try_io(raw);
|
||||
if (raw->tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
|
||||
if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
|
||||
tasklet_schedule(&raw->tlet);
|
||||
}
|
||||
|
||||
@@ -368,10 +368,11 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
|
||||
raw = dev_get_drvdata(&cdev->dev);
|
||||
req = (struct raw3215_req *) intparm;
|
||||
tty = tty_port_tty_get(&raw->port);
|
||||
cstat = irb->scsw.cmd.cstat;
|
||||
dstat = irb->scsw.cmd.dstat;
|
||||
if (cstat != 0)
|
||||
raw3215_next_io(raw);
|
||||
raw3215_next_io(raw, tty);
|
||||
if (dstat & 0x01) { /* we got a unit exception */
|
||||
dstat &= ~0x01; /* we can ignore it */
|
||||
}
|
||||
@@ -381,13 +382,13 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
break;
|
||||
/* Attention interrupt, someone hit the enter key */
|
||||
raw3215_mk_read_req(raw);
|
||||
raw3215_next_io(raw);
|
||||
raw3215_next_io(raw, tty);
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x0C:
|
||||
/* Channel end interrupt. */
|
||||
if ((raw = req->info) == NULL)
|
||||
return; /* That shouldn't happen ... */
|
||||
goto put_tty; /* That shouldn't happen ... */
|
||||
if (req->type == RAW3215_READ) {
|
||||
/* store residual count, then wait for device end */
|
||||
req->residual = irb->scsw.cmd.count;
|
||||
@@ -397,11 +398,10 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
case 0x04:
|
||||
/* Device end interrupt. */
|
||||
if ((raw = req->info) == NULL)
|
||||
return; /* That shouldn't happen ... */
|
||||
if (req->type == RAW3215_READ && raw->tty != NULL) {
|
||||
goto put_tty; /* That shouldn't happen ... */
|
||||
if (req->type == RAW3215_READ && tty != NULL) {
|
||||
unsigned int cchar;
|
||||
|
||||
tty = raw->tty;
|
||||
count = 160 - req->residual;
|
||||
EBCASC(raw->inbuf, count);
|
||||
cchar = ctrlchar_handle(raw->inbuf, count, tty);
|
||||
@@ -411,7 +411,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
|
||||
case CTRLCHAR_CTRL:
|
||||
tty_insert_flip_char(tty, cchar, TTY_NORMAL);
|
||||
tty_flip_buffer_push(raw->tty);
|
||||
tty_flip_buffer_push(tty);
|
||||
break;
|
||||
|
||||
case CTRLCHAR_NONE:
|
||||
@@ -424,7 +424,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
} else
|
||||
count -= 2;
|
||||
tty_insert_flip_string(tty, raw->inbuf, count);
|
||||
tty_flip_buffer_push(raw->tty);
|
||||
tty_flip_buffer_push(tty);
|
||||
break;
|
||||
}
|
||||
} else if (req->type == RAW3215_WRITE) {
|
||||
@@ -439,7 +439,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
raw->queued_read == NULL) {
|
||||
wake_up_interruptible(&raw->empty_wait);
|
||||
}
|
||||
raw3215_next_io(raw);
|
||||
raw3215_next_io(raw, tty);
|
||||
break;
|
||||
default:
|
||||
/* Strange interrupt, I'll do my best to clean up */
|
||||
@@ -451,9 +451,10 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
raw->flags &= ~RAW3215_WORKING;
|
||||
raw3215_free_req(req);
|
||||
}
|
||||
raw3215_next_io(raw);
|
||||
raw3215_next_io(raw, tty);
|
||||
}
|
||||
return;
|
||||
put_tty:
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -487,7 +488,7 @@ static void raw3215_make_room(struct raw3215_info *raw, unsigned int length)
|
||||
/* While console is frozen for suspend we have no other
|
||||
* choice but to drop message from the buffer to make
|
||||
* room for even more messages. */
|
||||
if (raw->flags & RAW3215_FROZEN) {
|
||||
if (raw->port.flags & ASYNC_SUSPENDED) {
|
||||
raw3215_drop_line(raw);
|
||||
continue;
|
||||
}
|
||||
@@ -609,10 +610,10 @@ static int raw3215_startup(struct raw3215_info *raw)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (raw->flags & RAW3215_ACTIVE)
|
||||
if (raw->port.flags & ASYNC_INITIALIZED)
|
||||
return 0;
|
||||
raw->line_pos = 0;
|
||||
raw->flags |= RAW3215_ACTIVE;
|
||||
raw->port.flags |= ASYNC_INITIALIZED;
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw3215_try_io(raw);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
@@ -628,14 +629,15 @@ static void raw3215_shutdown(struct raw3215_info *raw)
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
unsigned long flags;
|
||||
|
||||
if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))
|
||||
if (!(raw->port.flags & ASYNC_INITIALIZED) ||
|
||||
(raw->flags & RAW3215_FIXED))
|
||||
return;
|
||||
/* Wait for outstanding requests, then free irq */
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
if ((raw->flags & RAW3215_WORKING) ||
|
||||
raw->queued_write != NULL ||
|
||||
raw->queued_read != NULL) {
|
||||
raw->flags |= RAW3215_CLOSING;
|
||||
raw->port.flags |= ASYNC_CLOSING;
|
||||
add_wait_queue(&raw->empty_wait, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
@@ -643,11 +645,41 @@ static void raw3215_shutdown(struct raw3215_info *raw)
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
remove_wait_queue(&raw->empty_wait, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING);
|
||||
raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING);
|
||||
}
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
}
|
||||
|
||||
static struct raw3215_info *raw3215_alloc_info(void)
|
||||
{
|
||||
struct raw3215_info *info;
|
||||
|
||||
info = kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
if (!info->buffer || !info->inbuf) {
|
||||
kfree(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
setup_timer(&info->timer, raw3215_timeout, (unsigned long)info);
|
||||
init_waitqueue_head(&info->empty_wait);
|
||||
tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info);
|
||||
tty_port_init(&info->port);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void raw3215_free_info(struct raw3215_info *raw)
|
||||
{
|
||||
kfree(raw->inbuf);
|
||||
kfree(raw->buffer);
|
||||
kfree(raw);
|
||||
}
|
||||
|
||||
static int raw3215_probe (struct ccw_device *cdev)
|
||||
{
|
||||
struct raw3215_info *raw;
|
||||
@@ -656,11 +688,15 @@ static int raw3215_probe (struct ccw_device *cdev)
|
||||
/* Console is special. */
|
||||
if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev)))
|
||||
return 0;
|
||||
raw = kmalloc(sizeof(struct raw3215_info) +
|
||||
RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA);
|
||||
|
||||
raw = raw3215_alloc_info();
|
||||
if (raw == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
raw->cdev = cdev;
|
||||
dev_set_drvdata(&cdev->dev, raw);
|
||||
cdev->handler = raw3215_irq;
|
||||
|
||||
spin_lock(&raw3215_device_lock);
|
||||
for (line = 0; line < NR_3215; line++) {
|
||||
if (!raw3215[line]) {
|
||||
@@ -670,28 +706,10 @@ static int raw3215_probe (struct ccw_device *cdev)
|
||||
}
|
||||
spin_unlock(&raw3215_device_lock);
|
||||
if (line == NR_3215) {
|
||||
kfree(raw);
|
||||
raw3215_free_info(raw);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
raw->cdev = cdev;
|
||||
raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
|
||||
memset(raw, 0, sizeof(struct raw3215_info));
|
||||
raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
|
||||
GFP_KERNEL|GFP_DMA);
|
||||
if (raw->buffer == NULL) {
|
||||
spin_lock(&raw3215_device_lock);
|
||||
raw3215[line] = NULL;
|
||||
spin_unlock(&raw3215_device_lock);
|
||||
kfree(raw);
|
||||
return -ENOMEM;
|
||||
}
|
||||
init_waitqueue_head(&raw->empty_wait);
|
||||
tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
|
||||
|
||||
dev_set_drvdata(&cdev->dev, raw);
|
||||
cdev->handler = raw3215_irq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -703,8 +721,7 @@ static void raw3215_remove (struct ccw_device *cdev)
|
||||
raw = dev_get_drvdata(&cdev->dev);
|
||||
if (raw) {
|
||||
dev_set_drvdata(&cdev->dev, NULL);
|
||||
kfree(raw->buffer);
|
||||
kfree(raw);
|
||||
raw3215_free_info(raw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,7 +758,7 @@ static int raw3215_pm_stop(struct ccw_device *cdev)
|
||||
raw = dev_get_drvdata(&cdev->dev);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw3215_make_room(raw, RAW3215_BUFFER_SIZE);
|
||||
raw->flags |= RAW3215_FROZEN;
|
||||
raw->port.flags |= ASYNC_SUSPENDED;
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
return 0;
|
||||
}
|
||||
@@ -754,7 +771,7 @@ static int raw3215_pm_start(struct ccw_device *cdev)
|
||||
/* Allow I/O again and flush output buffer. */
|
||||
raw = dev_get_drvdata(&cdev->dev);
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
raw->flags &= ~RAW3215_FROZEN;
|
||||
raw->port.flags &= ~ASYNC_SUSPENDED;
|
||||
raw->flags |= RAW3215_FLUSHING;
|
||||
raw3215_try_io(raw);
|
||||
raw->flags &= ~RAW3215_FLUSHING;
|
||||
@@ -827,7 +844,7 @@ static void con3215_flush(void)
|
||||
unsigned long flags;
|
||||
|
||||
raw = raw3215[0]; /* console 3215 is the first one */
|
||||
if (raw->flags & RAW3215_FROZEN)
|
||||
if (raw->port.flags & ASYNC_SUSPENDED)
|
||||
/* The console is still frozen for suspend. */
|
||||
if (ccw_device_force_console())
|
||||
/* Forcing didn't work, no panic message .. */
|
||||
@@ -897,23 +914,16 @@ static int __init con3215_init(void)
|
||||
if (IS_ERR(cdev))
|
||||
return -ENODEV;
|
||||
|
||||
raw3215[0] = raw = (struct raw3215_info *)
|
||||
kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
|
||||
raw->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
raw->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
raw3215[0] = raw = raw3215_alloc_info();
|
||||
raw->cdev = cdev;
|
||||
dev_set_drvdata(&cdev->dev, raw);
|
||||
cdev->handler = raw3215_irq;
|
||||
|
||||
raw->flags |= RAW3215_FIXED;
|
||||
init_waitqueue_head(&raw->empty_wait);
|
||||
tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
|
||||
|
||||
/* Request the console irq */
|
||||
if (raw3215_startup(raw) != 0) {
|
||||
kfree(raw->inbuf);
|
||||
kfree(raw->buffer);
|
||||
kfree(raw);
|
||||
raw3215_free_info(raw);
|
||||
raw3215[0] = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -940,7 +950,7 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp)
|
||||
return -ENODEV;
|
||||
|
||||
tty->driver_data = raw;
|
||||
raw->tty = tty;
|
||||
tty_port_tty_set(&raw->port, tty);
|
||||
|
||||
tty->low_latency = 0; /* don't use bottom half for pushing chars */
|
||||
/*
|
||||
@@ -971,7 +981,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp)
|
||||
raw3215_shutdown(raw);
|
||||
tasklet_kill(&raw->tlet);
|
||||
tty->closing = 0;
|
||||
raw->tty = NULL;
|
||||
tty_port_tty_set(&raw->port, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch)
|
||||
if (ch == ' ' || ch == d)
|
||||
return d;
|
||||
|
||||
kbd_put_queue(kbd->tty, d);
|
||||
kbd_put_queue(kbd->port, d);
|
||||
return ch;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value)
|
||||
{
|
||||
if (kbd->diacr)
|
||||
value = handle_diacr(kbd, value);
|
||||
kbd_put_queue(kbd->tty, value);
|
||||
kbd_put_queue(kbd->port, value);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -239,7 +239,7 @@ static void
|
||||
k_fn(struct kbd_data *kbd, unsigned char value)
|
||||
{
|
||||
if (kbd->func_table[value])
|
||||
kbd_puts_queue(kbd->tty, kbd->func_table[value]);
|
||||
kbd_puts_queue(kbd->port, kbd->func_table[value]);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value)
|
||||
* but we need only 16 bits here
|
||||
*/
|
||||
static void
|
||||
to_utf8(struct tty_struct *tty, ushort c)
|
||||
to_utf8(struct tty_port *port, ushort c)
|
||||
{
|
||||
if (c < 0x80)
|
||||
/* 0******* */
|
||||
kbd_put_queue(tty, c);
|
||||
kbd_put_queue(port, c);
|
||||
else if (c < 0x800) {
|
||||
/* 110***** 10****** */
|
||||
kbd_put_queue(tty, 0xc0 | (c >> 6));
|
||||
kbd_put_queue(tty, 0x80 | (c & 0x3f));
|
||||
kbd_put_queue(port, 0xc0 | (c >> 6));
|
||||
kbd_put_queue(port, 0x80 | (c & 0x3f));
|
||||
} else {
|
||||
/* 1110**** 10****** 10****** */
|
||||
kbd_put_queue(tty, 0xe0 | (c >> 12));
|
||||
kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f));
|
||||
kbd_put_queue(tty, 0x80 | (c & 0x3f));
|
||||
kbd_put_queue(port, 0xe0 | (c >> 12));
|
||||
kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f));
|
||||
kbd_put_queue(port, 0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
|
||||
unsigned short keysym;
|
||||
unsigned char type, value;
|
||||
|
||||
if (!kbd || !kbd->tty)
|
||||
if (!kbd)
|
||||
return;
|
||||
|
||||
if (keycode >= 384)
|
||||
@@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
|
||||
#endif
|
||||
(*k_handler[type])(kbd, value);
|
||||
} else
|
||||
to_utf8(kbd->tty, keysym);
|
||||
to_utf8(kbd->port, keysym);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -457,6 +457,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
|
||||
|
||||
int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
void __user *argp;
|
||||
unsigned int ct;
|
||||
int perm;
|
||||
@@ -467,7 +468,10 @@ int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
|
||||
* To have permissions to do most of the vt ioctls, we either have
|
||||
* to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
|
||||
*/
|
||||
perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG);
|
||||
tty = tty_port_tty_get(kbd->port);
|
||||
/* FIXME this test is pretty racy */
|
||||
perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG);
|
||||
tty_kref_put(tty);
|
||||
switch (cmd) {
|
||||
case KDGKBTYPE:
|
||||
return put_user(KB_101, (char __user *)argp);
|
||||
|
||||
@@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *);
|
||||
*/
|
||||
|
||||
struct kbd_data {
|
||||
struct tty_struct *tty;
|
||||
struct tty_port *port;
|
||||
unsigned short **key_maps;
|
||||
char **func_table;
|
||||
fn_handler_fn **fn_handler;
|
||||
@@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
|
||||
* Helper Functions.
|
||||
*/
|
||||
static inline void
|
||||
kbd_put_queue(struct tty_struct *tty, int ch)
|
||||
kbd_put_queue(struct tty_port *port, int ch)
|
||||
{
|
||||
struct tty_struct *tty = tty_port_tty_get(port);
|
||||
if (!tty)
|
||||
return;
|
||||
tty_insert_flip_char(tty, ch, 0);
|
||||
tty_schedule_flip(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
static inline void
|
||||
kbd_puts_queue(struct tty_struct *tty, char *cp)
|
||||
kbd_puts_queue(struct tty_port *port, char *cp)
|
||||
{
|
||||
struct tty_struct *tty = tty_port_tty_get(port);
|
||||
if (!tty)
|
||||
return;
|
||||
while (*cp)
|
||||
tty_insert_flip_char(tty, *cp++, 0);
|
||||
tty_schedule_flip(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ static struct sclp_buffer *sclp_ttybuf;
|
||||
/* Timer for delayed output of console messages. */
|
||||
static struct timer_list sclp_tty_timer;
|
||||
|
||||
static struct tty_struct *sclp_tty;
|
||||
static struct tty_port sclp_port;
|
||||
static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
|
||||
static unsigned short int sclp_tty_chars_count;
|
||||
|
||||
@@ -64,7 +64,7 @@ static int sclp_tty_columns = 80;
|
||||
static int
|
||||
sclp_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
sclp_tty = tty;
|
||||
tty_port_tty_set(&sclp_port, tty);
|
||||
tty->driver_data = NULL;
|
||||
tty->low_latency = 0;
|
||||
return 0;
|
||||
@@ -76,7 +76,7 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
if (tty->count > 1)
|
||||
return;
|
||||
sclp_tty = NULL;
|
||||
tty_port_tty_set(&sclp_port, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -108,6 +108,7 @@ sclp_tty_write_room (struct tty_struct *tty)
|
||||
static void
|
||||
sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
unsigned long flags;
|
||||
void *page;
|
||||
|
||||
@@ -126,8 +127,10 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
|
||||
spin_unlock_irqrestore(&sclp_tty_lock, flags);
|
||||
} while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
|
||||
/* check if the tty needs a wake up call */
|
||||
if (sclp_tty != NULL) {
|
||||
tty_wakeup(sclp_tty);
|
||||
tty = tty_port_tty_get(&sclp_port);
|
||||
if (tty != NULL) {
|
||||
tty_wakeup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,21 +329,22 @@ sclp_tty_flush_buffer(struct tty_struct *tty)
|
||||
static void
|
||||
sclp_tty_input(unsigned char* buf, unsigned int count)
|
||||
{
|
||||
struct tty_struct *tty = tty_port_tty_get(&sclp_port);
|
||||
unsigned int cchar;
|
||||
|
||||
/*
|
||||
* If this tty driver is currently closed
|
||||
* then throw the received input away.
|
||||
*/
|
||||
if (sclp_tty == NULL)
|
||||
if (tty == NULL)
|
||||
return;
|
||||
cchar = ctrlchar_handle(buf, count, sclp_tty);
|
||||
cchar = ctrlchar_handle(buf, count, tty);
|
||||
switch (cchar & CTRLCHAR_MASK) {
|
||||
case CTRLCHAR_SYSRQ:
|
||||
break;
|
||||
case CTRLCHAR_CTRL:
|
||||
tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
|
||||
tty_flip_buffer_push(sclp_tty);
|
||||
tty_insert_flip_char(tty, cchar, TTY_NORMAL);
|
||||
tty_flip_buffer_push(tty);
|
||||
break;
|
||||
case CTRLCHAR_NONE:
|
||||
/* send (normal) input to line discipline */
|
||||
@@ -348,13 +352,14 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
|
||||
(strncmp((const char *) buf + count - 2, "^n", 2) &&
|
||||
strncmp((const char *) buf + count - 2, "\252n", 2))) {
|
||||
/* add the auto \n */
|
||||
tty_insert_flip_string(sclp_tty, buf, count);
|
||||
tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
|
||||
tty_insert_flip_string(tty, buf, count);
|
||||
tty_insert_flip_char(tty, '\n', TTY_NORMAL);
|
||||
} else
|
||||
tty_insert_flip_string(sclp_tty, buf, count - 2);
|
||||
tty_flip_buffer_push(sclp_tty);
|
||||
tty_insert_flip_string(tty, buf, count - 2);
|
||||
tty_flip_buffer_push(tty);
|
||||
break;
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -543,7 +548,7 @@ sclp_tty_init(void)
|
||||
sclp_tty_tolower = 1;
|
||||
}
|
||||
sclp_tty_chars_count = 0;
|
||||
sclp_tty = NULL;
|
||||
tty_port_init(&sclp_port);
|
||||
|
||||
rc = sclp_register(&sclp_input_event);
|
||||
if (rc) {
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define SCLP_VT220_DEVICE_NAME "ttysclp"
|
||||
#define SCLP_VT220_CONSOLE_NAME "ttyS"
|
||||
#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */
|
||||
#define SCLP_VT220_BUF_SIZE 80
|
||||
|
||||
/* Representation of a single write request */
|
||||
struct sclp_vt220_request {
|
||||
@@ -56,8 +55,7 @@ struct sclp_vt220_sccb {
|
||||
/* Structures and data needed to register tty driver */
|
||||
static struct tty_driver *sclp_vt220_driver;
|
||||
|
||||
/* The tty_struct that the kernel associated with us */
|
||||
static struct tty_struct *sclp_vt220_tty;
|
||||
static struct tty_port sclp_vt220_port;
|
||||
|
||||
/* Lock to protect internal data from concurrent access */
|
||||
static spinlock_t sclp_vt220_lock;
|
||||
@@ -116,6 +114,7 @@ static struct sclp_register sclp_vt220_register = {
|
||||
static void
|
||||
sclp_vt220_process_queue(struct sclp_vt220_request *request)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
unsigned long flags;
|
||||
void *page;
|
||||
|
||||
@@ -141,8 +140,10 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
|
||||
if (request == NULL && sclp_vt220_flush_later)
|
||||
sclp_vt220_emit_current();
|
||||
/* Check if the tty needs a wake up call */
|
||||
if (sclp_vt220_tty != NULL) {
|
||||
tty_wakeup(sclp_vt220_tty);
|
||||
tty = tty_port_tty_get(&sclp_vt220_port);
|
||||
if (tty) {
|
||||
tty_wakeup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,11 +461,12 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
|
||||
static void
|
||||
sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
|
||||
{
|
||||
struct tty_struct *tty = tty_port_tty_get(&sclp_vt220_port);
|
||||
char *buffer;
|
||||
unsigned int count;
|
||||
|
||||
/* Ignore input if device is not open */
|
||||
if (sclp_vt220_tty == NULL)
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header));
|
||||
@@ -478,10 +480,11 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
|
||||
/* Send input to line discipline */
|
||||
buffer++;
|
||||
count--;
|
||||
tty_insert_flip_string(sclp_vt220_tty, buffer, count);
|
||||
tty_flip_buffer_push(sclp_vt220_tty);
|
||||
tty_insert_flip_string(tty, buffer, count);
|
||||
tty_flip_buffer_push(tty);
|
||||
break;
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -491,10 +494,7 @@ static int
|
||||
sclp_vt220_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
if (tty->count == 1) {
|
||||
sclp_vt220_tty = tty;
|
||||
tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL);
|
||||
if (tty->driver_data == NULL)
|
||||
return -ENOMEM;
|
||||
tty_port_tty_set(&sclp_vt220_port, tty);
|
||||
tty->low_latency = 0;
|
||||
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
|
||||
tty->winsize.ws_row = 24;
|
||||
@@ -510,11 +510,8 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp)
|
||||
static void
|
||||
sclp_vt220_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
if (tty->count == 1) {
|
||||
sclp_vt220_tty = NULL;
|
||||
kfree(tty->driver_data);
|
||||
tty->driver_data = NULL;
|
||||
}
|
||||
if (tty->count == 1)
|
||||
tty_port_tty_set(&sclp_vt220_port, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -635,9 +632,9 @@ static int __init __sclp_vt220_init(int num_pages)
|
||||
INIT_LIST_HEAD(&sclp_vt220_empty);
|
||||
INIT_LIST_HEAD(&sclp_vt220_outqueue);
|
||||
init_timer(&sclp_vt220_timer);
|
||||
tty_port_init(&sclp_vt220_port);
|
||||
sclp_vt220_current_request = NULL;
|
||||
sclp_vt220_buffered_chars = 0;
|
||||
sclp_vt220_tty = NULL;
|
||||
sclp_vt220_flush_later = 0;
|
||||
|
||||
/* Allocate pages for output buffering */
|
||||
|
||||
+56
-65
@@ -61,7 +61,7 @@ struct tty3270_line {
|
||||
*/
|
||||
struct tty3270 {
|
||||
struct raw3270_view view;
|
||||
struct tty_struct *tty; /* Pointer to tty structure */
|
||||
struct tty_port port;
|
||||
void **freemem_pages; /* Array of pages used for freemem. */
|
||||
struct list_head freemem; /* List of free memory for strings. */
|
||||
|
||||
@@ -324,9 +324,8 @@ tty3270_blank_line(struct tty3270 *tp)
|
||||
static void
|
||||
tty3270_write_callback(struct raw3270_request *rq, void *data)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
|
||||
|
||||
tp = (struct tty3270 *) rq->view;
|
||||
if (rq->rc != 0) {
|
||||
/* Write wasn't successful. Refresh all. */
|
||||
tp->update_flags = TTY_UPDATE_ALL;
|
||||
@@ -450,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
|
||||
static void
|
||||
tty3270_rcl_backward(struct kbd_data *kbd)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
|
||||
struct string *s;
|
||||
|
||||
tp = kbd->tty->driver_data;
|
||||
spin_lock_bh(&tp->view.lock);
|
||||
if (tp->inattr == TF_INPUT) {
|
||||
if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
|
||||
@@ -478,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd)
|
||||
static void
|
||||
tty3270_exit_tty(struct kbd_data *kbd)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
|
||||
|
||||
tp = kbd->tty->driver_data;
|
||||
raw3270_deactivate_view(&tp->view);
|
||||
}
|
||||
|
||||
@@ -490,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd)
|
||||
static void
|
||||
tty3270_scroll_forward(struct kbd_data *kbd)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
|
||||
int nr_up;
|
||||
|
||||
tp = kbd->tty->driver_data;
|
||||
spin_lock_bh(&tp->view.lock);
|
||||
nr_up = tp->nr_up - tp->view.rows + 2;
|
||||
if (nr_up < 0)
|
||||
@@ -513,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd)
|
||||
static void
|
||||
tty3270_scroll_backward(struct kbd_data *kbd)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
|
||||
int nr_up;
|
||||
|
||||
tp = kbd->tty->driver_data;
|
||||
spin_lock_bh(&tp->view.lock);
|
||||
nr_up = tp->nr_up + tp->view.rows - 2;
|
||||
if (nr_up + tp->view.rows - 2 > tp->nr_lines)
|
||||
@@ -537,11 +532,10 @@ static void
|
||||
tty3270_read_tasklet(struct raw3270_request *rrq)
|
||||
{
|
||||
static char kreset_data = TW_KR;
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(rrq->view, struct tty3270, view);
|
||||
char *input;
|
||||
int len;
|
||||
|
||||
tp = (struct tty3270 *) rrq->view;
|
||||
spin_lock_bh(&tp->view.lock);
|
||||
/*
|
||||
* Two AID keys are special: For 0x7d (enter) the input line
|
||||
@@ -577,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
|
||||
raw3270_request_add_data(tp->kreset, &kreset_data, 1);
|
||||
raw3270_start(&tp->view, tp->kreset);
|
||||
|
||||
/* Emit input string. */
|
||||
if (tp->tty) {
|
||||
while (len-- > 0)
|
||||
kbd_keycode(tp->kbd, *input++);
|
||||
/* Emit keycode for AID byte. */
|
||||
kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
|
||||
}
|
||||
while (len-- > 0)
|
||||
kbd_keycode(tp->kbd, *input++);
|
||||
/* Emit keycode for AID byte. */
|
||||
kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
|
||||
|
||||
raw3270_request_reset(rrq);
|
||||
xchg(&tp->read, rrq);
|
||||
@@ -596,9 +587,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
|
||||
static void
|
||||
tty3270_read_callback(struct raw3270_request *rq, void *data)
|
||||
{
|
||||
struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
|
||||
raw3270_get_view(rq->view);
|
||||
/* Schedule tasklet to pass input to tty. */
|
||||
tasklet_schedule(&((struct tty3270 *) rq->view)->readlet);
|
||||
tasklet_schedule(&tp->readlet);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -635,9 +627,8 @@ tty3270_issue_read(struct tty3270 *tp, int lock)
|
||||
static int
|
||||
tty3270_activate(struct raw3270_view *view)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(view, struct tty3270, view);
|
||||
|
||||
tp = (struct tty3270 *) view;
|
||||
tp->update_flags = TTY_UPDATE_ALL;
|
||||
tty3270_set_timer(tp, 1);
|
||||
return 0;
|
||||
@@ -646,9 +637,8 @@ tty3270_activate(struct raw3270_view *view)
|
||||
static void
|
||||
tty3270_deactivate(struct raw3270_view *view)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = container_of(view, struct tty3270, view);
|
||||
|
||||
tp = (struct tty3270 *) view;
|
||||
del_timer(&tp->timer);
|
||||
}
|
||||
|
||||
@@ -690,6 +680,17 @@ tty3270_alloc_view(void)
|
||||
if (!tp->freemem_pages)
|
||||
goto out_tp;
|
||||
INIT_LIST_HEAD(&tp->freemem);
|
||||
INIT_LIST_HEAD(&tp->lines);
|
||||
INIT_LIST_HEAD(&tp->update);
|
||||
INIT_LIST_HEAD(&tp->rcl_lines);
|
||||
tp->rcl_max = 20;
|
||||
tty_port_init(&tp->port);
|
||||
setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
|
||||
(unsigned long) tp);
|
||||
tasklet_init(&tp->readlet,
|
||||
(void (*)(unsigned long)) tty3270_read_tasklet,
|
||||
(unsigned long) tp->read);
|
||||
|
||||
for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
|
||||
tp->freemem_pages[pages] = (void *)
|
||||
__get_free_pages(GFP_KERNEL|GFP_DMA, 0);
|
||||
@@ -794,16 +795,15 @@ tty3270_free_screen(struct tty3270 *tp)
|
||||
static void
|
||||
tty3270_release(struct raw3270_view *view)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty_struct *tty;
|
||||
struct tty3270 *tp = container_of(view, struct tty3270, view);
|
||||
struct tty_struct *tty = tty_port_tty_get(&tp->port);
|
||||
|
||||
tp = (struct tty3270 *) view;
|
||||
tty = tp->tty;
|
||||
if (tty) {
|
||||
tty->driver_data = NULL;
|
||||
tp->tty = tp->kbd->tty = NULL;
|
||||
tty_port_tty_set(&tp->port, NULL);
|
||||
tty_hangup(tty);
|
||||
raw3270_put_view(&tp->view);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,8 +813,9 @@ tty3270_release(struct raw3270_view *view)
|
||||
static void
|
||||
tty3270_free(struct raw3270_view *view)
|
||||
{
|
||||
tty3270_free_screen((struct tty3270 *) view);
|
||||
tty3270_free_view((struct tty3270 *) view);
|
||||
struct tty3270 *tp = container_of(view, struct tty3270, view);
|
||||
tty3270_free_screen(tp);
|
||||
tty3270_free_view(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -823,14 +824,13 @@ tty3270_free(struct raw3270_view *view)
|
||||
static void
|
||||
tty3270_del_views(void)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tty3270_max_index; i++) {
|
||||
tp = (struct tty3270 *)
|
||||
struct raw3270_view *view =
|
||||
raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
|
||||
if (!IS_ERR(tp))
|
||||
raw3270_del_view(&tp->view);
|
||||
if (!IS_ERR(view))
|
||||
raw3270_del_view(view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,22 +848,23 @@ static struct raw3270_fn tty3270_fn = {
|
||||
static int
|
||||
tty3270_open(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
struct raw3270_view *view;
|
||||
struct tty3270 *tp;
|
||||
int i, rc;
|
||||
|
||||
if (tty->count > 1)
|
||||
return 0;
|
||||
/* Check if the tty3270 is already there. */
|
||||
tp = (struct tty3270 *)
|
||||
raw3270_find_view(&tty3270_fn,
|
||||
view = raw3270_find_view(&tty3270_fn,
|
||||
tty->index + RAW3270_FIRSTMINOR);
|
||||
if (!IS_ERR(tp)) {
|
||||
if (!IS_ERR(view)) {
|
||||
tp = container_of(view, struct tty3270, view);
|
||||
tty->driver_data = tp;
|
||||
tty->winsize.ws_row = tp->view.rows - 2;
|
||||
tty->winsize.ws_col = tp->view.cols;
|
||||
tty->low_latency = 0;
|
||||
tp->tty = tty;
|
||||
tp->kbd->tty = tty;
|
||||
/* why to reassign? */
|
||||
tty_port_tty_set(&tp->port, tty);
|
||||
tp->inattr = TF_INPUT;
|
||||
return 0;
|
||||
}
|
||||
@@ -871,7 +872,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
|
||||
tty3270_max_index = tty->index + 1;
|
||||
|
||||
/* Quick exit if there is no device for tty->index. */
|
||||
if (PTR_ERR(tp) == -ENODEV)
|
||||
if (PTR_ERR(view) == -ENODEV)
|
||||
return -ENODEV;
|
||||
|
||||
/* Allocate tty3270 structure on first open. */
|
||||
@@ -879,16 +880,6 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
|
||||
if (IS_ERR(tp))
|
||||
return PTR_ERR(tp);
|
||||
|
||||
INIT_LIST_HEAD(&tp->lines);
|
||||
INIT_LIST_HEAD(&tp->update);
|
||||
INIT_LIST_HEAD(&tp->rcl_lines);
|
||||
tp->rcl_max = 20;
|
||||
setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
|
||||
(unsigned long) tp);
|
||||
tasklet_init(&tp->readlet,
|
||||
(void (*)(unsigned long)) tty3270_read_tasklet,
|
||||
(unsigned long) tp->read);
|
||||
|
||||
rc = raw3270_add_view(&tp->view, &tty3270_fn,
|
||||
tty->index + RAW3270_FIRSTMINOR);
|
||||
if (rc) {
|
||||
@@ -903,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
|
||||
return rc;
|
||||
}
|
||||
|
||||
tp->tty = tty;
|
||||
tty_port_tty_set(&tp->port, tty);
|
||||
tty->low_latency = 0;
|
||||
tty->driver_data = tp;
|
||||
tty->winsize.ws_row = tp->view.rows - 2;
|
||||
@@ -917,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
|
||||
for (i = 0; i < tp->view.rows - 2; i++)
|
||||
tty3270_blank_line(tp);
|
||||
|
||||
tp->kbd->tty = tty;
|
||||
tp->kbd->port = &tp->port;
|
||||
tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
|
||||
tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
|
||||
tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
|
||||
@@ -935,14 +926,13 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
|
||||
static void
|
||||
tty3270_close(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
struct tty3270 *tp;
|
||||
struct tty3270 *tp = tty->driver_data;
|
||||
|
||||
if (tty->count > 1)
|
||||
return;
|
||||
tp = (struct tty3270 *) tty->driver_data;
|
||||
if (tp) {
|
||||
tty->driver_data = NULL;
|
||||
tp->tty = tp->kbd->tty = NULL;
|
||||
tty_port_tty_set(&tp->port, NULL);
|
||||
raw3270_put_view(&tp->view);
|
||||
}
|
||||
}
|
||||
@@ -1391,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
|
||||
tty3270_lf(tp);
|
||||
break;
|
||||
case 'Z': /* Respond ID. */
|
||||
kbd_puts_queue(tp->tty, "\033[?6c");
|
||||
kbd_puts_queue(&tp->port, "\033[?6c");
|
||||
break;
|
||||
case '7': /* Save cursor position. */
|
||||
tp->saved_cx = tp->cx;
|
||||
@@ -1437,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
|
||||
tp->esc_state = ESnormal;
|
||||
if (ch == 'n' && !tp->esc_ques) {
|
||||
if (tp->esc_par[0] == 5) /* Status report. */
|
||||
kbd_puts_queue(tp->tty, "\033[0n");
|
||||
kbd_puts_queue(&tp->port, "\033[0n");
|
||||
else if (tp->esc_par[0] == 6) { /* Cursor report. */
|
||||
char buf[40];
|
||||
sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
|
||||
kbd_puts_queue(tp->tty, buf);
|
||||
kbd_puts_queue(&tp->port, buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1513,12 +1503,13 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
|
||||
* String write routine for 3270 ttys
|
||||
*/
|
||||
static void
|
||||
tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count)
|
||||
tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty,
|
||||
const unsigned char *buf, int count)
|
||||
{
|
||||
int i_msg, i;
|
||||
|
||||
spin_lock_bh(&tp->view.lock);
|
||||
for (i_msg = 0; !tp->tty->stopped && i_msg < count; i_msg++) {
|
||||
for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) {
|
||||
if (tp->esc_state != 0) {
|
||||
/* Continue escape sequence. */
|
||||
tty3270_escape_sequence(tp, buf[i_msg]);
|
||||
@@ -1595,10 +1586,10 @@ tty3270_write(struct tty_struct * tty,
|
||||
if (!tp)
|
||||
return 0;
|
||||
if (tp->char_count > 0) {
|
||||
tty3270_do_write(tp, tp->char_buf, tp->char_count);
|
||||
tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
|
||||
tp->char_count = 0;
|
||||
}
|
||||
tty3270_do_write(tp, buf, count);
|
||||
tty3270_do_write(tp, tty, buf, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -1629,7 +1620,7 @@ tty3270_flush_chars(struct tty_struct *tty)
|
||||
if (!tp)
|
||||
return;
|
||||
if (tp->char_count > 0) {
|
||||
tty3270_do_write(tp, tp->char_buf, tp->char_count);
|
||||
tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
|
||||
tp->char_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user