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); }
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; }
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; }