示例#1
0
/*
 * Try to start the next IO and wake up processes waiting on the tty.
 */
static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
{
	raw3215_mk_write_req(raw);
	raw3215_try_io(raw);
	if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
		tasklet_schedule(&raw->tlet);
}
示例#2
0
/*
 * Wait until length bytes are available int the output buffer.
 * Has to be called with the s390irq lock held. Can be called
 * disabled.
 */
static void raw3215_make_room(struct raw3215_info *raw, unsigned int length)
{
	while (RAW3215_BUFFER_SIZE - raw->count < 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->port.flags & ASYNC_SUSPENDED) {
			raw3215_drop_line(raw);
			continue;
		}
		/* there might be a request pending */
		raw->flags |= RAW3215_FLUSHING;
		raw3215_mk_write_req(raw);
		raw3215_try_io(raw);
		raw->flags &= ~RAW3215_FLUSHING;
#ifdef CONFIG_TN3215_CONSOLE
		ccw_device_wait_idle(raw->cdev);
#endif
		/* Enough room freed up ? */
		if (RAW3215_BUFFER_SIZE - raw->count >= length)
			break;
		/* there might be another cpu waiting for the lock */
		spin_unlock(get_ccwdev_lock(raw->cdev));
		udelay(100);
		spin_lock(get_ccwdev_lock(raw->cdev));
	}
}
/*
 * The bottom half handler routine for 3215 devices. It tries to start
 * the next IO and wakes up processes waiting on the tty.
 */
static void raw3215_softint(void *data)
{
	raw3215_info *raw;
	struct tty_struct *tty;
	unsigned long flags;

	raw = (raw3215_info *) data;
	s390irq_spin_lock_irqsave(raw->irq, flags);
        raw3215_mk_write_req(raw);
        raw3215_try_io(raw);
        raw->flags &= ~RAW3215_BH_PENDING;
	s390irq_spin_unlock_irqrestore(raw->irq, flags);
	/* Check for pending message from raw3215_irq */
	if (raw->message != NULL) {
		printk(raw->message, raw->irq, raw->msg_dstat, raw->msg_cstat);
		raw->message = NULL;
	}
	tty = raw->tty;
	if (tty != NULL &&
	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
}
示例#4
0
/*
 * Put character routine for 3215 devices
 */
static void raw3215_putchar(struct raw3215_info *raw, unsigned char ch)
{
	unsigned long flags;
	unsigned int length, i;

	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
	if (ch == '\t') {
		length = TAB_STOP_SIZE - (raw->line_pos%TAB_STOP_SIZE);
		raw->line_pos += length;
		ch = ' ';
	} else if (ch == '\n') {
		length = 1;
		raw->line_pos = 0;
	} else {
		length = 1;
		raw->line_pos++;
	}
	raw3215_make_room(raw, length);

	for (i = 0; i < length; i++) {
		raw->buffer[raw->head] = (char) _ascebc[(int) ch];
		raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1);
		raw->count++;
	}
	if (!(raw->flags & RAW3215_WORKING)) {
		raw3215_mk_write_req(raw);
		/* start or queue request */
		raw3215_try_io(raw);
	}
	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
}
/*
 * Flush routine, it simply sets the flush flag and tries to start 
 * pending IO.
 */
static void raw3215_flush_buffer(raw3215_info *raw)
{
	unsigned long flags;

	s390irq_spin_lock_irqsave(raw->irq, flags);
	if (raw->count > 0) {
		raw->flags |= RAW3215_FLUSHING;
		raw3215_try_io(raw);
		raw->flags &= ~RAW3215_FLUSHING;
	}
	s390irq_spin_unlock_irqrestore(raw->irq, flags);
}
示例#6
0
/*
 * Try to start the next IO and wake up processes waiting on the tty.
 */
static void raw3215_next_io(struct raw3215_info *raw)
{
	struct tty_struct *tty;

	raw3215_mk_write_req(raw);
	raw3215_try_io(raw);
	tty = raw->tty;
	if (tty != NULL &&
	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
	    	tty_wakeup(tty);
	}
}
示例#7
0
/*
 * Flush routine, it simply sets the flush flag and tries to start
 * pending IO.
 */
static void raw3215_flush_buffer(struct raw3215_info *raw)
{
	unsigned long flags;

	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
	if (raw->count > 0) {
		raw->flags |= RAW3215_FLUSHING;
		raw3215_try_io(raw);
		raw->flags &= ~RAW3215_FLUSHING;
	}
	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
}
/*
 * Enable writing to a 3215 tty
 */
