static int
vcons_write(NkPort*	     	   port,
            const u_char*      buf,
            int                count)
{
    int				res;
    unsigned long		flags;

    spin_lock_irqsave(&port->lock, flags);
    res = os_ctx->cops.write(port->id, buf, count);
    if (vcons_write_room(port) > 0) {
        if (port->tty)
            tty_wakeup(port->tty);
    }
    spin_unlock_irqrestore(&port->lock, flags);

    return res;
}
Пример #2
0
static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
{
	struct tty_struct *to = tty->link;

	if (tty->stopped)
		return 0;

	if (c > 0) {
		/* Stuff the data into the input queue of the other end */
		c = tty_insert_flip_string(to, buf, c);
		/* And shovel */
		if (c) {
			tty_flip_buffer_push(to);
			tty_wakeup(tty);
		}
	}
	return c;
}
Пример #3
0
/**
 * gs_start_io - start USB I/O streams
 * @dev: encapsulates endpoints to use
 * Context: holding port_lock; port_tty and port_usb are non-null
 *
 * We only start I/O when something is connected to both sides of
 * this port.  If nothing is listening on the host side, we may
 * be pointlessly filling up our TX buffers and FIFO.
 */
static int gs_start_io(struct gs_port *port)
{
    struct list_head	*head = &port->read_pool;
    struct usb_ep		*ep = port->port_usb->out;
    int			status;
    unsigned		started;

    /* Allocate RX and TX I/O buffers.  We can't easily do this much
     * earlier (with GFP_KERNEL) because the requests are coupled to
     * endpoints, as are the packet sizes we'll be using.  Different
     * configurations may use different endpoints with a given port;
     * and high speed vs full speed changes packet sizes too.
     */
    status = gs_alloc_requests(ep, head, RX_QUEUE_SIZE, RX_BUF_SIZE,
                               gs_read_complete, &port->read_allocated);
    if (status)
        return status;

    status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
                               TX_QUEUE_SIZE, TX_BUF_SIZE, gs_write_complete, &port->write_allocated);
    if (status) {
        gs_free_requests(ep, head, &port->read_allocated);
        return status;
    }

    /* queue read requests */
    port->n_read = 0;
    started = gs_start_rx(port);

    if (!port->port_usb)
        return -EIO;
    /* unblock any pending writes into our circular buffer */
    if (started) {
        if(port->port_tty)
            tty_wakeup(port->port_tty);
    } else {
        gs_free_requests(ep, head, &port->read_allocated);
        gs_free_requests(port->port_usb->in, &port->write_pool,
                         &port->write_allocated);
        status = -EIO;
    }

    return status;
}
Пример #4
0
static void smd_tty_read(unsigned long param)
{
	unsigned char *ptr;
	int avail;
	struct smd_tty_info *info = (struct smd_tty_info *)param;
	struct tty_struct *tty = info->tty;

	if (!tty)
		return;

	for (;;) {
		if (is_in_reset(info)) {
			
			tty_insert_flip_char(tty, 0x00, TTY_BREAK);
			tty_flip_buffer_push(tty);
			break;
		}

		if (test_bit(TTY_THROTTLED, &tty->flags)) break;
		avail = smd_read_avail(info->ch);
		if (avail == 0)
			break;

		if (avail > MAX_TTY_BUF_SIZE)
			avail = MAX_TTY_BUF_SIZE;

		avail = tty_prepare_flip_string(tty, &ptr, avail);
		if (avail <= 0) {
			mod_timer(&info->buf_req_timer,
					jiffies + msecs_to_jiffies(30));
			return;
		}

		if (smd_read(info->ch, ptr, avail) != avail) {
			printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!");
		}

		wake_lock_timeout(&info->wake_lock, HZ / 2);
		tty_flip_buffer_push(tty);
	}

	
	tty_wakeup(tty);
}
Пример #5
0
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 ();
}
Пример #6
0
/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
static void hvsi_write_worker(struct work_struct *work)
{
	struct hvsi_struct *hp =
		container_of(work, struct hvsi_struct, writer.work);
	unsigned long flags;
#ifdef DEBUG
	static long start_j = 0;

	if (start_j == 0)
		start_j = jiffies;
#endif /* DEBUG */

	spin_lock_irqsave(&hp->lock, flags);

	pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);

	if (!is_open(hp)) {
		/*
		 * We could have a non-open connection if the service processor died
		 * while we were busily scheduling ourselves. In that case, it could
		 * be minutes before the service processor comes back, so only try
		 * again once a second.
		 */
		schedule_delayed_work(&hp->writer, HZ);
		goto out;
	}

	hvsi_push(hp);
	if (hp->n_outbuf > 0)
		schedule_delayed_work(&hp->writer, 10);
	else {
#ifdef DEBUG
		pr_debug("%s: outbuf emptied after %li jiffies\n", __func__,
				jiffies - start_j);
		start_j = 0;
#endif /* DEBUG */
		wake_up_all(&hp->emptyq);
		tty_wakeup(hp->tty);
	}

