static _INLINE_ void transmit_chars(struct NIOS_serial *info)
{
	np_uart *	uart= (np_uart *)(info->port);
	if (info->x_char) {
		/* Send next char */
		uart->np_uarttxdata = info->x_char;
		info->x_char = 0;
		goto clear_and_return;
	}

	if((info->xmit_cnt <= 0) || info->tty->stopped) {
		/* That's peculiar... TX ints off */
		uart->np_uartcontrol &= ~np_uartcontrol_itrdy_mask;
		goto clear_and_return;
	}

	/* Send char */
	uart->np_uarttxdata = info->xmit_buf[info->xmit_tail++];
	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
	info->xmit_cnt--;

	if (info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

	if(info->xmit_cnt <= 0) {
		/* All done for now... TX ints off */
		uart->np_uartcontrol &= ~np_uartcontrol_itrdy_mask;
		goto clear_and_return;
	}

clear_and_return:
	/* Clear interrupt (should be auto)*/
	return;
}
static _INLINE_ void transmit_chars(struct bf535_serial *info)
{
	int idx = info->hub2;

	if (info->x_char) { /* Send next char */
		local_put_char(idx, info->x_char);
		info->x_char = 0;
		goto clear_and_return;
	}

	if((info->xmit_cnt <= 0) || info->tty->stopped) { /* TX ints off */
		ACCESS_PORT_IER(idx) /* Change access to IER & data port */
		UART_IER(idx) &= ~UART_IER_ETBEI;
		goto clear_and_return;
	}

	/* Send char */
	local_put_char(idx,info->xmit_buf[info->xmit_tail++]);
	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
	info->xmit_cnt--;

	if (info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

	if(info->xmit_cnt <= 0) { /* All done for now... TX ints off */
		ACCESS_PORT_IER(idx) /* Change access to IER & data port */
		UART_IER(idx) &= ~UART_IER_ETBEI;
		goto clear_and_return;
	}

clear_and_return:
	/* Clear interrupt (should be auto)*/
	return;
}
예제 #3
0
static _INLINE_ void transmit_chars(struct m68k_serial *info)
{
    m68328_uart *uart = &uart_addr[info->line];

    if (info->x_char) {
        /* Send next char */
        uart->utx.b.txdata = info->x_char;
        info->x_char = 0;
        goto clear_and_return;
    }

    if((info->xmit_cnt <= 0) || info->tty->stopped) {
        /* That's peculiar... TX ints off */
        uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
        goto clear_and_return;
    }

    /* Send char */
    uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++];
    info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
    info->xmit_cnt--;

    if (info->xmit_cnt < WAKEUP_CHARS)
        rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

    if(info->xmit_cnt <= 0) {
        /* All done for now... TX ints off */
        uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
        goto clear_and_return;
    }

clear_and_return:
    /* Clear interrupt (should be auto)*/
    return;
}
예제 #4
0
static _INLINE_ void transmit_chars(struct LEON_serial *info)
{
	if (info->x_char) {
		/* Send next char */
		leon->uartdata1 = info->x_char;
		info->x_char = 0;
		goto clear_and_return;
	}

	if((info->xmit_cnt <= 0) || info->tty->stopped) {
		/* That's peculiar... TX ints off */
		leon->uartctrl1 &= ~UCTRL_TI;
		goto clear_and_return;
	}

	/* Send char */
	leon->uartdata1 = info->xmit_buf[info->xmit_tail++];
	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
	info->xmit_cnt--;

	if (info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

	if(info->xmit_cnt <= 0) {
		/* All done for now... TX ints off */
		leon->uartctrl1 &= ~UCTRL_TI;
		goto clear_and_return;
	}

clear_and_return:
	/* Clear interrupt (should be auto)*/
	return;
}
예제 #5
0
static _INLINE_ void transmit_chars(struct sci_struct *sci)
{
	if (sci->info->x_char) {
		sci_outp(sci, SCI_TDR, sci->info->x_char);
		sci->info->x_char = 0;
		return;
	}
	if ((sci->info->xmit_cnt <= 0) || sci->info->tty->stopped) {
		sci_ctrl_reset(sci, SCI_SCR_TIE);
		return;
	}
	
	sci_outp(sci, SCI_TDR, sci->info->xmit_buf[sci->info->xmit_tail++]);
	sci->info->xmit_tail = sci->info->xmit_tail & (SERIAL_XMIT_SIZE-1);
	sci_outp(sci,SCI_SSR,sci_in(sci,SCI_SSR) & ~SCI_SSR_TDRE);
	sci->info->xmit_cnt--;
	if (sci->info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(sci, RS_EVENT_WRITE_WAKEUP);
#ifdef SERIAL_DEBUG_INTR
	printk("THRE...");
#endif
	if (sci->info->xmit_cnt <= 0) {
		sci_ctrl_reset(sci, SCI_SCR_TIE);
	}
}
static inline void transmit_chars(struct cnxt_serial *info)
{
  struct uart_regs *uart = info->uart;

	if (info->x_char) {
		/* Send next char */
	  //xmit_char(info->x_char);
		uart->fifo=info->x_char;		
		info->x_char = 0;
		goto clear_and_return;
	}

	if((info->xmit_cnt <= 0) || info->tty->stopped) {
		/* That's peculiar... */
		goto clear_and_return;
	}

	/* Send char */
	//xmit_char(info->xmit_buf[info->xmit_tail++]);
	info->uart->fifo=info->xmit_buf[info->xmit_tail++];
	
	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
	info->xmit_cnt--;

	if (info->xmit_cnt < 256)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

	if(info->xmit_cnt <= 0) {
		goto clear_and_return;
	}

clear_and_return:
	/* Clear interrupt (should be auto)*/
	return;
}
static void transmit_chars(struct async_struct *info)
{
	custom.intreq = IF_TBE;
	mb();
	if (info->x_char) {
	        custom.serdat = info->x_char | 0x100;
		mb();
		info->state->icount.tx++;
		info->x_char = 0;
		return;
	}
	if (info->xmit.head == info->xmit.tail
	    || info->tty->stopped
	    || info->tty->hw_stopped) {
		info->IER &= ~UART_IER_THRI;
	        custom.intena = IF_TBE;
		mb();
		return;
	}

	custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
	mb();
	info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
	info->state->icount.tx++;

	if (CIRC_CNT(info->xmit.head,
		     info->xmit.tail,
		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

#ifdef SERIAL_DEBUG_INTR
	printk("THRE...");
#endif
	if (info->xmit.head == info->xmit.tail) {
	        custom.intena = IF_TBE;
		mb();
		info->IER &= ~UART_IER_THRI;
	}
}
예제 #8
0
파일: serial.c 프로젝트: rohsaini/mkunity
static void serial_send_next_write(struct async_struct *info)
{
	int			line;
	mach_msg_type_number_t	data_count;
	kern_return_t		kr;

	line = MINOR(info->tty->device) - info->tty->driver.minor_start;

	data_count = SERIAL_XMIT_SIZE - info->xmit_tail;
	if (data_count > info->xmit_cnt)
		data_count = info->xmit_cnt;
	if (data_count > IO_INBAND_MAX)
		data_count = IO_INBAND_MAX;

	info->write_busy = TRUE;

	kr = serv_device_write_async(info->device_port,
			info->reply_port, 0,
			0, &info->xmit_buf[info->xmit_tail],
			data_count, TRUE);

	if (kr != D_SUCCESS) {
		if (info->tty != NULL) {
			MACH3_DEBUG(1, kr,
				    ("transmit_chars(dev 0x%x): "
				     "serv_device_write_async",
				     info->tty->device));
		}
		info->xmit_cnt = 0;
		info->write_busy = FALSE;
	}
	
	if (info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

#ifdef SERIAL_DEBUG_INTR
	printk("THRE...");
#endif
}
예제 #9
0
/*  
 *	This is the serial driver's generic interrupt routine
 */ 
static void rs_interruptTx(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned int count, status;
	struct s3c3410_serial *info = &s3c3410_info;

	if  (info->x_char) {
		outb(info->x_char, S3C3410X_UART_BASE+S3C3410X_UTXH_B);
		info->x_char = 0;
		return;
	}

	if  ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped ) {
		tx_stop();
		return;
	}

	for (count = TX_FIFO_DEPTH; count > 0; --count) {
		status = inb(S3C3410X_UART_BASE+S3C3410X_UFSTAT);
		if (status & UFSTAT_TFF) {
			handle_status (info, UFSTAT_TFF);
			break;
		} else {
			outb(info->xmit_buf[info->xmit_tail++], 
				S3C3410X_UART_BASE+S3C3410X_UTXH_B);
			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
			if (--info->xmit_cnt <= 0) 
				break;
		}
	}

	if (info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

	if (info->xmit_cnt <= 0)
		tx_stop();
	return;
}
예제 #10
0
	/* I need to do this for the SCCs, so it is left as a reminder.
	*/
static _INLINE_ void check_modem_status(struct async_struct *info)
{
	int	status;
	/* struct	async_icount *icount; */
	struct	async_icount_24 *icount;
	
	status = serial_in(info, UART_MSR);

	if (status & UART_MSR_ANY_DELTA) {
		icount = &info->state->icount;
		/* update input line counters */
		if (status & UART_MSR_TERI)
			icount->rng++;
		if (status & UART_MSR_DDSR)
			icount->dsr++;
		if (status & UART_MSR_DDCD) {
			icount->dcd++;
#ifdef CONFIG_HARD_PPS
			if ((info->flags & ASYNC_HARDPPS_CD) &&
			    (status & UART_MSR_DCD))
				hardpps();
#endif
		}
		if (status & UART_MSR_DCTS)
			icount->cts++;
		wake_up_interruptible(&info->delta_msr_wait);
	}

	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
		printk("ttys%d CD now %s...", info->line,
		       (status & UART_MSR_DCD) ? "on" : "off");
#endif		
		if (status & UART_MSR_DCD)
			wake_up_interruptible(&info->open_wait);
		else {
#ifdef SERIAL_DEBUG_OPEN
			printk("scheduling hangup...");
#endif
			queue_task(&info->tqueue_hangup,
					   &tq_scheduler);
		}
	}
	if (info->flags & ASYNC_CTS_FLOW) {
		if (info->port.tty->hw_stopped) {
			if (status & UART_MSR_CTS) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
				printk("CTS tx start...");
#endif
				info->port.tty->hw_stopped = 0;
				info->IER |= UART_IER_THRI;
				serial_out(info, UART_IER, info->IER);
				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
				return;
			}
		} else {
			if (!(status & UART_MSR_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
				printk("CTS tx stop...");
#endif
				info->port.tty->hw_stopped = 1;
				info->IER &= ~UART_IER_THRI;
				serial_out(info, UART_IER, info->IER);
			}
		}
	}
}
예제 #11
0
static void ser_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct async_struct *info = data;
u_char iir,lsr;
unsigned char ch;

/* Get value in IIR for future use */

	if ((iir=uart.IIR) & IRQ_PEND)	return;


/* If we got here, then there is an interrupt waiting for us to service */

	while (!(iir & IRQ_PEND))	/* loop until no more ints */
	{
		switch (iir & (IRQ_ID1 | IRQ_ID2 | IRQ_ID3))
		{
			case IRQ_RLS:		/* Receiver Line Status */
			case IRQ_CTI:		/* Character Timeout */
			case IRQ_RDA:		/* Received Data Available */
	/*
	 * Copy chars to the tty-queue ...
	 * Be careful that we aren't passing one of the
	 * Receiver Line Status interrupt-conditions without noticing.
	 */
			{
				int ch;

				lsr = uart.LSR;
				while (lsr & DR)
				{
					u_char err = 0;
					ch = uart.RBR;

					if (lsr & BI)      err = TTY_BREAK;
					else if (lsr & PE) err = TTY_PARITY;
					else if (lsr & OE) err = TTY_OVERRUN;
					else if (lsr & FE) err = TTY_FRAME;

					rs_receive_char(info, ch, err);
					lsr = uart.LSR;
				}
			}
			break;

			case IRQ_THRE:	/* Transmitter holding register empty */
			{
				int fifo_space = 16;

	/* If the uart is ready to receive data and there are chars in */
	/* the queue we transfer all we can to the uart's FIFO         */

				if (info->xmit_cnt <= 0    ||
				    info->tty->stopped     ||
				    info->tty->hw_stopped)
				{

		/* Disable transmitter empty interrupt */
					uart.IER &= ~(ETHREI);

		/* Need to send a char to acknowledge the interrupt */
					uart.THR = 0;
					break;
				}

		/* Handle software flow control */
				if (info->x_char)
				{
					uart.THR = info->x_char;
					info->x_char = 0;
					fifo_space--;
				}

		/* Fill the fifo */
				while (fifo_space > 0)
				{
					fifo_space--;
					uart.THR = info->xmit_buf[info->xmit_tail++];
					info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
					if (--info->xmit_cnt == 0) break;
				}

		/* Don't need THR interrupts any more */
				if (info->xmit_cnt == 0)
					uart.IER &= ~(ETHREI);

				if (info->xmit_cnt < WAKEUP_CHARS)
				    rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
			}
			break;

			case IRQ_MS: /* Must be modem status register interrupt? */
			{
				u_char msr = uart.MSR;

				if (info->flags & ASYNC_INITIALIZED)
				{
					if (msr & DCTS)
						rs_check_cts(info, (msr & CTS));	/* active high */
					if (msr & DDCD)
						rs_dcd_changed(info, !(msr & DCD));	/* active low */
				}
			}
			break;

		} /* switch (iir) */
		iir = uart.IIR;
	} /* while IRQ_PEND */

	ch=inb(GAYLE_IRQ_STATUS);
/*	printk("gayle: %02X - %02X (pre)\n",inb(GAYLE_IRQ_STATUS2),inb(GAYLE_IRQ_STATUS)); */
	outb(0xdc | (ch & 0x03),GAYLE_IRQ_STATUS);
/*	printk("gayle: %02X - %02X (post)\n",inb(GAYLE_IRQ_STATUS2), inb(GAYLE_IRQ_STATUS)); */
}
예제 #12
0
static void check_modem_status(struct async_struct *info)
{
	unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
	unsigned char dstatus;
	struct	async_icount *icount;

	/* Determine bits that have changed */
	dstatus = status ^ current_ctl_bits;
	current_ctl_bits = status;

	if (dstatus) {
		icount = &info->state->icount;
		/* update input line counters */
		if (dstatus & SER_DSR)
			icount->dsr++;
		if (dstatus & SER_DCD) {
			icount->dcd++;
#ifdef CONFIG_HARD_PPS
			if ((info->flags & ASYNC_HARDPPS_CD) &&
			    !(status & SER_DCD))
				hardpps();
#endif
		}
		if (dstatus & SER_CTS)
			icount->cts++;
		wake_up_interruptible(&info->delta_msr_wait);
	}

	if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
		printk("ttyS%d CD now %s...", info->line,
		       (!(status & SER_DCD)) ? "on" : "off");
#endif
		if (!(status & SER_DCD))
			wake_up_interruptible(&info->open_wait);
		else {
#ifdef SERIAL_DEBUG_OPEN
			printk("doing serial hangup...");
#endif
			if (info->tty)
				tty_hangup(info->tty);
		}
	}
	if (info->flags & ASYNC_CTS_FLOW) {
		if (info->tty->hw_stopped) {
			if (!(status & SER_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
				printk("CTS tx start...");
#endif
				info->tty->hw_stopped = 0;
				info->IER |= UART_IER_THRI;
				custom.intena = IF_SETCLR | IF_TBE;
				mb();
				/* set a pending Tx Interrupt, transmitter should restart now */
				custom.intreq = IF_SETCLR | IF_TBE;
				mb();
				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
				return;
			}
		} else {
			if ((status & SER_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
				printk("CTS tx stop...");
#endif
				info->tty->hw_stopped = 1;
				info->IER &= ~UART_IER_THRI;
				/* disable Tx interrupt and remove any pending interrupts */
				custom.intena = IF_TBE;
				mb();
				custom.intreq = IF_TBE;
				mb();
			}
		}
	}
}