static void tty3215_start(struct tty_struct *tty)
{
	raw3215_info *raw;
	unsigned long flags;

	raw = (raw3215_info *) tty->driver_data;
	if (raw->flags & RAW3215_STOPPED) {
		s390irq_spin_lock_irqsave(raw->irq, flags);
		raw->flags &= ~RAW3215_STOPPED;
		raw3215_try_io(raw);
		s390irq_spin_unlock_irqrestore(raw->irq, flags);
	}
}
示例#9
0
/*
 * Enable writing to a 3215 tty
 */
static void tty3215_start(struct tty_struct *tty)
{
	struct raw3215_info *raw;
	unsigned long flags;

	raw = (struct raw3215_info *) tty->driver_data;
	if (raw->flags & RAW3215_STOPPED) {
		spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
		raw->flags &= ~RAW3215_STOPPED;
		raw3215_try_io(raw);
		spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
	}
}
示例#10
0
/*
 * Fire up a 3215 device.
 */
static int raw3215_startup(struct raw3215_info *raw)
{
	unsigned long flags;

	if (raw->port.flags & ASYNC_INITIALIZED)
		return 0;
	raw->line_pos = 0;
	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);

	return 0;
}
示例#11
0
文件: con3215.c 项目: 513855417/linux
/*
 * Fire up a 3215 device.
 */
static int raw3215_startup(struct raw3215_info *raw)
{
	unsigned long flags;

	if (tty_port_initialized(&raw->port))
		return 0;
	raw->line_pos = 0;
	tty_port_set_initialized(&raw->port, 1);
	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
	raw3215_try_io(raw);
	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);

	return 0;
}
示例#12
0
/*
 * Enable reading from a 3215 tty
 */
static void
tty3215_unthrottle(struct tty_struct * tty)
{
	struct raw3215_info *raw;
	unsigned long flags;

	raw = (struct raw3215_info *) tty->driver_data;
	if (raw->flags & RAW3215_THROTTLED) {
		spin_lock_irqsave(raw->lock, flags);
		raw->flags &= ~RAW3215_THROTTLED;
		raw3215_try_io(raw);
		spin_unlock_irqrestore(raw->lock, flags);
	}
}
示例#13
0
/*
 * Fire up a 3215 device.
 */
static int raw3215_startup(struct raw3215_info *raw)
{
	unsigned long flags;

	if (raw->flags & RAW3215_ACTIVE)
		return 0;
	raw->line_pos = 0;
	raw->flags |= RAW3215_ACTIVE;
	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
	raw3215_try_io(raw);
	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);

	return 0;
}
示例#14
0
static int raw3215_pm_start(struct ccw_device *cdev)
{
	struct raw3215_info *raw;
	unsigned long flags;

	/* Allow I/O again and flush output buffer. */
	raw = dev_get_drvdata(&cdev->dev);
	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
	raw->port.flags &= ~ASYNC_SUSPENDED;
	raw->flags |= RAW3215_FLUSHING;
	raw3215_try_io(raw);
	raw->flags &= ~RAW3215_FLUSHING;
	spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
	return 0;
}
/*
 * Fire up a 3215 device.
 */
static int raw3215_startup(raw3215_info *raw)
{
	unsigned long flags;

	if (raw->flags & RAW3215_ACTIVE)
		return 0;
	if (request_irq(raw->irq, raw3215_irq, SA_INTERRUPT,
			"3215 terminal driver", &raw->devstat) != 0)
		return -1;
	raw->line_pos = 0;
	raw->flags |= RAW3215_ACTIVE;
	s390irq_spin_lock_irqsave(raw->irq, flags);
        set_cons_dev(raw->irq);
	raw3215_try_io(raw);
	s390irq_spin_unlock_irqrestore(raw->irq, flags);

	return 0;	
}
示例#16
0
/*
 * Wait until length bytes are available int the output buffer.
 * Has to be called with the s390irq lock held. Can be called
 * disabled.
 */
static void
raw3215_make_room(struct raw3215_info *raw, unsigned int length)
{
	while (RAW3215_BUFFER_SIZE - raw->count < length) {
		/* there might be a request pending */
		raw->flags |= RAW3215_FLUSHING;
		raw3215_mk_write_req(raw);
		raw3215_try_io(raw);
		raw->flags &= ~RAW3215_FLUSHING;
#ifdef CONFIG_TN3215_CONSOLE
		wait_cons_dev();
#endif
		/* Enough room freed up ? */
		if (RAW3215_BUFFER_SIZE - raw->count >= length)
			break;
		/* there might be another cpu waiting for the lock */
		spin_unlock(raw->lock);
		udelay(100);
		spin_lock(raw->lock);
	}
}
/*
 * Wait until length bytes are available int the output buffer.
 * Has to be called with the s390irq lock held. Can be called
 * disabled.
 */
