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;
}
static void local_put_char(int hub2, char ch)
{
	int flags = 0;

	if (hub2 < 0 || hub2 > 1) {
		printk("Error: Invalid serial port requested.\n");
		return; /* validate port op(UART 0|1) */
	}

	save_flags(flags); cli();

	while (!(UART_LSR(hub2) & UART_LSR_THRE)) {
		SYNC_ALL;
	}

	ACCESS_PORT_IER(hub2)
	UART_THR(hub2) = ch;
	SYNC_ALL;

	while (UART_LSR(hub2) & UART_LSR_THRE) {
		udelay(5);
	}

	restore_flags(flags);
}
/*
 * ------------------------------------------------------------
 * rs_stop() and rs_start()
 *
 * This routines are called before setting or resetting tty->stopped.
 * They enable or disable transmitter interrupts, as necessary.
 * ------------------------------------------------------------
 */
static void rs_stop(struct tty_struct *tty)
{
	struct bf535_serial *info = (struct bf535_serial *)tty->driver_data;
	unsigned long flags = 0;
	unsigned int idx = (unsigned int) info->hub2;

	if (serial_paranoia_check(info, tty->device, "rs_stop"))
		return;
	
	save_flags(flags); cli();
	   ACCESS_PORT_IER(idx) /* Change access to IER & data port */
	   UART_IER(idx) = 0;
	restore_flags(flags);
}
예제 #4
0
int serial_getc(void)
{
	uint16_t uart_rbr_val;

	/* wait for data ! */
	while (!serial_tstc())
		continue;

	/* grab the new byte */
	uart_rbr_val = *pUART_RBR;

#ifdef CONFIG_DEBUG_SERIAL
	/* grab & clear the LSR */
	uint16_t uart_lsr_val = uart_lsr_read();

	cached_lsr[cache_count] = uart_lsr_val;
	cached_rbr[cache_count] = uart_rbr_val;
	cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr);

	if (uart_lsr_val & (OE|PE|FE|BI)) {
		uint16_t dll, dlh;
		printf("\n[SERIAL ERROR]\n");
		ACCESS_LATCH();
		dll = *pUART_DLL;
		dlh = *pUART_DLH;
		ACCESS_PORT_IER();
		printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh);
		do {
			--cache_count;
			printf("\t%3i: RBR=0x%02x LSR=0x%02x\n", cache_count,
				cached_rbr[cache_count], cached_lsr[cache_count]);
		} while (cache_count > 0);
		return -1;
	}
#endif
	uart_lsr_clear();

	return uart_rbr_val;
}
예제 #5
0
static int uart_getc(uint32_t uart_base)
{
	uint16_t uart_rbr_val;

	/* wait for data ! */
	while (!uart_tstc(uart_base))
		continue;

	/* grab the new byte */
	uart_rbr_val = bfin_read(&pUART->rbr);

#ifdef CONFIG_DEBUG_SERIAL
	/* grab & clear the LSR */
	uint16_t uart_lsr_val = uart_lsr_read(uart_base);

	cached_lsr[cache_count] = uart_lsr_val;
	cached_rbr[cache_count] = uart_rbr_val;
	cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr);

	if (uart_lsr_val & (OE|PE|FE|BI)) {
		uint16_t dll, dlh;
		printf("\n[SERIAL ERROR]\n");
		ACCESS_LATCH();
		dll = bfin_read(&pUART->dll);
		dlh = bfin_read(&pUART->dlh);
		ACCESS_PORT_IER();
		printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh);
		do {
			--cache_count;
			printf("\t%3zu: RBR=0x%02x LSR=0x%02x\n", cache_count,
				cached_rbr[cache_count], cached_lsr[cache_count]);
		} while (cache_count > 0);
		return -1;
	}
#endif
	uart_lsr_clear(uart_base);

	return uart_rbr_val;
}
static _INLINE_ void receive_chars(struct bf535_serial *info, struct pt_regs *regs, unsigned short rx)
{
	struct tty_struct *tty = info->tty;
	unsigned char ch;
	int idx = info->hub2;

	/*
	 * This do { } while() loop will get ALL chars out of Rx FIFO 
         */
	do {
		ch = (unsigned char) rx;
	
		if(info->is_cons) {
			if (UART_LSR(idx) & UART_LSR_BI){ /* break received */ 
				status_handle(info, UART_LSR(idx));
				return;
			} else if (ch == 0x10) { /* ^P */
				show_state();
				show_free_areas();
				show_buffers();
/*				show_net_buffers(); */
				return;
			} else if (ch == 0x12) { /* ^R */
				machine_restart(NULL);
				return;
			}
		}

		if(!tty){
			printk("no tty\n");
			goto clear_and_exit;
		}
		
		/*
		 * Make sure that we do not overflow the buffer
		 */
		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			queue_task(&tty->flip.tqueue, &tq_timer);
			return;
		}

		if(UART_LSR(idx) & UART_LSR_PE) {
			*tty->flip.flag_buf_ptr++ = TTY_PARITY;
			status_handle(info, UART_LSR(idx));
		} else if(UART_LSR(idx) & UART_LSR_OE) {
			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
			status_handle(info, UART_LSR(idx));
		} else if(UART_LSR(idx) & UART_LSR_FE) {
			*tty->flip.flag_buf_ptr++ = TTY_FRAME;
			status_handle(info, UART_LSR(idx));
		} else {
			*tty->flip.flag_buf_ptr++ = 0; /* XXX */
		}

		tty->flip.count++;
                *tty->flip.char_buf_ptr++ = ch;

		ACCESS_PORT_IER(idx) /* change access to port data */
		rx = UART_RBR(idx);
	} while(UART_LSR(idx) & UART_LSR_DR);

	queue_task(&tty->flip.tqueue, &tq_timer);

clear_and_exit:
	return;
}