out:
	spin_unlock_irqrestore(&hp->lock, flags);
}
Пример #7
0
void gs_do_softint(void *private_)
{
	struct gs_port *port = private_;
	struct tty_struct *tty;

	func_enter ();

	if (!port) return;

	tty = port->tty;

	if (!tty) return;

	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
		tty_wakeup(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	func_exit ();
}
Пример #8
0
static void change_pins(struct nullmodem_end *end, unsigned int set, unsigned int clear)
{
	int is_end_b = (end == &end->pair->b);
	int old_pins = end->pair->control_lines;
	if (is_end_b)
		old_pins = switch_pin_view(old_pins);

	int new_pins = (old_pins & ~clear) | set;
	int change = old_pins ^ new_pins;

	if (is_end_b)
		new_pins = switch_pin_view(new_pins);

	end->pair->control_lines = new_pins;

	if (change & TIOCM_RTS)
	{
		end->other->icount.cts++;
	}
	if (change & TIOCM_DTR)
	{
		end->other->icount.dsr++;
		end->other->icount.dcd++;
	}

	if (end->other->tty
	&& (end->other->tty->termios.c_cflag & CRTSCTS)
	&& (change&TIOCM_RTS))
	{
		if (!(new_pins&TIOCM_RTS))
			end->other->tty->hw_stopped = 1;
		else
		{
			end->other->tty->hw_stopped = 0;
			tty_wakeup(end->other->tty);
		}
	}

	if (change)
		wake_up_interruptible(&end->pair->control_lines_wait);
}
Пример #9
0
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;
}
Пример #10
0
static void uart_flush_buffer(struct tty_struct *tty)
{
	struct uart_state *state = tty->driver_data;
	struct uart_port *port;
	unsigned long flags;

	if (!state) {
		WARN_ON(1);
		return;
	}

	port = state->uart_port;
	pr_debug("uart_flush_buffer(%d) called\n", tty->index);

	spin_lock_irqsave(&port->lock, flags);
	uart_circ_clear(&state->xmit);
	if (port->ops->flush_buffer)
		port->ops->flush_buffer(port);
	spin_unlock_irqrestore(&port->lock, flags);
	tty_wakeup(tty);
}
Пример #11
0
static void qt_write_bulk_callback(struct urb *urb)
{
	struct tty_struct *tty;
	int status;
	struct quatech_port *quatech_port;

	status = urb->status;

	if (status) {
		dev_dbg(&urb->dev->dev,
			"nonzero write bulk status received:%d\n", status);
		return;
	}

	quatech_port = urb->context;

	tty = tty_port_tty_get(&quatech_port->port->port);

	if (tty)
		tty_wakeup(tty);
	tty_kref_put(tty);
}
Пример #12
0
void gs_flush_buffer(struct tty_struct *tty)
{
	struct gs_port *port;
	unsigned long flags;

	func_enter ();

	if (!tty) return;

	port = tty->driver_data;

	if (!port) return;

	/* XXX Would the write semaphore do? */
	save_flags(flags); cli();
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	restore_flags(flags);

	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	func_exit ();
}
Пример #13
0
static void transmit_chars(struct serial_state *info)
{
	custom.intreq = IF_TBE;
	mb();
	if (info->x_char) {
	        custom.serdat = info->x_char | 0x100;
		mb();
		info->icount.tx++;
		info->x_char = 0;
		return;
	}
	if (info->xmit.head == info->xmit.tail
	    || info->tport.tty->stopped
	    || info->tport.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->icount.tx++;

	if (CIRC_CNT(info->xmit.head,
		     info->xmit.tail,
		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
		tty_wakeup(info->tport.tty);

#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
cons_timeout (unsigned long data)
{
    struct tty_struct*	tty  = (struct tty_struct*)data;
    NkPort*          	port = NKPORT(tty);
    unsigned long	flags;

    if (port->count == 0) {
        return;
    }

    cons_flush_input(port);

    spin_lock_irqsave(&port->lock, flags);
    if (port->sz) {
        cons_flush_chars(port);
        tty_wakeup(port->tty);
    }
    spin_unlock_irqrestore(&port->lock, flags);

    port->timer.expires = jiffies + SERIAL_NK_TIMEOUT;
    add_timer(&(port->timer));
}
Пример #15
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);
	}
}
Пример #16
0
static int gs_start_io(struct gs_port *port)
{
	struct list_head	*head = &port->read_pool;
	struct usb_ep		*ep = port->port_usb->out;
	int			status;
	unsigned		started;

	status = gs_alloc_requests(ep, head, RX_QUEUE_SIZE, RX_BUF_SIZE,
			 gs_read_complete, &port->read_allocated);
	if (status)
		return status;

	status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
			TX_QUEUE_SIZE, TX_BUF_SIZE, gs_write_complete, &port->write_allocated);
	if (status) {
		gs_free_requests(ep, head, &port->read_allocated);
		return status;
	}

	
	port->n_read = 0;
	started = gs_start_rx(port);

	if (!port->port_usb)
		return -EIO;
	
	if (started) {
		tty_wakeup(port->port_tty);
	} else {
		gs_free_requests(ep, head, &port->read_allocated);
		gs_free_requests(port->port_usb->in, &port->write_pool,
			&port->write_allocated);
		status = -EIO;
	}

	return status;
}
Пример #17
0
static void smd_tty_read(unsigned long param)
{
	unsigned char *ptr;
	int avail;
	struct smd_tty_info *info = (struct smd_tty_info *)param;
	struct tty_struct *tty = info->tty;

	if (!tty)
		return;

	for (;;) {
		if (test_bit(TTY_THROTTLED, &tty->flags)) break;
		avail = smd_read_avail(info->ch);
		if (avail == 0)
			break;

		if (avail > MAX_TTY_BUF_SIZE)
             avail = MAX_TTY_BUF_SIZE;

		avail = tty_prepare_flip_string(tty, &ptr, avail);

		if (smd_read(info->ch, ptr, avail) != avail) {
			/* shouldn't be possible since we're in interrupt
			** context here and nobody else could 'steal' our
			** characters.
			*/
			printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!");
		}

		wake_lock_timeout(&info->wake_lock, HZ / 2);
		tty_flip_buffer_push(tty);
	}

	/* XXX only when writable and necessary */
	tty_wakeup(tty);
}
Пример #18
0
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;

	for (;count > 0;count--, port++) {
		/* port not active or tx disabled to force flow control */
		if (!(port->flags & ASYNC_INITIALIZED) ||
				!(port->status & ISI_TXOK))
			continue;

		tty = port->tty;

		if (tty == NULL)
			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_dbg("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->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->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->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);
	}

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));
}
Пример #19
0
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int gs_start_tx(struct gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool = &port->write_pool;
	struct usb_ep		*in = port->port_usb->in;
	int			status = 0;
	bool			do_tty_wake = false;

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, in->maxpacket);