void raw3215_make_room(raw3215_info *raw, unsigned int length)
{
	while (RAW3215_BUFFER_SIZE - raw->count < length) {
		/* there might be a request pending */
		raw->flags |= RAW3215_FLUSHING;
		raw3215_mk_write_req(raw);
		raw3215_try_io(raw);
		raw->flags &= ~RAW3215_FLUSHING;
		if (wait_cons_dev(raw->irq) != 0) {
			/* that shouldn't happen */
			raw->count = 0;
			raw->written = 0;
		}
		/* Enough room freed up ? */
		if (RAW3215_BUFFER_SIZE - raw->count >= length)
			break;
		/* there might be another cpu waiting for the lock */
		s390irq_spin_unlock(raw->irq);
		udelay(100);
		s390irq_spin_lock(raw->irq);
	}
}
示例#18
0
/*
 * The bottom half handler routine for 3215 devices. It tries to start
 * the next IO and wakes up processes waiting on the tty.
 */
static void
raw3215_tasklet(void *data)
{
	struct raw3215_info *raw;
	struct tty_struct *tty;
	unsigned long flags;

	raw = (struct raw3215_info *) data;
	spin_lock_irqsave(raw->lock, flags);
	raw3215_mk_write_req(raw);
	raw3215_try_io(raw);
	spin_unlock_irqrestore(raw->lock, flags);
	/* Check for pending message from raw3215_irq */
	if (raw->message != NULL) {
		printk(raw->message, raw->msg_dstat, raw->msg_cstat);
		raw->message = NULL;
	}
	tty = raw->tty;
	if (tty != NULL &&
	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
	    	tty_wakeup(tty);
	}
}
示例#19
0
/*
 * String write routine for 3215 devices
 */
static void raw3215_write(struct raw3215_info *raw, const char *str,
			  unsigned int length)
{
	unsigned long flags;
	int c, count;

	while (length > 0) {
		spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
		count = (length > RAW3215_BUFFER_SIZE) ?
					     RAW3215_BUFFER_SIZE : length;
		length -= count;

		raw3215_make_room(raw, count);

		/* copy string to output buffer and convert it to EBCDIC */
		while (1) {
			c = min_t(int, count,
				  min(RAW3215_BUFFER_SIZE - raw->count,
				      RAW3215_BUFFER_SIZE - raw->head));
			if (c <= 0)
				break;
			memcpy(raw->buffer + raw->head, str, c);
			ASCEBC(raw->buffer + raw->head, c);
			raw->head = (raw->head + c) & (RAW3215_BUFFER_SIZE - 1);
			raw->count += c;
			raw->line_pos += c;
			str += c;
			count -= c;
		}
		if (!(raw->flags & RAW3215_WORKING)) {
			raw3215_mk_write_req(raw);
			/* start or queue request */
			raw3215_try_io(raw);
		}
		spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
	}
}
/*
 * String write routine for 3215 devices
 */
static int
raw3215_write(raw3215_info *raw, const char *str,
	      int from_user, unsigned int length)
{
	unsigned long flags;
	int ret, c;
	int count;
	
	ret = 0;
	while (length > 0) {
		s390irq_spin_lock_irqsave(raw->irq, flags);
		count = (length > RAW3215_BUFFER_SIZE) ?
					     RAW3215_BUFFER_SIZE : length;
		length -= count;

                raw3215_make_room(raw, count);

		/* copy string to output buffer and convert it to EBCDIC */
		if (from_user) {
			while (1) {
				c = MIN(count,
					MIN(RAW3215_BUFFER_SIZE - raw->count,
					    RAW3215_BUFFER_SIZE - raw->head));
				if (c <= 0)
					break;
				c -= copy_from_user(raw->buffer + raw->head,
						    str, c);
				if (c == 0) {
					if (!ret)
						ret = -EFAULT;
					break;
				}
				ASCEBC(raw->buffer + raw->head, c);
				raw->head = (raw->head + c) &
					    (RAW3215_BUFFER_SIZE - 1);
				raw->count += c;
				raw->line_pos += c;
				str += c;
				count -= c;
				ret += c;
			}
		} else {
			while (1) {
				c = MIN(count,
					MIN(RAW3215_BUFFER_SIZE - raw->count,
					    RAW3215_BUFFER_SIZE - raw->head));
				if (c <= 0)
					break;
				memcpy(raw->buffer + raw->head, str, c);
				ASCEBC(raw->buffer + raw->head, c);
				raw->head = (raw->head + c) &
					    (RAW3215_BUFFER_SIZE - 1);
				raw->count += c;
				raw->line_pos += c;
				str += c;
				count -= c;
				ret += c;
			}
		}
                if (!(raw->flags & RAW3215_WORKING)) {
                        raw3215_mk_write_req(raw);
		        /* start or queue request */
		        raw3215_try_io(raw);
                }
		s390irq_spin_unlock_irqrestore(raw->irq, flags);
	}

	return ret;
}