Ejemplo n.º 1
0
static void
clear_device(const uintptr_t *port) 
{
	write_omap(port[OMAP_UART_IER], 0);					// Disable all interrupts
	/* Clear FIFOs */
	set_port(port[OMAP_UART_FCR], OMAP_FCR_RXCLR | OMAP_FCR_TXCLR, OMAP_FCR_RXCLR | OMAP_FCR_TXCLR); 
	read_omap(port[OMAP_UART_LSR]);						// Clear Line Status Interrupt
	read_omap(port[OMAP_UART_MSR]);						// Clear Modem Interrupt
}
Ejemplo n.º 2
0
/*
 * Process data in a line status register
 */
static int
process_lsr(DEV_OMAP *dev, unsigned char lsr) {
	unsigned key = 0, eventflag = 0;

	// Return immediately if no errors.
	if((lsr & (OMAP_LSR_BI|OMAP_LSR_OE|OMAP_LSR_FE|OMAP_LSR_PE)) == 0)
		return(0);

	// Save the error as out-of-band data which can be retrieved via devctl().
	dev->tty.oband_data |= (lsr >> 1) & 0x0f;
	atomic_set(&dev->tty.flags, OBAND_DATA);
// Uncomment for post 1.0 since there was no time to test sufficiently
//	if(dev->tty.notify[2].cnt) {
//		dev->tty.notify[2].cnt = 0;	// Disarm
//		dev->tty.notify[2].event.sigev_value.sival_int |= _NOTIFY_COND_OBAND;
//		atomic_set(&dev->tty.flags, EVENT_NOTIFY_OBAND);
//		eventflag = 1;
//		}

	// Read whatever input data happens to be in the buffer to "eat" the
	// spurious data associated with break, parity error, etc.
	key = read_omap(dev->port[OMAP_UART_RHR]);

	if(lsr & OMAP_LSR_BI)
		key |= TTI_BREAK;
	else if(lsr & OMAP_LSR_OE)
		key |= TTI_OVERRUN;
	else if(lsr & OMAP_LSR_FE)
		key |= TTI_FRAME;
	else if(lsr & OMAP_LSR_PE)
		key |= TTI_PARITY;

	return(tti(&dev->tty, key) | eventflag);
	}
Ejemplo n.º 3
0
static void seromap_enable(DEV_OMAP *dev, int enable)
{
	uintptr_t		*port = dev->port;

	write_omap(port[OMAP_UART_LCR], 0x80);

	if (!enable) {
		atomic_set(&dev->pwm_flag, SEROMAP_PWM_PAGED);

		// If HW flow control is ON, assert the RTS line
		if (dev->tty.c_cflag & IHFLOW)
			set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR|OMAP_MCR_RTS, 0);

		while (!(read_omap(port[OMAP_UART_LSR]) & OMAP_LSR_TSRE))
			;
		nanospin_ns(1000000);			// pause for 1ms
		write_omap(port[OMAP_UART_MDR1], 0x07);
		write_omap(port[OMAP_UART_DLL], 0xFF);
		write_omap(port[OMAP_UART_DLH], 0xFF);
	}
	else {
		write_omap(port[OMAP_UART_DLL], dev->brd);
		write_omap(port[OMAP_UART_DLH], (dev->brd >> 8) & 0xff);
		write_omap(port[OMAP_UART_MDR1], 0x00);

		// If HW flow control is ON, de-assert the RTS line
		if(dev->tty.c_cflag & IHFLOW)
			set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR|OMAP_MCR_RTS, OMAP_MCR_DTR|OMAP_MCR_RTS);

		// Allow data transmission to resume
		atomic_clr(&dev->pwm_flag, SEROMAP_PWM_PAGED);
	}

	write_omap(port[OMAP_UART_LCR], dev->lcr);
}
Ejemplo n.º 4
0
void
set_port(unsigned port, unsigned mask, unsigned data) 
{
	unsigned char c;

	c = read_omap(port);
	write_omap(port, (c & ~mask) | (data & mask));
}
Ejemplo n.º 5
0
//
// Clean up the device then add it to the interrupt list and enable it.
//
void
ser_attach_intr(DEV_OMAP *dev) {
	uintptr_t	*port = dev->port;
	// interrupt sources except transmit and modem status interrupt
	unsigned	ier = OMAP_IER_RHR|OMAP_IER_LS;
	
	// According to the National bug sheet you must wait for the transmit
	// holding register to be empty.
	do {
	} while((read_omap(port[OMAP_UART_LSR]) & OMAP_LSR_TXRDY) == 0);

	clear_device(port);

	dev->iid = InterruptAttach(dev->intr, ser_intr, dev, 0, 0);

	// Enable modem status interrupt (default)
	if (!dev->no_msr_int) {
		ier |= OMAP_IER_MS;
	}
	// Enable interrupt sources.
	write_omap(port[OMAP_UART_IER], ier);
}
Ejemplo n.º 6
0
/*
 * Serial interrupt handler
 */