#if ACM_ZLP
		if (len == 0) {
			//printk("[%s] len == 0 ;\n", __func__);
			if (s3c_need_zlp == 0) {
				req->zero = 0;
				wake_up_interruptible(&port->drain_wait);
				break;
			} else {
				//printk("[%s] zlp: => req.zero = true ;\n", __func__);
				req->zero = 1;
				s3c_need_zlp = 0;
				s3c_multiple = 0;
			}
		}
#else
		if (len == 0) {
			wake_up_interruptible(&port->drain_wait);
			break;
		}
#endif
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}

		/* abort immediately after disconnect */
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port_tty)
		tty_wakeup(port->port_tty);
	return status;
}
Пример #20
0
static int gs_start_tx(struct gs_port *port)

{
	struct list_head	*pool = &port->write_pool;
	struct usb_ep		*in = port->port_usb->in;
	int			status = 0;
	static long 		prev_len;
	bool			do_tty_wake = false;

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, TX_BUF_SIZE);
		if (len == 0) {
			
			if (prev_len & (prev_len % in->maxpacket == 0)) {
				req->length = 0;
				list_del(&req->list);

				spin_unlock(&port->port_lock);
				status = usb_ep_queue(in, req, GFP_ATOMIC);
				spin_lock(&port->port_lock);
				if (status) {
					printk(KERN_ERR "%s: %s err %d\n",
					__func__, "queue", status);
					list_add(&req->list, pool);
				}
				prev_len = 0;
			}
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}
		prev_len = req->length;

		
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port_tty)
		tty_wakeup(port->port_tty);
	return status;
}
Пример #21
0
static void check_modem_status(struct serial_state *info)
{
	struct tty_port *port = &info->tport;
	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->icount;
		/* update input line counters */
		if (dstatus & SER_DSR)
			icount->dsr++;
		if (dstatus & SER_DCD) {
			icount->dcd++;
#ifdef CONFIG_HARD_PPS
			if ((port->flags & ASYNC_HARDPPS_CD) &&
			    !(status & SER_DCD))
				hardpps();
#endif
		}
		if (dstatus & SER_CTS)
			icount->cts++;
		wake_up_interruptible(&port->delta_msr_wait);
	}

	if ((port->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(&port->open_wait);
		else {
#ifdef SERIAL_DEBUG_OPEN
			printk("doing serial hangup...");
#endif
			if (port->tty)
				tty_hangup(port->tty);
		}
	}
	if (port->flags & ASYNC_CTS_FLOW) {
		if (port->tty->hw_stopped) {
			if (!(status & SER_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
				printk("CTS tx start...");
#endif
				port->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();
				tty_wakeup(port->tty);
				return;
			}
		} else {
			if ((status & SER_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
				printk("CTS tx stop...");
#endif
				port->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();
			}
		}
	}
}
Пример #22
0
void uart_write_wakeup(struct uart_port *port)
{
	struct uart_state *state = port->state;
	BUG_ON(!state);
	tty_wakeup(state->port.tty);
}
Пример #23
0
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
Пример #24
0
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int gs_start_tx(struct gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool = &port->write_pool;
	//struct usb_ep		*in = port->port_usb->in;
	struct usb_ep		*in;
	int			status = 0;
	bool			do_tty_wake = false;

	if (!port->port_usb) /* abort immediately after disconnect */
        return -EINVAL;
    in = port->port_usb->in;

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		if (port->write_started >= QUEUE_SIZE)
			break;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, in->maxpacket);
		if (len == 0) {
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);
		req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		USB_LOGGER(GS_START_TX, GS_START_TX, port->port_num, len);

		#define OUTPUT_BTYE_NUM 5
		{
			int i,j = 0;
			char* prefix[] = {"p1","p2","p3","p4","p5"};
			char* suffix[] = {"s1","s2","s3","s4","s5"};
			for (i = 0; i < req->actual && i < OUTPUT_BTYE_NUM; i++)
				USB_LOGGER(HEX_NUM, GS_START_TX, prefix[i], *((u8 *)req->buf+i));

			if (req->actual >= OUTPUT_BTYE_NUM*2) {
				for(i = req->actual-1, j = 1; i >= (req->actual - OUTPUT_BTYE_NUM) \
					&& i >= OUTPUT_BTYE_NUM; i--,j++) {
					USB_LOGGER(HEX_NUM, GS_START_TX, suffix[OUTPUT_BTYE_NUM-j], \
							*((u8 *)req->buf+i));
				}
			}
		}

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}

		port->write_started++;

		/* abort immediately after disconnect */
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port_tty)
		tty_wakeup(port->port_tty);
	return status;
}
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int pxa910_gs_start_tx(struct pxa910_gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool;
	struct usb_ep		*in;
	int			status = 0;
	bool			do_tty_wake = false;

	if (NULL == port)
		return 0;

	pool = &port->write_pool;
	in = port->port_usb->in;

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		if (port->write_started >= QUEUE_SIZE)
			break;

		req = list_entry(pool->next, struct usb_request, list);
		len = pxa910_gs_send_packet(port, req->buf, in->maxpacket);
		if (len == 0) {
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);
		req->zero =
			(pxa910_gs_buf_data_avail(&port->port_write_buf) == 0);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}

		port->write_started++;

		/* abort immediately after disconnect */
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port_usb)
		wake_up_interruptible(&port->port_usb->port_send);

	if (do_tty_wake && port->port_tty)
		tty_wakeup(port->port_tty);
	return status;
}
Пример #26
0
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int gs_start_tx(struct gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool = &port->write_pool;
	struct usb_ep		*in = port->port_usb->in;
	int			status = 0;
	bool			do_tty_wake = false;
	static unsigned int	skip = 0;
	static DEFINE_RATELIMIT_STATE(ratelimit, 1 * HZ, 10);

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		if (port->write_started >= QUEUE_SIZE)
			break;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, REQ_BUF_SIZE);
		if (len == 0) {
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);
		req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		if (__ratelimit(&ratelimit)) {
			printk( ACM_LOG \
				"%s: ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n", \
				__func__, port->port_num, len, *((u8 *)req->buf), \
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));
			if (skip > 0) {
				printk( ACM_LOG "%s Too many data, skipped %d bytes", __func__, skip);
				skip = 0;
			}
		} else
			skip += req->actual;

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}

		port->write_started++;

		/* abort immediately after disconnect */
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port.tty)
		tty_wakeup(port->port.tty);
	return status;
}
Пример #27
0
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int gs_start_tx(struct gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool = &port->write_pool;
	struct usb_ep		*in = port->port_usb->in;
	int			status = 0;
	static long 		prev_len;
	bool			do_tty_wake = false;

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		if (port->write_started >= TX_QUEUE_SIZE)
			break;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, TX_BUF_SIZE);
		if (len == 0) {
			/* Queue zero length packet explicitly to make it
			 * work with UDCs which don't support req->zero flag
			 */
			if (prev_len && (prev_len % in->maxpacket == 0)) {
				req->length = 0;
				list_del(&req->list);
				spin_unlock(&port->port_lock);
				status = usb_ep_queue(in, req, GFP_ATOMIC);
				spin_lock(&port->port_lock);
				if (!port->port_usb) {
					gs_free_req(in, req);
					break;
				}
				if (status) {
					printk(KERN_ERR "%s: %s err %d\n",
					__func__, "queue", status);
					list_add(&req->list, pool);
				}
				prev_len = 0;
			}
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);
		/*
		 * If port_usb is NULL, gserial disconnect is called
		 * while the spinlock is dropped and all requests are
		 * freed. Free the current request here.
		 */
		if (!port->port_usb) {
			do_tty_wake = false;
			gs_free_req(in, req);
			break;
		}
		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}
		prev_len = req->length;
		port->nbytes_from_tty += req->length;

		port->write_started++;

	}

	if (do_tty_wake && port->port_tty)
		tty_wakeup(port->port_tty);
	return status;
}
Пример #28
0
int atcmd_write_toatd(struct gdata_port *port, struct sk_buff *skb)
{
    struct tty_struct *tty;
    unsigned char *ptr;
    int avail;
    char *cmd;
    int i;

    pr_debug("%s\n", __func__);

    tty = port->tty;
    if (!tty)
        return -ENODEV;

    avail = skb->len;
    if (avail == 0)
        return -EINVAL;

    ptr = skb->data + avail - 1;
    if (strncasecmp(skb->data, "AT", 2) ||
        !(*ptr == '\r' || *ptr == '\n' || *ptr == '\0')) {
        return -EINVAL;
    }

    cmd = kstrdup(skb->data + 2, GFP_ATOMIC);
    if (!cmd) {
        pr_debug("%s: ENOMEM\n", __func__);
        return -ENOMEM;
    }
    if ((ptr = strchr(cmd, '=')) ||
        (ptr = strchr(cmd, '?')) ||
        (ptr = strchr(cmd, '\r')) ) {
        *ptr = '\0';
    }

    if (*cmd != '\0') {
        for (i = 0; at_table[i] != NULL; i++) {
            if (!strcasecmp(cmd, at_table[i])) {
                kfree(cmd);

                if (!test_bit(CH_OPENED, &port->bridge_sts)) {
                    /* signal TTY clients using TTY_BREAK */
                    tty_insert_flip_char(tty, 0x00, TTY_BREAK);
                    tty_flip_buffer_push(tty);
                    break;
                } else {
                    avail = tty_prepare_flip_string(tty, &ptr, avail);
                    if (avail <= 0) {
                        return -EBUSY;
                    }

#ifdef VERBOSE_DEBUG
                    print_hex_dump(KERN_DEBUG, "toatd:", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, 1);
#endif

                    memcpy(ptr, skb->data, avail);
                    dev_kfree_skb_any(skb);

                    tty_flip_buffer_push(tty);
                }

                /* XXX only when writable and necessary */
                tty_wakeup(tty);

                return 0;
            }
        }
    }

    kfree(cmd);
    return -ENOENT;
}
Пример #29
0
/*
 * The unthrottle routine is called by the line discipline to signal
 * that it can receive more characters.  For PTY's, the TTY_THROTTLED
 * flag is always set, to force the line discipline to always call the
 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
 * characters in the queue.  This is necessary since each time this
 * happens, we need to wake up any sleeping processes that could be
 * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
 * for the pty buffer to be drained.
 */