const struct sigevent *
ser_intr(void *area, int id) {
	int				status, cnt;
	unsigned char	msr, lsr;
	DEV_OMAP		*dev = area;
	struct sigevent *event = NULL;
	unsigned		iir;
	uintptr_t		*port = dev->port;

#ifdef PWR_MAN
	/* Our idle state can be changed by a devctl so we must use a spinlock */
	InterruptLock(&dev->idle_spinlock);
#endif

	while (1) {
		status = 0;

#ifdef PWR_MAN
        if (dev->idle) {

            omap_clock_enable_isr(dev);
#ifdef WINBT            
            omap_force_rts(dev, 0);

            // once we are in idle mode the only interrupt that can wake us up is from am CTS line change
            tti(&dev->tty, TTI_OHW_STOP);

            // start a spare timer for debouncing, if this timer actually
            // expires, then this was a CTS glitch, if the timer
            // is cleared by having data on the RX line, it will send up the
            // oband notification to wake up the host.
            dev->signal_oband_notification = 1;

            if( dev->tty.un.s.spare_tmr == 0 ){
                atomic_set (&dev->tty.eflags, EVENT_TIMER_QUEUE);
                dev->tty.un.s.spare_tmr = 4;

                // queue the event here because the switch statement can just exit
                // without actually queuing the event with setting the status flag
                if((dev->tty.flags & EVENT_QUEUED) == 0) {
                    event = &ttyctrl.event;
                    dev_lock(&ttyctrl);
                    ttyctrl.event_queue[ttyctrl.num_events++] = &dev->tty;
                    atomic_set(&dev->tty.flags, EVENT_QUEUED);
                    dev_unlock(&ttyctrl);
                    continue;
                }
            }
#endif // End of #ifdef WINBT
        }

		unsigned ssr = read_omap(port[OMAP_UART_SSR]);
		if (ssr & OMAP_SSR_WAKEUP_STS) {
			/* Clear the wake up interrupt */
			set_port(port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, 0);
		}
#endif


		iir = read_omap(port[OMAP_UART_IIR]) & OMAP_II_MASK;

		switch(iir) {
			case OMAP_II_RX:		// Receive data
			case OMAP_II_RXTO:		// Receive data timeout
			case OMAP_II_LS:		// Line status change
				cnt = 0;
				lsr = read_omap(port[OMAP_UART_LSR]);
				do {
					if( lsr & (OMAP_LSR_BI|OMAP_LSR_OE|OMAP_LSR_FE|OMAP_LSR_PE) ) {
						// Error character
						status |= process_lsr(dev, lsr);
					}
					else {
						// Good character
						status |= tti(&dev->tty, (read_omap(port[OMAP_UART_RHR])) & 0xff);
						cnt++;
					}
					lsr = read_omap(port[OMAP_UART_LSR]);
				} while(lsr & OMAP_LSR_RXRDY && cnt < FIFO_SIZE);
#ifdef WINBT
				if( cnt && dev->signal_oband_notification ){

				    // received data after a CTS wake up
				    // notify the host that it's a valid CTS wakeup.
				    dev->signal_oband_notification = 0;
		            dev->tty.oband_data |= _OBAND_SER_MS;
		            atomic_set(&dev->tty.flags, OBAND_DATA);
		            atomic_set(&dev->tty.flags, EVENT_NOTIFY_OBAND);
		            status |= 1;
				}

				if (cnt && dev->tty.un.s.spare_tmr) {
				    // received data, clear spare timer
	                dev->tty.un.s.spare_tmr = 0;
	            }
#endif
				break;

			case OMAP_II_TX:		// Transmit buffer empty

				// disable thr interrupt
				set_port(dev->port[OMAP_UART_IER], OMAP_IER_THR, 0);

				dev->tty.un.s.tx_tmr = 0;
				/* Send event to io-char, tto() will be processed at thread time */
				atomic_set(&dev->tty.flags, EVENT_TTO);
				status |= 1;
				break;

			case OMAP_II_MS:		// Modem change
				msr = read_omap(port[OMAP_UART_MSR]);

				if(msr & OMAP_MSR_DDCD) {
					status |= tti(&dev->tty, (msr & OMAP_MSR_DCD) ? TTI_CARRIER : TTI_HANGUP);
				}

				if((msr & OMAP_MSR_DCTS)  &&  (dev->tty.c_cflag & OHFLOW)) {
					status |= tti(&dev->tty, (msr & OMAP_MSR_CTS) ? TTI_OHW_CONT : TTI_OHW_STOP);
				}

				/* OBAND notification of Modem status change */
				dev->tty.oband_data |= _OBAND_SER_MS;
				atomic_set(&dev->tty.flags, OBAND_DATA);
				atomic_set(&dev->tty.flags, EVENT_NOTIFY_OBAND);
				status |= 1;

				break;

			case OMAP_II_NOINTR:	// No interrupt
				if (read_omap(port[OMAP_UART_SSR]) & OMAP_SSR_WAKEUP_STS) {	// Wake up interrupt
					set_port(port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, 0);		// clear wakeup interrupt
					set_port(port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, OMAP_SCR_WAKEUPEN);	// re-enable wakeup interrupt
				}
			default:
				goto done;
		}

		if (status) {
			if((dev->tty.flags & EVENT_QUEUED) == 0) {
				event = &ttyctrl.event;
				dev_lock(&ttyctrl);
				ttyctrl.event_queue[ttyctrl.num_events++] = &dev->tty;
				atomic_set(&dev->tty.flags, EVENT_QUEUED);
				dev_unlock(&ttyctrl);
			}
		}
	}

done:
#ifdef PWR_MAN
	InterruptUnlock(&dev->idle_spinlock);
#endif

	return (event);
}
Ejemplo n.º 7
0
DEV_OMAP *
create_device(TTYINIT_OMAP *dip, unsigned unit, unsigned maxim_xcvr_kick) {
	DEV_OMAP 			*dev;
	unsigned			i;
	uintptr_t			port;
	unsigned char		msr;
	unsigned char		tlr = 0, tcr = 0;
#ifdef PWR_MAN
    clk_enable_t        clk_cfg = clk_enable_none;
#endif

	// Get a device entry and the input/output buffers for it.
	if ((dev = malloc(sizeof(*dev))) == NULL)
	{
		slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of device entry failed (%d)", errno);
		return (dev);
	}	
	memset(dev, 0, sizeof(*dev));

	// Get buffers.
	dev->tty.ibuf.head = dev->tty.ibuf.tail = dev->tty.ibuf.buff = malloc(dev->tty.ibuf.size = dip->tty.isize);
	if (dev->tty.ibuf.buff == NULL)
	{
		slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of input buffer failed (%d)", errno);
		free(dev);
		return (NULL);
	}
						   
	dev->tty.obuf.head = dev->tty.obuf.tail = dev->tty.obuf.buff = malloc(dev->tty.obuf.size = dip->tty.osize);
	if (dev->tty.obuf.buff == NULL)
	{
		slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of output buffer failed (%d)", errno);
		free(dev->tty.ibuf.buff);
		free(dev);
		return (NULL);
	}

	dev->tty.cbuf.head = dev->tty.cbuf.tail = dev->tty.cbuf.buff = malloc(dev->tty.cbuf.size = dip->tty.csize);
	if (dev->tty.cbuf.buff == NULL)
	{
		slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of canonical buffer failed (%d)", errno);
		free(dev->tty.ibuf.buff);
		free(dev->tty.obuf.buff);
		free(dev);
		return (NULL);
	}

	if (dip->tty.highwater)
		dev->tty.highwater = dip->tty.highwater;
	else
		dev->tty.highwater = dev->tty.ibuf.size - (FIFO_SIZE * 2);

	strcpy(dev->tty.name, dip->tty.name);

	dev->tty.baud = dip->tty.baud;
	dev->tty.fifo = dip->tty.fifo;
	dev->tty.verbose = dip->tty.verbose;

	port = mmap_device_io(OMAP_UART_SIZE, dip->tty.port);
	for (i = 0; i < OMAP_UART_SIZE; i += 4)
		dev->port[i] = port + i;

	dev->intr = dip->tty.intr;
	dev->clk = dip->tty.clk;
	dev->div = dip->tty.div;

	dev->tty.flags = EDIT_INSERT | LOSES_TX_INTR;
	dev->tty.c_cflag = dip->tty.c_cflag;
	dev->tty.c_iflag = dip->tty.c_iflag;
	dev->tty.c_lflag = dip->tty.c_lflag;
	dev->tty.c_oflag = dip->tty.c_oflag;
	dev->tty.lflags = dip->tty.lflags;
	if (dip->tty.logging_path[0] != NULL)
		dev->tty.logging_path = strdup(dip->tty.logging_path);

#ifdef PWR_MAN
	dev->physbase = dip->tty.port;
	
	if (omap_clock_toggle_init(dev) != EOK)
	{
		slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Fail to initialize clocks for PM!");
		free(dev->tty.ibuf.buff);
		free(dev->tty.obuf.buff);
		free(dev);
		return (NULL);
	}
#ifdef WINBT
    clk_cfg = clk_enable_smart_wkup;
    
	if (omap_force_rts_init(dev) != EOK)
	{
		slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Fail to initialize force_rts for PM!");
		free(dev->tty.ibuf.buff);
		free(dev->tty.obuf.buff);
		free(dev);
		return (NULL);
	}
#endif

	omap_clock_enable(dev, clk_cfg);

#ifdef WINBT	
	bt_ctrl_init();
#endif	
#endif

	/* Set auto_rts mode */
	dev->auto_rts_enable = dip->auto_rts_enable;
	
	// Do not enable MSR interrupt                                                                                                        
	dev->no_msr_int  = dip->no_msr_int;   

	// Initialize termios cc codes to an ANSI terminal.
	ttc(TTC_INIT_CC, &dev->tty, 0);

	// Initialize the device's name.
	// Assume that the basename is set in device name.  This will attach
	// to the path assigned by the unit number/minor number combination
	unit = SET_NAME_NUMBER(unit) | NUMBER_DEV_FROM_USER;
	ttc(TTC_INIT_TTYNAME, &dev->tty, unit);

	// see if we have a maxim rs-232 transceiver that needs to be
	// kicked after it goes to sleep
	dev->kick_maxim = maxim_xcvr_kick;

	// Only setup IRQ handler for non-pcmcia devices.
	// Pcmcia devices will have this done later when card is inserted.
	if (dip->tty.port != 0 && dip->tty.intr != _NTO_INTR_SPARE) {
#ifdef OMAP5910
		/*
		 * Don't change default mode set in the very distant past. Even though
		 * MODE_SELECT should be DISABLE before changing DLH, DLL.
		 */
                // enable the UART
                write_omap(dev->port[OMAP_UART_MDR1], OMAP_MDR1_MODE_16X);
#else
		/*
		 * TRM states: Before initializing or modifying clock parameter controls
		 * (DLH, DLL), MODE_SELECT must be set to 0x7 (DISABLE). Failure to observe
		 * this rule can result in unpredictable module behavior.
		 */
		write_omap(dev->port[OMAP_UART_MDR1], OMAP_MDR1_MODE_DISABLE);
#endif
		/* Work around for silicon errata i202 states: */
		/* Need a delay = 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) */
		nanospin_ns(200);
		/* Clear FIFOs */
		set_port(dev->port[OMAP_UART_FCR], OMAP_FCR_RXCLR | OMAP_FCR_TXCLR, OMAP_FCR_RXCLR | OMAP_FCR_TXCLR);
		/* Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and TX_FIFO_E bit is 1 */
		i = 5;
		while ((read_omap(dev->port[OMAP_UART_LSR]) & (OMAP_UART_LSR_THRE | OMAP_UART_LSR_DR)) != OMAP_UART_LSR_THRE)
		{
		   nanospin_ns(200);
		   if (--i == 0)
		   {
		      break;  /* No need to do anything drastic if FIFO is still not empty */
		   }
		}
		// enable access to divisor registers
		write_omap(dev->port[OMAP_UART_LCR], OMAP_LCR_DLAB);
		write_omap(dev->port[OMAP_UART_DLL], 0);
		write_omap(dev->port[OMAP_UART_DLH], 0);

		/* Switch to config mode B to get access to EFR Register */
		write_omap(dev->port[OMAP_UART_LCR], 0xBF);
		/* Enable access to TLR register */
		set_port(dev->port[OMAP_UART_EFR], OMAP_EFR_ENHANCED, OMAP_EFR_ENHANCED);
		/* Switch to operational mode to get acces to MCR register */
		write_omap(dev->port[OMAP_UART_LCR], 0x00);
		/* set MCR bit 6 to enable access to TCR and TLR registers */
	    set_port(dev->port[OMAP_UART_MCR], OMAP_MCR_TCRTLR, OMAP_MCR_TCRTLR);
		write_omap(dev->port[OMAP_UART_FCR], OMAP_FCR_ENABLE|OMAP_FCR_RXCLR|OMAP_FCR_TXCLR);

		tcr = 0x0e; 	/* set auto-rts assert at 56 bytes, restore at 0 bytes */
    	if (dev->tty.fifo) 
		{
        	/* Set RX fifo trigger level */
	        switch (dev->tty.fifo >> 4) {
    	        case FIFO_TRIG_8:
				default:   
					tlr = 0x20; 
					break;
        	    case FIFO_TRIG_16:  tlr = 0x40; break;
	            case FIFO_TRIG_32:  tlr = 0x80; break;
    	        case FIFO_TRIG_56:  tlr = 0xe0; break;
        	    case FIFO_TRIG_60:  
					tlr = 0xf0; 
					tcr = 0x0f; /* Ensure auto-rts trigger is not less the RX trigger */
					break;
	        }

    	    /* Set TX fifo trigger level */
        	switch (dev->tty.fifo & 0x0f) {
	            case FIFO_TRIG_8:   
				default:
					tlr |= 0x02;
					break;
    	        case FIFO_TRIG_16:  tlr |= 0x04; break;
        	    case FIFO_TRIG_32:  tlr |= 0x08; break;
            	case FIFO_TRIG_56:  tlr |= 0x0e; break;
	            case FIFO_TRIG_60:  tlr |= 0x0f; break;
    	    }
	    }

	    write_omap(dev->port[OMAP_UART_TCR], tcr);
	    write_omap(dev->port[OMAP_UART_TLR], tlr);
#ifdef PWR_MAN
	    write_omap(dev->port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN);
#else
		write_omap(dev->port[OMAP_UART_SCR], 0x00);
#endif
		/* Switch back to Config mode B to gain access to EFR again */
		write_omap(dev->port[OMAP_UART_LCR], 0xBF);
		/* remove access to TLR register */
		set_port(dev->port[OMAP_UART_EFR], OMAP_EFR_ENHANCED, 0);
		/* Switch to operational mode to get acces to MCR register */
		write_omap(dev->port[OMAP_UART_LCR], 0x00);
		/* clr MCR bit 6 to remove access to TCR and TLR registers */
	    set_port(dev->port[OMAP_UART_MCR], OMAP_MCR_TCRTLR, 0);

		ser_stty(dev);
		ser_attach_intr(dev);
	}
Ejemplo n.º 8
0
int
tto(TTYDEV *ttydev, int action, int arg1) {
	TTYBUF 			*bup = &ttydev->obuf;
	DEV_OMAP		*dev = (DEV_OMAP *)ttydev;
	const uintptr_t	*port = dev->port;
	unsigned char 	c;
	
#ifdef PWR_MAN

	if (dev->idle) {

		/* Check the client lists for notify conditions */
		return(tto_checkclients(&dev->tty));
	}
#endif

	switch(action) {
	case TTO_STTY:
//            if (dev->driver_pmd.cur_mode == PM_MODE_ACTIVE)
			ser_stty(dev);
		return (0);

	case TTO_CTRL:

		if(arg1 & _SERCTL_BRK_CHG)
			set_port(port[OMAP_UART_LCR], OMAP_LCR_BREAK, arg1 &_SERCTL_BRK ? OMAP_LCR_BREAK : 0);

		if(arg1 & _SERCTL_DTR_CHG)
			set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR, arg1 & _SERCTL_DTR ? OMAP_MCR_DTR : 0);

		if(arg1 & _SERCTL_RTS_CHG)
		{
			if (dev->auto_rts_enable)
			{
				/* For auto-rts enable/disable RX & LS interrupts to assert/clear 
				 * input flow control (the FIFO will automatically handle the RTS line) 
				*/
				if (arg1 & _SERCTL_RTS)
					write_omap(port[OMAP_UART_IER], read_omap(port[OMAP_UART_IER] ) | OMAP_IER_RHR | OMAP_IER_LS );
				else
					write_omap(port[OMAP_UART_IER], read_omap(port[OMAP_UART_IER] ) & ~(OMAP_IER_RHR | OMAP_IER_LS ) );
			}
			else
				set_port(port[OMAP_UART_MCR], OMAP_MCR_RTS, arg1 & _SERCTL_RTS ? OMAP_MCR_RTS : 0);
		}

#ifdef WINBT
        if (arg1 & _CTL_TIMED_CHG) {

            slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Turning clocks OFF due to CTS glitch\n", __FUNCTION__);
            dev->signal_oband_notification = 0;
            omap_clock_disable(dev);
        }
#endif
		return (0);

	case TTO_LINESTATUS:
		return (((read_omap(port[OMAP_UART_MSR]) << 8) | read_omap(port[OMAP_UART_MCR])) & 0xf003);

	case TTO_DATA:
	case TTO_EVENT:
		break;

	default:
		return (0);
	}


	while (bup->cnt > 0 && (!(read_omap(port[OMAP_UART_SSR]) & OMAP_SSR_TXFULL)) )
	{
		/*
    		* If the OSW_PAGED_OVERRIDE flag is set then allow
   		* transmit of character even if output is suspended via
    		* the OSW_PAGED flag. This flag implies that the next
    		* character in the obuf is a software flow control
    		* charater (STOP/START).
    		* Note: tx_inject sets it up so that the contol
    		*       character is at the start (tail) of the buffer.
    		*
		*/
	

		if (dev->tty.flags & (OHW_PAGED | OSW_PAGED) && !(dev->tty.xflags & OSW_PAGED_OVERRIDE))
			break;

		/* Get character from obuf and do any output processing */
		dev_lock(&dev->tty);
		c = tto_getchar(&dev->tty);
		dev_unlock(&dev->tty);
	    	
		/* Print the character */
		dev->tty.un.s.tx_tmr = 3;       /* Timeout 3 */
		write_omap(port[OMAP_UART_THR], c);

		/* Clear the OSW_PAGED_OVERRIDE flag as we only want
      		* one character to be transmitted in this case.
     		*/
    		if (dev->tty.xflags & OSW_PAGED_OVERRIDE){
           		atomic_clr(&dev->tty.xflags, OSW_PAGED_OVERRIDE);
			break;
 		}	
 	}

	/* If there is still data in the obuf and we are not in a flow 
	 * controlled state then turn TX interrupts back on to notify us
	 * when the hardware is ready for more characters.
	 */
	if (bup->cnt > 0 && !(dev->tty.flags & (OHW_PAGED|OSW_PAGED)) )
	 { 
		// enable all interrupts
		set_port(dev->port[OMAP_UART_IER], OMAP_IER_THR, OMAP_IER_THR);
	 }
	 

	/* Check the client lists for notify conditions */
	return(tto_checkclients(&dev->tty));
}