static void pty_unthrottle(struct tty_struct *tty)
{
	tty_wakeup(tty->link);
	set_bit(TTY_THROTTLED, &tty->flags);
}
Пример #30
0
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int gs_start_tx(struct gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool = &port->write_pool;
	struct usb_ep		*in;
	int			status = 0;
	static long 		prev_len;
	bool			do_tty_wake = false;

	if ( port->port_usb )
		in = port->port_usb->in;
	else
		return status; //nikantonelli 20110615: Assumes it is set to zero in declaration above

	while (!list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, in->maxpacket);
		if (len == 0) {
			/* Queue zero length packet */
			if (prev_len == in->maxpacket) {
				req->length = 0;
				list_del(&req->list);

				spin_unlock(&port->port_lock);
				status = usb_ep_queue(in, req, GFP_ATOMIC);
				spin_lock(&port->port_lock);
				if (status) {
					printk(KERN_ERR "%s: %s err %d\n",
					__func__, "queue", status);
					list_add(&req->list, pool);
				}
				prev_len = 0;
			}
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);

		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
				port->port_num, len, *((u8 *)req->buf),
				*((u8 *)req->buf+1), *((u8 *)req->buf+2));

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}
		prev_len = req->length;

		/* abort immediately after disconnect */
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port_tty)
		tty_wakeup(port->port_tty);
	return status;
}